simplepie.inc 436 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772
  1. <?php
  2. /**
  3. * SimplePie
  4. *
  5. * A PHP-Based RSS and Atom Feed Framework.
  6. * Takes the hard work out of managing a complete RSS/Atom solution.
  7. *
  8. * Please note: This file is automatically generated by a build script. The
  9. * full original source is always available from http://simplepie.org/
  10. *
  11. * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without modification, are
  15. * permitted provided that the following conditions are met:
  16. *
  17. * * Redistributions of source code must retain the above copyright notice, this list of
  18. * conditions and the following disclaimer.
  19. *
  20. * * Redistributions in binary form must reproduce the above copyright notice, this list
  21. * of conditions and the following disclaimer in the documentation and/or other materials
  22. * provided with the distribution.
  23. *
  24. * * Neither the name of the SimplePie Team nor the names of its contributors may be used
  25. * to endorse or promote products derived from this software without specific prior
  26. * written permission.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  30. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
  31. * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  33. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  34. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  35. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * @package SimplePie
  39. * @version 1.3.1
  40. * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
  41. * @author Ryan Parman
  42. * @author Geoffrey Sneddon
  43. * @author Ryan McCue
  44. * @link http://simplepie.org/ SimplePie
  45. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  46. */
  47. /**
  48. * SimplePie Name
  49. */
  50. define('SIMPLEPIE_NAME', 'SimplePie');
  51. /**
  52. * SimplePie Version
  53. */
  54. define('SIMPLEPIE_VERSION', '1.3.1');
  55. /**
  56. * SimplePie Build
  57. * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::get_build() only every load of simplepie.inc)
  58. */
  59. define('SIMPLEPIE_BUILD', '20121030175911');
  60. /**
  61. * SimplePie Website URL
  62. */
  63. define('SIMPLEPIE_URL', 'http://simplepie.org');
  64. /**
  65. * SimplePie Useragent
  66. * @see SimplePie::set_useragent()
  67. */
  68. define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
  69. /**
  70. * SimplePie Linkback
  71. */
  72. define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
  73. /**
  74. * No Autodiscovery
  75. * @see SimplePie::set_autodiscovery_level()
  76. */
  77. define('SIMPLEPIE_LOCATOR_NONE', 0);
  78. /**
  79. * Feed Link Element Autodiscovery
  80. * @see SimplePie::set_autodiscovery_level()
  81. */
  82. define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
  83. /**
  84. * Local Feed Extension Autodiscovery
  85. * @see SimplePie::set_autodiscovery_level()
  86. */
  87. define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
  88. /**
  89. * Local Feed Body Autodiscovery
  90. * @see SimplePie::set_autodiscovery_level()
  91. */
  92. define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
  93. /**
  94. * Remote Feed Extension Autodiscovery
  95. * @see SimplePie::set_autodiscovery_level()
  96. */
  97. define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
  98. /**
  99. * Remote Feed Body Autodiscovery
  100. * @see SimplePie::set_autodiscovery_level()
  101. */
  102. define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
  103. /**
  104. * All Feed Autodiscovery
  105. * @see SimplePie::set_autodiscovery_level()
  106. */
  107. define('SIMPLEPIE_LOCATOR_ALL', 31);
  108. /**
  109. * No known feed type
  110. */
  111. define('SIMPLEPIE_TYPE_NONE', 0);
  112. /**
  113. * RSS 0.90
  114. */
  115. define('SIMPLEPIE_TYPE_RSS_090', 1);
  116. /**
  117. * RSS 0.91 (Netscape)
  118. */
  119. define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
  120. /**
  121. * RSS 0.91 (Userland)
  122. */
  123. define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
  124. /**
  125. * RSS 0.91 (both Netscape and Userland)
  126. */
  127. define('SIMPLEPIE_TYPE_RSS_091', 6);
  128. /**
  129. * RSS 0.92
  130. */
  131. define('SIMPLEPIE_TYPE_RSS_092', 8);
  132. /**
  133. * RSS 0.93
  134. */
  135. define('SIMPLEPIE_TYPE_RSS_093', 16);
  136. /**
  137. * RSS 0.94
  138. */
  139. define('SIMPLEPIE_TYPE_RSS_094', 32);
  140. /**
  141. * RSS 1.0
  142. */
  143. define('SIMPLEPIE_TYPE_RSS_10', 64);
  144. /**
  145. * RSS 2.0
  146. */
  147. define('SIMPLEPIE_TYPE_RSS_20', 128);
  148. /**
  149. * RDF-based RSS
  150. */
  151. define('SIMPLEPIE_TYPE_RSS_RDF', 65);
  152. /**
  153. * Non-RDF-based RSS (truly intended as syndication format)
  154. */
  155. define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
  156. /**
  157. * All RSS
  158. */
  159. define('SIMPLEPIE_TYPE_RSS_ALL', 255);
  160. /**
  161. * Atom 0.3
  162. */
  163. define('SIMPLEPIE_TYPE_ATOM_03', 256);
  164. /**
  165. * Atom 1.0
  166. */
  167. define('SIMPLEPIE_TYPE_ATOM_10', 512);
  168. /**
  169. * All Atom
  170. */
  171. define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
  172. /**
  173. * All feed types
  174. */
  175. define('SIMPLEPIE_TYPE_ALL', 1023);
  176. /**
  177. * No construct
  178. */
  179. define('SIMPLEPIE_CONSTRUCT_NONE', 0);
  180. /**
  181. * Text construct
  182. */
  183. define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
  184. /**
  185. * HTML construct
  186. */
  187. define('SIMPLEPIE_CONSTRUCT_HTML', 2);
  188. /**
  189. * XHTML construct
  190. */
  191. define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
  192. /**
  193. * base64-encoded construct
  194. */
  195. define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
  196. /**
  197. * IRI construct
  198. */
  199. define('SIMPLEPIE_CONSTRUCT_IRI', 16);
  200. /**
  201. * A construct that might be HTML
  202. */
  203. define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
  204. /**
  205. * All constructs
  206. */
  207. define('SIMPLEPIE_CONSTRUCT_ALL', 63);
  208. /**
  209. * Don't change case
  210. */
  211. define('SIMPLEPIE_SAME_CASE', 1);
  212. /**
  213. * Change to lowercase
  214. */
  215. define('SIMPLEPIE_LOWERCASE', 2);
  216. /**
  217. * Change to uppercase
  218. */
  219. define('SIMPLEPIE_UPPERCASE', 4);
  220. /**
  221. * PCRE for HTML attributes
  222. */
  223. define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
  224. /**
  225. * PCRE for XML attributes
  226. */
  227. define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
  228. /**
  229. * XML Namespace
  230. */
  231. define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
  232. /**
  233. * Atom 1.0 Namespace
  234. */
  235. define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
  236. /**
  237. * Atom 0.3 Namespace
  238. */
  239. define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
  240. /**
  241. * RDF Namespace
  242. */
  243. define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
  244. /**
  245. * RSS 0.90 Namespace
  246. */
  247. define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
  248. /**
  249. * RSS 1.0 Namespace
  250. */
  251. define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
  252. /**
  253. * RSS 1.0 Content Module Namespace
  254. */
  255. define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
  256. /**
  257. * RSS 2.0 Namespace
  258. * (Stupid, I know, but I'm certain it will confuse people less with support.)
  259. */
  260. define('SIMPLEPIE_NAMESPACE_RSS_20', '');
  261. /**
  262. * DC 1.0 Namespace
  263. */
  264. define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
  265. /**
  266. * DC 1.1 Namespace
  267. */
  268. define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
  269. /**
  270. * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
  271. */
  272. define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
  273. /**
  274. * GeoRSS Namespace
  275. */
  276. define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
  277. /**
  278. * Media RSS Namespace
  279. */
  280. define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
  281. /**
  282. * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
  283. */
  284. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
  285. /**
  286. * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
  287. */
  288. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');
  289. /**
  290. * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
  291. */
  292. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');
  293. /**
  294. * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
  295. */
  296. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');
  297. /**
  298. * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
  299. */
  300. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');
  301. /**
  302. * iTunes RSS Namespace
  303. */
  304. define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
  305. /**
  306. * XHTML Namespace
  307. */
  308. define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
  309. /**
  310. * IANA Link Relations Registry
  311. */
  312. define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
  313. /**
  314. * No file source
  315. */
  316. define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
  317. /**
  318. * Remote file source
  319. */
  320. define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
  321. /**
  322. * Local file source
  323. */
  324. define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
  325. /**
  326. * fsockopen() file source
  327. */
  328. define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
  329. /**
  330. * cURL file source
  331. */
  332. define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
  333. /**
  334. * file_get_contents() file source
  335. */
  336. define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
  337. /**
  338. * SimplePie
  339. *
  340. * @package SimplePie
  341. * @subpackage API
  342. */
  343. class SimplePie
  344. {
  345. /**
  346. * @var array Raw data
  347. * @access private
  348. */
  349. public $data = array();
  350. /**
  351. * @var mixed Error string
  352. * @access private
  353. */
  354. public $error;
  355. /**
  356. * @var object Instance of SimplePie_Sanitize (or other class)
  357. * @see SimplePie::set_sanitize_class()
  358. * @access private
  359. */
  360. public $sanitize;
  361. /**
  362. * @var string SimplePie Useragent
  363. * @see SimplePie::set_useragent()
  364. * @access private
  365. */
  366. public $useragent = SIMPLEPIE_USERAGENT;
  367. /**
  368. * @var string Feed URL
  369. * @see SimplePie::set_feed_url()
  370. * @access private
  371. */
  372. public $feed_url;
  373. /**
  374. * @var object Instance of SimplePie_File to use as a feed
  375. * @see SimplePie::set_file()
  376. * @access private
  377. */
  378. public $file;
  379. /**
  380. * @var string Raw feed data
  381. * @see SimplePie::set_raw_data()
  382. * @access private
  383. */
  384. public $raw_data;
  385. /**
  386. * @var int Timeout for fetching remote files
  387. * @see SimplePie::set_timeout()
  388. * @access private
  389. */
  390. public $timeout = 10;
  391. /**
  392. * @var bool Forces fsockopen() to be used for remote files instead
  393. * of cURL, even if a new enough version is installed
  394. * @see SimplePie::force_fsockopen()
  395. * @access private
  396. */
  397. public $force_fsockopen = false;
  398. /**
  399. * @var bool Force the given data/URL to be treated as a feed no matter what
  400. * it appears like
  401. * @see SimplePie::force_feed()
  402. * @access private
  403. */
  404. public $force_feed = false;
  405. /**
  406. * @var bool Enable/Disable Caching
  407. * @see SimplePie::enable_cache()
  408. * @access private
  409. */
  410. public $cache = true;
  411. /**
  412. * @var int Cache duration (in seconds)
  413. * @see SimplePie::set_cache_duration()
  414. * @access private
  415. */
  416. public $cache_duration = 3600;
  417. /**
  418. * @var int Auto-discovery cache duration (in seconds)
  419. * @see SimplePie::set_autodiscovery_cache_duration()
  420. * @access private
  421. */
  422. public $autodiscovery_cache_duration = 604800; // 7 Days.
  423. /**
  424. * @var string Cache location (relative to executing script)
  425. * @see SimplePie::set_cache_location()
  426. * @access private
  427. */
  428. public $cache_location = './cache';
  429. /**
  430. * @var string Function that creates the cache filename
  431. * @see SimplePie::set_cache_name_function()
  432. * @access private
  433. */
  434. public $cache_name_function = 'md5';
  435. /**
  436. * @var bool Reorder feed by date descending
  437. * @see SimplePie::enable_order_by_date()
  438. * @access private
  439. */
  440. public $order_by_date = true;
  441. /**
  442. * @var mixed Force input encoding to be set to the follow value
  443. * (false, or anything type-cast to false, disables this feature)
  444. * @see SimplePie::set_input_encoding()
  445. * @access private
  446. */
  447. public $input_encoding = false;
  448. /**
  449. * @var int Feed Autodiscovery Level
  450. * @see SimplePie::set_autodiscovery_level()
  451. * @access private
  452. */
  453. public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
  454. /**
  455. * Class registry object
  456. *
  457. * @var SimplePie_Registry
  458. */
  459. public $registry;
  460. /**
  461. * @var int Maximum number of feeds to check with autodiscovery
  462. * @see SimplePie::set_max_checked_feeds()
  463. * @access private
  464. */
  465. public $max_checked_feeds = 10;
  466. /**
  467. * @var array All the feeds found during the autodiscovery process
  468. * @see SimplePie::get_all_discovered_feeds()
  469. * @access private
  470. */
  471. public $all_discovered_feeds = array();
  472. /**
  473. * @var string Web-accessible path to the handler_image.php file.
  474. * @see SimplePie::set_image_handler()
  475. * @access private
  476. */
  477. public $image_handler = '';
  478. /**
  479. * @var array Stores the URLs when multiple feeds are being initialized.
  480. * @see SimplePie::set_feed_url()
  481. * @access private
  482. */
  483. public $multifeed_url = array();
  484. /**
  485. * @var array Stores SimplePie objects when multiple feeds initialized.
  486. * @access private
  487. */
  488. public $multifeed_objects = array();
  489. /**
  490. * @var array Stores the get_object_vars() array for use with multifeeds.
  491. * @see SimplePie::set_feed_url()
  492. * @access private
  493. */
  494. public $config_settings = null;
  495. /**
  496. * @var integer Stores the number of items to return per-feed with multifeeds.
  497. * @see SimplePie::set_item_limit()
  498. * @access private
  499. */
  500. public $item_limit = 0;
  501. /**
  502. * @var array Stores the default attributes to be stripped by strip_attributes().
  503. * @see SimplePie::strip_attributes()
  504. * @access private
  505. */
  506. public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
  507. /**
  508. * @var array Stores the default tags to be stripped by strip_htmltags().
  509. * @see SimplePie::strip_htmltags()
  510. * @access private
  511. */
  512. public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
  513. /**
  514. * The SimplePie class contains feed level data and options
  515. *
  516. * To use SimplePie, create the SimplePie object with no parameters. You can
  517. * then set configuration options using the provided methods. After setting
  518. * them, you must initialise the feed using $feed->init(). At that point the
  519. * object's methods and properties will be available to you.
  520. *
  521. * Previously, it was possible to pass in the feed URL along with cache
  522. * options directly into the constructor. This has been removed as of 1.3 as
  523. * it caused a lot of confusion.
  524. *
  525. * @since 1.0 Preview Release
  526. */
  527. public function __construct()
  528. {
  529. if (version_compare(PHP_VERSION, '5.2', '<'))
  530. {
  531. trigger_error('PHP 4.x, 5.0 and 5.1 are no longer supported. Please upgrade to PHP 5.2 or newer.');
  532. die();
  533. }
  534. // Other objects, instances created here so we can set options on them
  535. $this->sanitize = new SimplePie_Sanitize();
  536. $this->registry = new SimplePie_Registry();
  537. if (func_num_args() > 0)
  538. {
  539. $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
  540. trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.', $level);
  541. $args = func_get_args();
  542. switch (count($args)) {
  543. case 3:
  544. $this->set_cache_duration($args[2]);
  545. case 2:
  546. $this->set_cache_location($args[1]);
  547. case 1:
  548. $this->set_feed_url($args[0]);
  549. $this->init();
  550. }
  551. }
  552. }
  553. /**
  554. * Used for converting object to a string
  555. */
  556. public function __toString()
  557. {
  558. return md5(serialize($this->data));
  559. }
  560. /**
  561. * Remove items that link back to this before destroying this object
  562. */
  563. public function __destruct()
  564. {
  565. if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
  566. {
  567. if (!empty($this->data['items']))
  568. {
  569. foreach ($this->data['items'] as $item)
  570. {
  571. $item->__destruct();
  572. }
  573. unset($item, $this->data['items']);
  574. }
  575. if (!empty($this->data['ordered_items']))
  576. {
  577. foreach ($this->data['ordered_items'] as $item)
  578. {
  579. $item->__destruct();
  580. }
  581. unset($item, $this->data['ordered_items']);
  582. }
  583. }
  584. }
  585. /**
  586. * Force the given data/URL to be treated as a feed
  587. *
  588. * This tells SimplePie to ignore the content-type provided by the server.
  589. * Be careful when using this option, as it will also disable autodiscovery.
  590. *
  591. * @since 1.1
  592. * @param bool $enable Force the given data/URL to be treated as a feed
  593. */
  594. public function force_feed($enable = false)
  595. {
  596. $this->force_feed = (bool) $enable;
  597. }
  598. /**
  599. * Set the URL of the feed you want to parse
  600. *
  601. * This allows you to enter the URL of the feed you want to parse, or the
  602. * website you want to try to use auto-discovery on. This takes priority
  603. * over any set raw data.
  604. *
  605. * You can set multiple feeds to mash together by passing an array instead
  606. * of a string for the $url. Remember that with each additional feed comes
  607. * additional processing and resources.
  608. *
  609. * @since 1.0 Preview Release
  610. * @see set_raw_data()
  611. * @param string|array $url This is the URL (or array of URLs) that you want to parse.
  612. */
  613. public function set_feed_url($url)
  614. {
  615. $this->multifeed_url = array();
  616. if (is_array($url))
  617. {
  618. foreach ($url as $value)
  619. {
  620. $this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1));
  621. }
  622. }
  623. else
  624. {
  625. $this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));
  626. }
  627. }
  628. /**
  629. * Set an instance of {@see SimplePie_File} to use as a feed
  630. *
  631. * @param SimplePie_File &$file
  632. * @return bool True on success, false on failure
  633. */
  634. public function set_file(&$file)
  635. {
  636. if ($file instanceof SimplePie_File)
  637. {
  638. $this->feed_url = $file->url;
  639. $this->file =& $file;
  640. return true;
  641. }
  642. return false;
  643. }
  644. /**
  645. * Set the raw XML data to parse
  646. *
  647. * Allows you to use a string of RSS/Atom data instead of a remote feed.
  648. *
  649. * If you have a feed available as a string in PHP, you can tell SimplePie
  650. * to parse that data string instead of a remote feed. Any set feed URL
  651. * takes precedence.
  652. *
  653. * @since 1.0 Beta 3
  654. * @param string $data RSS or Atom data as a string.
  655. * @see set_feed_url()
  656. */
  657. public function set_raw_data($data)
  658. {
  659. $this->raw_data = $data;
  660. }
  661. /**
  662. * Set the the default timeout for fetching remote feeds
  663. *
  664. * This allows you to change the maximum time the feed's server to respond
  665. * and send the feed back.
  666. *
  667. * @since 1.0 Beta 3
  668. * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
  669. */
  670. public function set_timeout($timeout = 10)
  671. {
  672. $this->timeout = (int) $timeout;
  673. }
  674. /**
  675. * Force SimplePie to use fsockopen() instead of cURL
  676. *
  677. * @since 1.0 Beta 3
  678. * @param bool $enable Force fsockopen() to be used
  679. */
  680. public function force_fsockopen($enable = false)
  681. {
  682. $this->force_fsockopen = (bool) $enable;
  683. }
  684. /**
  685. * Enable/disable caching in SimplePie.
  686. *
  687. * This option allows you to disable caching all-together in SimplePie.
  688. * However, disabling the cache can lead to longer load times.
  689. *
  690. * @since 1.0 Preview Release
  691. * @param bool $enable Enable caching
  692. */
  693. public function enable_cache($enable = true)
  694. {
  695. $this->cache = (bool) $enable;
  696. }
  697. /**
  698. * Set the length of time (in seconds) that the contents of a feed will be
  699. * cached
  700. *
  701. * @param int $seconds The feed content cache duration
  702. */
  703. public function set_cache_duration($seconds = 3600)
  704. {
  705. $this->cache_duration = (int) $seconds;
  706. }
  707. /**
  708. * Set the length of time (in seconds) that the autodiscovered feed URL will
  709. * be cached
  710. *
  711. * @param int $seconds The autodiscovered feed URL cache duration.
  712. */
  713. public function set_autodiscovery_cache_duration($seconds = 604800)
  714. {
  715. $this->autodiscovery_cache_duration = (int) $seconds;
  716. }
  717. /**
  718. * Set the file system location where the cached files should be stored
  719. *
  720. * @param string $location The file system location.
  721. */
  722. public function set_cache_location($location = './cache')
  723. {
  724. $this->cache_location = (string) $location;
  725. }
  726. /**
  727. * Set whether feed items should be sorted into reverse chronological order
  728. *
  729. * @param bool $enable Sort as reverse chronological order.
  730. */
  731. public function enable_order_by_date($enable = true)
  732. {
  733. $this->order_by_date = (bool) $enable;
  734. }
  735. /**
  736. * Set the character encoding used to parse the feed
  737. *
  738. * This overrides the encoding reported by the feed, however it will fall
  739. * back to the normal encoding detection if the override fails
  740. *
  741. * @param string $encoding Character encoding
  742. */
  743. public function set_input_encoding($encoding = false)
  744. {
  745. if ($encoding)
  746. {
  747. $this->input_encoding = (string) $encoding;
  748. }
  749. else
  750. {
  751. $this->input_encoding = false;
  752. }
  753. }
  754. /**
  755. * Set how much feed autodiscovery to do
  756. *
  757. * @see SIMPLEPIE_LOCATOR_NONE
  758. * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
  759. * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
  760. * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
  761. * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
  762. * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
  763. * @see SIMPLEPIE_LOCATOR_ALL
  764. * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)
  765. */
  766. public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
  767. {
  768. $this->autodiscovery = (int) $level;
  769. }
  770. /**
  771. * Get the class registry
  772. *
  773. * Use this to override SimplePie's default classes
  774. * @see SimplePie_Registry
  775. * @return SimplePie_Registry
  776. */
  777. public function &get_registry()
  778. {
  779. return $this->registry;
  780. }
  781. /**#@+
  782. * Useful when you are overloading or extending SimplePie's default classes.
  783. *
  784. * @deprecated Use {@see get_registry()} instead
  785. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  786. * @param string $class Name of custom class
  787. * @return boolean True on success, false otherwise
  788. */
  789. /**
  790. * Set which class SimplePie uses for caching
  791. */
  792. public function set_cache_class($class = 'SimplePie_Cache')
  793. {
  794. return $this->registry->register('Cache', $class, true);
  795. }
  796. /**
  797. * Set which class SimplePie uses for auto-discovery
  798. */
  799. public function set_locator_class($class = 'SimplePie_Locator')
  800. {
  801. return $this->registry->register('Locator', $class, true);
  802. }
  803. /**
  804. * Set which class SimplePie uses for XML parsing
  805. */
  806. public function set_parser_class($class = 'SimplePie_Parser')
  807. {
  808. return $this->registry->register('Parser', $class, true);
  809. }
  810. /**
  811. * Set which class SimplePie uses for remote file fetching
  812. */
  813. public function set_file_class($class = 'SimplePie_File')
  814. {
  815. return $this->registry->register('File', $class, true);
  816. }
  817. /**
  818. * Set which class SimplePie uses for data sanitization
  819. */
  820. public function set_sanitize_class($class = 'SimplePie_Sanitize')
  821. {
  822. return $this->registry->register('Sanitize', $class, true);
  823. }
  824. /**
  825. * Set which class SimplePie uses for handling feed items
  826. */
  827. public function set_item_class($class = 'SimplePie_Item')
  828. {
  829. return $this->registry->register('Item', $class, true);
  830. }
  831. /**
  832. * Set which class SimplePie uses for handling author data
  833. */
  834. public function set_author_class($class = 'SimplePie_Author')
  835. {
  836. return $this->registry->register('Author', $class, true);
  837. }
  838. /**
  839. * Set which class SimplePie uses for handling category data
  840. */
  841. public function set_category_class($class = 'SimplePie_Category')
  842. {
  843. return $this->registry->register('Category', $class, true);
  844. }
  845. /**
  846. * Set which class SimplePie uses for feed enclosures
  847. */
  848. public function set_enclosure_class($class = 'SimplePie_Enclosure')
  849. {
  850. return $this->registry->register('Enclosure', $class, true);
  851. }
  852. /**
  853. * Set which class SimplePie uses for `<media:text>` captions
  854. */
  855. public function set_caption_class($class = 'SimplePie_Caption')
  856. {
  857. return $this->registry->register('Caption', $class, true);
  858. }
  859. /**
  860. * Set which class SimplePie uses for `<media:copyright>`
  861. */
  862. public function set_copyright_class($class = 'SimplePie_Copyright')
  863. {
  864. return $this->registry->register('Copyright', $class, true);
  865. }
  866. /**
  867. * Set which class SimplePie uses for `<media:credit>`
  868. */
  869. public function set_credit_class($class = 'SimplePie_Credit')
  870. {
  871. return $this->registry->register('Credit', $class, true);
  872. }
  873. /**
  874. * Set which class SimplePie uses for `<media:rating>`
  875. */
  876. public function set_rating_class($class = 'SimplePie_Rating')
  877. {
  878. return $this->registry->register('Rating', $class, true);
  879. }
  880. /**
  881. * Set which class SimplePie uses for `<media:restriction>`
  882. */
  883. public function set_restriction_class($class = 'SimplePie_Restriction')
  884. {
  885. return $this->registry->register('Restriction', $class, true);
  886. }
  887. /**
  888. * Set which class SimplePie uses for content-type sniffing
  889. */
  890. public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
  891. {
  892. return $this->registry->register('Content_Type_Sniffer', $class, true);
  893. }
  894. /**
  895. * Set which class SimplePie uses item sources
  896. */
  897. public function set_source_class($class = 'SimplePie_Source')
  898. {
  899. return $this->registry->register('Source', $class, true);
  900. }
  901. /**#@-*/
  902. /**
  903. * Set the user agent string
  904. *
  905. * @param string $ua New user agent string.
  906. */
  907. public function set_useragent($ua = SIMPLEPIE_USERAGENT)
  908. {
  909. $this->useragent = (string) $ua;
  910. }
  911. /**
  912. * Set callback function to create cache filename with
  913. *
  914. * @param mixed $function Callback function
  915. */
  916. public function set_cache_name_function($function = 'md5')
  917. {
  918. if (is_callable($function))
  919. {
  920. $this->cache_name_function = $function;
  921. }
  922. }
  923. /**
  924. * Set options to make SP as fast as possible
  925. *
  926. * Forgoes a substantial amount of data sanitization in favor of speed. This
  927. * turns SimplePie into a dumb parser of feeds.
  928. *
  929. * @param bool $set Whether to set them or not
  930. */
  931. public function set_stupidly_fast($set = false)
  932. {
  933. if ($set)
  934. {
  935. $this->enable_order_by_date(false);
  936. $this->remove_div(false);
  937. $this->strip_comments(false);
  938. $this->strip_htmltags(false);
  939. $this->strip_attributes(false);
  940. $this->set_image_handler(false);
  941. }
  942. }
  943. /**
  944. * Set maximum number of feeds to check with autodiscovery
  945. *
  946. * @param int $max Maximum number of feeds to check
  947. */
  948. public function set_max_checked_feeds($max = 10)
  949. {
  950. $this->max_checked_feeds = (int) $max;
  951. }
  952. public function remove_div($enable = true)
  953. {
  954. $this->sanitize->remove_div($enable);
  955. }
  956. public function strip_htmltags($tags = '', $encode = null)
  957. {
  958. if ($tags === '')
  959. {
  960. $tags = $this->strip_htmltags;
  961. }
  962. $this->sanitize->strip_htmltags($tags);
  963. if ($encode !== null)
  964. {
  965. $this->sanitize->encode_instead_of_strip($tags);
  966. }
  967. }
  968. public function encode_instead_of_strip($enable = true)
  969. {
  970. $this->sanitize->encode_instead_of_strip($enable);
  971. }
  972. public function strip_attributes($attribs = '')
  973. {
  974. if ($attribs === '')
  975. {
  976. $attribs = $this->strip_attributes;
  977. }
  978. $this->sanitize->strip_attributes($attribs);
  979. }
  980. /**
  981. * Set the output encoding
  982. *
  983. * Allows you to override SimplePie's output to match that of your webpage.
  984. * This is useful for times when your webpages are not being served as
  985. * UTF-8. This setting will be obeyed by {@see handle_content_type()}, and
  986. * is similar to {@see set_input_encoding()}.
  987. *
  988. * It should be noted, however, that not all character encodings can support
  989. * all characters. If your page is being served as ISO-8859-1 and you try
  990. * to display a Japanese feed, you'll likely see garbled characters.
  991. * Because of this, it is highly recommended to ensure that your webpages
  992. * are served as UTF-8.
  993. *
  994. * The number of supported character encodings depends on whether your web
  995. * host supports {@link http://php.net/mbstring mbstring},
  996. * {@link http://php.net/iconv iconv}, or both. See
  997. * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for
  998. * more information.
  999. *
  1000. * @param string $encoding
  1001. */
  1002. public function set_output_encoding($encoding = 'UTF-8')
  1003. {
  1004. $this->sanitize->set_output_encoding($encoding);
  1005. }
  1006. public function strip_comments($strip = false)
  1007. {
  1008. $this->sanitize->strip_comments($strip);
  1009. }
  1010. /**
  1011. * Set element/attribute key/value pairs of HTML attributes
  1012. * containing URLs that need to be resolved relative to the feed
  1013. *
  1014. * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
  1015. * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
  1016. * |q|@cite
  1017. *
  1018. * @since 1.0
  1019. * @param array|null $element_attribute Element/attribute key/value pairs, null for default
  1020. */
  1021. public function set_url_replacements($element_attribute = null)
  1022. {
  1023. $this->sanitize->set_url_replacements($element_attribute);
  1024. }
  1025. /**
  1026. * Set the handler to enable the display of cached images.
  1027. *
  1028. * @param str $page Web-accessible path to the handler_image.php file.
  1029. * @param str $qs The query string that the value should be passed to.
  1030. */
  1031. public function set_image_handler($page = false, $qs = 'i')
  1032. {
  1033. if ($page !== false)
  1034. {
  1035. $this->sanitize->set_image_handler($page . '?' . $qs . '=');
  1036. }
  1037. else
  1038. {
  1039. $this->image_handler = '';
  1040. }
  1041. }
  1042. /**
  1043. * Set the limit for items returned per-feed with multifeeds
  1044. *
  1045. * @param integer $limit The maximum number of items to return.
  1046. */
  1047. public function set_item_limit($limit = 0)
  1048. {
  1049. $this->item_limit = (int) $limit;
  1050. }
  1051. /**
  1052. * Initialize the feed object
  1053. *
  1054. * This is what makes everything happen. Period. This is where all of the
  1055. * configuration options get processed, feeds are fetched, cached, and
  1056. * parsed, and all of that other good stuff.
  1057. *
  1058. * @return boolean True if successful, false otherwise
  1059. */
  1060. public function init()
  1061. {
  1062. // Check absolute bare minimum requirements.
  1063. if (!extension_loaded('xml') || !extension_loaded('pcre'))
  1064. {
  1065. return false;
  1066. }
  1067. // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
  1068. elseif (!extension_loaded('xmlreader'))
  1069. {
  1070. static $xml_is_sane = null;
  1071. if ($xml_is_sane === null)
  1072. {
  1073. $parser_check = xml_parser_create();
  1074. xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
  1075. xml_parser_free($parser_check);
  1076. $xml_is_sane = isset($values[0]['value']);
  1077. }
  1078. if (!$xml_is_sane)
  1079. {
  1080. return false;
  1081. }
  1082. }
  1083. if (method_exists($this->sanitize, 'set_registry'))
  1084. {
  1085. $this->sanitize->set_registry($this->registry);
  1086. }
  1087. // Pass whatever was set with config options over to the sanitizer.
  1088. // Pass the classes in for legacy support; new classes should use the registry instead
  1089. $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));
  1090. $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen);
  1091. if (!empty($this->multifeed_url))
  1092. {
  1093. $i = 0;
  1094. $success = 0;
  1095. $this->multifeed_objects = array();
  1096. $this->error = array();
  1097. foreach ($this->multifeed_url as $url)
  1098. {
  1099. $this->multifeed_objects[$i] = clone $this;
  1100. $this->multifeed_objects[$i]->set_feed_url($url);
  1101. $single_success = $this->multifeed_objects[$i]->init();
  1102. $success |= $single_success;
  1103. if (!$single_success)
  1104. {
  1105. $this->error[$i] = $this->multifeed_objects[$i]->error();
  1106. }
  1107. $i++;
  1108. }
  1109. return (bool) $success;
  1110. }
  1111. elseif ($this->feed_url === null && $this->raw_data === null)
  1112. {
  1113. return false;
  1114. }
  1115. $this->error = null;
  1116. $this->data = array();
  1117. $this->multifeed_objects = array();
  1118. $cache = false;
  1119. if ($this->feed_url !== null)
  1120. {
  1121. $parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));
  1122. // Decide whether to enable caching
  1123. if ($this->cache && $parsed_feed_url['scheme'] !== '')
  1124. {
  1125. $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'));
  1126. }
  1127. // Fetch the data via SimplePie_File into $this->raw_data
  1128. if (($fetched = $this->fetch_data($cache)) === true)
  1129. {
  1130. return true;
  1131. }
  1132. elseif ($fetched === false) {
  1133. return false;
  1134. }
  1135. list($headers, $sniffed) = $fetched;
  1136. }
  1137. // Set up array of possible encodings
  1138. $encodings = array();
  1139. // First check to see if input has been overridden.
  1140. if ($this->input_encoding !== false)
  1141. {
  1142. $encodings[] = $this->input_encoding;
  1143. }
  1144. $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
  1145. $text_types = array('text/xml', 'text/xml-external-parsed-entity');
  1146. // RFC 3023 (only applies to sniffed content)
  1147. if (isset($sniffed))
  1148. {
  1149. if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
  1150. {
  1151. if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
  1152. {
  1153. $encodings[] = strtoupper($charset[1]);
  1154. }
  1155. $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
  1156. $encodings[] = 'UTF-8';
  1157. }
  1158. elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
  1159. {
  1160. if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
  1161. {
  1162. $encodings[] = $charset[1];
  1163. }
  1164. $encodings[] = 'US-ASCII';
  1165. }
  1166. // Text MIME-type default
  1167. elseif (substr($sniffed, 0, 5) === 'text/')
  1168. {
  1169. $encodings[] = 'US-ASCII';
  1170. }
  1171. }
  1172. // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
  1173. $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
  1174. $encodings[] = 'UTF-8';
  1175. $encodings[] = 'ISO-8859-1';
  1176. // There's no point in trying an encoding twice
  1177. $encodings = array_unique($encodings);
  1178. // Loop through each possible encoding, till we return something, or run out of possibilities
  1179. foreach ($encodings as $encoding)
  1180. {
  1181. // Change the encoding to UTF-8 (as we always use UTF-8 internally)
  1182. if ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($this->raw_data, $encoding, 'UTF-8')))
  1183. {
  1184. // Create new parser
  1185. $parser = $this->registry->create('Parser');
  1186. // If it's parsed fine
  1187. if ($parser->parse($utf8_data, 'UTF-8'))
  1188. {
  1189. $this->data = $parser->get_data();
  1190. if (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE))
  1191. {
  1192. $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
  1193. $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
  1194. return false;
  1195. }
  1196. if (isset($headers))
  1197. {
  1198. $this->data['headers'] = $headers;
  1199. }
  1200. $this->data['build'] = SIMPLEPIE_BUILD;
  1201. // Cache the file if caching is enabled
  1202. if ($cache && !$cache->save($this))
  1203. {
  1204. trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
  1205. }
  1206. return true;
  1207. }
  1208. }
  1209. }
  1210. if (isset($parser))
  1211. {
  1212. // We have an error, just set SimplePie_Misc::error to it and quit
  1213. $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
  1214. }
  1215. else
  1216. {
  1217. $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
  1218. }
  1219. $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
  1220. return false;
  1221. }
  1222. /**
  1223. * Fetch the data via SimplePie_File
  1224. *
  1225. * If the data is already cached, attempt to fetch it from there instead
  1226. * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache
  1227. * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
  1228. */
  1229. protected function fetch_data(&$cache)
  1230. {
  1231. // If it's enabled, use the cache
  1232. if ($cache)
  1233. {
  1234. // Load the Cache
  1235. $this->data = $cache->load();
  1236. if (!empty($this->data))
  1237. {
  1238. // If the cache is for an outdated build of SimplePie
  1239. if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
  1240. {
  1241. $cache->unlink();
  1242. $this->data = array();
  1243. }
  1244. // If we've hit a collision just rerun it with caching disabled
  1245. elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
  1246. {
  1247. $cache = false;
  1248. $this->data = array();
  1249. }
  1250. // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
  1251. elseif (isset($this->data['feed_url']))
  1252. {
  1253. // If the autodiscovery cache is still valid use it.
  1254. if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
  1255. {
  1256. // Do not need to do feed autodiscovery yet.
  1257. if ($this->data['feed_url'] !== $this->data['url'])
  1258. {
  1259. $this->set_feed_url($this->data['feed_url']);
  1260. return $this->init();
  1261. }
  1262. $cache->unlink();
  1263. $this->data = array();
  1264. }
  1265. }
  1266. // Check if the cache has been updated
  1267. elseif ($cache->mtime() + $this->cache_duration < time())
  1268. {
  1269. // If we have last-modified and/or etag set
  1270. if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
  1271. {
  1272. $headers = array(
  1273. 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
  1274. );
  1275. if (isset($this->data['headers']['last-modified']))
  1276. {
  1277. $headers['if-modified-since'] = $this->data['headers']['last-modified'];
  1278. }
  1279. if (isset($this->data['headers']['etag']))
  1280. {
  1281. $headers['if-none-match'] = $this->data['headers']['etag'];
  1282. }
  1283. $file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen));
  1284. if ($file->success)
  1285. {
  1286. if ($file->status_code === 304)
  1287. {
  1288. $cache->touch();
  1289. return true;
  1290. }
  1291. }
  1292. else
  1293. {
  1294. unset($file);
  1295. }
  1296. }
  1297. }
  1298. // If the cache is still valid, just return true
  1299. else
  1300. {
  1301. $this->raw_data = false;
  1302. return true;
  1303. }
  1304. }
  1305. // If the cache is empty, delete it
  1306. else
  1307. {
  1308. $cache->unlink();
  1309. $this->data = array();
  1310. }
  1311. }
  1312. // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
  1313. if (!isset($file))
  1314. {
  1315. if ($this->file instanceof SimplePie_File && $this->file->url === $this->feed_url)
  1316. {
  1317. $file =& $this->file;
  1318. }
  1319. else
  1320. {
  1321. $headers = array(
  1322. 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
  1323. );
  1324. $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen));
  1325. }
  1326. }
  1327. // If the file connection has an error, set SimplePie::error to that and quit
  1328. if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
  1329. {
  1330. $this->error = $file->error;
  1331. return !empty($this->data);
  1332. }
  1333. if (!$this->force_feed)
  1334. {
  1335. // Check if the supplied URL is a feed, if it isn't, look for it.
  1336. $locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds));
  1337. if (!$locate->is_feed($file))
  1338. {
  1339. // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
  1340. unset($file);
  1341. try
  1342. {
  1343. if (!($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds)))
  1344. {
  1345. $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
  1346. $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
  1347. return false;
  1348. }
  1349. }
  1350. catch (SimplePie_Exception $e)
  1351. {
  1352. // This is usually because DOMDocument doesn't exist
  1353. $this->error = $e->getMessage();
  1354. $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()));
  1355. return false;
  1356. }
  1357. if ($cache)
  1358. {
  1359. $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
  1360. if (!$cache->save($this))
  1361. {
  1362. trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
  1363. }
  1364. $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));
  1365. }
  1366. $this->feed_url = $file->url;
  1367. }
  1368. $locate = null;
  1369. }
  1370. $this->raw_data = $file->body;
  1371. $headers = $file->headers;
  1372. $sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));
  1373. $sniffed = $sniffer->get_type();
  1374. return array($headers, $sniffed);
  1375. }
  1376. /**
  1377. * Get the error message for the occured error
  1378. *
  1379. * @return string|array Error message, or array of messages for multifeeds
  1380. */
  1381. public function error()
  1382. {
  1383. return $this->error;
  1384. }
  1385. /**
  1386. * Get the raw XML
  1387. *
  1388. * This is the same as the old `$feed->enable_xml_dump(true)`, but returns
  1389. * the data instead of printing it.
  1390. *
  1391. * @return string|boolean Raw XML data, false if the cache is used
  1392. */
  1393. public function get_raw_data()
  1394. {
  1395. return $this->raw_data;
  1396. }
  1397. /**
  1398. * Get the character encoding used for output
  1399. *
  1400. * @since Preview Release
  1401. * @return string
  1402. */
  1403. public function get_encoding()
  1404. {
  1405. return $this->sanitize->output_encoding;
  1406. }
  1407. /**
  1408. * Send the content-type header with correct encoding
  1409. *
  1410. * This method ensures that the SimplePie-enabled page is being served with
  1411. * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}
  1412. * and character encoding HTTP headers (character encoding determined by the
  1413. * {@see set_output_encoding} config option).
  1414. *
  1415. * This won't work properly if any content or whitespace has already been
  1416. * sent to the browser, because it relies on PHP's
  1417. * {@link http://php.net/header header()} function, and these are the
  1418. * circumstances under which the function works.
  1419. *
  1420. * Because it's setting these settings for the entire page (as is the nature
  1421. * of HTTP headers), this should only be used once per page (again, at the
  1422. * top).
  1423. *
  1424. * @param string $mime MIME type to serve the page as
  1425. */
  1426. public function handle_content_type($mime = 'text/html')
  1427. {
  1428. if (!headers_sent())
  1429. {
  1430. $header = "Content-type: $mime;";
  1431. if ($this->get_encoding())
  1432. {
  1433. $header .= ' charset=' . $this->get_encoding();
  1434. }
  1435. else
  1436. {
  1437. $header .= ' charset=UTF-8';
  1438. }
  1439. header($header);
  1440. }
  1441. }
  1442. /**
  1443. * Get the type of the feed
  1444. *
  1445. * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against
  1446. * using {@link http://php.net/language.operators.bitwise bitwise operators}
  1447. *
  1448. * @since 0.8 (usage changed to using constants in 1.0)
  1449. * @see SIMPLEPIE_TYPE_NONE Unknown.
  1450. * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90.
  1451. * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).
  1452. * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland).
  1453. * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91.
  1454. * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92.
  1455. * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93.
  1456. * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94.
  1457. * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0.
  1458. * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x.
  1459. * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS.
  1460. * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).
  1461. * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS.
  1462. * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3.
  1463. * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0.
  1464. * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom.
  1465. * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type.
  1466. * @return int SIMPLEPIE_TYPE_* constant
  1467. */
  1468. public function get_type()
  1469. {
  1470. if (!isset($this->data['type']))
  1471. {
  1472. $this->data['type'] = SIMPLEPIE_TYPE_ALL;
  1473. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
  1474. {
  1475. $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
  1476. }
  1477. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
  1478. {
  1479. $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
  1480. }
  1481. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
  1482. {
  1483. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
  1484. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
  1485. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
  1486. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
  1487. {
  1488. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
  1489. }
  1490. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
  1491. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
  1492. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
  1493. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
  1494. {
  1495. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
  1496. }
  1497. }
  1498. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
  1499. {
  1500. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
  1501. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
  1502. {
  1503. switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
  1504. {
  1505. case '0.91':
  1506. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
  1507. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
  1508. {
  1509. switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
  1510. {
  1511. case '0':
  1512. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
  1513. break;
  1514. case '24':
  1515. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
  1516. break;
  1517. }
  1518. }
  1519. break;
  1520. case '0.92':
  1521. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
  1522. break;
  1523. case '0.93':
  1524. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
  1525. break;
  1526. case '0.94':
  1527. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
  1528. break;
  1529. case '2.0':
  1530. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
  1531. break;
  1532. }
  1533. }
  1534. }
  1535. else
  1536. {
  1537. $this->data['type'] = SIMPLEPIE_TYPE_NONE;
  1538. }
  1539. }
  1540. return $this->data['type'];
  1541. }
  1542. /**
  1543. * Get the URL for the feed
  1544. *
  1545. * May or may not be different from the URL passed to {@see set_feed_url()},
  1546. * depending on whether auto-discovery was used.
  1547. *
  1548. * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)
  1549. * @todo If we have a perm redirect we should return the new URL
  1550. * @todo When we make the above change, let's support <itunes:new-feed-url> as well
  1551. * @todo Also, |atom:link|@rel=self
  1552. * @return string|null
  1553. */
  1554. public function subscribe_url()
  1555. {
  1556. if ($this->feed_url !== null)
  1557. {
  1558. return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
  1559. }
  1560. else
  1561. {
  1562. return null;
  1563. }
  1564. }
  1565. /**
  1566. * Get data for an feed-level element
  1567. *
  1568. * This method allows you to get access to ANY element/attribute that is a
  1569. * sub-element of the opening feed tag.
  1570. *
  1571. * The return value is an indexed array of elements matching the given
  1572. * namespace and tag name. Each element has `attribs`, `data` and `child`
  1573. * subkeys. For `attribs` and `child`, these contain namespace subkeys.
  1574. * `attribs` then has one level of associative name => value data (where
  1575. * `value` is a string) after the namespace. `child` has tag-indexed keys
  1576. * after the namespace, each member of which is an indexed array matching
  1577. * this same format.
  1578. *
  1579. * For example:
  1580. * <pre>
  1581. * // This is probably a bad example because we already support
  1582. * // <media:content> natively, but it shows you how to parse through
  1583. * // the nodes.
  1584. * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group');
  1585. * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'];
  1586. * $file = $content[0]['attribs']['']['url'];
  1587. * echo $file;
  1588. * </pre>
  1589. *
  1590. * @since 1.0
  1591. * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
  1592. * @param string $namespace The URL of the XML namespace of the elements you're trying to access
  1593. * @param string $tag Tag name
  1594. * @return array
  1595. */
  1596. public function get_feed_tags($namespace, $tag)
  1597. {
  1598. $type = $this->get_type();
  1599. if ($type & SIMPLEPIE_TYPE_ATOM_10)
  1600. {
  1601. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
  1602. {
  1603. return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
  1604. }
  1605. }
  1606. if ($type & SIMPLEPIE_TYPE_ATOM_03)
  1607. {
  1608. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
  1609. {
  1610. return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
  1611. }
  1612. }
  1613. if ($type & SIMPLEPIE_TYPE_RSS_RDF)
  1614. {
  1615. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
  1616. {
  1617. return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
  1618. }
  1619. }
  1620. if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  1621. {
  1622. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
  1623. {
  1624. return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
  1625. }
  1626. }
  1627. return null;
  1628. }
  1629. /**
  1630. * Get data for an channel-level element
  1631. *
  1632. * This method allows you to get access to ANY element/attribute in the
  1633. * channel/header section of the feed.
  1634. *
  1635. * See {@see SimplePie::get_feed_tags()} for a description of the return value
  1636. *
  1637. * @since 1.0
  1638. * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
  1639. * @param string $namespace The URL of the XML namespace of the elements you're trying to access
  1640. * @param string $tag Tag name
  1641. * @return array
  1642. */
  1643. public function get_channel_tags($namespace, $tag)
  1644. {
  1645. $type = $this->get_type();
  1646. if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
  1647. {
  1648. if ($return = $this->get_feed_tags($namespace, $tag))
  1649. {
  1650. return $return;
  1651. }
  1652. }
  1653. if ($type & SIMPLEPIE_TYPE_RSS_10)
  1654. {
  1655. if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
  1656. {
  1657. if (isset($channel[0]['child'][$namespace][$tag]))
  1658. {
  1659. return $channel[0]['child'][$namespace][$tag];
  1660. }
  1661. }
  1662. }
  1663. if ($type & SIMPLEPIE_TYPE_RSS_090)
  1664. {
  1665. if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
  1666. {
  1667. if (isset($channel[0]['child'][$namespace][$tag]))
  1668. {
  1669. return $channel[0]['child'][$namespace][$tag];
  1670. }
  1671. }
  1672. }
  1673. if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  1674. {
  1675. if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
  1676. {
  1677. if (isset($channel[0]['child'][$namespace][$tag]))
  1678. {
  1679. return $channel[0]['child'][$namespace][$tag];
  1680. }
  1681. }
  1682. }
  1683. return null;
  1684. }
  1685. /**
  1686. * Get data for an channel-level element
  1687. *
  1688. * This method allows you to get access to ANY element/attribute in the
  1689. * image/logo section of the feed.
  1690. *
  1691. * See {@see SimplePie::get_feed_tags()} for a description of the return value
  1692. *
  1693. * @since 1.0
  1694. * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
  1695. * @param string $namespace The URL of the XML namespace of the elements you're trying to access
  1696. * @param string $tag Tag name
  1697. * @return array
  1698. */
  1699. public function get_image_tags($namespace, $tag)
  1700. {
  1701. $type = $this->get_type();
  1702. if ($type & SIMPLEPIE_TYPE_RSS_10)
  1703. {
  1704. if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
  1705. {
  1706. if (isset($image[0]['child'][$namespace][$tag]))
  1707. {
  1708. return $image[0]['child'][$namespace][$tag];
  1709. }
  1710. }
  1711. }
  1712. if ($type & SIMPLEPIE_TYPE_RSS_090)
  1713. {
  1714. if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
  1715. {
  1716. if (isset($image[0]['child'][$namespace][$tag]))
  1717. {
  1718. return $image[0]['child'][$namespace][$tag];
  1719. }
  1720. }
  1721. }
  1722. if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  1723. {
  1724. if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
  1725. {
  1726. if (isset($image[0]['child'][$namespace][$tag]))
  1727. {
  1728. return $image[0]['child'][$namespace][$tag];
  1729. }
  1730. }
  1731. }
  1732. return null;
  1733. }
  1734. /**
  1735. * Get the base URL value from the feed
  1736. *
  1737. * Uses `<xml:base>` if available, otherwise uses the first link in the
  1738. * feed, or failing that, the URL of the feed itself.
  1739. *
  1740. * @see get_link
  1741. * @see subscribe_url
  1742. *
  1743. * @param array $element
  1744. * @return string
  1745. */
  1746. public function get_base($element = array())
  1747. {
  1748. if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
  1749. {
  1750. return $element['xml_base'];
  1751. }
  1752. elseif ($this->get_link() !== null)
  1753. {
  1754. return $this->get_link();
  1755. }
  1756. else
  1757. {
  1758. return $this->subscribe_url();
  1759. }
  1760. }
  1761. /**
  1762. * Sanitize feed data
  1763. *
  1764. * @access private
  1765. * @see SimplePie_Sanitize::sanitize()
  1766. * @param string $data Data to sanitize
  1767. * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
  1768. * @param string $base Base URL to resolve URLs against
  1769. * @return string Sanitized data
  1770. */
  1771. public function sanitize($data, $type, $base = '')
  1772. {
  1773. return $this->sanitize->sanitize($data, $type, $base);
  1774. }
  1775. /**
  1776. * Get the title of the feed
  1777. *
  1778. * Uses `<atom:title>`, `<title>` or `<dc:title>`
  1779. *
  1780. * @since 1.0 (previously called `get_feed_title` since 0.8)
  1781. * @return string|null
  1782. */
  1783. public function get_title()
  1784. {
  1785. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  1786. {
  1787. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  1788. }
  1789. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  1790. {
  1791. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  1792. }
  1793. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  1794. {
  1795. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  1796. }
  1797. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  1798. {
  1799. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  1800. }
  1801. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  1802. {
  1803. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  1804. }
  1805. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  1806. {
  1807. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1808. }
  1809. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  1810. {
  1811. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1812. }
  1813. else
  1814. {
  1815. return null;
  1816. }
  1817. }
  1818. /**
  1819. * Get a category for the feed
  1820. *
  1821. * @since Unknown
  1822. * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1
  1823. * @return SimplePie_Category|null
  1824. */
  1825. public function get_category($key = 0)
  1826. {
  1827. $categories = $this->get_categories();
  1828. if (isset($categories[$key]))
  1829. {
  1830. return $categories[$key];
  1831. }
  1832. else
  1833. {
  1834. return null;
  1835. }
  1836. }
  1837. /**
  1838. * Get all categories for the feed
  1839. *
  1840. * Uses `<atom:category>`, `<category>` or `<dc:subject>`
  1841. *
  1842. * @since Unknown
  1843. * @return array|null List of {@see SimplePie_Category} objects
  1844. */
  1845. public function get_categories()
  1846. {
  1847. $categories = array();
  1848. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  1849. {
  1850. $term = null;
  1851. $scheme = null;
  1852. $label = null;
  1853. if (isset($category['attribs']['']['term']))
  1854. {
  1855. $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  1856. }
  1857. if (isset($category['attribs']['']['scheme']))
  1858. {
  1859. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  1860. }
  1861. if (isset($category['attribs']['']['label']))
  1862. {
  1863. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  1864. }
  1865. $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
  1866. }
  1867. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  1868. {
  1869. // This is really the label, but keep this as the term also for BC.
  1870. // Label will also work on retrieving because that falls back to term.
  1871. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1872. if (isset($category['attribs']['']['domain']))
  1873. {
  1874. $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  1875. }
  1876. else
  1877. {
  1878. $scheme = null;
  1879. }
  1880. $categories[] = $this->registry->create('Category', array($term, $scheme, null));
  1881. }
  1882. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  1883. {
  1884. $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  1885. }
  1886. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  1887. {
  1888. $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  1889. }
  1890. if (!empty($categories))
  1891. {
  1892. return array_unique($categories);
  1893. }
  1894. else
  1895. {
  1896. return null;
  1897. }
  1898. }
  1899. /**
  1900. * Get an author for the feed
  1901. *
  1902. * @since 1.1
  1903. * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1
  1904. * @return SimplePie_Author|null
  1905. */
  1906. public function get_author($key = 0)
  1907. {
  1908. $authors = $this->get_authors();
  1909. if (isset($authors[$key]))
  1910. {
  1911. return $authors[$key];
  1912. }
  1913. else
  1914. {
  1915. return null;
  1916. }
  1917. }
  1918. /**
  1919. * Get all authors for the feed
  1920. *
  1921. * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
  1922. *
  1923. * @since 1.1
  1924. * @return array|null List of {@see SimplePie_Author} objects
  1925. */
  1926. public function get_authors()
  1927. {
  1928. $authors = array();
  1929. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  1930. {
  1931. $name = null;
  1932. $uri = null;
  1933. $email = null;
  1934. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  1935. {
  1936. $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1937. }
  1938. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  1939. {
  1940. $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  1941. }
  1942. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  1943. {
  1944. $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1945. }
  1946. if ($name !== null || $email !== null || $uri !== null)
  1947. {
  1948. $authors[] = $this->registry->create('Author', array($name, $uri, $email));
  1949. }
  1950. }
  1951. if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  1952. {
  1953. $name = null;
  1954. $url = null;
  1955. $email = null;
  1956. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  1957. {
  1958. $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1959. }
  1960. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  1961. {
  1962. $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  1963. }
  1964. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  1965. {
  1966. $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1967. }
  1968. if ($name !== null || $email !== null || $url !== null)
  1969. {
  1970. $authors[] = $this->registry->create('Author', array($name, $url, $email));
  1971. }
  1972. }
  1973. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  1974. {
  1975. $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  1976. }
  1977. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  1978. {
  1979. $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  1980. }
  1981. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  1982. {
  1983. $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  1984. }
  1985. if (!empty($authors))
  1986. {
  1987. return array_unique($authors);
  1988. }
  1989. else
  1990. {
  1991. return null;
  1992. }
  1993. }
  1994. /**
  1995. * Get a contributor for the feed
  1996. *
  1997. * @since 1.1
  1998. * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1
  1999. * @return SimplePie_Author|null
  2000. */
  2001. public function get_contributor($key = 0)
  2002. {
  2003. $contributors = $this->get_contributors();
  2004. if (isset($contributors[$key]))
  2005. {
  2006. return $contributors[$key];
  2007. }
  2008. else
  2009. {
  2010. return null;
  2011. }
  2012. }
  2013. /**
  2014. * Get all contributors for the feed
  2015. *
  2016. * Uses `<atom:contributor>`
  2017. *
  2018. * @since 1.1
  2019. * @return array|null List of {@see SimplePie_Author} objects
  2020. */
  2021. public function get_contributors()
  2022. {
  2023. $contributors = array();
  2024. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  2025. {
  2026. $name = null;
  2027. $uri = null;
  2028. $email = null;
  2029. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  2030. {
  2031. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2032. }
  2033. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  2034. {
  2035. $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  2036. }
  2037. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  2038. {
  2039. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2040. }
  2041. if ($name !== null || $email !== null || $uri !== null)
  2042. {
  2043. $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
  2044. }
  2045. }
  2046. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  2047. {
  2048. $name = null;
  2049. $url = null;
  2050. $email = null;
  2051. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  2052. {
  2053. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2054. }
  2055. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  2056. {
  2057. $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  2058. }
  2059. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  2060. {
  2061. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2062. }
  2063. if ($name !== null || $email !== null || $url !== null)
  2064. {
  2065. $contributors[] = $this->registry->create('Author', array($name, $url, $email));
  2066. }
  2067. }
  2068. if (!empty($contributors))
  2069. {
  2070. return array_unique($contributors);
  2071. }
  2072. else
  2073. {
  2074. return null;
  2075. }
  2076. }
  2077. /**
  2078. * Get a single link for the feed
  2079. *
  2080. * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
  2081. * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1
  2082. * @param string $rel The relationship of the link to return
  2083. * @return string|null Link URL
  2084. */
  2085. public function get_link($key = 0, $rel = 'alternate')
  2086. {
  2087. $links = $this->get_links($rel);
  2088. if (isset($links[$key]))
  2089. {
  2090. return $links[$key];
  2091. }
  2092. else
  2093. {
  2094. return null;
  2095. }
  2096. }
  2097. /**
  2098. * Get the permalink for the item
  2099. *
  2100. * Returns the first link available with a relationship of "alternate".
  2101. * Identical to {@see get_link()} with key 0
  2102. *
  2103. * @see get_link
  2104. * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
  2105. * @internal Added for parity between the parent-level and the item/entry-level.
  2106. * @return string|null Link URL
  2107. */
  2108. public function get_permalink()
  2109. {
  2110. return $this->get_link(0);
  2111. }
  2112. /**
  2113. * Get all links for the feed
  2114. *
  2115. * Uses `<atom:link>` or `<link>`
  2116. *
  2117. * @since Beta 2
  2118. * @param string $rel The relationship of links to return
  2119. * @return array|null Links found for the feed (strings)
  2120. */
  2121. public function get_links($rel = 'alternate')
  2122. {
  2123. if (!isset($this->data['links']))
  2124. {
  2125. $this->data['links'] = array();
  2126. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
  2127. {
  2128. foreach ($links as $link)
  2129. {
  2130. if (isset($link['attribs']['']['href']))
  2131. {
  2132. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  2133. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  2134. }
  2135. }
  2136. }
  2137. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
  2138. {
  2139. foreach ($links as $link)
  2140. {
  2141. if (isset($link['attribs']['']['href']))
  2142. {
  2143. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  2144. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  2145. }
  2146. }
  2147. }
  2148. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  2149. {
  2150. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  2151. }
  2152. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  2153. {
  2154. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  2155. }
  2156. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  2157. {
  2158. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  2159. }
  2160. $keys = array_keys($this->data['links']);
  2161. foreach ($keys as $key)
  2162. {
  2163. if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
  2164. {
  2165. if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  2166. {
  2167. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  2168. $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  2169. }
  2170. else
  2171. {
  2172. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  2173. }
  2174. }
  2175. elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  2176. {
  2177. $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  2178. }
  2179. $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  2180. }
  2181. }
  2182. if (isset($this->data['links'][$rel]))
  2183. {
  2184. return $this->data['links'][$rel];
  2185. }
  2186. else
  2187. {
  2188. return null;
  2189. }
  2190. }
  2191. public function get_all_discovered_feeds()
  2192. {
  2193. return $this->all_discovered_feeds;
  2194. }
  2195. /**
  2196. * Get the content for the item
  2197. *
  2198. * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,
  2199. * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`
  2200. *
  2201. * @since 1.0 (previously called `get_feed_description()` since 0.8)
  2202. * @return string|null
  2203. */
  2204. public function get_description()
  2205. {
  2206. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
  2207. {
  2208. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  2209. }
  2210. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
  2211. {
  2212. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  2213. }
  2214. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  2215. {
  2216. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2217. }
  2218. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
  2219. {
  2220. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2221. }
  2222. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  2223. {
  2224. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2225. }
  2226. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  2227. {
  2228. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2229. }
  2230. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  2231. {
  2232. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2233. }
  2234. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  2235. {
  2236. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2237. }
  2238. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  2239. {
  2240. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2241. }
  2242. else
  2243. {
  2244. return null;
  2245. }
  2246. }
  2247. /**
  2248. * Get the copyright info for the feed
  2249. *
  2250. * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`
  2251. *
  2252. * @since 1.0 (previously called `get_feed_copyright()` since 0.8)
  2253. * @return string|null
  2254. */
  2255. public function get_copyright()
  2256. {
  2257. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  2258. {
  2259. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  2260. }
  2261. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
  2262. {
  2263. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  2264. }
  2265. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
  2266. {
  2267. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2268. }
  2269. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  2270. {
  2271. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2272. }
  2273. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  2274. {
  2275. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2276. }
  2277. else
  2278. {
  2279. return null;
  2280. }
  2281. }
  2282. /**
  2283. * Get the language for the feed
  2284. *
  2285. * Uses `<language>`, `<dc:language>`, or @xml_lang
  2286. *
  2287. * @since 1.0 (previously called `get_feed_language()` since 0.8)
  2288. * @return string|null
  2289. */
  2290. public function get_language()
  2291. {
  2292. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
  2293. {
  2294. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2295. }
  2296. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
  2297. {
  2298. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2299. }
  2300. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
  2301. {
  2302. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2303. }
  2304. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
  2305. {
  2306. return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  2307. }
  2308. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
  2309. {
  2310. return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  2311. }
  2312. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
  2313. {
  2314. return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  2315. }
  2316. elseif (isset($this->data['headers']['content-language']))
  2317. {
  2318. return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
  2319. }
  2320. else
  2321. {
  2322. return null;
  2323. }
  2324. }
  2325. /**
  2326. * Get the latitude coordinates for the item
  2327. *
  2328. * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
  2329. *
  2330. * Uses `<geo:lat>` or `<georss:point>`
  2331. *
  2332. * @since 1.0
  2333. * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
  2334. * @link http://www.georss.org/ GeoRSS
  2335. * @return string|null
  2336. */
  2337. public function get_latitude()
  2338. {
  2339. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  2340. {
  2341. return (float) $return[0]['data'];
  2342. }
  2343. elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  2344. {
  2345. return (float) $match[1];
  2346. }
  2347. else
  2348. {
  2349. return null;
  2350. }
  2351. }
  2352. /**
  2353. * Get the longitude coordinates for the feed
  2354. *
  2355. * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
  2356. *
  2357. * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
  2358. *
  2359. * @since 1.0
  2360. * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
  2361. * @link http://www.georss.org/ GeoRSS
  2362. * @return string|null
  2363. */
  2364. public function get_longitude()
  2365. {
  2366. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  2367. {
  2368. return (float) $return[0]['data'];
  2369. }
  2370. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  2371. {
  2372. return (float) $return[0]['data'];
  2373. }
  2374. elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  2375. {
  2376. return (float) $match[2];
  2377. }
  2378. else
  2379. {
  2380. return null;
  2381. }
  2382. }
  2383. /**
  2384. * Get the feed logo's title
  2385. *
  2386. * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title.
  2387. *
  2388. * Uses `<image><title>` or `<image><dc:title>`
  2389. *
  2390. * @return string|null
  2391. */
  2392. public function get_image_title()
  2393. {
  2394. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  2395. {
  2396. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2397. }
  2398. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  2399. {
  2400. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2401. }
  2402. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  2403. {
  2404. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2405. }
  2406. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  2407. {
  2408. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2409. }
  2410. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  2411. {
  2412. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2413. }
  2414. else
  2415. {
  2416. return null;
  2417. }
  2418. }
  2419. /**
  2420. * Get the feed logo's URL
  2421. *
  2422. * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to
  2423. * have a "feed logo" URL. This points directly to the image itself.
  2424. *
  2425. * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
  2426. * `<image><title>` or `<image><dc:title>`
  2427. *
  2428. * @return string|null
  2429. */
  2430. public function get_image_url()
  2431. {
  2432. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
  2433. {
  2434. return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
  2435. }
  2436. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
  2437. {
  2438. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2439. }
  2440. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
  2441. {
  2442. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2443. }
  2444. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
  2445. {
  2446. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2447. }
  2448. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
  2449. {
  2450. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2451. }
  2452. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  2453. {
  2454. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2455. }
  2456. else
  2457. {
  2458. return null;
  2459. }
  2460. }
  2461. /**
  2462. * Get the feed logo's link
  2463. *
  2464. * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This
  2465. * points to a human-readable page that the image should link to.
  2466. *
  2467. * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
  2468. * `<image><title>` or `<image><dc:title>`
  2469. *
  2470. * @return string|null
  2471. */
  2472. public function get_image_link()
  2473. {
  2474. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  2475. {
  2476. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2477. }
  2478. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  2479. {
  2480. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2481. }
  2482. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  2483. {
  2484. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2485. }
  2486. else
  2487. {
  2488. return null;
  2489. }
  2490. }
  2491. /**
  2492. * Get the feed logo's link
  2493. *
  2494. * RSS 2.0 feeds are allowed to have a "feed logo" width.
  2495. *
  2496. * Uses `<image><width>` or defaults to 88.0 if no width is specified and
  2497. * the feed is an RSS 2.0 feed.
  2498. *
  2499. * @return int|float|null
  2500. */
  2501. public function get_image_width()
  2502. {
  2503. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
  2504. {
  2505. return round($return[0]['data']);
  2506. }
  2507. elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  2508. {
  2509. return 88.0;
  2510. }
  2511. else
  2512. {
  2513. return null;
  2514. }
  2515. }
  2516. /**
  2517. * Get the feed logo's height
  2518. *
  2519. * RSS 2.0 feeds are allowed to have a "feed logo" height.
  2520. *
  2521. * Uses `<image><height>` or defaults to 31.0 if no height is specified and
  2522. * the feed is an RSS 2.0 feed.
  2523. *
  2524. * @return int|float|null
  2525. */
  2526. public function get_image_height()
  2527. {
  2528. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
  2529. {
  2530. return round($return[0]['data']);
  2531. }
  2532. elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  2533. {
  2534. return 31.0;
  2535. }
  2536. else
  2537. {
  2538. return null;
  2539. }
  2540. }
  2541. /**
  2542. * Get the number of items in the feed
  2543. *
  2544. * This is well-suited for {@link http://php.net/for for()} loops with
  2545. * {@see get_item()}
  2546. *
  2547. * @param int $max Maximum value to return. 0 for no limit
  2548. * @return int Number of items in the feed
  2549. */
  2550. public function get_item_quantity($max = 0)
  2551. {
  2552. $max = (int) $max;
  2553. $qty = count($this->get_items());
  2554. if ($max === 0)
  2555. {
  2556. return $qty;
  2557. }
  2558. else
  2559. {
  2560. return ($qty > $max) ? $max : $qty;
  2561. }
  2562. }
  2563. /**
  2564. * Get a single item from the feed
  2565. *
  2566. * This is better suited for {@link http://php.net/for for()} loops, whereas
  2567. * {@see get_items()} is better suited for
  2568. * {@link http://php.net/foreach foreach()} loops.
  2569. *
  2570. * @see get_item_quantity()
  2571. * @since Beta 2
  2572. * @param int $key The item that you want to return. Remember that arrays begin with 0, not 1
  2573. * @return SimplePie_Item|null
  2574. */
  2575. public function get_item($key = 0)
  2576. {
  2577. $items = $this->get_items();
  2578. if (isset($items[$key]))
  2579. {
  2580. return $items[$key];
  2581. }
  2582. else
  2583. {
  2584. return null;
  2585. }
  2586. }
  2587. /**
  2588. * Get all items from the feed
  2589. *
  2590. * This is better suited for {@link http://php.net/for for()} loops, whereas
  2591. * {@see get_items()} is better suited for
  2592. * {@link http://php.net/foreach foreach()} loops.
  2593. *
  2594. * @see get_item_quantity
  2595. * @since Beta 2
  2596. * @param int $start Index to start at
  2597. * @param int $end Number of items to return. 0 for all items after `$start`
  2598. * @return array|null List of {@see SimplePie_Item} objects
  2599. */
  2600. public function get_items($start = 0, $end = 0)
  2601. {
  2602. if (!isset($this->data['items']))
  2603. {
  2604. if (!empty($this->multifeed_objects))
  2605. {
  2606. $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
  2607. }
  2608. else
  2609. {
  2610. $this->data['items'] = array();
  2611. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
  2612. {
  2613. $keys = array_keys($items);
  2614. foreach ($keys as $key)
  2615. {
  2616. $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
  2617. }
  2618. }
  2619. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
  2620. {
  2621. $keys = array_keys($items);
  2622. foreach ($keys as $key)
  2623. {
  2624. $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
  2625. }
  2626. }
  2627. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
  2628. {
  2629. $keys = array_keys($items);
  2630. foreach ($keys as $key)
  2631. {
  2632. $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
  2633. }
  2634. }
  2635. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
  2636. {
  2637. $keys = array_keys($items);
  2638. foreach ($keys as $key)
  2639. {
  2640. $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
  2641. }
  2642. }
  2643. if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
  2644. {
  2645. $keys = array_keys($items);
  2646. foreach ($keys as $key)
  2647. {
  2648. $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
  2649. }
  2650. }
  2651. }
  2652. }
  2653. if (!empty($this->data['items']))
  2654. {
  2655. // If we want to order it by date, check if all items have a date, and then sort it
  2656. if ($this->order_by_date && empty($this->multifeed_objects))
  2657. {
  2658. if (!isset($this->data['ordered_items']))
  2659. {
  2660. $do_sort = true;
  2661. foreach ($this->data['items'] as $item)
  2662. {
  2663. if (!$item->get_date('U'))
  2664. {
  2665. $do_sort = false;
  2666. break;
  2667. }
  2668. }
  2669. $item = null;
  2670. $this->data['ordered_items'] = $this->data['items'];
  2671. if ($do_sort)
  2672. {
  2673. usort($this->data['ordered_items'], array(get_class($this), 'sort_items'));
  2674. }
  2675. }
  2676. $items = $this->data['ordered_items'];
  2677. }
  2678. else
  2679. {
  2680. $items = $this->data['items'];
  2681. }
  2682. // Slice the data as desired
  2683. if ($end === 0)
  2684. {
  2685. return array_slice($items, $start);
  2686. }
  2687. else
  2688. {
  2689. return array_slice($items, $start, $end);
  2690. }
  2691. }
  2692. else
  2693. {
  2694. return array();
  2695. }
  2696. }
  2697. /**
  2698. * Set the favicon handler
  2699. *
  2700. * @deprecated Use your own favicon handling instead
  2701. */
  2702. public function set_favicon_handler($page = false, $qs = 'i')
  2703. {
  2704. $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
  2705. trigger_error('Favicon handling has been removed, please use your own handling', $level);
  2706. return false;
  2707. }
  2708. /**
  2709. * Get the favicon for the current feed
  2710. *
  2711. * @deprecated Use your own favicon handling instead
  2712. */
  2713. public function get_favicon()
  2714. {
  2715. $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
  2716. trigger_error('Favicon handling has been removed, please use your own handling', $level);
  2717. if (($url = $this->get_link()) !== null)
  2718. {
  2719. return 'http://g.etfv.co/' . urlencode($url);
  2720. }
  2721. return false;
  2722. }
  2723. /**
  2724. * Magic method handler
  2725. *
  2726. * @param string $method Method name
  2727. * @param array $args Arguments to the method
  2728. * @return mixed
  2729. */
  2730. public function __call($method, $args)
  2731. {
  2732. if (strpos($method, 'subscribe_') === 0)
  2733. {
  2734. $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
  2735. trigger_error('subscribe_*() has been deprecated, implement the callback yourself', $level);
  2736. return '';
  2737. }
  2738. if ($method === 'enable_xml_dump')
  2739. {
  2740. $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
  2741. trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', $level);
  2742. return false;
  2743. }
  2744. $class = get_class($this);
  2745. $trace = debug_backtrace();
  2746. $file = $trace[0]['file'];
  2747. $line = $trace[0]['line'];
  2748. trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
  2749. }
  2750. /**
  2751. * Sorting callback for items
  2752. *
  2753. * @access private
  2754. * @param SimplePie $a
  2755. * @param SimplePie $b
  2756. * @return boolean
  2757. */
  2758. public static function sort_items($a, $b)
  2759. {
  2760. return $a->get_date('U') <= $b->get_date('U');
  2761. }
  2762. /**
  2763. * Merge items from several feeds into one
  2764. *
  2765. * If you're merging multiple feeds together, they need to all have dates
  2766. * for the items or else SimplePie will refuse to sort them.
  2767. *
  2768. * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings
  2769. * @param array $urls List of SimplePie feed objects to merge
  2770. * @param int $start Starting item
  2771. * @param int $end Number of items to return
  2772. * @param int $limit Maximum number of items per feed
  2773. * @return array
  2774. */
  2775. public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
  2776. {
  2777. if (is_array($urls) && sizeof($urls) > 0)
  2778. {
  2779. $items = array();
  2780. foreach ($urls as $arg)
  2781. {
  2782. if ($arg instanceof SimplePie)
  2783. {
  2784. $items = array_merge($items, $arg->get_items(0, $limit));
  2785. }
  2786. else
  2787. {
  2788. trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
  2789. }
  2790. }
  2791. $do_sort = true;
  2792. foreach ($items as $item)
  2793. {
  2794. if (!$item->get_date('U'))
  2795. {
  2796. $do_sort = false;
  2797. break;
  2798. }
  2799. }
  2800. $item = null;
  2801. if ($do_sort)
  2802. {
  2803. usort($items, array(get_class($urls[0]), 'sort_items'));
  2804. }
  2805. if ($end === 0)
  2806. {
  2807. return array_slice($items, $start);
  2808. }
  2809. else
  2810. {
  2811. return array_slice($items, $start, $end);
  2812. }
  2813. }
  2814. else
  2815. {
  2816. trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
  2817. return array();
  2818. }
  2819. }
  2820. }
  2821. /**
  2822. * Manages all author-related data
  2823. *
  2824. * Used by {@see SimplePie_Item::get_author()} and {@see SimplePie::get_authors()}
  2825. *
  2826. * This class can be overloaded with {@see SimplePie::set_author_class()}
  2827. *
  2828. * @package SimplePie
  2829. * @subpackage API
  2830. */
  2831. class SimplePie_Author
  2832. {
  2833. /**
  2834. * Author's name
  2835. *
  2836. * @var string
  2837. * @see get_name()
  2838. */
  2839. var $name;
  2840. /**
  2841. * Author's link
  2842. *
  2843. * @var string
  2844. * @see get_link()
  2845. */
  2846. var $link;
  2847. /**
  2848. * Author's email address
  2849. *
  2850. * @var string
  2851. * @see get_email()
  2852. */
  2853. var $email;
  2854. /**
  2855. * Constructor, used to input the data
  2856. *
  2857. * @param string $name
  2858. * @param string $link
  2859. * @param string $email
  2860. */
  2861. public function __construct($name = null, $link = null, $email = null)
  2862. {
  2863. $this->name = $name;
  2864. $this->link = $link;
  2865. $this->email = $email;
  2866. }
  2867. /**
  2868. * String-ified version
  2869. *
  2870. * @return string
  2871. */
  2872. public function __toString()
  2873. {
  2874. // There is no $this->data here
  2875. return md5(serialize($this));
  2876. }
  2877. /**
  2878. * Author's name
  2879. *
  2880. * @return string|null
  2881. */
  2882. public function get_name()
  2883. {
  2884. if ($this->name !== null)
  2885. {
  2886. return $this->name;
  2887. }
  2888. else
  2889. {
  2890. return null;
  2891. }
  2892. }
  2893. /**
  2894. * Author's link
  2895. *
  2896. * @return string|null
  2897. */
  2898. public function get_link()
  2899. {
  2900. if ($this->link !== null)
  2901. {
  2902. return $this->link;
  2903. }
  2904. else
  2905. {
  2906. return null;
  2907. }
  2908. }
  2909. /**
  2910. * Author's email address
  2911. *
  2912. * @return string|null
  2913. */
  2914. public function get_email()
  2915. {
  2916. if ($this->email !== null)
  2917. {
  2918. return $this->email;
  2919. }
  2920. else
  2921. {
  2922. return null;
  2923. }
  2924. }
  2925. }
  2926. /**
  2927. * Base for cache objects
  2928. *
  2929. * Classes to be used with {@see SimplePie_Cache::register()} are expected
  2930. * to implement this interface.
  2931. *
  2932. * @package SimplePie
  2933. * @subpackage Caching
  2934. */
  2935. interface SimplePie_Cache_Base
  2936. {
  2937. /**
  2938. * Feed cache type
  2939. *
  2940. * @var string
  2941. */
  2942. const TYPE_FEED = 'spc';
  2943. /**
  2944. * Image cache type
  2945. *
  2946. * @var string
  2947. */
  2948. const TYPE_IMAGE = 'spi';
  2949. /**
  2950. * Create a new cache object
  2951. *
  2952. * @param string $location Location string (from SimplePie::$cache_location)
  2953. * @param string $name Unique ID for the cache
  2954. * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
  2955. */
  2956. public function __construct($location, $name, $type);
  2957. /**
  2958. * Save data to the cache
  2959. *
  2960. * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
  2961. * @return bool Successfulness
  2962. */
  2963. public function save($data);
  2964. /**
  2965. * Retrieve the data saved to the cache
  2966. *
  2967. * @return array Data for SimplePie::$data
  2968. */
  2969. public function load();
  2970. /**
  2971. * Retrieve the last modified time for the cache
  2972. *
  2973. * @return int Timestamp
  2974. */
  2975. public function mtime();
  2976. /**
  2977. * Set the last modified time to the current time
  2978. *
  2979. * @return bool Success status
  2980. */
  2981. public function touch();
  2982. /**
  2983. * Remove the cache
  2984. *
  2985. * @return bool Success status
  2986. */
  2987. public function unlink();
  2988. }
  2989. /**
  2990. * Base class for database-based caches
  2991. *
  2992. * @package SimplePie
  2993. * @subpackage Caching
  2994. */
  2995. abstract class SimplePie_Cache_DB implements SimplePie_Cache_Base
  2996. {
  2997. /**
  2998. * Helper for database conversion
  2999. *
  3000. * Converts a given {@see SimplePie} object into data to be stored
  3001. *
  3002. * @param SimplePie $data
  3003. * @return array First item is the serialized data for storage, second item is the unique ID for this item
  3004. */
  3005. protected static function prepare_simplepie_object_for_cache($data)
  3006. {
  3007. $items = $data->get_items();
  3008. $items_by_id = array();
  3009. if (!empty($items))
  3010. {
  3011. foreach ($items as $item)
  3012. {
  3013. $items_by_id[$item->get_id()] = $item;
  3014. }
  3015. if (count($items_by_id) !== count($items))
  3016. {
  3017. $items_by_id = array();
  3018. foreach ($items as $item)
  3019. {
  3020. $items_by_id[$item->get_id(true)] = $item;
  3021. }
  3022. }
  3023. if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
  3024. {
  3025. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
  3026. }
  3027. elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
  3028. {
  3029. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
  3030. }
  3031. elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
  3032. {
  3033. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
  3034. }
  3035. elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
  3036. {
  3037. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
  3038. }
  3039. else
  3040. {
  3041. $channel = null;
  3042. }
  3043. if ($channel !== null)
  3044. {
  3045. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
  3046. {
  3047. unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
  3048. }
  3049. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
  3050. {
  3051. unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
  3052. }
  3053. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
  3054. {
  3055. unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
  3056. }
  3057. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
  3058. {
  3059. unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
  3060. }
  3061. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
  3062. {
  3063. unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
  3064. }
  3065. }
  3066. if (isset($data->data['items']))
  3067. {
  3068. unset($data->data['items']);
  3069. }
  3070. if (isset($data->data['ordered_items']))
  3071. {
  3072. unset($data->data['ordered_items']);
  3073. }
  3074. }
  3075. return array(serialize($data->data), $items_by_id);
  3076. }
  3077. }
  3078. /**
  3079. * Caches data to the filesystem
  3080. *
  3081. * @package SimplePie
  3082. * @subpackage Caching
  3083. */
  3084. class SimplePie_Cache_File implements SimplePie_Cache_Base
  3085. {
  3086. /**
  3087. * Location string
  3088. *
  3089. * @see SimplePie::$cache_location
  3090. * @var string
  3091. */
  3092. protected $location;
  3093. /**
  3094. * Filename
  3095. *
  3096. * @var string
  3097. */
  3098. protected $filename;
  3099. /**
  3100. * File extension
  3101. *
  3102. * @var string
  3103. */
  3104. protected $extension;
  3105. /**
  3106. * File path
  3107. *
  3108. * @var string
  3109. */
  3110. protected $name;
  3111. /**
  3112. * Create a new cache object
  3113. *
  3114. * @param string $location Location string (from SimplePie::$cache_location)
  3115. * @param string $name Unique ID for the cache
  3116. * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
  3117. */
  3118. public function __construct($location, $name, $type)
  3119. {
  3120. $this->location = $location;
  3121. $this->filename = $name;
  3122. $this->extension = $type;
  3123. $this->name = "$this->location/$this->filename.$this->extension";
  3124. }
  3125. /**
  3126. * Save data to the cache
  3127. *
  3128. * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
  3129. * @return bool Successfulness
  3130. */
  3131. public function save($data)
  3132. {
  3133. if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
  3134. {
  3135. if ($data instanceof SimplePie)
  3136. {
  3137. $data = $data->data;
  3138. }
  3139. $data = serialize($data);
  3140. return (bool) file_put_contents($this->name, $data);
  3141. }
  3142. return false;
  3143. }
  3144. /**
  3145. * Retrieve the data saved to the cache
  3146. *
  3147. * @return array Data for SimplePie::$data
  3148. */
  3149. public function load()
  3150. {
  3151. if (file_exists($this->name) && is_readable($this->name))
  3152. {
  3153. return unserialize(file_get_contents($this->name));
  3154. }
  3155. return false;
  3156. }
  3157. /**
  3158. * Retrieve the last modified time for the cache
  3159. *
  3160. * @return int Timestamp
  3161. */
  3162. public function mtime()
  3163. {
  3164. if (file_exists($this->name))
  3165. {
  3166. return filemtime($this->name);
  3167. }
  3168. return false;
  3169. }
  3170. /**
  3171. * Set the last modified time to the current time
  3172. *
  3173. * @return bool Success status
  3174. */
  3175. public function touch()
  3176. {
  3177. if (file_exists($this->name))
  3178. {
  3179. return touch($this->name);
  3180. }
  3181. return false;
  3182. }
  3183. /**
  3184. * Remove the cache
  3185. *
  3186. * @return bool Success status
  3187. */
  3188. public function unlink()
  3189. {
  3190. if (file_exists($this->name))
  3191. {
  3192. return unlink($this->name);
  3193. }
  3194. return false;
  3195. }
  3196. }
  3197. /**
  3198. * Caches data to memcache
  3199. *
  3200. * Registered for URLs with the "memcache" protocol
  3201. *
  3202. * For example, `memcache://localhost:11211/?timeout=3600&prefix=sp_` will
  3203. * connect to memcache on `localhost` on port 11211. All tables will be
  3204. * prefixed with `sp_` and data will expire after 3600 seconds
  3205. *
  3206. * @package SimplePie
  3207. * @subpackage Caching
  3208. * @uses Memcache
  3209. */
  3210. class SimplePie_Cache_Memcache implements SimplePie_Cache_Base
  3211. {
  3212. /**
  3213. * Memcache instance
  3214. *
  3215. * @var Memcache
  3216. */
  3217. protected $cache;
  3218. /**
  3219. * Options
  3220. *
  3221. * @var array
  3222. */
  3223. protected $options;
  3224. /**
  3225. * Cache name
  3226. *
  3227. * @var string
  3228. */
  3229. protected $name;
  3230. /**
  3231. * Create a new cache object
  3232. *
  3233. * @param string $location Location string (from SimplePie::$cache_location)
  3234. * @param string $name Unique ID for the cache
  3235. * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
  3236. */
  3237. public function __construct($location, $name, $type)
  3238. {
  3239. $this->options = array(
  3240. 'host' => '127.0.0.1',
  3241. 'port' => 11211,
  3242. 'extras' => array(
  3243. 'timeout' => 3600, // one hour
  3244. 'prefix' => 'simplepie_',
  3245. ),
  3246. );
  3247. $parsed = SimplePie_Cache::parse_URL($location);
  3248. $this->options['host'] = empty($parsed['host']) ? $this->options['host'] : $parsed['host'];
  3249. $this->options['port'] = empty($parsed['port']) ? $this->options['port'] : $parsed['port'];
  3250. $this->options['extras'] = array_merge($this->options['extras'], $parsed['extras']);
  3251. $this->name = $this->options['extras']['prefix'] . md5("$name:$type");
  3252. $this->cache = new Memcache();
  3253. $this->cache->addServer($this->options['host'], (int) $this->options['port']);
  3254. }
  3255. /**
  3256. * Save data to the cache
  3257. *
  3258. * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
  3259. * @return bool Successfulness
  3260. */
  3261. public function save($data)
  3262. {
  3263. if ($data instanceof SimplePie)
  3264. {
  3265. $data = $data->data;
  3266. }
  3267. return $this->cache->set($this->name, serialize($data), MEMCACHE_COMPRESSED, (int) $this->options['extras']['timeout']);
  3268. }
  3269. /**
  3270. * Retrieve the data saved to the cache
  3271. *
  3272. * @return array Data for SimplePie::$data
  3273. */
  3274. public function load()
  3275. {
  3276. $data = $this->cache->get($this->name);
  3277. if ($data !== false)
  3278. {
  3279. return unserialize($data);
  3280. }
  3281. return false;
  3282. }
  3283. /**
  3284. * Retrieve the last modified time for the cache
  3285. *
  3286. * @return int Timestamp
  3287. */
  3288. public function mtime()
  3289. {
  3290. $data = $this->cache->get($this->name);
  3291. if ($data !== false)
  3292. {
  3293. // essentially ignore the mtime because Memcache expires on it's own
  3294. return time();
  3295. }
  3296. return false;
  3297. }
  3298. /**
  3299. * Set the last modified time to the current time
  3300. *
  3301. * @return bool Success status
  3302. */
  3303. public function touch()
  3304. {
  3305. $data = $this->cache->get($this->name);
  3306. if ($data !== false)
  3307. {
  3308. return $this->cache->set($this->name, $data, MEMCACHE_COMPRESSED, (int) $this->duration);
  3309. }
  3310. return false;
  3311. }
  3312. /**
  3313. * Remove the cache
  3314. *
  3315. * @return bool Success status
  3316. */
  3317. public function unlink()
  3318. {
  3319. return $this->cache->delete($this->name, 0);
  3320. }
  3321. }
  3322. /**
  3323. * Caches data to a MySQL database
  3324. *
  3325. * Registered for URLs with the "mysql" protocol
  3326. *
  3327. * For example, `mysql://root:password@localhost:3306/mydb?prefix=sp_` will
  3328. * connect to the `mydb` database on `localhost` on port 3306, with the user
  3329. * `root` and the password `password`. All tables will be prefixed with `sp_`
  3330. *
  3331. * @package SimplePie
  3332. * @subpackage Caching
  3333. */
  3334. class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
  3335. {
  3336. /**
  3337. * PDO instance
  3338. *
  3339. * @var PDO
  3340. */
  3341. protected $mysql;
  3342. /**
  3343. * Options
  3344. *
  3345. * @var array
  3346. */
  3347. protected $options;
  3348. /**
  3349. * Cache ID
  3350. *
  3351. * @var string
  3352. */
  3353. protected $id;
  3354. /**
  3355. * Create a new cache object
  3356. *
  3357. * @param string $location Location string (from SimplePie::$cache_location)
  3358. * @param string $name Unique ID for the cache
  3359. * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
  3360. */
  3361. public function __construct($location, $name, $type)
  3362. {
  3363. $this->options = array(
  3364. 'user' => null,
  3365. 'pass' => null,
  3366. 'host' => '127.0.0.1',
  3367. 'port' => '3306',
  3368. 'path' => '',
  3369. 'extras' => array(
  3370. 'prefix' => '',
  3371. ),
  3372. );
  3373. $this->options = array_merge_recursive($this->options, SimplePie_Cache::parse_URL($location));
  3374. // Path is prefixed with a "/"
  3375. $this->options['dbname'] = substr($this->options['path'], 1);
  3376. try
  3377. {
  3378. $this->mysql = new PDO("mysql:dbname={$this->options['dbname']};host={$this->options['host']};port={$this->options['port']}", $this->options['user'], $this->options['pass'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
  3379. }
  3380. catch (PDOException $e)
  3381. {
  3382. $this->mysql = null;
  3383. return;
  3384. }
  3385. $this->id = $name . $type;
  3386. if (!$query = $this->mysql->query('SHOW TABLES'))
  3387. {
  3388. $this->mysql = null;
  3389. return;
  3390. }
  3391. $db = array();
  3392. while ($row = $query->fetchColumn())
  3393. {
  3394. $db[] = $row;
  3395. }
  3396. if (!in_array($this->options['extras']['prefix'] . 'cache_data', $db))
  3397. {
  3398. $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))');
  3399. if ($query === false)
  3400. {
  3401. $this->mysql = null;
  3402. }
  3403. }
  3404. if (!in_array($this->options['extras']['prefix'] . 'items', $db))
  3405. {
  3406. $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))');
  3407. if ($query === false)
  3408. {
  3409. $this->mysql = null;
  3410. }
  3411. }
  3412. }
  3413. /**
  3414. * Save data to the cache
  3415. *
  3416. * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
  3417. * @return bool Successfulness
  3418. */
  3419. public function save($data)
  3420. {
  3421. if ($this->mysql === null)
  3422. {
  3423. return false;
  3424. }
  3425. if ($data instanceof SimplePie)
  3426. {
  3427. $data = clone $data;
  3428. $prepared = self::prepare_simplepie_object_for_cache($data);
  3429. $query = $this->mysql->prepare('SELECT COUNT(*) FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');
  3430. $query->bindValue(':feed', $this->id);
  3431. if ($query->execute())
  3432. {
  3433. if ($query->fetchColumn() > 0)
  3434. {
  3435. $items = count($prepared[1]);
  3436. if ($items)
  3437. {
  3438. $sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = :items, `data` = :data, `mtime` = :time WHERE `id` = :feed';
  3439. $query = $this->mysql->prepare($sql);
  3440. $query->bindValue(':items', $items);
  3441. }
  3442. else
  3443. {
  3444. $sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `data` = :data, `mtime` = :time WHERE `id` = :feed';
  3445. $query = $this->mysql->prepare($sql);
  3446. }
  3447. $query->bindValue(':data', $prepared[0]);
  3448. $query->bindValue(':time', time());
  3449. $query->bindValue(':feed', $this->id);
  3450. if (!$query->execute())
  3451. {
  3452. return false;
  3453. }
  3454. }
  3455. else
  3456. {
  3457. $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:feed, :count, :data, :time)');
  3458. $query->bindValue(':feed', $this->id);
  3459. $query->bindValue(':count', count($prepared[1]));
  3460. $query->bindValue(':data', $prepared[0]);
  3461. $query->bindValue(':time', time());
  3462. if (!$query->execute())
  3463. {
  3464. return false;
  3465. }
  3466. }
  3467. $ids = array_keys($prepared[1]);
  3468. if (!empty($ids))
  3469. {
  3470. foreach ($ids as $id)
  3471. {
  3472. $database_ids[] = $this->mysql->quote($id);
  3473. }
  3474. $query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `id` = ' . implode(' OR `id` = ', $database_ids) . ' AND `feed_id` = :feed');
  3475. $query->bindValue(':feed', $this->id);
  3476. if ($query->execute())
  3477. {
  3478. $existing_ids = array();
  3479. while ($row = $query->fetchColumn())
  3480. {
  3481. $existing_ids[] = $row;
  3482. }
  3483. $new_ids = array_diff($ids, $existing_ids);
  3484. foreach ($new_ids as $new_id)
  3485. {
  3486. if (!($date = $prepared[1][$new_id]->get_date('U')))
  3487. {
  3488. $date = time();
  3489. }
  3490. $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(:feed, :id, :data, :date)');
  3491. $query->bindValue(':feed', $this->id);
  3492. $query->bindValue(':id', $new_id);
  3493. $query->bindValue(':data', serialize($prepared[1][$new_id]->data));
  3494. $query->bindValue(':date', $date);
  3495. if (!$query->execute())
  3496. {
  3497. return false;
  3498. }
  3499. }
  3500. return true;
  3501. }
  3502. }
  3503. else
  3504. {
  3505. return true;
  3506. }
  3507. }
  3508. }
  3509. else
  3510. {
  3511. $query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');
  3512. $query->bindValue(':feed', $this->id);
  3513. if ($query->execute())
  3514. {
  3515. if ($query->rowCount() > 0)
  3516. {
  3517. $query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = 0, `data` = :data, `mtime` = :time WHERE `id` = :feed');
  3518. $query->bindValue(':data', serialize($data));
  3519. $query->bindValue(':time', time());
  3520. $query->bindValue(':feed', $this->id);
  3521. if ($this->execute())
  3522. {
  3523. return true;
  3524. }
  3525. }
  3526. else
  3527. {
  3528. $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:id, 0, :data, :time)');
  3529. $query->bindValue(':id', $this->id);
  3530. $query->bindValue(':data', serialize($data));
  3531. $query->bindValue(':time', time());
  3532. if ($query->execute())
  3533. {
  3534. return true;
  3535. }
  3536. }
  3537. }
  3538. }
  3539. return false;
  3540. }
  3541. /**
  3542. * Retrieve the data saved to the cache
  3543. *
  3544. * @return array Data for SimplePie::$data
  3545. */
  3546. public function load()
  3547. {
  3548. if ($this->mysql === null)
  3549. {
  3550. return false;
  3551. }
  3552. $query = $this->mysql->prepare('SELECT `items`, `data` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
  3553. $query->bindValue(':id', $this->id);
  3554. if ($query->execute() && ($row = $query->fetch()))
  3555. {
  3556. $data = unserialize($row[1]);
  3557. if (isset($this->options['items'][0]))
  3558. {
  3559. $items = (int) $this->options['items'][0];
  3560. }
  3561. else
  3562. {
  3563. $items = (int) $row[0];
  3564. }
  3565. if ($items !== 0)
  3566. {
  3567. if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
  3568. {
  3569. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
  3570. }
  3571. elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
  3572. {
  3573. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
  3574. }
  3575. elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
  3576. {
  3577. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
  3578. }
  3579. elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
  3580. {
  3581. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
  3582. }
  3583. else
  3584. {
  3585. $feed = null;
  3586. }
  3587. if ($feed !== null)
  3588. {
  3589. $sql = 'SELECT `data` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :feed ORDER BY `posted` DESC';
  3590. if ($items > 0)
  3591. {
  3592. $sql .= ' LIMIT ' . $items;
  3593. }
  3594. $query = $this->mysql->prepare($sql);
  3595. $query->bindValue(':feed', $this->id);
  3596. if ($query->execute())
  3597. {
  3598. while ($row = $query->fetchColumn())
  3599. {
  3600. $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row);
  3601. }
  3602. }
  3603. else
  3604. {
  3605. return false;
  3606. }
  3607. }
  3608. }
  3609. return $data;
  3610. }
  3611. return false;
  3612. }
  3613. /**
  3614. * Retrieve the last modified time for the cache
  3615. *
  3616. * @return int Timestamp
  3617. */
  3618. public function mtime()
  3619. {
  3620. if ($this->mysql === null)
  3621. {
  3622. return false;
  3623. }
  3624. $query = $this->mysql->prepare('SELECT `mtime` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
  3625. $query->bindValue(':id', $this->id);
  3626. if ($query->execute() && ($time = $query->fetchColumn()))
  3627. {
  3628. return $time;
  3629. }
  3630. else
  3631. {
  3632. return false;
  3633. }
  3634. }
  3635. /**
  3636. * Set the last modified time to the current time
  3637. *
  3638. * @return bool Success status
  3639. */
  3640. public function touch()
  3641. {
  3642. if ($this->mysql === null)
  3643. {
  3644. return false;
  3645. }
  3646. $query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `mtime` = :time WHERE `id` = :id');
  3647. $query->bindValue(':time', time());
  3648. $query->bindValue(':id', $this->id);
  3649. if ($query->execute() && $query->rowCount() > 0)
  3650. {
  3651. return true;
  3652. }
  3653. else
  3654. {
  3655. return false;
  3656. }
  3657. }
  3658. /**
  3659. * Remove the cache
  3660. *
  3661. * @return bool Success status
  3662. */
  3663. public function unlink()
  3664. {
  3665. if ($this->mysql === null)
  3666. {
  3667. return false;
  3668. }
  3669. $query = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
  3670. $query->bindValue(':id', $this->id);
  3671. $query2 = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :id');
  3672. $query2->bindValue(':id', $this->id);
  3673. if ($query->execute() && $query2->execute())
  3674. {
  3675. return true;
  3676. }
  3677. else
  3678. {
  3679. return false;
  3680. }
  3681. }
  3682. }
  3683. /**
  3684. * Used to create cache objects
  3685. *
  3686. * This class can be overloaded with {@see SimplePie::set_cache_class()},
  3687. * although the preferred way is to create your own handler
  3688. * via {@see register()}
  3689. *
  3690. * @package SimplePie
  3691. * @subpackage Caching
  3692. */
  3693. class SimplePie_Cache
  3694. {
  3695. /**
  3696. * Cache handler classes
  3697. *
  3698. * These receive 3 parameters to their constructor, as documented in
  3699. * {@see register()}
  3700. * @var array
  3701. */
  3702. protected static $handlers = array(
  3703. 'mysql' => 'SimplePie_Cache_MySQL',
  3704. 'memcache' => 'SimplePie_Cache_Memcache',
  3705. );
  3706. /**
  3707. * Don't call the constructor. Please.
  3708. */
  3709. private function __construct() { }
  3710. /**
  3711. * Create a new SimplePie_Cache object
  3712. *
  3713. * @param string $location URL location (scheme is used to determine handler)
  3714. * @param string $filename Unique identifier for cache object
  3715. * @param string $extension 'spi' or 'spc'
  3716. * @return SimplePie_Cache_Base Type of object depends on scheme of `$location`
  3717. */
  3718. public static function get_handler($location, $filename, $extension)
  3719. {
  3720. $type = explode(':', $location, 2);
  3721. $type = $type[0];
  3722. if (!empty(self::$handlers[$type]))
  3723. {
  3724. $class = self::$handlers[$type];
  3725. return new $class($location, $filename, $extension);
  3726. }
  3727. return new SimplePie_Cache_File($location, $filename, $extension);
  3728. }
  3729. /**
  3730. * Create a new SimplePie_Cache object
  3731. *
  3732. * @deprecated Use {@see get_handler} instead
  3733. */
  3734. public function create($location, $filename, $extension)
  3735. {
  3736. trigger_error('Cache::create() has been replaced with Cache::get_handler(). Switch to the registry system to use this.', E_USER_DEPRECATED);
  3737. return self::get_handler($location, $filename, $extension);
  3738. }
  3739. /**
  3740. * Register a handler
  3741. *
  3742. * @param string $type DSN type to register for
  3743. * @param string $class Name of handler class. Must implement SimplePie_Cache_Base
  3744. */
  3745. public static function register($type, $class)
  3746. {
  3747. self::$handlers[$type] = $class;
  3748. }
  3749. /**
  3750. * Parse a URL into an array
  3751. *
  3752. * @param string $url
  3753. * @return array
  3754. */
  3755. public static function parse_URL($url)
  3756. {
  3757. $params = parse_url($url);
  3758. $params['extras'] = array();
  3759. if (isset($params['query']))
  3760. {
  3761. parse_str($params['query'], $params['extras']);
  3762. }
  3763. return $params;
  3764. }
  3765. }
  3766. /**
  3767. * Handles `<media:text>` captions as defined in Media RSS.
  3768. *
  3769. * Used by {@see SimplePie_Enclosure::get_caption()} and {@see SimplePie_Enclosure::get_captions()}
  3770. *
  3771. * This class can be overloaded with {@see SimplePie::set_caption_class()}
  3772. *
  3773. * @package SimplePie
  3774. * @subpackage API
  3775. */
  3776. class SimplePie_Caption
  3777. {
  3778. /**
  3779. * Content type
  3780. *
  3781. * @var string
  3782. * @see get_type()
  3783. */
  3784. var $type;
  3785. /**
  3786. * Language
  3787. *
  3788. * @var string
  3789. * @see get_language()
  3790. */
  3791. var $lang;
  3792. /**
  3793. * Start time
  3794. *
  3795. * @var string
  3796. * @see get_starttime()
  3797. */
  3798. var $startTime;
  3799. /**
  3800. * End time
  3801. *
  3802. * @var string
  3803. * @see get_endtime()
  3804. */
  3805. var $endTime;
  3806. /**
  3807. * Caption text
  3808. *
  3809. * @var string
  3810. * @see get_text()
  3811. */
  3812. var $text;
  3813. /**
  3814. * Constructor, used to input the data
  3815. *
  3816. * For documentation on all the parameters, see the corresponding
  3817. * properties and their accessors
  3818. */
  3819. public function __construct($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
  3820. {
  3821. $this->type = $type;
  3822. $this->lang = $lang;
  3823. $this->startTime = $startTime;
  3824. $this->endTime = $endTime;
  3825. $this->text = $text;
  3826. }
  3827. /**
  3828. * String-ified version
  3829. *
  3830. * @return string
  3831. */
  3832. public function __toString()
  3833. {
  3834. // There is no $this->data here
  3835. return md5(serialize($this));
  3836. }
  3837. /**
  3838. * Get the end time
  3839. *
  3840. * @return string|null Time in the format 'hh:mm:ss.SSS'
  3841. */
  3842. public function get_endtime()
  3843. {
  3844. if ($this->endTime !== null)
  3845. {
  3846. return $this->endTime;
  3847. }
  3848. else
  3849. {
  3850. return null;
  3851. }
  3852. }
  3853. /**
  3854. * Get the language
  3855. *
  3856. * @link http://tools.ietf.org/html/rfc3066
  3857. * @return string|null Language code as per RFC 3066
  3858. */
  3859. public function get_language()
  3860. {
  3861. if ($this->lang !== null)
  3862. {
  3863. return $this->lang;
  3864. }
  3865. else
  3866. {
  3867. return null;
  3868. }
  3869. }
  3870. /**
  3871. * Get the start time
  3872. *
  3873. * @return string|null Time in the format 'hh:mm:ss.SSS'
  3874. */
  3875. public function get_starttime()
  3876. {
  3877. if ($this->startTime !== null)
  3878. {
  3879. return $this->startTime;
  3880. }
  3881. else
  3882. {
  3883. return null;
  3884. }
  3885. }
  3886. /**
  3887. * Get the text of the caption
  3888. *
  3889. * @return string|null
  3890. */
  3891. public function get_text()
  3892. {
  3893. if ($this->text !== null)
  3894. {
  3895. return $this->text;
  3896. }
  3897. else
  3898. {
  3899. return null;
  3900. }
  3901. }
  3902. /**
  3903. * Get the content type (not MIME type)
  3904. *
  3905. * @return string|null Either 'text' or 'html'
  3906. */
  3907. public function get_type()
  3908. {
  3909. if ($this->type !== null)
  3910. {
  3911. return $this->type;
  3912. }
  3913. else
  3914. {
  3915. return null;
  3916. }
  3917. }
  3918. }
  3919. /**
  3920. * Manages all category-related data
  3921. *
  3922. * Used by {@see SimplePie_Item::get_category()} and {@see SimplePie_Item::get_categories()}
  3923. *
  3924. * This class can be overloaded with {@see SimplePie::set_category_class()}
  3925. *
  3926. * @package SimplePie
  3927. * @subpackage API
  3928. */
  3929. class SimplePie_Category
  3930. {
  3931. /**
  3932. * Category identifier
  3933. *
  3934. * @var string
  3935. * @see get_term
  3936. */
  3937. var $term;
  3938. /**
  3939. * Categorization scheme identifier
  3940. *
  3941. * @var string
  3942. * @see get_scheme()
  3943. */
  3944. var $scheme;
  3945. /**
  3946. * Human readable label
  3947. *
  3948. * @var string
  3949. * @see get_label()
  3950. */
  3951. var $label;
  3952. /**
  3953. * Constructor, used to input the data
  3954. *
  3955. * @param string $term
  3956. * @param string $scheme
  3957. * @param string $label
  3958. */
  3959. public function __construct($term = null, $scheme = null, $label = null)
  3960. {
  3961. $this->term = $term;
  3962. $this->scheme = $scheme;
  3963. $this->label = $label;
  3964. }
  3965. /**
  3966. * String-ified version
  3967. *
  3968. * @return string
  3969. */
  3970. public function __toString()
  3971. {
  3972. // There is no $this->data here
  3973. return md5(serialize($this));
  3974. }
  3975. /**
  3976. * Get the category identifier
  3977. *
  3978. * @return string|null
  3979. */
  3980. public function get_term()
  3981. {
  3982. if ($this->term !== null)
  3983. {
  3984. return $this->term;
  3985. }
  3986. else
  3987. {
  3988. return null;
  3989. }
  3990. }
  3991. /**
  3992. * Get the categorization scheme identifier
  3993. *
  3994. * @return string|null
  3995. */
  3996. public function get_scheme()
  3997. {
  3998. if ($this->scheme !== null)
  3999. {
  4000. return $this->scheme;
  4001. }
  4002. else
  4003. {
  4004. return null;
  4005. }
  4006. }
  4007. /**
  4008. * Get the human readable label
  4009. *
  4010. * @return string|null
  4011. */
  4012. public function get_label()
  4013. {
  4014. if ($this->label !== null)
  4015. {
  4016. return $this->label;
  4017. }
  4018. else
  4019. {
  4020. return $this->get_term();
  4021. }
  4022. }
  4023. }
  4024. /**
  4025. * Content-type sniffing
  4026. *
  4027. * Based on the rules in http://tools.ietf.org/html/draft-abarth-mime-sniff-06
  4028. *
  4029. * This is used since we can't always trust Content-Type headers, and is based
  4030. * upon the HTML5 parsing rules.
  4031. *
  4032. *
  4033. * This class can be overloaded with {@see SimplePie::set_content_type_sniffer_class()}
  4034. *
  4035. * @package SimplePie
  4036. * @subpackage HTTP
  4037. */
  4038. class SimplePie_Content_Type_Sniffer
  4039. {
  4040. /**
  4041. * File object
  4042. *
  4043. * @var SimplePie_File
  4044. */
  4045. var $file;
  4046. /**
  4047. * Create an instance of the class with the input file
  4048. *
  4049. * @param SimplePie_Content_Type_Sniffer $file Input file
  4050. */
  4051. public function __construct($file)
  4052. {
  4053. $this->file = $file;
  4054. }
  4055. /**
  4056. * Get the Content-Type of the specified file
  4057. *
  4058. * @return string Actual Content-Type
  4059. */
  4060. public function get_type()
  4061. {
  4062. if (isset($this->file->headers['content-type']))
  4063. {
  4064. if (!isset($this->file->headers['content-encoding'])
  4065. && ($this->file->headers['content-type'] === 'text/plain'
  4066. || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
  4067. || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'
  4068. || $this->file->headers['content-type'] === 'text/plain; charset=UTF-8'))
  4069. {
  4070. return $this->text_or_binary();
  4071. }
  4072. if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
  4073. {
  4074. $official = substr($this->file->headers['content-type'], 0, $pos);
  4075. }
  4076. else
  4077. {
  4078. $official = $this->file->headers['content-type'];
  4079. }
  4080. $official = trim(strtolower($official));
  4081. if ($official === 'unknown/unknown'
  4082. || $official === 'application/unknown')
  4083. {
  4084. return $this->unknown();
  4085. }
  4086. elseif (substr($official, -4) === '+xml'
  4087. || $official === 'text/xml'
  4088. || $official === 'application/xml')
  4089. {
  4090. return $official;
  4091. }
  4092. elseif (substr($official, 0, 6) === 'image/')
  4093. {
  4094. if ($return = $this->image())
  4095. {
  4096. return $return;
  4097. }
  4098. else
  4099. {
  4100. return $official;
  4101. }
  4102. }
  4103. elseif ($official === 'text/html')
  4104. {
  4105. return $this->feed_or_html();
  4106. }
  4107. else
  4108. {
  4109. return $official;
  4110. }
  4111. }
  4112. else
  4113. {
  4114. return $this->unknown();
  4115. }
  4116. }
  4117. /**
  4118. * Sniff text or binary
  4119. *
  4120. * @return string Actual Content-Type
  4121. */
  4122. public function text_or_binary()
  4123. {
  4124. if (substr($this->file->body, 0, 2) === "\xFE\xFF"
  4125. || substr($this->file->body, 0, 2) === "\xFF\xFE"
  4126. || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
  4127. || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
  4128. {
  4129. return 'text/plain';
  4130. }
  4131. elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
  4132. {
  4133. return 'application/octect-stream';
  4134. }
  4135. else
  4136. {
  4137. return 'text/plain';
  4138. }
  4139. }
  4140. /**
  4141. * Sniff unknown
  4142. *
  4143. * @return string Actual Content-Type
  4144. */
  4145. public function unknown()
  4146. {
  4147. $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
  4148. if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
  4149. || strtolower(substr($this->file->body, $ws, 5)) === '<html'
  4150. || strtolower(substr($this->file->body, $ws, 7)) === '<script')
  4151. {
  4152. return 'text/html';
  4153. }
  4154. elseif (substr($this->file->body, 0, 5) === '%PDF-')
  4155. {
  4156. return 'application/pdf';
  4157. }
  4158. elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
  4159. {
  4160. return 'application/postscript';
  4161. }
  4162. elseif (substr($this->file->body, 0, 6) === 'GIF87a'
  4163. || substr($this->file->body, 0, 6) === 'GIF89a')
  4164. {
  4165. return 'image/gif';
  4166. }
  4167. elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
  4168. {
  4169. return 'image/png';
  4170. }
  4171. elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
  4172. {
  4173. return 'image/jpeg';
  4174. }
  4175. elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
  4176. {
  4177. return 'image/bmp';
  4178. }
  4179. elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00")
  4180. {
  4181. return 'image/vnd.microsoft.icon';
  4182. }
  4183. else
  4184. {
  4185. return $this->text_or_binary();
  4186. }
  4187. }
  4188. /**
  4189. * Sniff images
  4190. *
  4191. * @return string Actual Content-Type
  4192. */
  4193. public function image()
  4194. {
  4195. if (substr($this->file->body, 0, 6) === 'GIF87a'
  4196. || substr($this->file->body, 0, 6) === 'GIF89a')
  4197. {
  4198. return 'image/gif';
  4199. }
  4200. elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
  4201. {
  4202. return 'image/png';
  4203. }
  4204. elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
  4205. {
  4206. return 'image/jpeg';
  4207. }
  4208. elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
  4209. {
  4210. return 'image/bmp';
  4211. }
  4212. elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00")
  4213. {
  4214. return 'image/vnd.microsoft.icon';
  4215. }
  4216. else
  4217. {
  4218. return false;
  4219. }
  4220. }
  4221. /**
  4222. * Sniff HTML
  4223. *
  4224. * @return string Actual Content-Type
  4225. */
  4226. public function feed_or_html()
  4227. {
  4228. $len = strlen($this->file->body);
  4229. $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
  4230. while ($pos < $len)
  4231. {
  4232. switch ($this->file->body[$pos])
  4233. {
  4234. case "\x09":
  4235. case "\x0A":
  4236. case "\x0D":
  4237. case "\x20":
  4238. $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
  4239. continue 2;
  4240. case '<':
  4241. $pos++;
  4242. break;
  4243. default:
  4244. return 'text/html';
  4245. }
  4246. if (substr($this->file->body, $pos, 3) === '!--')
  4247. {
  4248. $pos += 3;
  4249. if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
  4250. {
  4251. $pos += 3;
  4252. }
  4253. else
  4254. {
  4255. return 'text/html';
  4256. }
  4257. }
  4258. elseif (substr($this->file->body, $pos, 1) === '!')
  4259. {
  4260. if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
  4261. {
  4262. $pos++;
  4263. }
  4264. else
  4265. {
  4266. return 'text/html';
  4267. }
  4268. }
  4269. elseif (substr($this->file->body, $pos, 1) === '?')
  4270. {
  4271. if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
  4272. {
  4273. $pos += 2;
  4274. }
  4275. else
  4276. {
  4277. return 'text/html';
  4278. }
  4279. }
  4280. elseif (substr($this->file->body, $pos, 3) === 'rss'
  4281. || substr($this->file->body, $pos, 7) === 'rdf:RDF')
  4282. {
  4283. return 'application/rss+xml';
  4284. }
  4285. elseif (substr($this->file->body, $pos, 4) === 'feed')
  4286. {
  4287. return 'application/atom+xml';
  4288. }
  4289. else
  4290. {
  4291. return 'text/html';
  4292. }
  4293. }
  4294. return 'text/html';
  4295. }
  4296. }
  4297. /**
  4298. * Manages `<media:copyright>` copyright tags as defined in Media RSS
  4299. *
  4300. * Used by {@see SimplePie_Enclosure::get_copyright()}
  4301. *
  4302. * This class can be overloaded with {@see SimplePie::set_copyright_class()}
  4303. *
  4304. * @package SimplePie
  4305. * @subpackage API
  4306. */
  4307. class SimplePie_Copyright
  4308. {
  4309. /**
  4310. * Copyright URL
  4311. *
  4312. * @var string
  4313. * @see get_url()
  4314. */
  4315. var $url;
  4316. /**
  4317. * Attribution
  4318. *
  4319. * @var string
  4320. * @see get_attribution()
  4321. */
  4322. var $label;
  4323. /**
  4324. * Constructor, used to input the data
  4325. *
  4326. * For documentation on all the parameters, see the corresponding
  4327. * properties and their accessors
  4328. */
  4329. public function __construct($url = null, $label = null)
  4330. {
  4331. $this->url = $url;
  4332. $this->label = $label;
  4333. }
  4334. /**
  4335. * String-ified version
  4336. *
  4337. * @return string
  4338. */
  4339. public function __toString()
  4340. {
  4341. // There is no $this->data here
  4342. return md5(serialize($this));
  4343. }
  4344. /**
  4345. * Get the copyright URL
  4346. *
  4347. * @return string|null URL to copyright information
  4348. */
  4349. public function get_url()
  4350. {
  4351. if ($this->url !== null)
  4352. {
  4353. return $this->url;
  4354. }
  4355. else
  4356. {
  4357. return null;
  4358. }
  4359. }
  4360. /**
  4361. * Get the attribution text
  4362. *
  4363. * @return string|null
  4364. */
  4365. public function get_attribution()
  4366. {
  4367. if ($this->label !== null)
  4368. {
  4369. return $this->label;
  4370. }
  4371. else
  4372. {
  4373. return null;
  4374. }
  4375. }
  4376. }
  4377. /**
  4378. * SimplePie class.
  4379. *
  4380. * Class for backward compatibility.
  4381. *
  4382. * @deprecated Use {@see SimplePie} directly
  4383. * @package SimplePie
  4384. * @subpackage API
  4385. */
  4386. class SimplePie_Core extends SimplePie
  4387. {
  4388. }
  4389. /**
  4390. * Handles `<media:credit>` as defined in Media RSS
  4391. *
  4392. * Used by {@see SimplePie_Enclosure::get_credit()} and {@see SimplePie_Enclosure::get_credits()}
  4393. *
  4394. * This class can be overloaded with {@see SimplePie::set_credit_class()}
  4395. *
  4396. * @package SimplePie
  4397. * @subpackage API
  4398. */
  4399. class SimplePie_Credit
  4400. {
  4401. /**
  4402. * Credited role
  4403. *
  4404. * @var string
  4405. * @see get_role()
  4406. */
  4407. var $role;
  4408. /**
  4409. * Organizational scheme
  4410. *
  4411. * @var string
  4412. * @see get_scheme()
  4413. */
  4414. var $scheme;
  4415. /**
  4416. * Credited name
  4417. *
  4418. * @var string
  4419. * @see get_name()
  4420. */
  4421. var $name;
  4422. /**
  4423. * Constructor, used to input the data
  4424. *
  4425. * For documentation on all the parameters, see the corresponding
  4426. * properties and their accessors
  4427. */
  4428. public function __construct($role = null, $scheme = null, $name = null)
  4429. {
  4430. $this->role = $role;
  4431. $this->scheme = $scheme;
  4432. $this->name = $name;
  4433. }
  4434. /**
  4435. * String-ified version
  4436. *
  4437. * @return string
  4438. */
  4439. public function __toString()
  4440. {
  4441. // There is no $this->data here
  4442. return md5(serialize($this));
  4443. }
  4444. /**
  4445. * Get the role of the person receiving credit
  4446. *
  4447. * @return string|null
  4448. */
  4449. public function get_role()
  4450. {
  4451. if ($this->role !== null)
  4452. {
  4453. return $this->role;
  4454. }
  4455. else
  4456. {
  4457. return null;
  4458. }
  4459. }
  4460. /**
  4461. * Get the organizational scheme
  4462. *
  4463. * @return string|null
  4464. */
  4465. public function get_scheme()
  4466. {
  4467. if ($this->scheme !== null)
  4468. {
  4469. return $this->scheme;
  4470. }
  4471. else
  4472. {
  4473. return null;
  4474. }
  4475. }
  4476. /**
  4477. * Get the credited person/entity's name
  4478. *
  4479. * @return string|null
  4480. */
  4481. public function get_name()
  4482. {
  4483. if ($this->name !== null)
  4484. {
  4485. return $this->name;
  4486. }
  4487. else
  4488. {
  4489. return null;
  4490. }
  4491. }
  4492. }
  4493. /**
  4494. * Decode HTML Entities
  4495. *
  4496. * This implements HTML5 as of revision 967 (2007-06-28)
  4497. *
  4498. * @deprecated Use DOMDocument instead!
  4499. * @package SimplePie
  4500. */
  4501. class SimplePie_Decode_HTML_Entities
  4502. {
  4503. /**
  4504. * Data to be parsed
  4505. *
  4506. * @access private
  4507. * @var string
  4508. */
  4509. var $data = '';
  4510. /**
  4511. * Currently consumed bytes
  4512. *
  4513. * @access private
  4514. * @var string
  4515. */
  4516. var $consumed = '';
  4517. /**
  4518. * Position of the current byte being parsed
  4519. *
  4520. * @access private
  4521. * @var int
  4522. */
  4523. var $position = 0;
  4524. /**
  4525. * Create an instance of the class with the input data
  4526. *
  4527. * @access public
  4528. * @param string $data Input data
  4529. */
  4530. public function __construct($data)
  4531. {
  4532. $this->data = $data;
  4533. }
  4534. /**
  4535. * Parse the input data
  4536. *
  4537. * @access public
  4538. * @return string Output data
  4539. */
  4540. public function parse()
  4541. {
  4542. while (($this->position = strpos($this->data, '&', $this->position)) !== false)
  4543. {
  4544. $this->consume();
  4545. $this->entity();
  4546. $this->consumed = '';
  4547. }
  4548. return $this->data;
  4549. }
  4550. /**
  4551. * Consume the next byte
  4552. *
  4553. * @access private
  4554. * @return mixed The next byte, or false, if there is no more data
  4555. */
  4556. public function consume()
  4557. {
  4558. if (isset($this->data[$this->position]))
  4559. {
  4560. $this->consumed .= $this->data[$this->position];
  4561. return $this->data[$this->position++];
  4562. }
  4563. else
  4564. {
  4565. return false;
  4566. }
  4567. }
  4568. /**
  4569. * Consume a range of characters
  4570. *
  4571. * @access private
  4572. * @param string $chars Characters to consume
  4573. * @return mixed A series of characters that match the range, or false
  4574. */
  4575. public function consume_range($chars)
  4576. {
  4577. if ($len = strspn($this->data, $chars, $this->position))
  4578. {
  4579. $data = substr($this->data, $this->position, $len);
  4580. $this->consumed .= $data;
  4581. $this->position += $len;
  4582. return $data;
  4583. }
  4584. else
  4585. {
  4586. return false;
  4587. }
  4588. }
  4589. /**
  4590. * Unconsume one byte
  4591. *
  4592. * @access private
  4593. */
  4594. public function unconsume()
  4595. {
  4596. $this->consumed = substr($this->consumed, 0, -1);
  4597. $this->position--;
  4598. }
  4599. /**
  4600. * Decode an entity
  4601. *
  4602. * @access private
  4603. */
  4604. public function entity()
  4605. {
  4606. switch ($this->consume())
  4607. {
  4608. case "\x09":
  4609. case "\x0A":
  4610. case "\x0B":
  4611. case "\x0B":
  4612. case "\x0C":
  4613. case "\x20":
  4614. case "\x3C":
  4615. case "\x26":
  4616. case false:
  4617. break;
  4618. case "\x23":
  4619. switch ($this->consume())
  4620. {
  4621. case "\x78":
  4622. case "\x58":
  4623. $range = '0123456789ABCDEFabcdef';
  4624. $hex = true;
  4625. break;
  4626. default:
  4627. $range = '0123456789';
  4628. $hex = false;
  4629. $this->unconsume();
  4630. break;
  4631. }
  4632. if ($codepoint = $this->consume_range($range))
  4633. {
  4634. static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8");
  4635. if ($hex)
  4636. {
  4637. $codepoint = hexdec($codepoint);
  4638. }
  4639. else
  4640. {
  4641. $codepoint = intval($codepoint);
  4642. }
  4643. if (isset($windows_1252_specials[$codepoint]))
  4644. {
  4645. $replacement = $windows_1252_specials[$codepoint];
  4646. }
  4647. else
  4648. {
  4649. $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
  4650. }
  4651. if (!in_array($this->consume(), array(';', false), true))
  4652. {
  4653. $this->unconsume();
  4654. }
  4655. $consumed_length = strlen($this->consumed);
  4656. $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
  4657. $this->position += strlen($replacement) - $consumed_length;
  4658. }
  4659. break;
  4660. default:
  4661. static $entities = array(
  4662. 'Aacute' => "\xC3\x81",
  4663. 'aacute' => "\xC3\xA1",
  4664. 'Aacute;' => "\xC3\x81",
  4665. 'aacute;' => "\xC3\xA1",
  4666. 'Acirc' => "\xC3\x82",
  4667. 'acirc' => "\xC3\xA2",
  4668. 'Acirc;' => "\xC3\x82",
  4669. 'acirc;' => "\xC3\xA2",
  4670. 'acute' => "\xC2\xB4",
  4671. 'acute;' => "\xC2\xB4",
  4672. 'AElig' => "\xC3\x86",
  4673. 'aelig' => "\xC3\xA6",
  4674. 'AElig;' => "\xC3\x86",
  4675. 'aelig;' => "\xC3\xA6",
  4676. 'Agrave' => "\xC3\x80",
  4677. 'agrave' => "\xC3\xA0",
  4678. 'Agrave;' => "\xC3\x80",
  4679. 'agrave;' => "\xC3\xA0",
  4680. 'alefsym;' => "\xE2\x84\xB5",
  4681. 'Alpha;' => "\xCE\x91",
  4682. 'alpha;' => "\xCE\xB1",
  4683. 'AMP' => "\x26",
  4684. 'amp' => "\x26",
  4685. 'AMP;' => "\x26",
  4686. 'amp;' => "\x26",
  4687. 'and;' => "\xE2\x88\xA7",
  4688. 'ang;' => "\xE2\x88\xA0",
  4689. 'apos;' => "\x27",
  4690. 'Aring' => "\xC3\x85",
  4691. 'aring' => "\xC3\xA5",
  4692. 'Aring;' => "\xC3\x85",
  4693. 'aring;' => "\xC3\xA5",
  4694. 'asymp;' => "\xE2\x89\x88",
  4695. 'Atilde' => "\xC3\x83",
  4696. 'atilde' => "\xC3\xA3",
  4697. 'Atilde;' => "\xC3\x83",
  4698. 'atilde;' => "\xC3\xA3",
  4699. 'Auml' => "\xC3\x84",
  4700. 'auml' => "\xC3\xA4",
  4701. 'Auml;' => "\xC3\x84",
  4702. 'auml;' => "\xC3\xA4",
  4703. 'bdquo;' => "\xE2\x80\x9E",
  4704. 'Beta;' => "\xCE\x92",
  4705. 'beta;' => "\xCE\xB2",
  4706. 'brvbar' => "\xC2\xA6",
  4707. 'brvbar;' => "\xC2\xA6",
  4708. 'bull;' => "\xE2\x80\xA2",
  4709. 'cap;' => "\xE2\x88\xA9",
  4710. 'Ccedil' => "\xC3\x87",
  4711. 'ccedil' => "\xC3\xA7",
  4712. 'Ccedil;' => "\xC3\x87",
  4713. 'ccedil;' => "\xC3\xA7",
  4714. 'cedil' => "\xC2\xB8",
  4715. 'cedil;' => "\xC2\xB8",
  4716. 'cent' => "\xC2\xA2",
  4717. 'cent;' => "\xC2\xA2",
  4718. 'Chi;' => "\xCE\xA7",
  4719. 'chi;' => "\xCF\x87",
  4720. 'circ;' => "\xCB\x86",
  4721. 'clubs;' => "\xE2\x99\xA3",
  4722. 'cong;' => "\xE2\x89\x85",
  4723. 'COPY' => "\xC2\xA9",
  4724. 'copy' => "\xC2\xA9",
  4725. 'COPY;' => "\xC2\xA9",
  4726. 'copy;' => "\xC2\xA9",
  4727. 'crarr;' => "\xE2\x86\xB5",
  4728. 'cup;' => "\xE2\x88\xAA",
  4729. 'curren' => "\xC2\xA4",
  4730. 'curren;' => "\xC2\xA4",
  4731. 'Dagger;' => "\xE2\x80\xA1",
  4732. 'dagger;' => "\xE2\x80\xA0",
  4733. 'dArr;' => "\xE2\x87\x93",
  4734. 'darr;' => "\xE2\x86\x93",
  4735. 'deg' => "\xC2\xB0",
  4736. 'deg;' => "\xC2\xB0",
  4737. 'Delta;' => "\xCE\x94",
  4738. 'delta;' => "\xCE\xB4",
  4739. 'diams;' => "\xE2\x99\xA6",
  4740. 'divide' => "\xC3\xB7",
  4741. 'divide;' => "\xC3\xB7",
  4742. 'Eacute' => "\xC3\x89",
  4743. 'eacute' => "\xC3\xA9",
  4744. 'Eacute;' => "\xC3\x89",
  4745. 'eacute;' => "\xC3\xA9",
  4746. 'Ecirc' => "\xC3\x8A",
  4747. 'ecirc' => "\xC3\xAA",
  4748. 'Ecirc;' => "\xC3\x8A",
  4749. 'ecirc;' => "\xC3\xAA",
  4750. 'Egrave' => "\xC3\x88",
  4751. 'egrave' => "\xC3\xA8",
  4752. 'Egrave;' => "\xC3\x88",
  4753. 'egrave;' => "\xC3\xA8",
  4754. 'empty;' => "\xE2\x88\x85",
  4755. 'emsp;' => "\xE2\x80\x83",
  4756. 'ensp;' => "\xE2\x80\x82",
  4757. 'Epsilon;' => "\xCE\x95",
  4758. 'epsilon;' => "\xCE\xB5",
  4759. 'equiv;' => "\xE2\x89\xA1",
  4760. 'Eta;' => "\xCE\x97",
  4761. 'eta;' => "\xCE\xB7",
  4762. 'ETH' => "\xC3\x90",
  4763. 'eth' => "\xC3\xB0",
  4764. 'ETH;' => "\xC3\x90",
  4765. 'eth;' => "\xC3\xB0",
  4766. 'Euml' => "\xC3\x8B",
  4767. 'euml' => "\xC3\xAB",
  4768. 'Euml;' => "\xC3\x8B",
  4769. 'euml;' => "\xC3\xAB",
  4770. 'euro;' => "\xE2\x82\xAC",
  4771. 'exist;' => "\xE2\x88\x83",
  4772. 'fnof;' => "\xC6\x92",
  4773. 'forall;' => "\xE2\x88\x80",
  4774. 'frac12' => "\xC2\xBD",
  4775. 'frac12;' => "\xC2\xBD",
  4776. 'frac14' => "\xC2\xBC",
  4777. 'frac14;' => "\xC2\xBC",
  4778. 'frac34' => "\xC2\xBE",
  4779. 'frac34;' => "\xC2\xBE",
  4780. 'frasl;' => "\xE2\x81\x84",
  4781. 'Gamma;' => "\xCE\x93",
  4782. 'gamma;' => "\xCE\xB3",
  4783. 'ge;' => "\xE2\x89\xA5",
  4784. 'GT' => "\x3E",
  4785. 'gt' => "\x3E",
  4786. 'GT;' => "\x3E",
  4787. 'gt;' => "\x3E",
  4788. 'hArr;' => "\xE2\x87\x94",
  4789. 'harr;' => "\xE2\x86\x94",
  4790. 'hearts;' => "\xE2\x99\xA5",
  4791. 'hellip;' => "\xE2\x80\xA6",
  4792. 'Iacute' => "\xC3\x8D",
  4793. 'iacute' => "\xC3\xAD",
  4794. 'Iacute;' => "\xC3\x8D",
  4795. 'iacute;' => "\xC3\xAD",
  4796. 'Icirc' => "\xC3\x8E",
  4797. 'icirc' => "\xC3\xAE",
  4798. 'Icirc;' => "\xC3\x8E",
  4799. 'icirc;' => "\xC3\xAE",
  4800. 'iexcl' => "\xC2\xA1",
  4801. 'iexcl;' => "\xC2\xA1",
  4802. 'Igrave' => "\xC3\x8C",
  4803. 'igrave' => "\xC3\xAC",
  4804. 'Igrave;' => "\xC3\x8C",
  4805. 'igrave;' => "\xC3\xAC",
  4806. 'image;' => "\xE2\x84\x91",
  4807. 'infin;' => "\xE2\x88\x9E",
  4808. 'int;' => "\xE2\x88\xAB",
  4809. 'Iota;' => "\xCE\x99",
  4810. 'iota;' => "\xCE\xB9",
  4811. 'iquest' => "\xC2\xBF",
  4812. 'iquest;' => "\xC2\xBF",
  4813. 'isin;' => "\xE2\x88\x88",
  4814. 'Iuml' => "\xC3\x8F",
  4815. 'iuml' => "\xC3\xAF",
  4816. 'Iuml;' => "\xC3\x8F",
  4817. 'iuml;' => "\xC3\xAF",
  4818. 'Kappa;' => "\xCE\x9A",
  4819. 'kappa;' => "\xCE\xBA",
  4820. 'Lambda;' => "\xCE\x9B",
  4821. 'lambda;' => "\xCE\xBB",
  4822. 'lang;' => "\xE3\x80\x88",
  4823. 'laquo' => "\xC2\xAB",
  4824. 'laquo;' => "\xC2\xAB",
  4825. 'lArr;' => "\xE2\x87\x90",
  4826. 'larr;' => "\xE2\x86\x90",
  4827. 'lceil;' => "\xE2\x8C\x88",
  4828. 'ldquo;' => "\xE2\x80\x9C",
  4829. 'le;' => "\xE2\x89\xA4",
  4830. 'lfloor;' => "\xE2\x8C\x8A",
  4831. 'lowast;' => "\xE2\x88\x97",
  4832. 'loz;' => "\xE2\x97\x8A",
  4833. 'lrm;' => "\xE2\x80\x8E",
  4834. 'lsaquo;' => "\xE2\x80\xB9",
  4835. 'lsquo;' => "\xE2\x80\x98",
  4836. 'LT' => "\x3C",
  4837. 'lt' => "\x3C",
  4838. 'LT;' => "\x3C",
  4839. 'lt;' => "\x3C",
  4840. 'macr' => "\xC2\xAF",
  4841. 'macr;' => "\xC2\xAF",
  4842. 'mdash;' => "\xE2\x80\x94",
  4843. 'micro' => "\xC2\xB5",
  4844. 'micro;' => "\xC2\xB5",
  4845. 'middot' => "\xC2\xB7",
  4846. 'middot;' => "\xC2\xB7",
  4847. 'minus;' => "\xE2\x88\x92",
  4848. 'Mu;' => "\xCE\x9C",
  4849. 'mu;' => "\xCE\xBC",
  4850. 'nabla;' => "\xE2\x88\x87",
  4851. 'nbsp' => "\xC2\xA0",
  4852. 'nbsp;' => "\xC2\xA0",
  4853. 'ndash;' => "\xE2\x80\x93",
  4854. 'ne;' => "\xE2\x89\xA0",
  4855. 'ni;' => "\xE2\x88\x8B",
  4856. 'not' => "\xC2\xAC",
  4857. 'not;' => "\xC2\xAC",
  4858. 'notin;' => "\xE2\x88\x89",
  4859. 'nsub;' => "\xE2\x8A\x84",
  4860. 'Ntilde' => "\xC3\x91",
  4861. 'ntilde' => "\xC3\xB1",
  4862. 'Ntilde;' => "\xC3\x91",
  4863. 'ntilde;' => "\xC3\xB1",
  4864. 'Nu;' => "\xCE\x9D",
  4865. 'nu;' => "\xCE\xBD",
  4866. 'Oacute' => "\xC3\x93",
  4867. 'oacute' => "\xC3\xB3",
  4868. 'Oacute;' => "\xC3\x93",
  4869. 'oacute;' => "\xC3\xB3",
  4870. 'Ocirc' => "\xC3\x94",
  4871. 'ocirc' => "\xC3\xB4",
  4872. 'Ocirc;' => "\xC3\x94",
  4873. 'ocirc;' => "\xC3\xB4",
  4874. 'OElig;' => "\xC5\x92",
  4875. 'oelig;' => "\xC5\x93",
  4876. 'Ograve' => "\xC3\x92",
  4877. 'ograve' => "\xC3\xB2",
  4878. 'Ograve;' => "\xC3\x92",
  4879. 'ograve;' => "\xC3\xB2",
  4880. 'oline;' => "\xE2\x80\xBE",
  4881. 'Omega;' => "\xCE\xA9",
  4882. 'omega;' => "\xCF\x89",
  4883. 'Omicron;' => "\xCE\x9F",
  4884. 'omicron;' => "\xCE\xBF",
  4885. 'oplus;' => "\xE2\x8A\x95",
  4886. 'or;' => "\xE2\x88\xA8",
  4887. 'ordf' => "\xC2\xAA",
  4888. 'ordf;' => "\xC2\xAA",
  4889. 'ordm' => "\xC2\xBA",
  4890. 'ordm;' => "\xC2\xBA",
  4891. 'Oslash' => "\xC3\x98",
  4892. 'oslash' => "\xC3\xB8",
  4893. 'Oslash;' => "\xC3\x98",
  4894. 'oslash;' => "\xC3\xB8",
  4895. 'Otilde' => "\xC3\x95",
  4896. 'otilde' => "\xC3\xB5",
  4897. 'Otilde;' => "\xC3\x95",
  4898. 'otilde;' => "\xC3\xB5",
  4899. 'otimes;' => "\xE2\x8A\x97",
  4900. 'Ouml' => "\xC3\x96",
  4901. 'ouml' => "\xC3\xB6",
  4902. 'Ouml;' => "\xC3\x96",
  4903. 'ouml;' => "\xC3\xB6",
  4904. 'para' => "\xC2\xB6",
  4905. 'para;' => "\xC2\xB6",
  4906. 'part;' => "\xE2\x88\x82",
  4907. 'permil;' => "\xE2\x80\xB0",
  4908. 'perp;' => "\xE2\x8A\xA5",
  4909. 'Phi;' => "\xCE\xA6",
  4910. 'phi;' => "\xCF\x86",
  4911. 'Pi;' => "\xCE\xA0",
  4912. 'pi;' => "\xCF\x80",
  4913. 'piv;' => "\xCF\x96",
  4914. 'plusmn' => "\xC2\xB1",
  4915. 'plusmn;' => "\xC2\xB1",
  4916. 'pound' => "\xC2\xA3",
  4917. 'pound;' => "\xC2\xA3",
  4918. 'Prime;' => "\xE2\x80\xB3",
  4919. 'prime;' => "\xE2\x80\xB2",
  4920. 'prod;' => "\xE2\x88\x8F",
  4921. 'prop;' => "\xE2\x88\x9D",
  4922. 'Psi;' => "\xCE\xA8",
  4923. 'psi;' => "\xCF\x88",
  4924. 'QUOT' => "\x22",
  4925. 'quot' => "\x22",
  4926. 'QUOT;' => "\x22",
  4927. 'quot;' => "\x22",
  4928. 'radic;' => "\xE2\x88\x9A",
  4929. 'rang;' => "\xE3\x80\x89",
  4930. 'raquo' => "\xC2\xBB",
  4931. 'raquo;' => "\xC2\xBB",
  4932. 'rArr;' => "\xE2\x87\x92",
  4933. 'rarr;' => "\xE2\x86\x92",
  4934. 'rceil;' => "\xE2\x8C\x89",
  4935. 'rdquo;' => "\xE2\x80\x9D",
  4936. 'real;' => "\xE2\x84\x9C",
  4937. 'REG' => "\xC2\xAE",
  4938. 'reg' => "\xC2\xAE",
  4939. 'REG;' => "\xC2\xAE",
  4940. 'reg;' => "\xC2\xAE",
  4941. 'rfloor;' => "\xE2\x8C\x8B",
  4942. 'Rho;' => "\xCE\xA1",
  4943. 'rho;' => "\xCF\x81",
  4944. 'rlm;' => "\xE2\x80\x8F",
  4945. 'rsaquo;' => "\xE2\x80\xBA",
  4946. 'rsquo;' => "\xE2\x80\x99",
  4947. 'sbquo;' => "\xE2\x80\x9A",
  4948. 'Scaron;' => "\xC5\xA0",
  4949. 'scaron;' => "\xC5\xA1",
  4950. 'sdot;' => "\xE2\x8B\x85",
  4951. 'sect' => "\xC2\xA7",
  4952. 'sect;' => "\xC2\xA7",
  4953. 'shy' => "\xC2\xAD",
  4954. 'shy;' => "\xC2\xAD",
  4955. 'Sigma;' => "\xCE\xA3",
  4956. 'sigma;' => "\xCF\x83",
  4957. 'sigmaf;' => "\xCF\x82",
  4958. 'sim;' => "\xE2\x88\xBC",
  4959. 'spades;' => "\xE2\x99\xA0",
  4960. 'sub;' => "\xE2\x8A\x82",
  4961. 'sube;' => "\xE2\x8A\x86",
  4962. 'sum;' => "\xE2\x88\x91",
  4963. 'sup;' => "\xE2\x8A\x83",
  4964. 'sup1' => "\xC2\xB9",
  4965. 'sup1;' => "\xC2\xB9",
  4966. 'sup2' => "\xC2\xB2",
  4967. 'sup2;' => "\xC2\xB2",
  4968. 'sup3' => "\xC2\xB3",
  4969. 'sup3;' => "\xC2\xB3",
  4970. 'supe;' => "\xE2\x8A\x87",
  4971. 'szlig' => "\xC3\x9F",
  4972. 'szlig;' => "\xC3\x9F",
  4973. 'Tau;' => "\xCE\xA4",
  4974. 'tau;' => "\xCF\x84",
  4975. 'there4;' => "\xE2\x88\xB4",
  4976. 'Theta;' => "\xCE\x98",
  4977. 'theta;' => "\xCE\xB8",
  4978. 'thetasym;' => "\xCF\x91",
  4979. 'thinsp;' => "\xE2\x80\x89",
  4980. 'THORN' => "\xC3\x9E",
  4981. 'thorn' => "\xC3\xBE",
  4982. 'THORN;' => "\xC3\x9E",
  4983. 'thorn;' => "\xC3\xBE",
  4984. 'tilde;' => "\xCB\x9C",
  4985. 'times' => "\xC3\x97",
  4986. 'times;' => "\xC3\x97",
  4987. 'TRADE;' => "\xE2\x84\xA2",
  4988. 'trade;' => "\xE2\x84\xA2",
  4989. 'Uacute' => "\xC3\x9A",
  4990. 'uacute' => "\xC3\xBA",
  4991. 'Uacute;' => "\xC3\x9A",
  4992. 'uacute;' => "\xC3\xBA",
  4993. 'uArr;' => "\xE2\x87\x91",
  4994. 'uarr;' => "\xE2\x86\x91",
  4995. 'Ucirc' => "\xC3\x9B",
  4996. 'ucirc' => "\xC3\xBB",
  4997. 'Ucirc;' => "\xC3\x9B",
  4998. 'ucirc;' => "\xC3\xBB",
  4999. 'Ugrave' => "\xC3\x99",
  5000. 'ugrave' => "\xC3\xB9",
  5001. 'Ugrave;' => "\xC3\x99",
  5002. 'ugrave;' => "\xC3\xB9",
  5003. 'uml' => "\xC2\xA8",
  5004. 'uml;' => "\xC2\xA8",
  5005. 'upsih;' => "\xCF\x92",
  5006. 'Upsilon;' => "\xCE\xA5",
  5007. 'upsilon;' => "\xCF\x85",
  5008. 'Uuml' => "\xC3\x9C",
  5009. 'uuml' => "\xC3\xBC",
  5010. 'Uuml;' => "\xC3\x9C",
  5011. 'uuml;' => "\xC3\xBC",
  5012. 'weierp;' => "\xE2\x84\x98",
  5013. 'Xi;' => "\xCE\x9E",
  5014. 'xi;' => "\xCE\xBE",
  5015. 'Yacute' => "\xC3\x9D",
  5016. 'yacute' => "\xC3\xBD",
  5017. 'Yacute;' => "\xC3\x9D",
  5018. 'yacute;' => "\xC3\xBD",
  5019. 'yen' => "\xC2\xA5",
  5020. 'yen;' => "\xC2\xA5",
  5021. 'yuml' => "\xC3\xBF",
  5022. 'Yuml;' => "\xC5\xB8",
  5023. 'yuml;' => "\xC3\xBF",
  5024. 'Zeta;' => "\xCE\x96",
  5025. 'zeta;' => "\xCE\xB6",
  5026. 'zwj;' => "\xE2\x80\x8D",
  5027. 'zwnj;' => "\xE2\x80\x8C"
  5028. );
  5029. for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
  5030. {
  5031. $consumed = substr($this->consumed, 1);
  5032. if (isset($entities[$consumed]))
  5033. {
  5034. $match = $consumed;
  5035. }
  5036. }
  5037. if ($match !== null)
  5038. {
  5039. $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
  5040. $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
  5041. }
  5042. break;
  5043. }
  5044. }
  5045. }
  5046. /**
  5047. * Handles everything related to enclosures (including Media RSS and iTunes RSS)
  5048. *
  5049. * Used by {@see SimplePie_Item::get_enclosure()} and {@see SimplePie_Item::get_enclosures()}
  5050. *
  5051. * This class can be overloaded with {@see SimplePie::set_enclosure_class()}
  5052. *
  5053. * @package SimplePie
  5054. * @subpackage API
  5055. */
  5056. class SimplePie_Enclosure
  5057. {
  5058. /**
  5059. * @var string
  5060. * @see get_bitrate()
  5061. */
  5062. var $bitrate;
  5063. /**
  5064. * @var array
  5065. * @see get_captions()
  5066. */
  5067. var $captions;
  5068. /**
  5069. * @var array
  5070. * @see get_categories()
  5071. */
  5072. var $categories;
  5073. /**
  5074. * @var int
  5075. * @see get_channels()
  5076. */
  5077. var $channels;
  5078. /**
  5079. * @var SimplePie_Copyright
  5080. * @see get_copyright()
  5081. */
  5082. var $copyright;
  5083. /**
  5084. * @var array
  5085. * @see get_credits()
  5086. */
  5087. var $credits;
  5088. /**
  5089. * @var string
  5090. * @see get_description()
  5091. */
  5092. var $description;
  5093. /**
  5094. * @var int
  5095. * @see get_duration()
  5096. */
  5097. var $duration;
  5098. /**
  5099. * @var string
  5100. * @see get_expression()
  5101. */
  5102. var $expression;
  5103. /**
  5104. * @var string
  5105. * @see get_framerate()
  5106. */
  5107. var $framerate;
  5108. /**
  5109. * @var string
  5110. * @see get_handler()
  5111. */
  5112. var $handler;
  5113. /**
  5114. * @var array
  5115. * @see get_hashes()
  5116. */
  5117. var $hashes;
  5118. /**
  5119. * @var string
  5120. * @see get_height()
  5121. */
  5122. var $height;
  5123. /**
  5124. * @deprecated
  5125. * @var null
  5126. */
  5127. var $javascript;
  5128. /**
  5129. * @var array
  5130. * @see get_keywords()
  5131. */
  5132. var $keywords;
  5133. /**
  5134. * @var string
  5135. * @see get_language()
  5136. */
  5137. var $lang;
  5138. /**
  5139. * @var string
  5140. * @see get_length()
  5141. */
  5142. var $length;
  5143. /**
  5144. * @var string
  5145. * @see get_link()
  5146. */
  5147. var $link;
  5148. /**
  5149. * @var string
  5150. * @see get_medium()
  5151. */
  5152. var $medium;
  5153. /**
  5154. * @var string
  5155. * @see get_player()
  5156. */
  5157. var $player;
  5158. /**
  5159. * @var array
  5160. * @see get_ratings()
  5161. */
  5162. var $ratings;
  5163. /**
  5164. * @var array
  5165. * @see get_restrictions()
  5166. */
  5167. var $restrictions;
  5168. /**
  5169. * @var string
  5170. * @see get_sampling_rate()
  5171. */
  5172. var $samplingrate;
  5173. /**
  5174. * @var array
  5175. * @see get_thumbnails()
  5176. */
  5177. var $thumbnails;
  5178. /**
  5179. * @var string
  5180. * @see get_title()
  5181. */
  5182. var $title;
  5183. /**
  5184. * @var string
  5185. * @see get_type()
  5186. */
  5187. var $type;
  5188. /**
  5189. * @var string
  5190. * @see get_width()
  5191. */
  5192. var $width;
  5193. /**
  5194. * Constructor, used to input the data
  5195. *
  5196. * For documentation on all the parameters, see the corresponding
  5197. * properties and their accessors
  5198. *
  5199. * @uses idna_convert If available, this will convert an IDN
  5200. */
  5201. public function __construct($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null)
  5202. {
  5203. $this->bitrate = $bitrate;
  5204. $this->captions = $captions;
  5205. $this->categories = $categories;
  5206. $this->channels = $channels;
  5207. $this->copyright = $copyright;
  5208. $this->credits = $credits;
  5209. $this->description = $description;
  5210. $this->duration = $duration;
  5211. $this->expression = $expression;
  5212. $this->framerate = $framerate;
  5213. $this->hashes = $hashes;
  5214. $this->height = $height;
  5215. $this->keywords = $keywords;
  5216. $this->lang = $lang;
  5217. $this->length = $length;
  5218. $this->link = $link;
  5219. $this->medium = $medium;
  5220. $this->player = $player;
  5221. $this->ratings = $ratings;
  5222. $this->restrictions = $restrictions;
  5223. $this->samplingrate = $samplingrate;
  5224. $this->thumbnails = $thumbnails;
  5225. $this->title = $title;
  5226. $this->type = $type;
  5227. $this->width = $width;
  5228. if (class_exists('idna_convert'))
  5229. {
  5230. $idn = new idna_convert();
  5231. $parsed = SimplePie_Misc::parse_url($link);
  5232. $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
  5233. }
  5234. $this->handler = $this->get_handler(); // Needs to load last
  5235. }
  5236. /**
  5237. * String-ified version
  5238. *
  5239. * @return string
  5240. */
  5241. public function __toString()
  5242. {
  5243. // There is no $this->data here
  5244. return md5(serialize($this));
  5245. }
  5246. /**
  5247. * Get the bitrate
  5248. *
  5249. * @return string|null
  5250. */
  5251. public function get_bitrate()
  5252. {
  5253. if ($this->bitrate !== null)
  5254. {
  5255. return $this->bitrate;
  5256. }
  5257. else
  5258. {
  5259. return null;
  5260. }
  5261. }
  5262. /**
  5263. * Get a single caption
  5264. *
  5265. * @param int $key
  5266. * @return SimplePie_Caption|null
  5267. */
  5268. public function get_caption($key = 0)
  5269. {
  5270. $captions = $this->get_captions();
  5271. if (isset($captions[$key]))
  5272. {
  5273. return $captions[$key];
  5274. }
  5275. else
  5276. {
  5277. return null;
  5278. }
  5279. }
  5280. /**
  5281. * Get all captions
  5282. *
  5283. * @return array|null Array of {@see SimplePie_Caption} objects
  5284. */
  5285. public function get_captions()
  5286. {
  5287. if ($this->captions !== null)
  5288. {
  5289. return $this->captions;
  5290. }
  5291. else
  5292. {
  5293. return null;
  5294. }
  5295. }
  5296. /**
  5297. * Get a single category
  5298. *
  5299. * @param int $key
  5300. * @return SimplePie_Category|null
  5301. */
  5302. public function get_category($key = 0)
  5303. {
  5304. $categories = $this->get_categories();
  5305. if (isset($categories[$key]))
  5306. {
  5307. return $categories[$key];
  5308. }
  5309. else
  5310. {
  5311. return null;
  5312. }
  5313. }
  5314. /**
  5315. * Get all categories
  5316. *
  5317. * @return array|null Array of {@see SimplePie_Category} objects
  5318. */
  5319. public function get_categories()
  5320. {
  5321. if ($this->categories !== null)
  5322. {
  5323. return $this->categories;
  5324. }
  5325. else
  5326. {
  5327. return null;
  5328. }
  5329. }
  5330. /**
  5331. * Get the number of audio channels
  5332. *
  5333. * @return int|null
  5334. */
  5335. public function get_channels()
  5336. {
  5337. if ($this->channels !== null)
  5338. {
  5339. return $this->channels;
  5340. }
  5341. else
  5342. {
  5343. return null;
  5344. }
  5345. }
  5346. /**
  5347. * Get the copyright information
  5348. *
  5349. * @return SimplePie_Copyright|null
  5350. */
  5351. public function get_copyright()
  5352. {
  5353. if ($this->copyright !== null)
  5354. {
  5355. return $this->copyright;
  5356. }
  5357. else
  5358. {
  5359. return null;
  5360. }
  5361. }
  5362. /**
  5363. * Get a single credit
  5364. *
  5365. * @param int $key
  5366. * @return SimplePie_Credit|null
  5367. */
  5368. public function get_credit($key = 0)
  5369. {
  5370. $credits = $this->get_credits();
  5371. if (isset($credits[$key]))
  5372. {
  5373. return $credits[$key];
  5374. }
  5375. else
  5376. {
  5377. return null;
  5378. }
  5379. }
  5380. /**
  5381. * Get all credits
  5382. *
  5383. * @return array|null Array of {@see SimplePie_Credit} objects
  5384. */
  5385. public function get_credits()
  5386. {
  5387. if ($this->credits !== null)
  5388. {
  5389. return $this->credits;
  5390. }
  5391. else
  5392. {
  5393. return null;
  5394. }
  5395. }
  5396. /**
  5397. * Get the description of the enclosure
  5398. *
  5399. * @return string|null
  5400. */
  5401. public function get_description()
  5402. {
  5403. if ($this->description !== null)
  5404. {
  5405. return $this->description;
  5406. }
  5407. else
  5408. {
  5409. return null;
  5410. }
  5411. }
  5412. /**
  5413. * Get the duration of the enclosure
  5414. *
  5415. * @param string $convert Convert seconds into hh:mm:ss
  5416. * @return string|int|null 'hh:mm:ss' string if `$convert` was specified, otherwise integer (or null if none found)
  5417. */
  5418. public function get_duration($convert = false)
  5419. {
  5420. if ($this->duration !== null)
  5421. {
  5422. if ($convert)
  5423. {
  5424. $time = SimplePie_Misc::time_hms($this->duration);
  5425. return $time;
  5426. }
  5427. else
  5428. {
  5429. return $this->duration;
  5430. }
  5431. }
  5432. else
  5433. {
  5434. return null;
  5435. }
  5436. }
  5437. /**
  5438. * Get the expression
  5439. *
  5440. * @return string Probably one of 'sample', 'full', 'nonstop', 'clip'. Defaults to 'full'
  5441. */
  5442. public function get_expression()
  5443. {
  5444. if ($this->expression !== null)
  5445. {
  5446. return $this->expression;
  5447. }
  5448. else
  5449. {
  5450. return 'full';
  5451. }
  5452. }
  5453. /**
  5454. * Get the file extension
  5455. *
  5456. * @return string|null
  5457. */
  5458. public function get_extension()
  5459. {
  5460. if ($this->link !== null)
  5461. {
  5462. $url = SimplePie_Misc::parse_url($this->link);
  5463. if ($url['path'] !== '')
  5464. {
  5465. return pathinfo($url['path'], PATHINFO_EXTENSION);
  5466. }
  5467. }
  5468. return null;
  5469. }
  5470. /**
  5471. * Get the framerate (in frames-per-second)
  5472. *
  5473. * @return string|null
  5474. */
  5475. public function get_framerate()
  5476. {
  5477. if ($this->framerate !== null)
  5478. {
  5479. return $this->framerate;
  5480. }
  5481. else
  5482. {
  5483. return null;
  5484. }
  5485. }
  5486. /**
  5487. * Get the preferred handler
  5488. *
  5489. * @return string|null One of 'flash', 'fmedia', 'quicktime', 'wmedia', 'mp3'
  5490. */
  5491. public function get_handler()
  5492. {
  5493. return $this->get_real_type(true);
  5494. }
  5495. /**
  5496. * Get a single hash
  5497. *
  5498. * @link http://www.rssboard.org/media-rss#media-hash
  5499. * @param int $key
  5500. * @return string|null Hash as per `media:hash`, prefixed with "$algo:"
  5501. */
  5502. public function get_hash($key = 0)
  5503. {
  5504. $hashes = $this->get_hashes();
  5505. if (isset($hashes[$key]))
  5506. {
  5507. return $hashes[$key];
  5508. }
  5509. else
  5510. {
  5511. return null;
  5512. }
  5513. }
  5514. /**
  5515. * Get all credits
  5516. *
  5517. * @return array|null Array of strings, see {@see get_hash()}
  5518. */
  5519. public function get_hashes()
  5520. {
  5521. if ($this->hashes !== null)
  5522. {
  5523. return $this->hashes;
  5524. }
  5525. else
  5526. {
  5527. return null;
  5528. }
  5529. }
  5530. /**
  5531. * Get the height
  5532. *
  5533. * @return string|null
  5534. */
  5535. public function get_height()
  5536. {
  5537. if ($this->height !== null)
  5538. {
  5539. return $this->height;
  5540. }
  5541. else
  5542. {
  5543. return null;
  5544. }
  5545. }
  5546. /**
  5547. * Get the language
  5548. *
  5549. * @link http://tools.ietf.org/html/rfc3066
  5550. * @return string|null Language code as per RFC 3066
  5551. */
  5552. public function get_language()
  5553. {
  5554. if ($this->lang !== null)
  5555. {
  5556. return $this->lang;
  5557. }
  5558. else
  5559. {
  5560. return null;
  5561. }
  5562. }
  5563. /**
  5564. * Get a single keyword
  5565. *
  5566. * @param int $key
  5567. * @return string|null
  5568. */
  5569. public function get_keyword($key = 0)
  5570. {
  5571. $keywords = $this->get_keywords();
  5572. if (isset($keywords[$key]))
  5573. {
  5574. return $keywords[$key];
  5575. }
  5576. else
  5577. {
  5578. return null;
  5579. }
  5580. }
  5581. /**
  5582. * Get all keywords
  5583. *
  5584. * @return array|null Array of strings
  5585. */
  5586. public function get_keywords()
  5587. {
  5588. if ($this->keywords !== null)
  5589. {
  5590. return $this->keywords;
  5591. }
  5592. else
  5593. {
  5594. return null;
  5595. }
  5596. }
  5597. /**
  5598. * Get length
  5599. *
  5600. * @return float Length in bytes
  5601. */
  5602. public function get_length()
  5603. {
  5604. if ($this->length !== null)
  5605. {
  5606. return $this->length;
  5607. }
  5608. else
  5609. {
  5610. return null;
  5611. }
  5612. }
  5613. /**
  5614. * Get the URL
  5615. *
  5616. * @return string|null
  5617. */
  5618. public function get_link()
  5619. {
  5620. if ($this->link !== null)
  5621. {
  5622. return urldecode($this->link);
  5623. }
  5624. else
  5625. {
  5626. return null;
  5627. }
  5628. }
  5629. /**
  5630. * Get the medium
  5631. *
  5632. * @link http://www.rssboard.org/media-rss#media-content
  5633. * @return string|null Should be one of 'image', 'audio', 'video', 'document', 'executable'
  5634. */
  5635. public function get_medium()
  5636. {
  5637. if ($this->medium !== null)
  5638. {
  5639. return $this->medium;
  5640. }
  5641. else
  5642. {
  5643. return null;
  5644. }
  5645. }
  5646. /**
  5647. * Get the player URL
  5648. *
  5649. * Typically the same as {@see get_permalink()}
  5650. * @return string|null Player URL
  5651. */
  5652. public function get_player()
  5653. {
  5654. if ($this->player !== null)
  5655. {
  5656. return $this->player;
  5657. }
  5658. else
  5659. {
  5660. return null;
  5661. }
  5662. }
  5663. /**
  5664. * Get a single rating
  5665. *
  5666. * @param int $key
  5667. * @return SimplePie_Rating|null
  5668. */
  5669. public function get_rating($key = 0)
  5670. {
  5671. $ratings = $this->get_ratings();
  5672. if (isset($ratings[$key]))
  5673. {
  5674. return $ratings[$key];
  5675. }
  5676. else
  5677. {
  5678. return null;
  5679. }
  5680. }
  5681. /**
  5682. * Get all ratings
  5683. *
  5684. * @return array|null Array of {@see SimplePie_Rating} objects
  5685. */
  5686. public function get_ratings()
  5687. {
  5688. if ($this->ratings !== null)
  5689. {
  5690. return $this->ratings;
  5691. }
  5692. else
  5693. {
  5694. return null;
  5695. }
  5696. }
  5697. /**
  5698. * Get a single restriction
  5699. *
  5700. * @param int $key
  5701. * @return SimplePie_Restriction|null
  5702. */
  5703. public function get_restriction($key = 0)
  5704. {
  5705. $restrictions = $this->get_restrictions();
  5706. if (isset($restrictions[$key]))
  5707. {
  5708. return $restrictions[$key];
  5709. }
  5710. else
  5711. {
  5712. return null;
  5713. }
  5714. }
  5715. /**
  5716. * Get all restrictions
  5717. *
  5718. * @return array|null Array of {@see SimplePie_Restriction} objects
  5719. */
  5720. public function get_restrictions()
  5721. {
  5722. if ($this->restrictions !== null)
  5723. {
  5724. return $this->restrictions;
  5725. }
  5726. else
  5727. {
  5728. return null;
  5729. }
  5730. }
  5731. /**
  5732. * Get the sampling rate (in kHz)
  5733. *
  5734. * @return string|null
  5735. */
  5736. public function get_sampling_rate()
  5737. {
  5738. if ($this->samplingrate !== null)
  5739. {
  5740. return $this->samplingrate;
  5741. }
  5742. else
  5743. {
  5744. return null;
  5745. }
  5746. }
  5747. /**
  5748. * Get the file size (in MiB)
  5749. *
  5750. * @return float|null File size in mebibytes (1048 bytes)
  5751. */
  5752. public function get_size()
  5753. {
  5754. $length = $this->get_length();
  5755. if ($length !== null)
  5756. {
  5757. return round($length/1048576, 2);
  5758. }
  5759. else
  5760. {
  5761. return null;
  5762. }
  5763. }
  5764. /**
  5765. * Get a single thumbnail
  5766. *
  5767. * @param int $key
  5768. * @return string|null Thumbnail URL
  5769. */
  5770. public function get_thumbnail($key = 0)
  5771. {
  5772. $thumbnails = $this->get_thumbnails();
  5773. if (isset($thumbnails[$key]))
  5774. {
  5775. return $thumbnails[$key];
  5776. }
  5777. else
  5778. {
  5779. return null;
  5780. }
  5781. }
  5782. /**
  5783. * Get all thumbnails
  5784. *
  5785. * @return array|null Array of thumbnail URLs
  5786. */
  5787. public function get_thumbnails()
  5788. {
  5789. if ($this->thumbnails !== null)
  5790. {
  5791. return $this->thumbnails;
  5792. }
  5793. else
  5794. {
  5795. return null;
  5796. }
  5797. }
  5798. /**
  5799. * Get the title
  5800. *
  5801. * @return string|null
  5802. */
  5803. public function get_title()
  5804. {
  5805. if ($this->title !== null)
  5806. {
  5807. return $this->title;
  5808. }
  5809. else
  5810. {
  5811. return null;
  5812. }
  5813. }
  5814. /**
  5815. * Get mimetype of the enclosure
  5816. *
  5817. * @see get_real_type()
  5818. * @return string|null MIME type
  5819. */
  5820. public function get_type()
  5821. {
  5822. if ($this->type !== null)
  5823. {
  5824. return $this->type;
  5825. }
  5826. else
  5827. {
  5828. return null;
  5829. }
  5830. }
  5831. /**
  5832. * Get the width
  5833. *
  5834. * @return string|null
  5835. */
  5836. public function get_width()
  5837. {
  5838. if ($this->width !== null)
  5839. {
  5840. return $this->width;
  5841. }
  5842. else
  5843. {
  5844. return null;
  5845. }
  5846. }
  5847. /**
  5848. * Embed the enclosure using `<embed>`
  5849. *
  5850. * @deprecated Use the second parameter to {@see embed} instead
  5851. *
  5852. * @param array|string $options See first paramter to {@see embed}
  5853. * @return string HTML string to output
  5854. */
  5855. public function native_embed($options='')
  5856. {
  5857. return $this->embed($options, true);
  5858. }
  5859. /**
  5860. * Embed the enclosure using Javascript
  5861. *
  5862. * `$options` is an array or comma-separated key:value string, with the
  5863. * following properties:
  5864. *
  5865. * - `alt` (string): Alternate content for when an end-user does not have
  5866. * the appropriate handler installed or when a file type is
  5867. * unsupported. Can be any text or HTML. Defaults to blank.
  5868. * - `altclass` (string): If a file type is unsupported, the end-user will
  5869. * see the alt text (above) linked directly to the content. That link
  5870. * will have this value as its class name. Defaults to blank.
  5871. * - `audio` (string): This is an image that should be used as a
  5872. * placeholder for audio files before they're loaded (QuickTime-only).
  5873. * Can be any relative or absolute URL. Defaults to blank.
  5874. * - `bgcolor` (string): The background color for the media, if not
  5875. * already transparent. Defaults to `#ffffff`.
  5876. * - `height` (integer): The height of the embedded media. Accepts any
  5877. * numeric pixel value (such as `360`) or `auto`. Defaults to `auto`,
  5878. * and it is recommended that you use this default.
  5879. * - `loop` (boolean): Do you want the media to loop when its done?
  5880. * Defaults to `false`.
  5881. * - `mediaplayer` (string): The location of the included
  5882. * `mediaplayer.swf` file. This allows for the playback of Flash Video
  5883. * (`.flv`) files, and is the default handler for non-Odeo MP3's.
  5884. * Defaults to blank.
  5885. * - `video` (string): This is an image that should be used as a
  5886. * placeholder for video files before they're loaded (QuickTime-only).
  5887. * Can be any relative or absolute URL. Defaults to blank.
  5888. * - `width` (integer): The width of the embedded media. Accepts any
  5889. * numeric pixel value (such as `480`) or `auto`. Defaults to `auto`,
  5890. * and it is recommended that you use this default.
  5891. * - `widescreen` (boolean): Is the enclosure widescreen or standard?
  5892. * This applies only to video enclosures, and will automatically resize
  5893. * the content appropriately. Defaults to `false`, implying 4:3 mode.
  5894. *
  5895. * Note: Non-widescreen (4:3) mode with `width` and `height` set to `auto`
  5896. * will default to 480x360 video resolution. Widescreen (16:9) mode with
  5897. * `width` and `height` set to `auto` will default to 480x270 video resolution.
  5898. *
  5899. * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
  5900. * @param array|string $options Comma-separated key:value list, or array
  5901. * @param bool $native Use `<embed>`
  5902. * @return string HTML string to output
  5903. */
  5904. public function embed($options = '', $native = false)
  5905. {
  5906. // Set up defaults
  5907. $audio = '';
  5908. $video = '';
  5909. $alt = '';
  5910. $altclass = '';
  5911. $loop = 'false';
  5912. $width = 'auto';
  5913. $height = 'auto';
  5914. $bgcolor = '#ffffff';
  5915. $mediaplayer = '';
  5916. $widescreen = false;
  5917. $handler = $this->get_handler();
  5918. $type = $this->get_real_type();
  5919. // Process options and reassign values as necessary
  5920. if (is_array($options))
  5921. {
  5922. extract($options);
  5923. }
  5924. else
  5925. {
  5926. $options = explode(',', $options);
  5927. foreach($options as $option)
  5928. {
  5929. $opt = explode(':', $option, 2);
  5930. if (isset($opt[0], $opt[1]))
  5931. {
  5932. $opt[0] = trim($opt[0]);
  5933. $opt[1] = trim($opt[1]);
  5934. switch ($opt[0])
  5935. {
  5936. case 'audio':
  5937. $audio = $opt[1];
  5938. break;
  5939. case 'video':
  5940. $video = $opt[1];
  5941. break;
  5942. case 'alt':
  5943. $alt = $opt[1];
  5944. break;
  5945. case 'altclass':
  5946. $altclass = $opt[1];
  5947. break;
  5948. case 'loop':
  5949. $loop = $opt[1];
  5950. break;
  5951. case 'width':
  5952. $width = $opt[1];
  5953. break;
  5954. case 'height':
  5955. $height = $opt[1];
  5956. break;
  5957. case 'bgcolor':
  5958. $bgcolor = $opt[1];
  5959. break;
  5960. case 'mediaplayer':
  5961. $mediaplayer = $opt[1];
  5962. break;
  5963. case 'widescreen':
  5964. $widescreen = $opt[1];
  5965. break;
  5966. }
  5967. }
  5968. }
  5969. }
  5970. $mime = explode('/', $type, 2);
  5971. $mime = $mime[0];
  5972. // Process values for 'auto'
  5973. if ($width === 'auto')
  5974. {
  5975. if ($mime === 'video')
  5976. {
  5977. if ($height === 'auto')
  5978. {
  5979. $width = 480;
  5980. }
  5981. elseif ($widescreen)
  5982. {
  5983. $width = round((intval($height)/9)*16);
  5984. }
  5985. else
  5986. {
  5987. $width = round((intval($height)/3)*4);
  5988. }
  5989. }
  5990. else
  5991. {
  5992. $width = '100%';
  5993. }
  5994. }
  5995. if ($height === 'auto')
  5996. {
  5997. if ($mime === 'audio')
  5998. {
  5999. $height = 0;
  6000. }
  6001. elseif ($mime === 'video')
  6002. {
  6003. if ($width === 'auto')
  6004. {
  6005. if ($widescreen)
  6006. {
  6007. $height = 270;
  6008. }
  6009. else
  6010. {
  6011. $height = 360;
  6012. }
  6013. }
  6014. elseif ($widescreen)
  6015. {
  6016. $height = round((intval($width)/16)*9);
  6017. }
  6018. else
  6019. {
  6020. $height = round((intval($width)/4)*3);
  6021. }
  6022. }
  6023. else
  6024. {
  6025. $height = 376;
  6026. }
  6027. }
  6028. elseif ($mime === 'audio')
  6029. {
  6030. $height = 0;
  6031. }
  6032. // Set proper placeholder value
  6033. if ($mime === 'audio')
  6034. {
  6035. $placeholder = $audio;
  6036. }
  6037. elseif ($mime === 'video')
  6038. {
  6039. $placeholder = $video;
  6040. }
  6041. $embed = '';
  6042. // Flash
  6043. if ($handler === 'flash')
  6044. {
  6045. if ($native)
  6046. {
  6047. $embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
  6048. }
  6049. else
  6050. {
  6051. $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
  6052. }
  6053. }
  6054. // Flash Media Player file types.
  6055. // Preferred handler for MP3 file types.
  6056. elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
  6057. {
  6058. $height += 20;
  6059. if ($native)
  6060. {
  6061. $embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>";
  6062. }
  6063. else
  6064. {
  6065. $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
  6066. }
  6067. }
  6068. // QuickTime 7 file types. Need to test with QuickTime 6.
  6069. // Only handle MP3's if the Flash Media Player is not present.
  6070. elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
  6071. {
  6072. $height += 16;
  6073. if ($native)
  6074. {
  6075. if ($placeholder !== '')
  6076. {
  6077. $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
  6078. }
  6079. else
  6080. {
  6081. $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
  6082. }
  6083. }
  6084. else
  6085. {
  6086. $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
  6087. }
  6088. }
  6089. // Windows Media
  6090. elseif ($handler === 'wmedia')
  6091. {
  6092. $height += 45;
  6093. if ($native)
  6094. {
  6095. $embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
  6096. }
  6097. else
  6098. {
  6099. $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
  6100. }
  6101. }
  6102. // Everything else
  6103. else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
  6104. return $embed;
  6105. }
  6106. /**
  6107. * Get the real media type
  6108. *
  6109. * Often, feeds lie to us, necessitating a bit of deeper inspection. This
  6110. * converts types to their canonical representations based on the file
  6111. * extension
  6112. *
  6113. * @see get_type()
  6114. * @param bool $find_handler Internal use only, use {@see get_handler()} instead
  6115. * @return string MIME type
  6116. */
  6117. public function get_real_type($find_handler = false)
  6118. {
  6119. // Mime-types by handler.
  6120. $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
  6121. $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
  6122. $types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime
  6123. $types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media
  6124. $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
  6125. if ($this->get_type() !== null)
  6126. {
  6127. $type = strtolower($this->type);
  6128. }
  6129. else
  6130. {
  6131. $type = null;
  6132. }
  6133. // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
  6134. if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
  6135. {
  6136. switch (strtolower($this->get_extension()))
  6137. {
  6138. // Audio mime-types
  6139. case 'aac':
  6140. case 'adts':
  6141. $type = 'audio/acc';
  6142. break;
  6143. case 'aif':
  6144. case 'aifc':
  6145. case 'aiff':
  6146. case 'cdda':
  6147. $type = 'audio/aiff';
  6148. break;
  6149. case 'bwf':
  6150. $type = 'audio/wav';
  6151. break;
  6152. case 'kar':
  6153. case 'mid':
  6154. case 'midi':
  6155. case 'smf':
  6156. $type = 'audio/midi';
  6157. break;
  6158. case 'm4a':
  6159. $type = 'audio/x-m4a';
  6160. break;
  6161. case 'mp3':
  6162. case 'swa':
  6163. $type = 'audio/mp3';
  6164. break;
  6165. case 'wav':
  6166. $type = 'audio/wav';
  6167. break;
  6168. case 'wax':
  6169. $type = 'audio/x-ms-wax';
  6170. break;
  6171. case 'wma':
  6172. $type = 'audio/x-ms-wma';
  6173. break;
  6174. // Video mime-types
  6175. case '3gp':
  6176. case '3gpp':
  6177. $type = 'video/3gpp';
  6178. break;
  6179. case '3g2':
  6180. case '3gp2':
  6181. $type = 'video/3gpp2';
  6182. break;
  6183. case 'asf':
  6184. $type = 'video/x-ms-asf';
  6185. break;
  6186. case 'flv':
  6187. $type = 'video/x-flv';
  6188. break;
  6189. case 'm1a':
  6190. case 'm1s':
  6191. case 'm1v':
  6192. case 'm15':
  6193. case 'm75':
  6194. case 'mp2':
  6195. case 'mpa':
  6196. case 'mpeg':
  6197. case 'mpg':
  6198. case 'mpm':
  6199. case 'mpv':
  6200. $type = 'video/mpeg';
  6201. break;
  6202. case 'm4v':
  6203. $type = 'video/x-m4v';
  6204. break;
  6205. case 'mov':
  6206. case 'qt':
  6207. $type = 'video/quicktime';
  6208. break;
  6209. case 'mp4':
  6210. case 'mpg4':
  6211. $type = 'video/mp4';
  6212. break;
  6213. case 'sdv':
  6214. $type = 'video/sd-video';
  6215. break;
  6216. case 'wm':
  6217. $type = 'video/x-ms-wm';
  6218. break;
  6219. case 'wmv':
  6220. $type = 'video/x-ms-wmv';
  6221. break;
  6222. case 'wvx':
  6223. $type = 'video/x-ms-wvx';
  6224. break;
  6225. // Flash mime-types
  6226. case 'spl':
  6227. $type = 'application/futuresplash';
  6228. break;
  6229. case 'swf':
  6230. $type = 'application/x-shockwave-flash';
  6231. break;
  6232. }
  6233. }
  6234. if ($find_handler)
  6235. {
  6236. if (in_array($type, $types_flash))
  6237. {
  6238. return 'flash';
  6239. }
  6240. elseif (in_array($type, $types_fmedia))
  6241. {
  6242. return 'fmedia';
  6243. }
  6244. elseif (in_array($type, $types_quicktime))
  6245. {
  6246. return 'quicktime';
  6247. }
  6248. elseif (in_array($type, $types_wmedia))
  6249. {
  6250. return 'wmedia';
  6251. }
  6252. elseif (in_array($type, $types_mp3))
  6253. {
  6254. return 'mp3';
  6255. }
  6256. else
  6257. {
  6258. return null;
  6259. }
  6260. }
  6261. else
  6262. {
  6263. return $type;
  6264. }
  6265. }
  6266. }
  6267. /**
  6268. * General SimplePie exception class
  6269. *
  6270. * @package SimplePie
  6271. */
  6272. class SimplePie_Exception extends Exception
  6273. {
  6274. }
  6275. /**
  6276. * Used for fetching remote files and reading local files
  6277. *
  6278. * Supports HTTP 1.0 via cURL or fsockopen, with spotty HTTP 1.1 support
  6279. *
  6280. * This class can be overloaded with {@see SimplePie::set_file_class()}
  6281. *
  6282. * @package SimplePie
  6283. * @subpackage HTTP
  6284. * @todo Move to properly supporting RFC2616 (HTTP/1.1)
  6285. */
  6286. class SimplePie_File
  6287. {
  6288. var $url;
  6289. var $useragent;
  6290. var $success = true;
  6291. var $headers = array();
  6292. var $body;
  6293. var $status_code;
  6294. var $redirects = 0;
  6295. var $error;
  6296. var $method = SIMPLEPIE_FILE_SOURCE_NONE;
  6297. public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
  6298. {
  6299. if (class_exists('idna_convert'))
  6300. {
  6301. $idn = new idna_convert();
  6302. $parsed = SimplePie_Misc::parse_url($url);
  6303. $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
  6304. }
  6305. $this->url = $url;
  6306. $this->useragent = $useragent;
  6307. if (preg_match('/^http(s)?:\/\//i', $url))
  6308. {
  6309. if ($useragent === null)
  6310. {
  6311. $useragent = ini_get('user_agent');
  6312. $this->useragent = $useragent;
  6313. }
  6314. if (!is_array($headers))
  6315. {
  6316. $headers = array();
  6317. }
  6318. if (!$force_fsockopen && function_exists('curl_exec'))
  6319. {
  6320. $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
  6321. $fp = curl_init();
  6322. $headers2 = array();
  6323. foreach ($headers as $key => $value)
  6324. {
  6325. $headers2[] = "$key: $value";
  6326. }
  6327. if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
  6328. {
  6329. curl_setopt($fp, CURLOPT_ENCODING, '');
  6330. }
  6331. curl_setopt($fp, CURLOPT_URL, $url);
  6332. curl_setopt($fp, CURLOPT_HEADER, 1);
  6333. curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
  6334. curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
  6335. curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
  6336. curl_setopt($fp, CURLOPT_REFERER, $url);
  6337. curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
  6338. curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
  6339. if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
  6340. {
  6341. curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
  6342. curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
  6343. }
  6344. /* Enable Digest authentication and SSL -fox */
  6345. curl_setopt($fp, CURLOPT_SSL_VERIFYPEER, false);
  6346. curl_setopt($fp, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
  6347. $this->headers = curl_exec($fp);
  6348. if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
  6349. {
  6350. curl_setopt($fp, CURLOPT_ENCODING, 'none');
  6351. $this->headers = curl_exec($fp);
  6352. }
  6353. if (curl_errno($fp))
  6354. {
  6355. $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
  6356. $this->success = false;
  6357. }
  6358. else
  6359. {
  6360. $info = curl_getinfo($fp);
  6361. curl_close($fp);
  6362. $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
  6363. $this->headers = array_pop($this->headers);
  6364. $parser = new SimplePie_HTTP_Parser($this->headers);
  6365. if ($parser->parse())
  6366. {
  6367. $this->headers = $parser->headers;
  6368. $this->body = $parser->body;
  6369. $this->status_code = $parser->status_code;
  6370. if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
  6371. {
  6372. $this->redirects++;
  6373. $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
  6374. return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
  6375. }
  6376. }
  6377. }
  6378. }
  6379. else
  6380. {
  6381. $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
  6382. $url_parts = parse_url($url);
  6383. $socket_host = $url_parts['host'];
  6384. if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
  6385. {
  6386. $socket_host = "ssl://$url_parts[host]";
  6387. $url_parts['port'] = 443;
  6388. }
  6389. if (!isset($url_parts['port']))
  6390. {
  6391. $url_parts['port'] = 80;
  6392. }
  6393. $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
  6394. if (!$fp)
  6395. {
  6396. $this->error = 'fsockopen error: ' . $errstr;
  6397. $this->success = false;
  6398. }
  6399. else
  6400. {
  6401. stream_set_timeout($fp, $timeout);
  6402. if (isset($url_parts['path']))
  6403. {
  6404. if (isset($url_parts['query']))
  6405. {
  6406. $get = "$url_parts[path]?$url_parts[query]";
  6407. }
  6408. else
  6409. {
  6410. $get = $url_parts['path'];
  6411. }
  6412. }
  6413. else
  6414. {
  6415. $get = '/';
  6416. }
  6417. $out = "GET $get HTTP/1.1\r\n";
  6418. $out .= "Host: $url_parts[host]\r\n";
  6419. $out .= "User-Agent: $useragent\r\n";
  6420. if (extension_loaded('zlib'))
  6421. {
  6422. $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
  6423. }
  6424. if (isset($url_parts['user']) && isset($url_parts['pass']))
  6425. {
  6426. $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
  6427. }
  6428. foreach ($headers as $key => $value)
  6429. {
  6430. $out .= "$key: $value\r\n";
  6431. }
  6432. $out .= "Connection: Close\r\n\r\n";
  6433. fwrite($fp, $out);
  6434. $info = stream_get_meta_data($fp);
  6435. $this->headers = '';
  6436. while (!$info['eof'] && !$info['timed_out'])
  6437. {
  6438. $this->headers .= fread($fp, 1160);
  6439. $info = stream_get_meta_data($fp);
  6440. }
  6441. if (!$info['timed_out'])
  6442. {
  6443. $parser = new SimplePie_HTTP_Parser($this->headers);
  6444. if ($parser->parse())
  6445. {
  6446. $this->headers = $parser->headers;
  6447. $this->body = $parser->body;
  6448. $this->status_code = $parser->status_code;
  6449. if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
  6450. {
  6451. $this->redirects++;
  6452. $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
  6453. return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
  6454. }
  6455. if (isset($this->headers['content-encoding']))
  6456. {
  6457. // Hey, we act dumb elsewhere, so let's do that here too
  6458. switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
  6459. {
  6460. case 'gzip':
  6461. case 'x-gzip':
  6462. $decoder = new SimplePie_gzdecode($this->body);
  6463. if (!$decoder->parse())
  6464. {
  6465. $this->error = 'Unable to decode HTTP "gzip" stream';
  6466. $this->success = false;
  6467. }
  6468. else
  6469. {
  6470. $this->body = $decoder->data;
  6471. }
  6472. break;
  6473. case 'deflate':
  6474. if (($decompressed = gzinflate($this->body)) !== false)
  6475. {
  6476. $this->body = $decompressed;
  6477. }
  6478. else if (($decompressed = gzuncompress($this->body)) !== false)
  6479. {
  6480. $this->body = $decompressed;
  6481. }
  6482. else if (function_exists('gzdecode') && ($decompressed = gzdecode($this->body)) !== false)
  6483. {
  6484. $this->body = $decompressed;
  6485. }
  6486. else
  6487. {
  6488. $this->error = 'Unable to decode HTTP "deflate" stream';
  6489. $this->success = false;
  6490. }
  6491. break;
  6492. default:
  6493. $this->error = 'Unknown content coding';
  6494. $this->success = false;
  6495. }
  6496. }
  6497. }
  6498. }
  6499. else
  6500. {
  6501. $this->error = 'fsocket timed out';
  6502. $this->success = false;
  6503. }
  6504. fclose($fp);
  6505. }
  6506. }
  6507. }
  6508. else
  6509. {
  6510. $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
  6511. if (!$this->body = file_get_contents($url))
  6512. {
  6513. $this->error = 'file_get_contents could not read the file';
  6514. $this->success = false;
  6515. }
  6516. }
  6517. }
  6518. }
  6519. /**
  6520. * Decode 'gzip' encoded HTTP data
  6521. *
  6522. * @package SimplePie
  6523. * @subpackage HTTP
  6524. * @link http://www.gzip.org/format.txt
  6525. */
  6526. class SimplePie_gzdecode
  6527. {
  6528. /**
  6529. * Compressed data
  6530. *
  6531. * @access private
  6532. * @var string
  6533. * @see gzdecode::$data
  6534. */
  6535. var $compressed_data;
  6536. /**
  6537. * Size of compressed data
  6538. *
  6539. * @access private
  6540. * @var int
  6541. */
  6542. var $compressed_size;
  6543. /**
  6544. * Minimum size of a valid gzip string
  6545. *
  6546. * @access private
  6547. * @var int
  6548. */
  6549. var $min_compressed_size = 18;
  6550. /**
  6551. * Current position of pointer
  6552. *
  6553. * @access private
  6554. * @var int
  6555. */
  6556. var $position = 0;
  6557. /**
  6558. * Flags (FLG)
  6559. *
  6560. * @access private
  6561. * @var int
  6562. */
  6563. var $flags;
  6564. /**
  6565. * Uncompressed data
  6566. *
  6567. * @access public
  6568. * @see gzdecode::$compressed_data
  6569. * @var string
  6570. */
  6571. var $data;
  6572. /**
  6573. * Modified time
  6574. *
  6575. * @access public
  6576. * @var int
  6577. */
  6578. var $MTIME;
  6579. /**
  6580. * Extra Flags
  6581. *
  6582. * @access public
  6583. * @var int
  6584. */
  6585. var $XFL;
  6586. /**
  6587. * Operating System
  6588. *
  6589. * @access public
  6590. * @var int
  6591. */
  6592. var $OS;
  6593. /**
  6594. * Subfield ID 1
  6595. *
  6596. * @access public
  6597. * @see gzdecode::$extra_field
  6598. * @see gzdecode::$SI2
  6599. * @var string
  6600. */
  6601. var $SI1;
  6602. /**
  6603. * Subfield ID 2
  6604. *
  6605. * @access public
  6606. * @see gzdecode::$extra_field
  6607. * @see gzdecode::$SI1
  6608. * @var string
  6609. */
  6610. var $SI2;
  6611. /**
  6612. * Extra field content
  6613. *
  6614. * @access public
  6615. * @see gzdecode::$SI1
  6616. * @see gzdecode::$SI2
  6617. * @var string
  6618. */
  6619. var $extra_field;
  6620. /**
  6621. * Original filename
  6622. *
  6623. * @access public
  6624. * @var string
  6625. */
  6626. var $filename;
  6627. /**
  6628. * Human readable comment
  6629. *
  6630. * @access public
  6631. * @var string
  6632. */
  6633. var $comment;
  6634. /**
  6635. * Don't allow anything to be set
  6636. *
  6637. * @param string $name
  6638. * @param mixed $value
  6639. */
  6640. public function __set($name, $value)
  6641. {
  6642. trigger_error("Cannot write property $name", E_USER_ERROR);
  6643. }
  6644. /**
  6645. * Set the compressed string and related properties
  6646. *
  6647. * @param string $data
  6648. */
  6649. public function __construct($data)
  6650. {
  6651. $this->compressed_data = $data;
  6652. $this->compressed_size = strlen($data);
  6653. }
  6654. /**
  6655. * Decode the GZIP stream
  6656. *
  6657. * @return bool Successfulness
  6658. */
  6659. public function parse()
  6660. {
  6661. if ($this->compressed_size >= $this->min_compressed_size)
  6662. {
  6663. // Check ID1, ID2, and CM
  6664. if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
  6665. {
  6666. return false;
  6667. }
  6668. // Get the FLG (FLaGs)
  6669. $this->flags = ord($this->compressed_data[3]);
  6670. // FLG bits above (1 << 4) are reserved
  6671. if ($this->flags > 0x1F)
  6672. {
  6673. return false;
  6674. }
  6675. // Advance the pointer after the above
  6676. $this->position += 4;
  6677. // MTIME
  6678. $mtime = substr($this->compressed_data, $this->position, 4);
  6679. // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
  6680. if (current(unpack('S', "\x00\x01")) === 1)
  6681. {
  6682. $mtime = strrev($mtime);
  6683. }
  6684. $this->MTIME = current(unpack('l', $mtime));
  6685. $this->position += 4;
  6686. // Get the XFL (eXtra FLags)
  6687. $this->XFL = ord($this->compressed_data[$this->position++]);
  6688. // Get the OS (Operating System)
  6689. $this->OS = ord($this->compressed_data[$this->position++]);
  6690. // Parse the FEXTRA
  6691. if ($this->flags & 4)
  6692. {
  6693. // Read subfield IDs
  6694. $this->SI1 = $this->compressed_data[$this->position++];
  6695. $this->SI2 = $this->compressed_data[$this->position++];
  6696. // SI2 set to zero is reserved for future use
  6697. if ($this->SI2 === "\x00")
  6698. {
  6699. return false;
  6700. }
  6701. // Get the length of the extra field
  6702. $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
  6703. $this->position += 2;
  6704. // Check the length of the string is still valid
  6705. $this->min_compressed_size += $len + 4;
  6706. if ($this->compressed_size >= $this->min_compressed_size)
  6707. {
  6708. // Set the extra field to the given data
  6709. $this->extra_field = substr($this->compressed_data, $this->position, $len);
  6710. $this->position += $len;
  6711. }
  6712. else
  6713. {
  6714. return false;
  6715. }
  6716. }
  6717. // Parse the FNAME
  6718. if ($this->flags & 8)
  6719. {
  6720. // Get the length of the filename
  6721. $len = strcspn($this->compressed_data, "\x00", $this->position);
  6722. // Check the length of the string is still valid
  6723. $this->min_compressed_size += $len + 1;
  6724. if ($this->compressed_size >= $this->min_compressed_size)
  6725. {
  6726. // Set the original filename to the given string
  6727. $this->filename = substr($this->compressed_data, $this->position, $len);
  6728. $this->position += $len + 1;
  6729. }
  6730. else
  6731. {
  6732. return false;
  6733. }
  6734. }
  6735. // Parse the FCOMMENT
  6736. if ($this->flags & 16)
  6737. {
  6738. // Get the length of the comment
  6739. $len = strcspn($this->compressed_data, "\x00", $this->position);
  6740. // Check the length of the string is still valid
  6741. $this->min_compressed_size += $len + 1;
  6742. if ($this->compressed_size >= $this->min_compressed_size)
  6743. {
  6744. // Set the original comment to the given string
  6745. $this->comment = substr($this->compressed_data, $this->position, $len);
  6746. $this->position += $len + 1;
  6747. }
  6748. else
  6749. {
  6750. return false;
  6751. }
  6752. }
  6753. // Parse the FHCRC
  6754. if ($this->flags & 2)
  6755. {
  6756. // Check the length of the string is still valid
  6757. $this->min_compressed_size += $len + 2;
  6758. if ($this->compressed_size >= $this->min_compressed_size)
  6759. {
  6760. // Read the CRC
  6761. $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
  6762. // Check the CRC matches
  6763. if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
  6764. {
  6765. $this->position += 2;
  6766. }
  6767. else
  6768. {
  6769. return false;
  6770. }
  6771. }
  6772. else
  6773. {
  6774. return false;
  6775. }
  6776. }
  6777. // Decompress the actual data
  6778. if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
  6779. {
  6780. return false;
  6781. }
  6782. else
  6783. {
  6784. $this->position = $this->compressed_size - 8;
  6785. }
  6786. // Check CRC of data
  6787. $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
  6788. $this->position += 4;
  6789. /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
  6790. {
  6791. return false;
  6792. }*/
  6793. // Check ISIZE of data
  6794. $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
  6795. $this->position += 4;
  6796. if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
  6797. {
  6798. return false;
  6799. }
  6800. // Wow, against all odds, we've actually got a valid gzip string
  6801. return true;
  6802. }
  6803. else
  6804. {
  6805. return false;
  6806. }
  6807. }
  6808. }
  6809. /**
  6810. * HTTP Response Parser
  6811. *
  6812. * @package SimplePie
  6813. * @subpackage HTTP
  6814. */
  6815. class SimplePie_HTTP_Parser
  6816. {
  6817. /**
  6818. * HTTP Version
  6819. *
  6820. * @var float
  6821. */
  6822. public $http_version = 0.0;
  6823. /**
  6824. * Status code
  6825. *
  6826. * @var int
  6827. */
  6828. public $status_code = 0;
  6829. /**
  6830. * Reason phrase
  6831. *
  6832. * @var string
  6833. */
  6834. public $reason = '';
  6835. /**
  6836. * Key/value pairs of the headers
  6837. *
  6838. * @var array
  6839. */
  6840. public $headers = array();
  6841. /**
  6842. * Body of the response
  6843. *
  6844. * @var string
  6845. */
  6846. public $body = '';
  6847. /**
  6848. * Current state of the state machine
  6849. *
  6850. * @var string
  6851. */
  6852. protected $state = 'http_version';
  6853. /**
  6854. * Input data
  6855. *
  6856. * @var string
  6857. */
  6858. protected $data = '';
  6859. /**
  6860. * Input data length (to avoid calling strlen() everytime this is needed)
  6861. *
  6862. * @var int
  6863. */
  6864. protected $data_length = 0;
  6865. /**
  6866. * Current position of the pointer
  6867. *
  6868. * @var int
  6869. */
  6870. protected $position = 0;
  6871. /**
  6872. * Name of the hedaer currently being parsed
  6873. *
  6874. * @var string
  6875. */
  6876. protected $name = '';
  6877. /**
  6878. * Value of the hedaer currently being parsed
  6879. *
  6880. * @var string
  6881. */
  6882. protected $value = '';
  6883. /**
  6884. * Create an instance of the class with the input data
  6885. *
  6886. * @param string $data Input data
  6887. */
  6888. public function __construct($data)
  6889. {
  6890. $this->data = $data;
  6891. $this->data_length = strlen($this->data);
  6892. }
  6893. /**
  6894. * Parse the input data
  6895. *
  6896. * @return bool true on success, false on failure
  6897. */
  6898. public function parse()
  6899. {
  6900. while ($this->state && $this->state !== 'emit' && $this->has_data())
  6901. {
  6902. $state = $this->state;
  6903. $this->$state();
  6904. }
  6905. $this->data = '';
  6906. if ($this->state === 'emit' || $this->state === 'body')
  6907. {
  6908. return true;
  6909. }
  6910. else
  6911. {
  6912. $this->http_version = '';
  6913. $this->status_code = '';
  6914. $this->reason = '';
  6915. $this->headers = array();
  6916. $this->body = '';
  6917. return false;
  6918. }
  6919. }
  6920. /**
  6921. * Check whether there is data beyond the pointer
  6922. *
  6923. * @return bool true if there is further data, false if not
  6924. */
  6925. protected function has_data()
  6926. {
  6927. return (bool) ($this->position < $this->data_length);
  6928. }
  6929. /**
  6930. * See if the next character is LWS
  6931. *
  6932. * @return bool true if the next character is LWS, false if not
  6933. */
  6934. protected function is_linear_whitespace()
  6935. {
  6936. return (bool) ($this->data[$this->position] === "\x09"
  6937. || $this->data[$this->position] === "\x20"
  6938. || ($this->data[$this->position] === "\x0A"
  6939. && isset($this->data[$this->position + 1])
  6940. && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
  6941. }
  6942. /**
  6943. * Parse the HTTP version
  6944. */
  6945. protected function http_version()
  6946. {
  6947. if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
  6948. {
  6949. $len = strspn($this->data, '0123456789.', 5);
  6950. $this->http_version = substr($this->data, 5, $len);
  6951. $this->position += 5 + $len;
  6952. if (substr_count($this->http_version, '.') <= 1)
  6953. {
  6954. $this->http_version = (float) $this->http_version;
  6955. $this->position += strspn($this->data, "\x09\x20", $this->position);
  6956. $this->state = 'status';
  6957. }
  6958. else
  6959. {
  6960. $this->state = false;
  6961. }
  6962. }
  6963. else
  6964. {
  6965. $this->state = false;
  6966. }
  6967. }
  6968. /**
  6969. * Parse the status code
  6970. */
  6971. protected function status()
  6972. {
  6973. if ($len = strspn($this->data, '0123456789', $this->position))
  6974. {
  6975. $this->status_code = (int) substr($this->data, $this->position, $len);
  6976. $this->position += $len;
  6977. $this->state = 'reason';
  6978. }
  6979. else
  6980. {
  6981. $this->state = false;
  6982. }
  6983. }
  6984. /**
  6985. * Parse the reason phrase
  6986. */
  6987. protected function reason()
  6988. {
  6989. $len = strcspn($this->data, "\x0A", $this->position);
  6990. $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
  6991. $this->position += $len + 1;
  6992. $this->state = 'new_line';
  6993. }
  6994. /**
  6995. * Deal with a new line, shifting data around as needed
  6996. */
  6997. protected function new_line()
  6998. {
  6999. $this->value = trim($this->value, "\x0D\x20");
  7000. if ($this->name !== '' && $this->value !== '')
  7001. {
  7002. $this->name = strtolower($this->name);
  7003. // We should only use the last Content-Type header. c.f. issue #1
  7004. if (isset($this->headers[$this->name]) && $this->name !== 'content-type')
  7005. {
  7006. $this->headers[$this->name] .= ', ' . $this->value;
  7007. }
  7008. else
  7009. {
  7010. $this->headers[$this->name] = $this->value;
  7011. }
  7012. }
  7013. $this->name = '';
  7014. $this->value = '';
  7015. if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
  7016. {
  7017. $this->position += 2;
  7018. $this->state = 'body';
  7019. }
  7020. elseif ($this->data[$this->position] === "\x0A")
  7021. {
  7022. $this->position++;
  7023. $this->state = 'body';
  7024. }
  7025. else
  7026. {
  7027. $this->state = 'name';
  7028. }
  7029. }
  7030. /**
  7031. * Parse a header name
  7032. */
  7033. protected function name()
  7034. {
  7035. $len = strcspn($this->data, "\x0A:", $this->position);
  7036. if (isset($this->data[$this->position + $len]))
  7037. {
  7038. if ($this->data[$this->position + $len] === "\x0A")
  7039. {
  7040. $this->position += $len;
  7041. $this->state = 'new_line';
  7042. }
  7043. else
  7044. {
  7045. $this->name = substr($this->data, $this->position, $len);
  7046. $this->position += $len + 1;
  7047. $this->state = 'value';
  7048. }
  7049. }
  7050. else
  7051. {
  7052. $this->state = false;
  7053. }
  7054. }
  7055. /**
  7056. * Parse LWS, replacing consecutive LWS characters with a single space
  7057. */
  7058. protected function linear_whitespace()
  7059. {
  7060. do
  7061. {
  7062. if (substr($this->data, $this->position, 2) === "\x0D\x0A")
  7063. {
  7064. $this->position += 2;
  7065. }
  7066. elseif ($this->data[$this->position] === "\x0A")
  7067. {
  7068. $this->position++;
  7069. }
  7070. $this->position += strspn($this->data, "\x09\x20", $this->position);
  7071. } while ($this->has_data() && $this->is_linear_whitespace());
  7072. $this->value .= "\x20";
  7073. }
  7074. /**
  7075. * See what state to move to while within non-quoted header values
  7076. */
  7077. protected function value()
  7078. {
  7079. if ($this->is_linear_whitespace())
  7080. {
  7081. $this->linear_whitespace();
  7082. }
  7083. else
  7084. {
  7085. switch ($this->data[$this->position])
  7086. {
  7087. case '"':
  7088. // Workaround for ETags: we have to include the quotes as
  7089. // part of the tag.
  7090. if (strtolower($this->name) === 'etag')
  7091. {
  7092. $this->value .= '"';
  7093. $this->position++;
  7094. $this->state = 'value_char';
  7095. break;
  7096. }
  7097. $this->position++;
  7098. $this->state = 'quote';
  7099. break;
  7100. case "\x0A":
  7101. $this->position++;
  7102. $this->state = 'new_line';
  7103. break;
  7104. default:
  7105. $this->state = 'value_char';
  7106. break;
  7107. }
  7108. }
  7109. }
  7110. /**
  7111. * Parse a header value while outside quotes
  7112. */
  7113. protected function value_char()
  7114. {
  7115. $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
  7116. $this->value .= substr($this->data, $this->position, $len);
  7117. $this->position += $len;
  7118. $this->state = 'value';
  7119. }
  7120. /**
  7121. * See what state to move to while within quoted header values
  7122. */
  7123. protected function quote()
  7124. {
  7125. if ($this->is_linear_whitespace())
  7126. {
  7127. $this->linear_whitespace();
  7128. }
  7129. else
  7130. {
  7131. switch ($this->data[$this->position])
  7132. {
  7133. case '"':
  7134. $this->position++;
  7135. $this->state = 'value';
  7136. break;
  7137. case "\x0A":
  7138. $this->position++;
  7139. $this->state = 'new_line';
  7140. break;
  7141. case '\\':
  7142. $this->position++;
  7143. $this->state = 'quote_escaped';
  7144. break;
  7145. default:
  7146. $this->state = 'quote_char';
  7147. break;
  7148. }
  7149. }
  7150. }
  7151. /**
  7152. * Parse a header value while within quotes
  7153. */
  7154. protected function quote_char()
  7155. {
  7156. $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
  7157. $this->value .= substr($this->data, $this->position, $len);
  7158. $this->position += $len;
  7159. $this->state = 'value';
  7160. }
  7161. /**
  7162. * Parse an escaped character within quotes
  7163. */
  7164. protected function quote_escaped()
  7165. {
  7166. $this->value .= $this->data[$this->position];
  7167. $this->position++;
  7168. $this->state = 'quote';
  7169. }
  7170. /**
  7171. * Parse the body
  7172. */
  7173. protected function body()
  7174. {
  7175. $this->body = substr($this->data, $this->position);
  7176. if (!empty($this->headers['transfer-encoding']))
  7177. {
  7178. unset($this->headers['transfer-encoding']);
  7179. $this->state = 'chunked';
  7180. }
  7181. else
  7182. {
  7183. $this->state = 'emit';
  7184. }
  7185. }
  7186. /**
  7187. * Parsed a "Transfer-Encoding: chunked" body
  7188. */
  7189. protected function chunked()
  7190. {
  7191. if (!preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', trim($this->body)))
  7192. {
  7193. $this->state = 'emit';
  7194. return;
  7195. }
  7196. $decoded = '';
  7197. $encoded = $this->body;
  7198. while (true)
  7199. {
  7200. $is_chunked = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $encoded, $matches );
  7201. if (!$is_chunked)
  7202. {
  7203. // Looks like it's not chunked after all
  7204. $this->state = 'emit';
  7205. return;
  7206. }
  7207. $length = hexdec(trim($matches[1]));
  7208. if ($length === 0)
  7209. {
  7210. // Ignore trailer headers
  7211. $this->state = 'emit';
  7212. $this->body = $decoded;
  7213. return;
  7214. }
  7215. $chunk_length = strlen($matches[0]);
  7216. $decoded .= $part = substr($encoded, $chunk_length, $length);
  7217. $encoded = substr($encoded, $chunk_length + $length + 2);
  7218. if (trim($encoded) === '0' || empty($encoded))
  7219. {
  7220. $this->state = 'emit';
  7221. $this->body = $decoded;
  7222. return;
  7223. }
  7224. }
  7225. }
  7226. }
  7227. /**
  7228. * IRI parser/serialiser/normaliser
  7229. *
  7230. * @package SimplePie
  7231. * @subpackage HTTP
  7232. * @author Geoffrey Sneddon
  7233. * @author Steve Minutillo
  7234. * @author Ryan McCue
  7235. * @copyright 2007-2012 Geoffrey Sneddon, Steve Minutillo, Ryan McCue
  7236. * @license http://www.opensource.org/licenses/bsd-license.php
  7237. */
  7238. class SimplePie_IRI
  7239. {
  7240. /**
  7241. * Scheme
  7242. *
  7243. * @var string
  7244. */
  7245. protected $scheme = null;
  7246. /**
  7247. * User Information
  7248. *
  7249. * @var string
  7250. */
  7251. protected $iuserinfo = null;
  7252. /**
  7253. * ihost
  7254. *
  7255. * @var string
  7256. */
  7257. protected $ihost = null;
  7258. /**
  7259. * Port
  7260. *
  7261. * @var string
  7262. */
  7263. protected $port = null;
  7264. /**
  7265. * ipath
  7266. *
  7267. * @var string
  7268. */
  7269. protected $ipath = '';
  7270. /**
  7271. * iquery
  7272. *
  7273. * @var string
  7274. */
  7275. protected $iquery = null;
  7276. /**
  7277. * ifragment
  7278. *
  7279. * @var string
  7280. */
  7281. protected $ifragment = null;
  7282. /**
  7283. * Normalization database
  7284. *
  7285. * Each key is the scheme, each value is an array with each key as the IRI
  7286. * part and value as the default value for that part.
  7287. */
  7288. protected $normalization = array(
  7289. 'acap' => array(
  7290. 'port' => 674
  7291. ),
  7292. 'dict' => array(
  7293. 'port' => 2628
  7294. ),
  7295. 'file' => array(
  7296. 'ihost' => 'localhost'
  7297. ),
  7298. 'http' => array(
  7299. 'port' => 80,
  7300. 'ipath' => '/'
  7301. ),
  7302. 'https' => array(
  7303. 'port' => 443,
  7304. 'ipath' => '/'
  7305. ),
  7306. );
  7307. /**
  7308. * Return the entire IRI when you try and read the object as a string
  7309. *
  7310. * @return string
  7311. */
  7312. public function __toString()
  7313. {
  7314. return $this->get_iri();
  7315. }
  7316. /**
  7317. * Overload __set() to provide access via properties
  7318. *
  7319. * @param string $name Property name
  7320. * @param mixed $value Property value
  7321. */
  7322. public function __set($name, $value)
  7323. {
  7324. if (method_exists($this, 'set_' . $name))
  7325. {
  7326. call_user_func(array($this, 'set_' . $name), $value);
  7327. }
  7328. elseif (
  7329. $name === 'iauthority'
  7330. || $name === 'iuserinfo'
  7331. || $name === 'ihost'
  7332. || $name === 'ipath'
  7333. || $name === 'iquery'
  7334. || $name === 'ifragment'
  7335. )
  7336. {
  7337. call_user_func(array($this, 'set_' . substr($name, 1)), $value);
  7338. }
  7339. }
  7340. /**
  7341. * Overload __get() to provide access via properties
  7342. *
  7343. * @param string $name Property name
  7344. * @return mixed
  7345. */
  7346. public function __get($name)
  7347. {
  7348. // isset() returns false for null, we don't want to do that
  7349. // Also why we use array_key_exists below instead of isset()
  7350. $props = get_object_vars($this);
  7351. if (
  7352. $name === 'iri' ||
  7353. $name === 'uri' ||
  7354. $name === 'iauthority' ||
  7355. $name === 'authority'
  7356. )
  7357. {
  7358. $return = $this->{"get_$name"}();
  7359. }
  7360. elseif (array_key_exists($name, $props))
  7361. {
  7362. $return = $this->$name;
  7363. }
  7364. // host -> ihost
  7365. elseif (($prop = 'i' . $name) && array_key_exists($prop, $props))
  7366. {
  7367. $name = $prop;
  7368. $return = $this->$prop;
  7369. }
  7370. // ischeme -> scheme
  7371. elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props))
  7372. {
  7373. $name = $prop;
  7374. $return = $this->$prop;
  7375. }
  7376. else
  7377. {
  7378. trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE);
  7379. $return = null;
  7380. }
  7381. if ($return === null && isset($this->normalization[$this->scheme][$name]))
  7382. {
  7383. return $this->normalization[$this->scheme][$name];
  7384. }
  7385. else
  7386. {
  7387. return $return;
  7388. }
  7389. }
  7390. /**
  7391. * Overload __isset() to provide access via properties
  7392. *
  7393. * @param string $name Property name
  7394. * @return bool
  7395. */
  7396. public function __isset($name)
  7397. {
  7398. if (method_exists($this, 'get_' . $name) || isset($this->$name))
  7399. {
  7400. return true;
  7401. }
  7402. else
  7403. {
  7404. return false;
  7405. }
  7406. }
  7407. /**
  7408. * Overload __unset() to provide access via properties
  7409. *
  7410. * @param string $name Property name
  7411. */
  7412. public function __unset($name)
  7413. {
  7414. if (method_exists($this, 'set_' . $name))
  7415. {
  7416. call_user_func(array($this, 'set_' . $name), '');
  7417. }
  7418. }
  7419. /**
  7420. * Create a new IRI object, from a specified string
  7421. *
  7422. * @param string $iri
  7423. */
  7424. public function __construct($iri = null)
  7425. {
  7426. $this->set_iri($iri);
  7427. }
  7428. /**
  7429. * Create a new IRI object by resolving a relative IRI
  7430. *
  7431. * Returns false if $base is not absolute, otherwise an IRI.
  7432. *
  7433. * @param IRI|string $base (Absolute) Base IRI
  7434. * @param IRI|string $relative Relative IRI
  7435. * @return IRI|false
  7436. */
  7437. public static function absolutize($base, $relative)
  7438. {
  7439. if (!($relative instanceof SimplePie_IRI))
  7440. {
  7441. $relative = new SimplePie_IRI($relative);
  7442. }
  7443. if (!$relative->is_valid())
  7444. {
  7445. return false;
  7446. }
  7447. elseif ($relative->scheme !== null)
  7448. {
  7449. return clone $relative;
  7450. }
  7451. else
  7452. {
  7453. if (!($base instanceof SimplePie_IRI))
  7454. {
  7455. $base = new SimplePie_IRI($base);
  7456. }
  7457. if ($base->scheme !== null && $base->is_valid())
  7458. {
  7459. if ($relative->get_iri() !== '')
  7460. {
  7461. if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null)
  7462. {
  7463. $target = clone $relative;
  7464. $target->scheme = $base->scheme;
  7465. }
  7466. else
  7467. {
  7468. $target = new SimplePie_IRI;
  7469. $target->scheme = $base->scheme;
  7470. $target->iuserinfo = $base->iuserinfo;
  7471. $target->ihost = $base->ihost;
  7472. $target->port = $base->port;
  7473. if ($relative->ipath !== '')
  7474. {
  7475. if ($relative->ipath[0] === '/')
  7476. {
  7477. $target->ipath = $relative->ipath;
  7478. }
  7479. elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '')
  7480. {
  7481. $target->ipath = '/' . $relative->ipath;
  7482. }
  7483. elseif (($last_segment = strrpos($base->ipath, '/')) !== false)
  7484. {
  7485. $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath;
  7486. }
  7487. else
  7488. {
  7489. $target->ipath = $relative->ipath;
  7490. }
  7491. $target->ipath = $target->remove_dot_segments($target->ipath);
  7492. $target->iquery = $relative->iquery;
  7493. }
  7494. else
  7495. {
  7496. $target->ipath = $base->ipath;
  7497. if ($relative->iquery !== null)
  7498. {
  7499. $target->iquery = $relative->iquery;
  7500. }
  7501. elseif ($base->iquery !== null)
  7502. {
  7503. $target->iquery = $base->iquery;
  7504. }
  7505. }
  7506. $target->ifragment = $relative->ifragment;
  7507. }
  7508. }
  7509. else
  7510. {
  7511. $target = clone $base;
  7512. $target->ifragment = null;
  7513. }
  7514. $target->scheme_normalization();
  7515. return $target;
  7516. }
  7517. else
  7518. {
  7519. return false;
  7520. }
  7521. }
  7522. }
  7523. /**
  7524. * Parse an IRI into scheme/authority/path/query/fragment segments
  7525. *
  7526. * @param string $iri
  7527. * @return array
  7528. */
  7529. protected function parse_iri($iri)
  7530. {
  7531. $iri = trim($iri, "\x20\x09\x0A\x0C\x0D");
  7532. if (preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match))
  7533. {
  7534. if ($match[1] === '')
  7535. {
  7536. $match['scheme'] = null;
  7537. }
  7538. if (!isset($match[3]) || $match[3] === '')
  7539. {
  7540. $match['authority'] = null;
  7541. }
  7542. if (!isset($match[5]))
  7543. {
  7544. $match['path'] = '';
  7545. }
  7546. if (!isset($match[6]) || $match[6] === '')
  7547. {
  7548. $match['query'] = null;
  7549. }
  7550. if (!isset($match[8]) || $match[8] === '')
  7551. {
  7552. $match['fragment'] = null;
  7553. }
  7554. return $match;
  7555. }
  7556. else
  7557. {
  7558. // This can occur when a paragraph is accidentally parsed as a URI
  7559. return false;
  7560. }
  7561. }
  7562. /**
  7563. * Remove dot segments from a path
  7564. *
  7565. * @param string $input
  7566. * @return string
  7567. */
  7568. protected function remove_dot_segments($input)
  7569. {
  7570. $output = '';
  7571. while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
  7572. {
  7573. // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
  7574. if (strpos($input, '../') === 0)
  7575. {
  7576. $input = substr($input, 3);
  7577. }
  7578. elseif (strpos($input, './') === 0)
  7579. {
  7580. $input = substr($input, 2);
  7581. }
  7582. // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
  7583. elseif (strpos($input, '/./') === 0)
  7584. {
  7585. $input = substr($input, 2);
  7586. }
  7587. elseif ($input === '/.')
  7588. {
  7589. $input = '/';
  7590. }
  7591. // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
  7592. elseif (strpos($input, '/../') === 0)
  7593. {
  7594. $input = substr($input, 3);
  7595. $output = substr_replace($output, '', strrpos($output, '/'));
  7596. }
  7597. elseif ($input === '/..')
  7598. {
  7599. $input = '/';
  7600. $output = substr_replace($output, '', strrpos($output, '/'));
  7601. }
  7602. // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
  7603. elseif ($input === '.' || $input === '..')
  7604. {
  7605. $input = '';
  7606. }
  7607. // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
  7608. elseif (($pos = strpos($input, '/', 1)) !== false)
  7609. {
  7610. $output .= substr($input, 0, $pos);
  7611. $input = substr_replace($input, '', 0, $pos);
  7612. }
  7613. else
  7614. {
  7615. $output .= $input;
  7616. $input = '';
  7617. }
  7618. }
  7619. return $output . $input;
  7620. }
  7621. /**
  7622. * Replace invalid character with percent encoding
  7623. *
  7624. * @param string $string Input string
  7625. * @param string $extra_chars Valid characters not in iunreserved or
  7626. * iprivate (this is ASCII-only)
  7627. * @param bool $iprivate Allow iprivate
  7628. * @return string
  7629. */
  7630. protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false)
  7631. {
  7632. // Normalize as many pct-encoded sections as possible
  7633. $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $string);
  7634. // Replace invalid percent characters
  7635. $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
  7636. // Add unreserved and % to $extra_chars (the latter is safe because all
  7637. // pct-encoded sections are now valid).
  7638. $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
  7639. // Now replace any bytes that aren't allowed with their pct-encoded versions
  7640. $position = 0;
  7641. $strlen = strlen($string);
  7642. while (($position += strspn($string, $extra_chars, $position)) < $strlen)
  7643. {
  7644. $value = ord($string[$position]);
  7645. // Start position
  7646. $start = $position;
  7647. // By default we are valid
  7648. $valid = true;
  7649. // No one byte sequences are valid due to the while.
  7650. // Two byte sequence:
  7651. if (($value & 0xE0) === 0xC0)
  7652. {
  7653. $character = ($value & 0x1F) << 6;
  7654. $length = 2;
  7655. $remaining = 1;
  7656. }
  7657. // Three byte sequence:
  7658. elseif (($value & 0xF0) === 0xE0)
  7659. {
  7660. $character = ($value & 0x0F) << 12;
  7661. $length = 3;
  7662. $remaining = 2;
  7663. }
  7664. // Four byte sequence:
  7665. elseif (($value & 0xF8) === 0xF0)
  7666. {
  7667. $character = ($value & 0x07) << 18;
  7668. $length = 4;
  7669. $remaining = 3;
  7670. }
  7671. // Invalid byte:
  7672. else
  7673. {
  7674. $valid = false;
  7675. $length = 1;
  7676. $remaining = 0;
  7677. }
  7678. if ($remaining)
  7679. {
  7680. if ($position + $length <= $strlen)
  7681. {
  7682. for ($position++; $remaining; $position++)
  7683. {
  7684. $value = ord($string[$position]);
  7685. // Check that the byte is valid, then add it to the character:
  7686. if (($value & 0xC0) === 0x80)
  7687. {
  7688. $character |= ($value & 0x3F) << (--$remaining * 6);
  7689. }
  7690. // If it is invalid, count the sequence as invalid and reprocess the current byte:
  7691. else
  7692. {
  7693. $valid = false;
  7694. $position--;
  7695. break;
  7696. }
  7697. }
  7698. }
  7699. else
  7700. {
  7701. $position = $strlen - 1;
  7702. $valid = false;
  7703. }
  7704. }
  7705. // Percent encode anything invalid or not in ucschar
  7706. if (
  7707. // Invalid sequences
  7708. !$valid
  7709. // Non-shortest form sequences are invalid
  7710. || $length > 1 && $character <= 0x7F
  7711. || $length > 2 && $character <= 0x7FF
  7712. || $length > 3 && $character <= 0xFFFF
  7713. // Outside of range of ucschar codepoints
  7714. // Noncharacters
  7715. || ($character & 0xFFFE) === 0xFFFE
  7716. || $character >= 0xFDD0 && $character <= 0xFDEF
  7717. || (
  7718. // Everything else not in ucschar
  7719. $character > 0xD7FF && $character < 0xF900
  7720. || $character < 0xA0
  7721. || $character > 0xEFFFD
  7722. )
  7723. && (
  7724. // Everything not in iprivate, if it applies
  7725. !$iprivate
  7726. || $character < 0xE000
  7727. || $character > 0x10FFFD
  7728. )
  7729. )
  7730. {
  7731. // If we were a character, pretend we weren't, but rather an error.
  7732. if ($valid)
  7733. $position--;
  7734. for ($j = $start; $j <= $position; $j++)
  7735. {
  7736. $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
  7737. $j += 2;
  7738. $position += 2;
  7739. $strlen += 2;
  7740. }
  7741. }
  7742. }
  7743. return $string;
  7744. }
  7745. /**
  7746. * Callback function for preg_replace_callback.
  7747. *
  7748. * Removes sequences of percent encoded bytes that represent UTF-8
  7749. * encoded characters in iunreserved
  7750. *
  7751. * @param array $match PCRE match
  7752. * @return string Replacement
  7753. */
  7754. protected function remove_iunreserved_percent_encoded($match)
  7755. {
  7756. // As we just have valid percent encoded sequences we can just explode
  7757. // and ignore the first member of the returned array (an empty string).
  7758. $bytes = explode('%', $match[0]);
  7759. // Initialize the new string (this is what will be returned) and that
  7760. // there are no bytes remaining in the current sequence (unsurprising
  7761. // at the first byte!).
  7762. $string = '';
  7763. $remaining = 0;
  7764. // Loop over each and every byte, and set $value to its value
  7765. for ($i = 1, $len = count($bytes); $i < $len; $i++)
  7766. {
  7767. $value = hexdec($bytes[$i]);
  7768. // If we're the first byte of sequence:
  7769. if (!$remaining)
  7770. {
  7771. // Start position
  7772. $start = $i;
  7773. // By default we are valid
  7774. $valid = true;
  7775. // One byte sequence:
  7776. if ($value <= 0x7F)
  7777. {
  7778. $character = $value;
  7779. $length = 1;
  7780. }
  7781. // Two byte sequence:
  7782. elseif (($value & 0xE0) === 0xC0)
  7783. {
  7784. $character = ($value & 0x1F) << 6;
  7785. $length = 2;
  7786. $remaining = 1;
  7787. }
  7788. // Three byte sequence:
  7789. elseif (($value & 0xF0) === 0xE0)
  7790. {
  7791. $character = ($value & 0x0F) << 12;
  7792. $length = 3;
  7793. $remaining = 2;
  7794. }
  7795. // Four byte sequence:
  7796. elseif (($value & 0xF8) === 0xF0)
  7797. {
  7798. $character = ($value & 0x07) << 18;
  7799. $length = 4;
  7800. $remaining = 3;
  7801. }
  7802. // Invalid byte:
  7803. else
  7804. {
  7805. $valid = false;
  7806. $remaining = 0;
  7807. }
  7808. }
  7809. // Continuation byte:
  7810. else
  7811. {
  7812. // Check that the byte is valid, then add it to the character:
  7813. if (($value & 0xC0) === 0x80)
  7814. {
  7815. $remaining--;
  7816. $character |= ($value & 0x3F) << ($remaining * 6);
  7817. }
  7818. // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
  7819. else
  7820. {
  7821. $valid = false;
  7822. $remaining = 0;
  7823. $i--;
  7824. }
  7825. }
  7826. // If we've reached the end of the current byte sequence, append it to Unicode::$data
  7827. if (!$remaining)
  7828. {
  7829. // Percent encode anything invalid or not in iunreserved
  7830. if (
  7831. // Invalid sequences
  7832. !$valid
  7833. // Non-shortest form sequences are invalid
  7834. || $length > 1 && $character <= 0x7F
  7835. || $length > 2 && $character <= 0x7FF
  7836. || $length > 3 && $character <= 0xFFFF
  7837. // Outside of range of iunreserved codepoints
  7838. || $character < 0x2D
  7839. || $character > 0xEFFFD
  7840. // Noncharacters
  7841. || ($character & 0xFFFE) === 0xFFFE
  7842. || $character >= 0xFDD0 && $character <= 0xFDEF
  7843. // Everything else not in iunreserved (this is all BMP)
  7844. || $character === 0x2F
  7845. || $character > 0x39 && $character < 0x41
  7846. || $character > 0x5A && $character < 0x61
  7847. || $character > 0x7A && $character < 0x7E
  7848. || $character > 0x7E && $character < 0xA0
  7849. || $character > 0xD7FF && $character < 0xF900
  7850. )
  7851. {
  7852. for ($j = $start; $j <= $i; $j++)
  7853. {
  7854. $string .= '%' . strtoupper($bytes[$j]);
  7855. }
  7856. }
  7857. else
  7858. {
  7859. for ($j = $start; $j <= $i; $j++)
  7860. {
  7861. $string .= chr(hexdec($bytes[$j]));
  7862. }
  7863. }
  7864. }
  7865. }
  7866. // If we have any bytes left over they are invalid (i.e., we are
  7867. // mid-way through a multi-byte sequence)
  7868. if ($remaining)
  7869. {
  7870. for ($j = $start; $j < $len; $j++)
  7871. {
  7872. $string .= '%' . strtoupper($bytes[$j]);
  7873. }
  7874. }
  7875. return $string;
  7876. }
  7877. protected function scheme_normalization()
  7878. {
  7879. if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo'])
  7880. {
  7881. $this->iuserinfo = null;
  7882. }
  7883. if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost'])
  7884. {
  7885. $this->ihost = null;
  7886. }
  7887. if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port'])
  7888. {
  7889. $this->port = null;
  7890. }
  7891. if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath'])
  7892. {
  7893. $this->ipath = '';
  7894. }
  7895. if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery'])
  7896. {
  7897. $this->iquery = null;
  7898. }
  7899. if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment'])
  7900. {
  7901. $this->ifragment = null;
  7902. }
  7903. }
  7904. /**
  7905. * Check if the object represents a valid IRI. This needs to be done on each
  7906. * call as some things change depending on another part of the IRI.
  7907. *
  7908. * @return bool
  7909. */
  7910. public function is_valid()
  7911. {
  7912. $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null;
  7913. if ($this->ipath !== '' &&
  7914. (
  7915. $isauthority && (
  7916. $this->ipath[0] !== '/' ||
  7917. substr($this->ipath, 0, 2) === '//'
  7918. ) ||
  7919. (
  7920. $this->scheme === null &&
  7921. !$isauthority &&
  7922. strpos($this->ipath, ':') !== false &&
  7923. (strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/'))
  7924. )
  7925. )
  7926. )
  7927. {
  7928. return false;
  7929. }
  7930. return true;
  7931. }
  7932. /**
  7933. * Set the entire IRI. Returns true on success, false on failure (if there
  7934. * are any invalid characters).
  7935. *
  7936. * @param string $iri
  7937. * @return bool
  7938. */
  7939. public function set_iri($iri)
  7940. {
  7941. static $cache;
  7942. if (!$cache)
  7943. {
  7944. $cache = array();
  7945. }
  7946. if ($iri === null)
  7947. {
  7948. return true;
  7949. }
  7950. elseif (isset($cache[$iri]))
  7951. {
  7952. list($this->scheme,
  7953. $this->iuserinfo,
  7954. $this->ihost,
  7955. $this->port,
  7956. $this->ipath,
  7957. $this->iquery,
  7958. $this->ifragment,
  7959. $return) = $cache[$iri];
  7960. return $return;
  7961. }
  7962. else
  7963. {
  7964. $parsed = $this->parse_iri((string) $iri);
  7965. if (!$parsed)
  7966. {
  7967. return false;
  7968. }
  7969. $return = $this->set_scheme($parsed['scheme'])
  7970. && $this->set_authority($parsed['authority'])
  7971. && $this->set_path($parsed['path'])
  7972. && $this->set_query($parsed['query'])
  7973. && $this->set_fragment($parsed['fragment']);
  7974. $cache[$iri] = array($this->scheme,
  7975. $this->iuserinfo,
  7976. $this->ihost,
  7977. $this->port,
  7978. $this->ipath,
  7979. $this->iquery,
  7980. $this->ifragment,
  7981. $return);
  7982. return $return;
  7983. }
  7984. }
  7985. /**
  7986. * Set the scheme. Returns true on success, false on failure (if there are
  7987. * any invalid characters).
  7988. *
  7989. * @param string $scheme
  7990. * @return bool
  7991. */
  7992. public function set_scheme($scheme)
  7993. {
  7994. if ($scheme === null)
  7995. {
  7996. $this->scheme = null;
  7997. }
  7998. elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme))
  7999. {
  8000. $this->scheme = null;
  8001. return false;
  8002. }
  8003. else
  8004. {
  8005. $this->scheme = strtolower($scheme);
  8006. }
  8007. return true;
  8008. }
  8009. /**
  8010. * Set the authority. Returns true on success, false on failure (if there are
  8011. * any invalid characters).
  8012. *
  8013. * @param string $authority
  8014. * @return bool
  8015. */
  8016. public function set_authority($authority)
  8017. {
  8018. static $cache;
  8019. if (!$cache)
  8020. $cache = array();
  8021. if ($authority === null)
  8022. {
  8023. $this->iuserinfo = null;
  8024. $this->ihost = null;
  8025. $this->port = null;
  8026. return true;
  8027. }
  8028. elseif (isset($cache[$authority]))
  8029. {
  8030. list($this->iuserinfo,
  8031. $this->ihost,
  8032. $this->port,
  8033. $return) = $cache[$authority];
  8034. return $return;
  8035. }
  8036. else
  8037. {
  8038. $remaining = $authority;
  8039. if (($iuserinfo_end = strrpos($remaining, '@')) !== false)
  8040. {
  8041. $iuserinfo = substr($remaining, 0, $iuserinfo_end);
  8042. $remaining = substr($remaining, $iuserinfo_end + 1);
  8043. }
  8044. else
  8045. {
  8046. $iuserinfo = null;
  8047. }
  8048. if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false)
  8049. {
  8050. if (($port = substr($remaining, $port_start + 1)) === false)
  8051. {
  8052. $port = null;
  8053. }
  8054. $remaining = substr($remaining, 0, $port_start);
  8055. }
  8056. else
  8057. {
  8058. $port = null;
  8059. }
  8060. $return = $this->set_userinfo($iuserinfo) &&
  8061. $this->set_host($remaining) &&
  8062. $this->set_port($port);
  8063. $cache[$authority] = array($this->iuserinfo,
  8064. $this->ihost,
  8065. $this->port,
  8066. $return);
  8067. return $return;
  8068. }
  8069. }
  8070. /**
  8071. * Set the iuserinfo.
  8072. *
  8073. * @param string $iuserinfo
  8074. * @return bool
  8075. */
  8076. public function set_userinfo($iuserinfo)
  8077. {
  8078. if ($iuserinfo === null)
  8079. {
  8080. $this->iuserinfo = null;
  8081. }
  8082. else
  8083. {
  8084. $this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:');
  8085. $this->scheme_normalization();
  8086. }
  8087. return true;
  8088. }
  8089. /**
  8090. * Set the ihost. Returns true on success, false on failure (if there are
  8091. * any invalid characters).
  8092. *
  8093. * @param string $ihost
  8094. * @return bool
  8095. */
  8096. public function set_host($ihost)
  8097. {
  8098. if ($ihost === null)
  8099. {
  8100. $this->ihost = null;
  8101. return true;
  8102. }
  8103. elseif (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']')
  8104. {
  8105. if (SimplePie_Net_IPv6::check_ipv6(substr($ihost, 1, -1)))
  8106. {
  8107. $this->ihost = '[' . SimplePie_Net_IPv6::compress(substr($ihost, 1, -1)) . ']';
  8108. }
  8109. else
  8110. {
  8111. $this->ihost = null;
  8112. return false;
  8113. }
  8114. }
  8115. else
  8116. {
  8117. $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;=');
  8118. // Lowercase, but ignore pct-encoded sections (as they should
  8119. // remain uppercase). This must be done after the previous step
  8120. // as that can add unescaped characters.
  8121. $position = 0;
  8122. $strlen = strlen($ihost);
  8123. while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen)
  8124. {
  8125. if ($ihost[$position] === '%')
  8126. {
  8127. $position += 3;
  8128. }
  8129. else
  8130. {
  8131. $ihost[$position] = strtolower($ihost[$position]);
  8132. $position++;
  8133. }
  8134. }
  8135. $this->ihost = $ihost;
  8136. }
  8137. $this->scheme_normalization();
  8138. return true;
  8139. }
  8140. /**
  8141. * Set the port. Returns true on success, false on failure (if there are
  8142. * any invalid characters).
  8143. *
  8144. * @param string $port
  8145. * @return bool
  8146. */
  8147. public function set_port($port)
  8148. {
  8149. if ($port === null)
  8150. {
  8151. $this->port = null;
  8152. return true;
  8153. }
  8154. elseif (strspn($port, '0123456789') === strlen($port))
  8155. {
  8156. $this->port = (int) $port;
  8157. $this->scheme_normalization();
  8158. return true;
  8159. }
  8160. else
  8161. {
  8162. $this->port = null;
  8163. return false;
  8164. }
  8165. }
  8166. /**
  8167. * Set the ipath.
  8168. *
  8169. * @param string $ipath
  8170. * @return bool
  8171. */
  8172. public function set_path($ipath)
  8173. {
  8174. static $cache;
  8175. if (!$cache)
  8176. {
  8177. $cache = array();
  8178. }
  8179. $ipath = (string) $ipath;
  8180. if (isset($cache[$ipath]))
  8181. {
  8182. $this->ipath = $cache[$ipath][(int) ($this->scheme !== null)];
  8183. }
  8184. else
  8185. {
  8186. $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/');
  8187. $removed = $this->remove_dot_segments($valid);
  8188. $cache[$ipath] = array($valid, $removed);
  8189. $this->ipath = ($this->scheme !== null) ? $removed : $valid;
  8190. }
  8191. $this->scheme_normalization();
  8192. return true;
  8193. }
  8194. /**
  8195. * Set the iquery.
  8196. *
  8197. * @param string $iquery
  8198. * @return bool
  8199. */
  8200. public function set_query($iquery)
  8201. {
  8202. if ($iquery === null)
  8203. {
  8204. $this->iquery = null;
  8205. }
  8206. else
  8207. {
  8208. $this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true);
  8209. $this->scheme_normalization();
  8210. }
  8211. return true;
  8212. }
  8213. /**
  8214. * Set the ifragment.
  8215. *
  8216. * @param string $ifragment
  8217. * @return bool
  8218. */
  8219. public function set_fragment($ifragment)
  8220. {
  8221. if ($ifragment === null)
  8222. {
  8223. $this->ifragment = null;
  8224. }
  8225. else
  8226. {
  8227. $this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?');
  8228. $this->scheme_normalization();
  8229. }
  8230. return true;
  8231. }
  8232. /**
  8233. * Convert an IRI to a URI (or parts thereof)
  8234. *
  8235. * @return string
  8236. */
  8237. public function to_uri($string)
  8238. {
  8239. static $non_ascii;
  8240. if (!$non_ascii)
  8241. {
  8242. $non_ascii = implode('', range("\x80", "\xFF"));
  8243. }
  8244. $position = 0;
  8245. $strlen = strlen($string);
  8246. while (($position += strcspn($string, $non_ascii, $position)) < $strlen)
  8247. {
  8248. $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1);
  8249. $position += 3;
  8250. $strlen += 2;
  8251. }
  8252. return $string;
  8253. }
  8254. /**
  8255. * Get the complete IRI
  8256. *
  8257. * @return string
  8258. */
  8259. public function get_iri()
  8260. {
  8261. if (!$this->is_valid())
  8262. {
  8263. return false;
  8264. }
  8265. $iri = '';
  8266. if ($this->scheme !== null)
  8267. {
  8268. $iri .= $this->scheme . ':';
  8269. }
  8270. if (($iauthority = $this->get_iauthority()) !== null)
  8271. {
  8272. $iri .= '//' . $iauthority;
  8273. }
  8274. if ($this->ipath !== '')
  8275. {
  8276. $iri .= $this->ipath;
  8277. }
  8278. elseif (!empty($this->normalization[$this->scheme]['ipath']) && $iauthority !== null && $iauthority !== '')
  8279. {
  8280. $iri .= $this->normalization[$this->scheme]['ipath'];
  8281. }
  8282. if ($this->iquery !== null)
  8283. {
  8284. $iri .= '?' . $this->iquery;
  8285. }
  8286. if ($this->ifragment !== null)
  8287. {
  8288. $iri .= '#' . $this->ifragment;
  8289. }
  8290. return $iri;
  8291. }
  8292. /**
  8293. * Get the complete URI
  8294. *
  8295. * @return string
  8296. */
  8297. public function get_uri()
  8298. {
  8299. return $this->to_uri($this->get_iri());
  8300. }
  8301. /**
  8302. * Get the complete iauthority
  8303. *
  8304. * @return string
  8305. */
  8306. protected function get_iauthority()
  8307. {
  8308. if ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null)
  8309. {
  8310. $iauthority = '';
  8311. if ($this->iuserinfo !== null)
  8312. {
  8313. $iauthority .= $this->iuserinfo . '@';
  8314. }
  8315. if ($this->ihost !== null)
  8316. {
  8317. $iauthority .= $this->ihost;
  8318. }
  8319. if ($this->port !== null)
  8320. {
  8321. $iauthority .= ':' . $this->port;
  8322. }
  8323. return $iauthority;
  8324. }
  8325. else
  8326. {
  8327. return null;
  8328. }
  8329. }
  8330. /**
  8331. * Get the complete authority
  8332. *
  8333. * @return string
  8334. */
  8335. protected function get_authority()
  8336. {
  8337. $iauthority = $this->get_iauthority();
  8338. if (is_string($iauthority))
  8339. return $this->to_uri($iauthority);
  8340. else
  8341. return $iauthority;
  8342. }
  8343. }
  8344. /**
  8345. * Manages all item-related data
  8346. *
  8347. * Used by {@see SimplePie::get_item()} and {@see SimplePie::get_items()}
  8348. *
  8349. * This class can be overloaded with {@see SimplePie::set_item_class()}
  8350. *
  8351. * @package SimplePie
  8352. * @subpackage API
  8353. */
  8354. class SimplePie_Item
  8355. {
  8356. /**
  8357. * Parent feed
  8358. *
  8359. * @access private
  8360. * @var SimplePie
  8361. */
  8362. var $feed;
  8363. /**
  8364. * Raw data
  8365. *
  8366. * @access private
  8367. * @var array
  8368. */
  8369. var $data = array();
  8370. /**
  8371. * Registry object
  8372. *
  8373. * @see set_registry
  8374. * @var SimplePie_Registry
  8375. */
  8376. protected $registry;
  8377. /**
  8378. * Create a new item object
  8379. *
  8380. * This is usually used by {@see SimplePie::get_items} and
  8381. * {@see SimplePie::get_item}. Avoid creating this manually.
  8382. *
  8383. * @param SimplePie $feed Parent feed
  8384. * @param array $data Raw data
  8385. */
  8386. public function __construct($feed, $data)
  8387. {
  8388. $this->feed = $feed;
  8389. $this->data = $data;
  8390. }
  8391. /**
  8392. * Set the registry handler
  8393. *
  8394. * This is usually used by {@see SimplePie_Registry::create}
  8395. *
  8396. * @since 1.3
  8397. * @param SimplePie_Registry $registry
  8398. */
  8399. public function set_registry(SimplePie_Registry $registry)
  8400. {
  8401. $this->registry = $registry;
  8402. }
  8403. /**
  8404. * Get a string representation of the item
  8405. *
  8406. * @return string
  8407. */
  8408. public function __toString()
  8409. {
  8410. return md5(serialize($this->data));
  8411. }
  8412. /**
  8413. * Remove items that link back to this before destroying this object
  8414. */
  8415. public function __destruct()
  8416. {
  8417. if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
  8418. {
  8419. unset($this->feed);
  8420. }
  8421. }
  8422. /**
  8423. * Get data for an item-level element
  8424. *
  8425. * This method allows you to get access to ANY element/attribute that is a
  8426. * sub-element of the item/entry tag.
  8427. *
  8428. * See {@see SimplePie::get_feed_tags()} for a description of the return value
  8429. *
  8430. * @since 1.0
  8431. * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
  8432. * @param string $namespace The URL of the XML namespace of the elements you're trying to access
  8433. * @param string $tag Tag name
  8434. * @return array
  8435. */
  8436. public function get_item_tags($namespace, $tag)
  8437. {
  8438. if (isset($this->data['child'][$namespace][$tag]))
  8439. {
  8440. return $this->data['child'][$namespace][$tag];
  8441. }
  8442. else
  8443. {
  8444. return null;
  8445. }
  8446. }
  8447. /**
  8448. * Get the base URL value from the parent feed
  8449. *
  8450. * Uses `<xml:base>`
  8451. *
  8452. * @param array $element
  8453. * @return string
  8454. */
  8455. public function get_base($element = array())
  8456. {
  8457. return $this->feed->get_base($element);
  8458. }
  8459. /**
  8460. * Sanitize feed data
  8461. *
  8462. * @access private
  8463. * @see SimplePie::sanitize()
  8464. * @param string $data Data to sanitize
  8465. * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
  8466. * @param string $base Base URL to resolve URLs against
  8467. * @return string Sanitized data
  8468. */
  8469. public function sanitize($data, $type, $base = '')
  8470. {
  8471. return $this->feed->sanitize($data, $type, $base);
  8472. }
  8473. /**
  8474. * Get the parent feed
  8475. *
  8476. * Note: this may not work as you think for multifeeds!
  8477. *
  8478. * @link http://simplepie.org/faq/typical_multifeed_gotchas#missing_data_from_feed
  8479. * @since 1.0
  8480. * @return SimplePie
  8481. */
  8482. public function get_feed()
  8483. {
  8484. return $this->feed;
  8485. }
  8486. /**
  8487. * Get the unique identifier for the item
  8488. *
  8489. * This is usually used when writing code to check for new items in a feed.
  8490. *
  8491. * Uses `<atom:id>`, `<guid>`, `<dc:identifier>` or the `about` attribute
  8492. * for RDF. If none of these are supplied (or `$hash` is true), creates an
  8493. * MD5 hash based on the permalink and title. If either of those are not
  8494. * supplied, creates a hash based on the full feed data.
  8495. *
  8496. * @since Beta 2
  8497. * @param boolean $hash Should we force using a hash instead of the supplied ID?
  8498. * @return string
  8499. */
  8500. public function get_id($hash = false)
  8501. {
  8502. if (!$hash)
  8503. {
  8504. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
  8505. {
  8506. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8507. }
  8508. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
  8509. {
  8510. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8511. }
  8512. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
  8513. {
  8514. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8515. }
  8516. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
  8517. {
  8518. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8519. }
  8520. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
  8521. {
  8522. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8523. }
  8524. elseif (isset($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about']))
  8525. {
  8526. return $this->sanitize($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about'], SIMPLEPIE_CONSTRUCT_TEXT);
  8527. }
  8528. elseif (($return = $this->get_permalink()) !== null)
  8529. {
  8530. return $return;
  8531. }
  8532. elseif (($return = $this->get_title()) !== null)
  8533. {
  8534. return $return;
  8535. }
  8536. }
  8537. if ($this->get_permalink() !== null || $this->get_title() !== null)
  8538. {
  8539. return md5($this->get_permalink() . $this->get_title());
  8540. }
  8541. else
  8542. {
  8543. return md5(serialize($this->data));
  8544. }
  8545. }
  8546. /**
  8547. * Get the title of the item
  8548. *
  8549. * Uses `<atom:title>`, `<title>` or `<dc:title>`
  8550. *
  8551. * @since Beta 2 (previously called `get_item_title` since 0.8)
  8552. * @return string|null
  8553. */
  8554. public function get_title()
  8555. {
  8556. if (!isset($this->data['title']))
  8557. {
  8558. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  8559. {
  8560. $this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  8561. }
  8562. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  8563. {
  8564. $this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  8565. }
  8566. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  8567. {
  8568. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  8569. }
  8570. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  8571. {
  8572. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  8573. }
  8574. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  8575. {
  8576. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  8577. }
  8578. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  8579. {
  8580. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8581. }
  8582. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  8583. {
  8584. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8585. }
  8586. else
  8587. {
  8588. $this->data['title'] = null;
  8589. }
  8590. }
  8591. return $this->data['title'];
  8592. }
  8593. /**
  8594. * Get the content for the item
  8595. *
  8596. * Prefers summaries over full content , but will return full content if a
  8597. * summary does not exist.
  8598. *
  8599. * To prefer full content instead, use {@see get_content}
  8600. *
  8601. * Uses `<atom:summary>`, `<description>`, `<dc:description>` or
  8602. * `<itunes:subtitle>`
  8603. *
  8604. * @since 0.8
  8605. * @param boolean $description_only Should we avoid falling back to the content?
  8606. * @return string|null
  8607. */
  8608. public function get_description($description_only = false)
  8609. {
  8610. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
  8611. {
  8612. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  8613. }
  8614. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
  8615. {
  8616. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  8617. }
  8618. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  8619. {
  8620. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  8621. }
  8622. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  8623. {
  8624. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  8625. }
  8626. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  8627. {
  8628. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8629. }
  8630. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  8631. {
  8632. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8633. }
  8634. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  8635. {
  8636. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  8637. }
  8638. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  8639. {
  8640. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8641. }
  8642. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
  8643. {
  8644. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
  8645. }
  8646. elseif (!$description_only)
  8647. {
  8648. return $this->get_content(true);
  8649. }
  8650. else
  8651. {
  8652. return null;
  8653. }
  8654. }
  8655. /**
  8656. * Get the content for the item
  8657. *
  8658. * Prefers full content over summaries, but will return a summary if full
  8659. * content does not exist.
  8660. *
  8661. * To prefer summaries instead, use {@see get_description}
  8662. *
  8663. * Uses `<atom:content>` or `<content:encoded>` (RSS 1.0 Content Module)
  8664. *
  8665. * @since 1.0
  8666. * @param boolean $content_only Should we avoid falling back to the description?
  8667. * @return string|null
  8668. */
  8669. public function get_content($content_only = false)
  8670. {
  8671. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
  8672. {
  8673. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_content_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  8674. }
  8675. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
  8676. {
  8677. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  8678. }
  8679. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
  8680. {
  8681. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  8682. }
  8683. elseif (!$content_only)
  8684. {
  8685. return $this->get_description(true);
  8686. }
  8687. else
  8688. {
  8689. return null;
  8690. }
  8691. }
  8692. /**
  8693. * Get a category for the item
  8694. *
  8695. * @since Beta 3 (previously called `get_categories()` since Beta 2)
  8696. * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1
  8697. * @return SimplePie_Category|null
  8698. */
  8699. public function get_category($key = 0)
  8700. {
  8701. $categories = $this->get_categories();
  8702. if (isset($categories[$key]))
  8703. {
  8704. return $categories[$key];
  8705. }
  8706. else
  8707. {
  8708. return null;
  8709. }
  8710. }
  8711. /**
  8712. * Get all categories for the item
  8713. *
  8714. * Uses `<atom:category>`, `<category>` or `<dc:subject>`
  8715. *
  8716. * @since Beta 3
  8717. * @return array|null List of {@see SimplePie_Category} objects
  8718. */
  8719. public function get_categories()
  8720. {
  8721. $categories = array();
  8722. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  8723. {
  8724. $term = null;
  8725. $scheme = null;
  8726. $label = null;
  8727. if (isset($category['attribs']['']['term']))
  8728. {
  8729. $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  8730. }
  8731. if (isset($category['attribs']['']['scheme']))
  8732. {
  8733. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  8734. }
  8735. if (isset($category['attribs']['']['label']))
  8736. {
  8737. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  8738. }
  8739. $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
  8740. }
  8741. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  8742. {
  8743. // This is really the label, but keep this as the term also for BC.
  8744. // Label will also work on retrieving because that falls back to term.
  8745. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8746. if (isset($category['attribs']['']['domain']))
  8747. {
  8748. $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  8749. }
  8750. else
  8751. {
  8752. $scheme = null;
  8753. }
  8754. $categories[] = $this->registry->create('Category', array($term, $scheme, null));
  8755. }
  8756. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  8757. {
  8758. $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  8759. }
  8760. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  8761. {
  8762. $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  8763. }
  8764. if (!empty($categories))
  8765. {
  8766. return array_unique($categories);
  8767. }
  8768. else
  8769. {
  8770. return null;
  8771. }
  8772. }
  8773. /**
  8774. * Get an author for the item
  8775. *
  8776. * @since Beta 2
  8777. * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1
  8778. * @return SimplePie_Author|null
  8779. */
  8780. public function get_author($key = 0)
  8781. {
  8782. $authors = $this->get_authors();
  8783. if (isset($authors[$key]))
  8784. {
  8785. return $authors[$key];
  8786. }
  8787. else
  8788. {
  8789. return null;
  8790. }
  8791. }
  8792. /**
  8793. * Get a contributor for the item
  8794. *
  8795. * @since 1.1
  8796. * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1
  8797. * @return SimplePie_Author|null
  8798. */
  8799. public function get_contributor($key = 0)
  8800. {
  8801. $contributors = $this->get_contributors();
  8802. if (isset($contributors[$key]))
  8803. {
  8804. return $contributors[$key];
  8805. }
  8806. else
  8807. {
  8808. return null;
  8809. }
  8810. }
  8811. /**
  8812. * Get all contributors for the item
  8813. *
  8814. * Uses `<atom:contributor>`
  8815. *
  8816. * @since 1.1
  8817. * @return array|null List of {@see SimplePie_Author} objects
  8818. */
  8819. public function get_contributors()
  8820. {
  8821. $contributors = array();
  8822. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  8823. {
  8824. $name = null;
  8825. $uri = null;
  8826. $email = null;
  8827. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  8828. {
  8829. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8830. }
  8831. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  8832. {
  8833. $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  8834. }
  8835. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  8836. {
  8837. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8838. }
  8839. if ($name !== null || $email !== null || $uri !== null)
  8840. {
  8841. $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
  8842. }
  8843. }
  8844. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  8845. {
  8846. $name = null;
  8847. $url = null;
  8848. $email = null;
  8849. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  8850. {
  8851. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8852. }
  8853. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  8854. {
  8855. $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  8856. }
  8857. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  8858. {
  8859. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8860. }
  8861. if ($name !== null || $email !== null || $url !== null)
  8862. {
  8863. $contributors[] = $this->registry->create('Author', array($name, $url, $email));
  8864. }
  8865. }
  8866. if (!empty($contributors))
  8867. {
  8868. return array_unique($contributors);
  8869. }
  8870. else
  8871. {
  8872. return null;
  8873. }
  8874. }
  8875. /**
  8876. * Get all authors for the item
  8877. *
  8878. * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
  8879. *
  8880. * @since Beta 2
  8881. * @return array|null List of {@see SimplePie_Author} objects
  8882. */
  8883. public function get_authors()
  8884. {
  8885. $authors = array();
  8886. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  8887. {
  8888. $name = null;
  8889. $uri = null;
  8890. $email = null;
  8891. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  8892. {
  8893. $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8894. }
  8895. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  8896. {
  8897. $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  8898. }
  8899. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  8900. {
  8901. $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8902. }
  8903. if ($name !== null || $email !== null || $uri !== null)
  8904. {
  8905. $authors[] = $this->registry->create('Author', array($name, $uri, $email));
  8906. }
  8907. }
  8908. if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  8909. {
  8910. $name = null;
  8911. $url = null;
  8912. $email = null;
  8913. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  8914. {
  8915. $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8916. }
  8917. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  8918. {
  8919. $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  8920. }
  8921. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  8922. {
  8923. $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8924. }
  8925. if ($name !== null || $email !== null || $url !== null)
  8926. {
  8927. $authors[] = $this->registry->create('Author', array($name, $url, $email));
  8928. }
  8929. }
  8930. if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
  8931. {
  8932. $authors[] = $this->registry->create('Author', array(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)));
  8933. }
  8934. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  8935. {
  8936. $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  8937. }
  8938. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  8939. {
  8940. $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  8941. }
  8942. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  8943. {
  8944. $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  8945. }
  8946. if (!empty($authors))
  8947. {
  8948. return array_unique($authors);
  8949. }
  8950. elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
  8951. {
  8952. return $authors;
  8953. }
  8954. elseif ($authors = $this->feed->get_authors())
  8955. {
  8956. return $authors;
  8957. }
  8958. else
  8959. {
  8960. return null;
  8961. }
  8962. }
  8963. /**
  8964. * Get the copyright info for the item
  8965. *
  8966. * Uses `<atom:rights>` or `<dc:rights>`
  8967. *
  8968. * @since 1.1
  8969. * @return string
  8970. */
  8971. public function get_copyright()
  8972. {
  8973. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  8974. {
  8975. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  8976. }
  8977. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  8978. {
  8979. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8980. }
  8981. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  8982. {
  8983. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8984. }
  8985. else
  8986. {
  8987. return null;
  8988. }
  8989. }
  8990. /**
  8991. * Get the posting date/time for the item
  8992. *
  8993. * Uses `<atom:published>`, `<atom:updated>`, `<atom:issued>`,
  8994. * `<atom:modified>`, `<pubDate>` or `<dc:date>`
  8995. *
  8996. * Note: obeys PHP's timezone setting. To get a UTC date/time, use
  8997. * {@see get_gmdate}
  8998. *
  8999. * @since Beta 2 (previously called `get_item_date` since 0.8)
  9000. *
  9001. * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data)
  9002. * @return int|string|null
  9003. */
  9004. public function get_date($date_format = 'j F Y, g:i a')
  9005. {
  9006. if (!isset($this->data['date']))
  9007. {
  9008. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
  9009. {
  9010. $this->data['date']['raw'] = $return[0]['data'];
  9011. }
  9012. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
  9013. {
  9014. $this->data['date']['raw'] = $return[0]['data'];
  9015. }
  9016. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
  9017. {
  9018. $this->data['date']['raw'] = $return[0]['data'];
  9019. }
  9020. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
  9021. {
  9022. $this->data['date']['raw'] = $return[0]['data'];
  9023. }
  9024. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
  9025. {
  9026. $this->data['date']['raw'] = $return[0]['data'];
  9027. }
  9028. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
  9029. {
  9030. $this->data['date']['raw'] = $return[0]['data'];
  9031. }
  9032. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
  9033. {
  9034. $this->data['date']['raw'] = $return[0]['data'];
  9035. }
  9036. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
  9037. {
  9038. $this->data['date']['raw'] = $return[0]['data'];
  9039. }
  9040. if (!empty($this->data['date']['raw']))
  9041. {
  9042. $parser = $this->registry->call('Parse_Date', 'get');
  9043. $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
  9044. }
  9045. else
  9046. {
  9047. $this->data['date'] = null;
  9048. }
  9049. }
  9050. if ($this->data['date'])
  9051. {
  9052. $date_format = (string) $date_format;
  9053. switch ($date_format)
  9054. {
  9055. case '':
  9056. return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
  9057. case 'U':
  9058. return $this->data['date']['parsed'];
  9059. default:
  9060. return date($date_format, $this->data['date']['parsed']);
  9061. }
  9062. }
  9063. else
  9064. {
  9065. return null;
  9066. }
  9067. }
  9068. /**
  9069. * Get the update date/time for the item
  9070. *
  9071. * Uses `<atom:updated>`
  9072. *
  9073. * Note: obeys PHP's timezone setting. To get a UTC date/time, use
  9074. * {@see get_gmdate}
  9075. *
  9076. * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data)
  9077. * @return int|string|null
  9078. */
  9079. public function get_updated_date($date_format = 'j F Y, g:i a')
  9080. {
  9081. if (!isset($this->data['updated']))
  9082. {
  9083. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
  9084. {
  9085. $this->data['updated']['raw'] = $return[0]['data'];
  9086. }
  9087. if (!empty($this->data['updated']['raw']))
  9088. {
  9089. $parser = $this->registry->call('Parse_Date', 'get');
  9090. $this->data['updated']['parsed'] = $parser->parse($this->data['date']['raw']);
  9091. }
  9092. else
  9093. {
  9094. $this->data['updated'] = null;
  9095. }
  9096. }
  9097. if ($this->data['updated'])
  9098. {
  9099. $date_format = (string) $date_format;
  9100. switch ($date_format)
  9101. {
  9102. case '':
  9103. return $this->sanitize($this->data['updated']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
  9104. case 'U':
  9105. return $this->data['updated']['parsed'];
  9106. default:
  9107. return date($date_format, $this->data['updated']['parsed']);
  9108. }
  9109. }
  9110. else
  9111. {
  9112. return null;
  9113. }
  9114. }
  9115. /**
  9116. * Get the localized posting date/time for the item
  9117. *
  9118. * Returns the date formatted in the localized language. To display in
  9119. * languages other than the server's default, you need to change the locale
  9120. * with {@link http://php.net/setlocale setlocale()}. The available
  9121. * localizations depend on which ones are installed on your web server.
  9122. *
  9123. * @since 1.0
  9124. *
  9125. * @param string $date_format Supports any PHP date format from {@see http://php.net/strftime} (empty for the raw data)
  9126. * @return int|string|null
  9127. */
  9128. public function get_local_date($date_format = '%c')
  9129. {
  9130. if (!$date_format)
  9131. {
  9132. return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
  9133. }
  9134. elseif (($date = $this->get_date('U')) !== null && $date !== false)
  9135. {
  9136. return strftime($date_format, $date);
  9137. }
  9138. else
  9139. {
  9140. return null;
  9141. }
  9142. }
  9143. /**
  9144. * Get the posting date/time for the item (UTC time)
  9145. *
  9146. * @see get_date
  9147. * @param string $date_format Supports any PHP date format from {@see http://php.net/date}
  9148. * @return int|string|null
  9149. */
  9150. public function get_gmdate($date_format = 'j F Y, g:i a')
  9151. {
  9152. $date = $this->get_date('U');
  9153. if ($date === null)
  9154. {
  9155. return null;
  9156. }
  9157. return gmdate($date_format, $date);
  9158. }
  9159. /**
  9160. * Get the update date/time for the item (UTC time)
  9161. *
  9162. * @see get_updated_date
  9163. * @param string $date_format Supports any PHP date format from {@see http://php.net/date}
  9164. * @return int|string|null
  9165. */
  9166. public function get_updated_gmdate($date_format = 'j F Y, g:i a')
  9167. {
  9168. $date = $this->get_updated_date('U');
  9169. if ($date === null)
  9170. {
  9171. return null;
  9172. }
  9173. return gmdate($date_format, $date);
  9174. }
  9175. /**
  9176. * Get the permalink for the item
  9177. *
  9178. * Returns the first link available with a relationship of "alternate".
  9179. * Identical to {@see get_link()} with key 0
  9180. *
  9181. * @see get_link
  9182. * @since 0.8
  9183. * @return string|null Permalink URL
  9184. */
  9185. public function get_permalink()
  9186. {
  9187. $link = $this->get_link();
  9188. $enclosure = $this->get_enclosure(0);
  9189. if ($link !== null)
  9190. {
  9191. return $link;
  9192. }
  9193. elseif ($enclosure !== null)
  9194. {
  9195. return $enclosure->get_link();
  9196. }
  9197. else
  9198. {
  9199. return null;
  9200. }
  9201. }
  9202. /**
  9203. * Get a single link for the item
  9204. *
  9205. * @since Beta 3
  9206. * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1
  9207. * @param string $rel The relationship of the link to return
  9208. * @return string|null Link URL
  9209. */
  9210. public function get_link($key = 0, $rel = 'alternate')
  9211. {
  9212. $links = $this->get_links($rel);
  9213. if ($links[$key] !== null)
  9214. {
  9215. return $links[$key];
  9216. }
  9217. else
  9218. {
  9219. return null;
  9220. }
  9221. }
  9222. /**
  9223. * Get all links for the item
  9224. *
  9225. * Uses `<atom:link>`, `<link>` or `<guid>`
  9226. *
  9227. * @since Beta 2
  9228. * @param string $rel The relationship of links to return
  9229. * @return array|null Links found for the item (strings)
  9230. */
  9231. public function get_links($rel = 'alternate')
  9232. {
  9233. if (!isset($this->data['links']))
  9234. {
  9235. $this->data['links'] = array();
  9236. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
  9237. {
  9238. if (isset($link['attribs']['']['href']))
  9239. {
  9240. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  9241. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  9242. }
  9243. }
  9244. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
  9245. {
  9246. if (isset($link['attribs']['']['href']))
  9247. {
  9248. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  9249. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  9250. }
  9251. }
  9252. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  9253. {
  9254. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  9255. }
  9256. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  9257. {
  9258. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  9259. }
  9260. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  9261. {
  9262. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  9263. }
  9264. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
  9265. {
  9266. if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
  9267. {
  9268. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  9269. }
  9270. }
  9271. $keys = array_keys($this->data['links']);
  9272. foreach ($keys as $key)
  9273. {
  9274. if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
  9275. {
  9276. if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  9277. {
  9278. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  9279. $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  9280. }
  9281. else
  9282. {
  9283. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  9284. }
  9285. }
  9286. elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  9287. {
  9288. $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  9289. }
  9290. $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  9291. }
  9292. }
  9293. if (isset($this->data['links'][$rel]))
  9294. {
  9295. return $this->data['links'][$rel];
  9296. }
  9297. else
  9298. {
  9299. return null;
  9300. }
  9301. }
  9302. /**
  9303. * Get an enclosure from the item
  9304. *
  9305. * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
  9306. *
  9307. * @since Beta 2
  9308. * @todo Add ability to prefer one type of content over another (in a media group).
  9309. * @param int $key The enclosure that you want to return. Remember that arrays begin with 0, not 1
  9310. * @return SimplePie_Enclosure|null
  9311. */
  9312. public function get_enclosure($key = 0, $prefer = null)
  9313. {
  9314. $enclosures = $this->get_enclosures();
  9315. if (isset($enclosures[$key]))
  9316. {
  9317. return $enclosures[$key];
  9318. }
  9319. else
  9320. {
  9321. return null;
  9322. }
  9323. }
  9324. /**
  9325. * Get all available enclosures (podcasts, etc.)
  9326. *
  9327. * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
  9328. *
  9329. * At this point, we're pretty much assuming that all enclosures for an item
  9330. * are the same content. Anything else is too complicated to
  9331. * properly support.
  9332. *
  9333. * @since Beta 2
  9334. * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
  9335. * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists).
  9336. * @return array|null List of SimplePie_Enclosure items
  9337. */
  9338. public function get_enclosures()
  9339. {
  9340. if (!isset($this->data['enclosures']))
  9341. {
  9342. $this->data['enclosures'] = array();
  9343. // Elements
  9344. $captions_parent = null;
  9345. $categories_parent = null;
  9346. $copyrights_parent = null;
  9347. $credits_parent = null;
  9348. $description_parent = null;
  9349. $duration_parent = null;
  9350. $hashes_parent = null;
  9351. $keywords_parent = null;
  9352. $player_parent = null;
  9353. $ratings_parent = null;
  9354. $restrictions_parent = null;
  9355. $thumbnails_parent = null;
  9356. $title_parent = null;
  9357. // Let's do the channel and item-level ones first, and just re-use them if we need to.
  9358. $parent = $this->get_feed();
  9359. // CAPTIONS
  9360. if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
  9361. {
  9362. foreach ($captions as $caption)
  9363. {
  9364. $caption_type = null;
  9365. $caption_lang = null;
  9366. $caption_startTime = null;
  9367. $caption_endTime = null;
  9368. $caption_text = null;
  9369. if (isset($caption['attribs']['']['type']))
  9370. {
  9371. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  9372. }
  9373. if (isset($caption['attribs']['']['lang']))
  9374. {
  9375. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  9376. }
  9377. if (isset($caption['attribs']['']['start']))
  9378. {
  9379. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  9380. }
  9381. if (isset($caption['attribs']['']['end']))
  9382. {
  9383. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  9384. }
  9385. if (isset($caption['data']))
  9386. {
  9387. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9388. }
  9389. $captions_parent[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
  9390. }
  9391. }
  9392. elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
  9393. {
  9394. foreach ($captions as $caption)
  9395. {
  9396. $caption_type = null;
  9397. $caption_lang = null;
  9398. $caption_startTime = null;
  9399. $caption_endTime = null;
  9400. $caption_text = null;
  9401. if (isset($caption['attribs']['']['type']))
  9402. {
  9403. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  9404. }
  9405. if (isset($caption['attribs']['']['lang']))
  9406. {
  9407. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  9408. }
  9409. if (isset($caption['attribs']['']['start']))
  9410. {
  9411. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  9412. }
  9413. if (isset($caption['attribs']['']['end']))
  9414. {
  9415. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  9416. }
  9417. if (isset($caption['data']))
  9418. {
  9419. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9420. }
  9421. $captions_parent[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
  9422. }
  9423. }
  9424. if (is_array($captions_parent))
  9425. {
  9426. $captions_parent = array_values(array_unique($captions_parent));
  9427. }
  9428. // CATEGORIES
  9429. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
  9430. {
  9431. $term = null;
  9432. $scheme = null;
  9433. $label = null;
  9434. if (isset($category['data']))
  9435. {
  9436. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9437. }
  9438. if (isset($category['attribs']['']['scheme']))
  9439. {
  9440. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  9441. }
  9442. else
  9443. {
  9444. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  9445. }
  9446. if (isset($category['attribs']['']['label']))
  9447. {
  9448. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  9449. }
  9450. $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));
  9451. }
  9452. foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
  9453. {
  9454. $term = null;
  9455. $scheme = null;
  9456. $label = null;
  9457. if (isset($category['data']))
  9458. {
  9459. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9460. }
  9461. if (isset($category['attribs']['']['scheme']))
  9462. {
  9463. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  9464. }
  9465. else
  9466. {
  9467. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  9468. }
  9469. if (isset($category['attribs']['']['label']))
  9470. {
  9471. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  9472. }
  9473. $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));
  9474. }
  9475. foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
  9476. {
  9477. $term = null;
  9478. $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
  9479. $label = null;
  9480. if (isset($category['attribs']['']['text']))
  9481. {
  9482. $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
  9483. }
  9484. $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));
  9485. if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
  9486. {
  9487. foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
  9488. {
  9489. if (isset($subcategory['attribs']['']['text']))
  9490. {
  9491. $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
  9492. }
  9493. $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));
  9494. }
  9495. }
  9496. }
  9497. if (is_array($categories_parent))
  9498. {
  9499. $categories_parent = array_values(array_unique($categories_parent));
  9500. }
  9501. // COPYRIGHT
  9502. if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
  9503. {
  9504. $copyright_url = null;
  9505. $copyright_label = null;
  9506. if (isset($copyright[0]['attribs']['']['url']))
  9507. {
  9508. $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  9509. }
  9510. if (isset($copyright[0]['data']))
  9511. {
  9512. $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9513. }
  9514. $copyrights_parent = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
  9515. }
  9516. elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
  9517. {
  9518. $copyright_url = null;
  9519. $copyright_label = null;
  9520. if (isset($copyright[0]['attribs']['']['url']))
  9521. {
  9522. $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  9523. }
  9524. if (isset($copyright[0]['data']))
  9525. {
  9526. $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9527. }
  9528. $copyrights_parent = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
  9529. }
  9530. // CREDITS
  9531. if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
  9532. {
  9533. foreach ($credits as $credit)
  9534. {
  9535. $credit_role = null;
  9536. $credit_scheme = null;
  9537. $credit_name = null;
  9538. if (isset($credit['attribs']['']['role']))
  9539. {
  9540. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  9541. }
  9542. if (isset($credit['attribs']['']['scheme']))
  9543. {
  9544. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  9545. }
  9546. else
  9547. {
  9548. $credit_scheme = 'urn:ebu';
  9549. }
  9550. if (isset($credit['data']))
  9551. {
  9552. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9553. }
  9554. $credits_parent[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
  9555. }
  9556. }
  9557. elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
  9558. {
  9559. foreach ($credits as $credit)
  9560. {
  9561. $credit_role = null;
  9562. $credit_scheme = null;
  9563. $credit_name = null;
  9564. if (isset($credit['attribs']['']['role']))
  9565. {
  9566. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  9567. }
  9568. if (isset($credit['attribs']['']['scheme']))
  9569. {
  9570. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  9571. }
  9572. else
  9573. {
  9574. $credit_scheme = 'urn:ebu';
  9575. }
  9576. if (isset($credit['data']))
  9577. {
  9578. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9579. }
  9580. $credits_parent[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
  9581. }
  9582. }
  9583. if (is_array($credits_parent))
  9584. {
  9585. $credits_parent = array_values(array_unique($credits_parent));
  9586. }
  9587. // DESCRIPTION
  9588. if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
  9589. {
  9590. if (isset($description_parent[0]['data']))
  9591. {
  9592. $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9593. }
  9594. }
  9595. elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
  9596. {
  9597. if (isset($description_parent[0]['data']))
  9598. {
  9599. $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9600. }
  9601. }
  9602. // DURATION
  9603. if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
  9604. {
  9605. $seconds = null;
  9606. $minutes = null;
  9607. $hours = null;
  9608. if (isset($duration_parent[0]['data']))
  9609. {
  9610. $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  9611. if (sizeof($temp) > 0)
  9612. {
  9613. $seconds = (int) array_pop($temp);
  9614. }
  9615. if (sizeof($temp) > 0)
  9616. {
  9617. $minutes = (int) array_pop($temp);
  9618. $seconds += $minutes * 60;
  9619. }
  9620. if (sizeof($temp) > 0)
  9621. {
  9622. $hours = (int) array_pop($temp);
  9623. $seconds += $hours * 3600;
  9624. }
  9625. unset($temp);
  9626. $duration_parent = $seconds;
  9627. }
  9628. }
  9629. // HASHES
  9630. if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
  9631. {
  9632. foreach ($hashes_iterator as $hash)
  9633. {
  9634. $value = null;
  9635. $algo = null;
  9636. if (isset($hash['data']))
  9637. {
  9638. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9639. }
  9640. if (isset($hash['attribs']['']['algo']))
  9641. {
  9642. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  9643. }
  9644. else
  9645. {
  9646. $algo = 'md5';
  9647. }
  9648. $hashes_parent[] = $algo.':'.$value;
  9649. }
  9650. }
  9651. elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
  9652. {
  9653. foreach ($hashes_iterator as $hash)
  9654. {
  9655. $value = null;
  9656. $algo = null;
  9657. if (isset($hash['data']))
  9658. {
  9659. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9660. }
  9661. if (isset($hash['attribs']['']['algo']))
  9662. {
  9663. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  9664. }
  9665. else
  9666. {
  9667. $algo = 'md5';
  9668. }
  9669. $hashes_parent[] = $algo.':'.$value;
  9670. }
  9671. }
  9672. if (is_array($hashes_parent))
  9673. {
  9674. $hashes_parent = array_values(array_unique($hashes_parent));
  9675. }
  9676. // KEYWORDS
  9677. if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
  9678. {
  9679. if (isset($keywords[0]['data']))
  9680. {
  9681. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  9682. foreach ($temp as $word)
  9683. {
  9684. $keywords_parent[] = trim($word);
  9685. }
  9686. }
  9687. unset($temp);
  9688. }
  9689. elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
  9690. {
  9691. if (isset($keywords[0]['data']))
  9692. {
  9693. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  9694. foreach ($temp as $word)
  9695. {
  9696. $keywords_parent[] = trim($word);
  9697. }
  9698. }
  9699. unset($temp);
  9700. }
  9701. elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
  9702. {
  9703. if (isset($keywords[0]['data']))
  9704. {
  9705. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  9706. foreach ($temp as $word)
  9707. {
  9708. $keywords_parent[] = trim($word);
  9709. }
  9710. }
  9711. unset($temp);
  9712. }
  9713. elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
  9714. {
  9715. if (isset($keywords[0]['data']))
  9716. {
  9717. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  9718. foreach ($temp as $word)
  9719. {
  9720. $keywords_parent[] = trim($word);
  9721. }
  9722. }
  9723. unset($temp);
  9724. }
  9725. if (is_array($keywords_parent))
  9726. {
  9727. $keywords_parent = array_values(array_unique($keywords_parent));
  9728. }
  9729. // PLAYER
  9730. if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
  9731. {
  9732. if (isset($player_parent[0]['attribs']['']['url']))
  9733. {
  9734. $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  9735. }
  9736. }
  9737. elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
  9738. {
  9739. if (isset($player_parent[0]['attribs']['']['url']))
  9740. {
  9741. $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  9742. }
  9743. }
  9744. // RATINGS
  9745. if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
  9746. {
  9747. foreach ($ratings as $rating)
  9748. {
  9749. $rating_scheme = null;
  9750. $rating_value = null;
  9751. if (isset($rating['attribs']['']['scheme']))
  9752. {
  9753. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  9754. }
  9755. else
  9756. {
  9757. $rating_scheme = 'urn:simple';
  9758. }
  9759. if (isset($rating['data']))
  9760. {
  9761. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9762. }
  9763. $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
  9764. }
  9765. }
  9766. elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
  9767. {
  9768. foreach ($ratings as $rating)
  9769. {
  9770. $rating_scheme = 'urn:itunes';
  9771. $rating_value = null;
  9772. if (isset($rating['data']))
  9773. {
  9774. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9775. }
  9776. $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
  9777. }
  9778. }
  9779. elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
  9780. {
  9781. foreach ($ratings as $rating)
  9782. {
  9783. $rating_scheme = null;
  9784. $rating_value = null;
  9785. if (isset($rating['attribs']['']['scheme']))
  9786. {
  9787. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  9788. }
  9789. else
  9790. {
  9791. $rating_scheme = 'urn:simple';
  9792. }
  9793. if (isset($rating['data']))
  9794. {
  9795. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9796. }
  9797. $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
  9798. }
  9799. }
  9800. elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
  9801. {
  9802. foreach ($ratings as $rating)
  9803. {
  9804. $rating_scheme = 'urn:itunes';
  9805. $rating_value = null;
  9806. if (isset($rating['data']))
  9807. {
  9808. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9809. }
  9810. $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
  9811. }
  9812. }
  9813. if (is_array($ratings_parent))
  9814. {
  9815. $ratings_parent = array_values(array_unique($ratings_parent));
  9816. }
  9817. // RESTRICTIONS
  9818. if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
  9819. {
  9820. foreach ($restrictions as $restriction)
  9821. {
  9822. $restriction_relationship = null;
  9823. $restriction_type = null;
  9824. $restriction_value = null;
  9825. if (isset($restriction['attribs']['']['relationship']))
  9826. {
  9827. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  9828. }
  9829. if (isset($restriction['attribs']['']['type']))
  9830. {
  9831. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  9832. }
  9833. if (isset($restriction['data']))
  9834. {
  9835. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9836. }
  9837. $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
  9838. }
  9839. }
  9840. elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
  9841. {
  9842. foreach ($restrictions as $restriction)
  9843. {
  9844. $restriction_relationship = 'allow';
  9845. $restriction_type = null;
  9846. $restriction_value = 'itunes';
  9847. if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
  9848. {
  9849. $restriction_relationship = 'deny';
  9850. }
  9851. $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
  9852. }
  9853. }
  9854. elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
  9855. {
  9856. foreach ($restrictions as $restriction)
  9857. {
  9858. $restriction_relationship = null;
  9859. $restriction_type = null;
  9860. $restriction_value = null;
  9861. if (isset($restriction['attribs']['']['relationship']))
  9862. {
  9863. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  9864. }
  9865. if (isset($restriction['attribs']['']['type']))
  9866. {
  9867. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  9868. }
  9869. if (isset($restriction['data']))
  9870. {
  9871. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9872. }
  9873. $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
  9874. }
  9875. }
  9876. elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
  9877. {
  9878. foreach ($restrictions as $restriction)
  9879. {
  9880. $restriction_relationship = 'allow';
  9881. $restriction_type = null;
  9882. $restriction_value = 'itunes';
  9883. if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
  9884. {
  9885. $restriction_relationship = 'deny';
  9886. }
  9887. $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
  9888. }
  9889. }
  9890. if (is_array($restrictions_parent))
  9891. {
  9892. $restrictions_parent = array_values(array_unique($restrictions_parent));
  9893. }
  9894. else
  9895. {
  9896. $restrictions_parent = array(new SimplePie_Restriction('allow', null, 'default'));
  9897. }
  9898. // THUMBNAILS
  9899. if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
  9900. {
  9901. foreach ($thumbnails as $thumbnail)
  9902. {
  9903. if (isset($thumbnail['attribs']['']['url']))
  9904. {
  9905. $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  9906. }
  9907. }
  9908. }
  9909. elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
  9910. {
  9911. foreach ($thumbnails as $thumbnail)
  9912. {
  9913. if (isset($thumbnail['attribs']['']['url']))
  9914. {
  9915. $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  9916. }
  9917. }
  9918. }
  9919. // TITLES
  9920. if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
  9921. {
  9922. if (isset($title_parent[0]['data']))
  9923. {
  9924. $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9925. }
  9926. }
  9927. elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
  9928. {
  9929. if (isset($title_parent[0]['data']))
  9930. {
  9931. $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  9932. }
  9933. }
  9934. // Clear the memory
  9935. unset($parent);
  9936. // Attributes
  9937. $bitrate = null;
  9938. $channels = null;
  9939. $duration = null;
  9940. $expression = null;
  9941. $framerate = null;
  9942. $height = null;
  9943. $javascript = null;
  9944. $lang = null;
  9945. $length = null;
  9946. $medium = null;
  9947. $samplingrate = null;
  9948. $type = null;
  9949. $url = null;
  9950. $width = null;
  9951. // Elements
  9952. $captions = null;
  9953. $categories = null;
  9954. $copyrights = null;
  9955. $credits = null;
  9956. $description = null;
  9957. $hashes = null;
  9958. $keywords = null;
  9959. $player = null;
  9960. $ratings = null;
  9961. $restrictions = null;
  9962. $thumbnails = null;
  9963. $title = null;
  9964. // If we have media:group tags, loop through them.
  9965. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
  9966. {
  9967. if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
  9968. {
  9969. // If we have media:content tags, loop through them.
  9970. foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
  9971. {
  9972. if (isset($content['attribs']['']['url']))
  9973. {
  9974. // Attributes
  9975. $bitrate = null;
  9976. $channels = null;
  9977. $duration = null;
  9978. $expression = null;
  9979. $framerate = null;
  9980. $height = null;
  9981. $javascript = null;
  9982. $lang = null;
  9983. $length = null;
  9984. $medium = null;
  9985. $samplingrate = null;
  9986. $type = null;
  9987. $url = null;
  9988. $width = null;
  9989. // Elements
  9990. $captions = null;
  9991. $categories = null;
  9992. $copyrights = null;
  9993. $credits = null;
  9994. $description = null;
  9995. $hashes = null;
  9996. $keywords = null;
  9997. $player = null;
  9998. $ratings = null;
  9999. $restrictions = null;
  10000. $thumbnails = null;
  10001. $title = null;
  10002. // Start checking the attributes of media:content
  10003. if (isset($content['attribs']['']['bitrate']))
  10004. {
  10005. $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  10006. }
  10007. if (isset($content['attribs']['']['channels']))
  10008. {
  10009. $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
  10010. }
  10011. if (isset($content['attribs']['']['duration']))
  10012. {
  10013. $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
  10014. }
  10015. else
  10016. {
  10017. $duration = $duration_parent;
  10018. }
  10019. if (isset($content['attribs']['']['expression']))
  10020. {
  10021. $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
  10022. }
  10023. if (isset($content['attribs']['']['framerate']))
  10024. {
  10025. $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
  10026. }
  10027. if (isset($content['attribs']['']['height']))
  10028. {
  10029. $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
  10030. }
  10031. if (isset($content['attribs']['']['lang']))
  10032. {
  10033. $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  10034. }
  10035. if (isset($content['attribs']['']['fileSize']))
  10036. {
  10037. $length = ceil($content['attribs']['']['fileSize']);
  10038. }
  10039. if (isset($content['attribs']['']['medium']))
  10040. {
  10041. $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
  10042. }
  10043. if (isset($content['attribs']['']['samplingrate']))
  10044. {
  10045. $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  10046. }
  10047. if (isset($content['attribs']['']['type']))
  10048. {
  10049. $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  10050. }
  10051. if (isset($content['attribs']['']['width']))
  10052. {
  10053. $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
  10054. }
  10055. $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  10056. // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
  10057. // CAPTIONS
  10058. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
  10059. {
  10060. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
  10061. {
  10062. $caption_type = null;
  10063. $caption_lang = null;
  10064. $caption_startTime = null;
  10065. $caption_endTime = null;
  10066. $caption_text = null;
  10067. if (isset($caption['attribs']['']['type']))
  10068. {
  10069. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  10070. }
  10071. if (isset($caption['attribs']['']['lang']))
  10072. {
  10073. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  10074. }
  10075. if (isset($caption['attribs']['']['start']))
  10076. {
  10077. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  10078. }
  10079. if (isset($caption['attribs']['']['end']))
  10080. {
  10081. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  10082. }
  10083. if (isset($caption['data']))
  10084. {
  10085. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10086. }
  10087. $captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
  10088. }
  10089. if (is_array($captions))
  10090. {
  10091. $captions = array_values(array_unique($captions));
  10092. }
  10093. }
  10094. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
  10095. {
  10096. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
  10097. {
  10098. $caption_type = null;
  10099. $caption_lang = null;
  10100. $caption_startTime = null;
  10101. $caption_endTime = null;
  10102. $caption_text = null;
  10103. if (isset($caption['attribs']['']['type']))
  10104. {
  10105. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  10106. }
  10107. if (isset($caption['attribs']['']['lang']))
  10108. {
  10109. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  10110. }
  10111. if (isset($caption['attribs']['']['start']))
  10112. {
  10113. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  10114. }
  10115. if (isset($caption['attribs']['']['end']))
  10116. {
  10117. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  10118. }
  10119. if (isset($caption['data']))
  10120. {
  10121. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10122. }
  10123. $captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
  10124. }
  10125. if (is_array($captions))
  10126. {
  10127. $captions = array_values(array_unique($captions));
  10128. }
  10129. }
  10130. else
  10131. {
  10132. $captions = $captions_parent;
  10133. }
  10134. // CATEGORIES
  10135. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
  10136. {
  10137. foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
  10138. {
  10139. $term = null;
  10140. $scheme = null;
  10141. $label = null;
  10142. if (isset($category['data']))
  10143. {
  10144. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10145. }
  10146. if (isset($category['attribs']['']['scheme']))
  10147. {
  10148. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  10149. }
  10150. else
  10151. {
  10152. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  10153. }
  10154. if (isset($category['attribs']['']['label']))
  10155. {
  10156. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  10157. }
  10158. $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
  10159. }
  10160. }
  10161. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
  10162. {
  10163. foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
  10164. {
  10165. $term = null;
  10166. $scheme = null;
  10167. $label = null;
  10168. if (isset($category['data']))
  10169. {
  10170. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10171. }
  10172. if (isset($category['attribs']['']['scheme']))
  10173. {
  10174. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  10175. }
  10176. else
  10177. {
  10178. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  10179. }
  10180. if (isset($category['attribs']['']['label']))
  10181. {
  10182. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  10183. }
  10184. $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
  10185. }
  10186. }
  10187. if (is_array($categories) && is_array($categories_parent))
  10188. {
  10189. $categories = array_values(array_unique(array_merge($categories, $categories_parent)));
  10190. }
  10191. elseif (is_array($categories))
  10192. {
  10193. $categories = array_values(array_unique($categories));
  10194. }
  10195. elseif (is_array($categories_parent))
  10196. {
  10197. $categories = array_values(array_unique($categories_parent));
  10198. }
  10199. // COPYRIGHTS
  10200. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
  10201. {
  10202. $copyright_url = null;
  10203. $copyright_label = null;
  10204. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
  10205. {
  10206. $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  10207. }
  10208. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
  10209. {
  10210. $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10211. }
  10212. $copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
  10213. }
  10214. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
  10215. {
  10216. $copyright_url = null;
  10217. $copyright_label = null;
  10218. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
  10219. {
  10220. $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  10221. }
  10222. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
  10223. {
  10224. $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10225. }
  10226. $copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
  10227. }
  10228. else
  10229. {
  10230. $copyrights = $copyrights_parent;
  10231. }
  10232. // CREDITS
  10233. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
  10234. {
  10235. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
  10236. {
  10237. $credit_role = null;
  10238. $credit_scheme = null;
  10239. $credit_name = null;
  10240. if (isset($credit['attribs']['']['role']))
  10241. {
  10242. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  10243. }
  10244. if (isset($credit['attribs']['']['scheme']))
  10245. {
  10246. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  10247. }
  10248. else
  10249. {
  10250. $credit_scheme = 'urn:ebu';
  10251. }
  10252. if (isset($credit['data']))
  10253. {
  10254. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10255. }
  10256. $credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
  10257. }
  10258. if (is_array($credits))
  10259. {
  10260. $credits = array_values(array_unique($credits));
  10261. }
  10262. }
  10263. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
  10264. {
  10265. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
  10266. {
  10267. $credit_role = null;
  10268. $credit_scheme = null;
  10269. $credit_name = null;
  10270. if (isset($credit['attribs']['']['role']))
  10271. {
  10272. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  10273. }
  10274. if (isset($credit['attribs']['']['scheme']))
  10275. {
  10276. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  10277. }
  10278. else
  10279. {
  10280. $credit_scheme = 'urn:ebu';
  10281. }
  10282. if (isset($credit['data']))
  10283. {
  10284. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10285. }
  10286. $credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
  10287. }
  10288. if (is_array($credits))
  10289. {
  10290. $credits = array_values(array_unique($credits));
  10291. }
  10292. }
  10293. else
  10294. {
  10295. $credits = $credits_parent;
  10296. }
  10297. // DESCRIPTION
  10298. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
  10299. {
  10300. $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10301. }
  10302. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
  10303. {
  10304. $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10305. }
  10306. else
  10307. {
  10308. $description = $description_parent;
  10309. }
  10310. // HASHES
  10311. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
  10312. {
  10313. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
  10314. {
  10315. $value = null;
  10316. $algo = null;
  10317. if (isset($hash['data']))
  10318. {
  10319. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10320. }
  10321. if (isset($hash['attribs']['']['algo']))
  10322. {
  10323. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  10324. }
  10325. else
  10326. {
  10327. $algo = 'md5';
  10328. }
  10329. $hashes[] = $algo.':'.$value;
  10330. }
  10331. if (is_array($hashes))
  10332. {
  10333. $hashes = array_values(array_unique($hashes));
  10334. }
  10335. }
  10336. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
  10337. {
  10338. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
  10339. {
  10340. $value = null;
  10341. $algo = null;
  10342. if (isset($hash['data']))
  10343. {
  10344. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10345. }
  10346. if (isset($hash['attribs']['']['algo']))
  10347. {
  10348. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  10349. }
  10350. else
  10351. {
  10352. $algo = 'md5';
  10353. }
  10354. $hashes[] = $algo.':'.$value;
  10355. }
  10356. if (is_array($hashes))
  10357. {
  10358. $hashes = array_values(array_unique($hashes));
  10359. }
  10360. }
  10361. else
  10362. {
  10363. $hashes = $hashes_parent;
  10364. }
  10365. // KEYWORDS
  10366. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
  10367. {
  10368. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
  10369. {
  10370. $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  10371. foreach ($temp as $word)
  10372. {
  10373. $keywords[] = trim($word);
  10374. }
  10375. unset($temp);
  10376. }
  10377. if (is_array($keywords))
  10378. {
  10379. $keywords = array_values(array_unique($keywords));
  10380. }
  10381. }
  10382. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
  10383. {
  10384. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
  10385. {
  10386. $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  10387. foreach ($temp as $word)
  10388. {
  10389. $keywords[] = trim($word);
  10390. }
  10391. unset($temp);
  10392. }
  10393. if (is_array($keywords))
  10394. {
  10395. $keywords = array_values(array_unique($keywords));
  10396. }
  10397. }
  10398. else
  10399. {
  10400. $keywords = $keywords_parent;
  10401. }
  10402. // PLAYER
  10403. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  10404. {
  10405. $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  10406. }
  10407. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  10408. {
  10409. $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  10410. }
  10411. else
  10412. {
  10413. $player = $player_parent;
  10414. }
  10415. // RATINGS
  10416. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
  10417. {
  10418. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
  10419. {
  10420. $rating_scheme = null;
  10421. $rating_value = null;
  10422. if (isset($rating['attribs']['']['scheme']))
  10423. {
  10424. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  10425. }
  10426. else
  10427. {
  10428. $rating_scheme = 'urn:simple';
  10429. }
  10430. if (isset($rating['data']))
  10431. {
  10432. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10433. }
  10434. $ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
  10435. }
  10436. if (is_array($ratings))
  10437. {
  10438. $ratings = array_values(array_unique($ratings));
  10439. }
  10440. }
  10441. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
  10442. {
  10443. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
  10444. {
  10445. $rating_scheme = null;
  10446. $rating_value = null;
  10447. if (isset($rating['attribs']['']['scheme']))
  10448. {
  10449. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  10450. }
  10451. else
  10452. {
  10453. $rating_scheme = 'urn:simple';
  10454. }
  10455. if (isset($rating['data']))
  10456. {
  10457. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10458. }
  10459. $ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
  10460. }
  10461. if (is_array($ratings))
  10462. {
  10463. $ratings = array_values(array_unique($ratings));
  10464. }
  10465. }
  10466. else
  10467. {
  10468. $ratings = $ratings_parent;
  10469. }
  10470. // RESTRICTIONS
  10471. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
  10472. {
  10473. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
  10474. {
  10475. $restriction_relationship = null;
  10476. $restriction_type = null;
  10477. $restriction_value = null;
  10478. if (isset($restriction['attribs']['']['relationship']))
  10479. {
  10480. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  10481. }
  10482. if (isset($restriction['attribs']['']['type']))
  10483. {
  10484. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  10485. }
  10486. if (isset($restriction['data']))
  10487. {
  10488. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10489. }
  10490. $restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
  10491. }
  10492. if (is_array($restrictions))
  10493. {
  10494. $restrictions = array_values(array_unique($restrictions));
  10495. }
  10496. }
  10497. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
  10498. {
  10499. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
  10500. {
  10501. $restriction_relationship = null;
  10502. $restriction_type = null;
  10503. $restriction_value = null;
  10504. if (isset($restriction['attribs']['']['relationship']))
  10505. {
  10506. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  10507. }
  10508. if (isset($restriction['attribs']['']['type']))
  10509. {
  10510. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  10511. }
  10512. if (isset($restriction['data']))
  10513. {
  10514. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10515. }
  10516. $restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
  10517. }
  10518. if (is_array($restrictions))
  10519. {
  10520. $restrictions = array_values(array_unique($restrictions));
  10521. }
  10522. }
  10523. else
  10524. {
  10525. $restrictions = $restrictions_parent;
  10526. }
  10527. // THUMBNAILS
  10528. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
  10529. {
  10530. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
  10531. {
  10532. $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  10533. }
  10534. if (is_array($thumbnails))
  10535. {
  10536. $thumbnails = array_values(array_unique($thumbnails));
  10537. }
  10538. }
  10539. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
  10540. {
  10541. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
  10542. {
  10543. $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  10544. }
  10545. if (is_array($thumbnails))
  10546. {
  10547. $thumbnails = array_values(array_unique($thumbnails));
  10548. }
  10549. }
  10550. else
  10551. {
  10552. $thumbnails = $thumbnails_parent;
  10553. }
  10554. // TITLES
  10555. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
  10556. {
  10557. $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10558. }
  10559. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
  10560. {
  10561. $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10562. }
  10563. else
  10564. {
  10565. $title = $title_parent;
  10566. }
  10567. $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width));
  10568. }
  10569. }
  10570. }
  10571. }
  10572. // If we have standalone media:content tags, loop through them.
  10573. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
  10574. {
  10575. foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
  10576. {
  10577. if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  10578. {
  10579. // Attributes
  10580. $bitrate = null;
  10581. $channels = null;
  10582. $duration = null;
  10583. $expression = null;
  10584. $framerate = null;
  10585. $height = null;
  10586. $javascript = null;
  10587. $lang = null;
  10588. $length = null;
  10589. $medium = null;
  10590. $samplingrate = null;
  10591. $type = null;
  10592. $url = null;
  10593. $width = null;
  10594. // Elements
  10595. $captions = null;
  10596. $categories = null;
  10597. $copyrights = null;
  10598. $credits = null;
  10599. $description = null;
  10600. $hashes = null;
  10601. $keywords = null;
  10602. $player = null;
  10603. $ratings = null;
  10604. $restrictions = null;
  10605. $thumbnails = null;
  10606. $title = null;
  10607. // Start checking the attributes of media:content
  10608. if (isset($content['attribs']['']['bitrate']))
  10609. {
  10610. $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  10611. }
  10612. if (isset($content['attribs']['']['channels']))
  10613. {
  10614. $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
  10615. }
  10616. if (isset($content['attribs']['']['duration']))
  10617. {
  10618. $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
  10619. }
  10620. else
  10621. {
  10622. $duration = $duration_parent;
  10623. }
  10624. if (isset($content['attribs']['']['expression']))
  10625. {
  10626. $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
  10627. }
  10628. if (isset($content['attribs']['']['framerate']))
  10629. {
  10630. $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
  10631. }
  10632. if (isset($content['attribs']['']['height']))
  10633. {
  10634. $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
  10635. }
  10636. if (isset($content['attribs']['']['lang']))
  10637. {
  10638. $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  10639. }
  10640. if (isset($content['attribs']['']['fileSize']))
  10641. {
  10642. $length = ceil($content['attribs']['']['fileSize']);
  10643. }
  10644. if (isset($content['attribs']['']['medium']))
  10645. {
  10646. $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
  10647. }
  10648. if (isset($content['attribs']['']['samplingrate']))
  10649. {
  10650. $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  10651. }
  10652. if (isset($content['attribs']['']['type']))
  10653. {
  10654. $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  10655. }
  10656. if (isset($content['attribs']['']['width']))
  10657. {
  10658. $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
  10659. }
  10660. if (isset($content['attribs']['']['url']))
  10661. {
  10662. $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  10663. }
  10664. // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
  10665. // CAPTIONS
  10666. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
  10667. {
  10668. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
  10669. {
  10670. $caption_type = null;
  10671. $caption_lang = null;
  10672. $caption_startTime = null;
  10673. $caption_endTime = null;
  10674. $caption_text = null;
  10675. if (isset($caption['attribs']['']['type']))
  10676. {
  10677. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  10678. }
  10679. if (isset($caption['attribs']['']['lang']))
  10680. {
  10681. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  10682. }
  10683. if (isset($caption['attribs']['']['start']))
  10684. {
  10685. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  10686. }
  10687. if (isset($caption['attribs']['']['end']))
  10688. {
  10689. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  10690. }
  10691. if (isset($caption['data']))
  10692. {
  10693. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10694. }
  10695. $captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
  10696. }
  10697. if (is_array($captions))
  10698. {
  10699. $captions = array_values(array_unique($captions));
  10700. }
  10701. }
  10702. else
  10703. {
  10704. $captions = $captions_parent;
  10705. }
  10706. // CATEGORIES
  10707. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
  10708. {
  10709. foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
  10710. {
  10711. $term = null;
  10712. $scheme = null;
  10713. $label = null;
  10714. if (isset($category['data']))
  10715. {
  10716. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10717. }
  10718. if (isset($category['attribs']['']['scheme']))
  10719. {
  10720. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  10721. }
  10722. else
  10723. {
  10724. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  10725. }
  10726. if (isset($category['attribs']['']['label']))
  10727. {
  10728. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  10729. }
  10730. $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
  10731. }
  10732. }
  10733. if (is_array($categories) && is_array($categories_parent))
  10734. {
  10735. $categories = array_values(array_unique(array_merge($categories, $categories_parent)));
  10736. }
  10737. elseif (is_array($categories))
  10738. {
  10739. $categories = array_values(array_unique($categories));
  10740. }
  10741. elseif (is_array($categories_parent))
  10742. {
  10743. $categories = array_values(array_unique($categories_parent));
  10744. }
  10745. else
  10746. {
  10747. $categories = null;
  10748. }
  10749. // COPYRIGHTS
  10750. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
  10751. {
  10752. $copyright_url = null;
  10753. $copyright_label = null;
  10754. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
  10755. {
  10756. $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  10757. }
  10758. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
  10759. {
  10760. $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10761. }
  10762. $copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
  10763. }
  10764. else
  10765. {
  10766. $copyrights = $copyrights_parent;
  10767. }
  10768. // CREDITS
  10769. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
  10770. {
  10771. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
  10772. {
  10773. $credit_role = null;
  10774. $credit_scheme = null;
  10775. $credit_name = null;
  10776. if (isset($credit['attribs']['']['role']))
  10777. {
  10778. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  10779. }
  10780. if (isset($credit['attribs']['']['scheme']))
  10781. {
  10782. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  10783. }
  10784. else
  10785. {
  10786. $credit_scheme = 'urn:ebu';
  10787. }
  10788. if (isset($credit['data']))
  10789. {
  10790. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10791. }
  10792. $credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
  10793. }
  10794. if (is_array($credits))
  10795. {
  10796. $credits = array_values(array_unique($credits));
  10797. }
  10798. }
  10799. else
  10800. {
  10801. $credits = $credits_parent;
  10802. }
  10803. // DESCRIPTION
  10804. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
  10805. {
  10806. $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10807. }
  10808. else
  10809. {
  10810. $description = $description_parent;
  10811. }
  10812. // HASHES
  10813. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
  10814. {
  10815. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
  10816. {
  10817. $value = null;
  10818. $algo = null;
  10819. if (isset($hash['data']))
  10820. {
  10821. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10822. }
  10823. if (isset($hash['attribs']['']['algo']))
  10824. {
  10825. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  10826. }
  10827. else
  10828. {
  10829. $algo = 'md5';
  10830. }
  10831. $hashes[] = $algo.':'.$value;
  10832. }
  10833. if (is_array($hashes))
  10834. {
  10835. $hashes = array_values(array_unique($hashes));
  10836. }
  10837. }
  10838. else
  10839. {
  10840. $hashes = $hashes_parent;
  10841. }
  10842. // KEYWORDS
  10843. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
  10844. {
  10845. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
  10846. {
  10847. $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  10848. foreach ($temp as $word)
  10849. {
  10850. $keywords[] = trim($word);
  10851. }
  10852. unset($temp);
  10853. }
  10854. if (is_array($keywords))
  10855. {
  10856. $keywords = array_values(array_unique($keywords));
  10857. }
  10858. }
  10859. else
  10860. {
  10861. $keywords = $keywords_parent;
  10862. }
  10863. // PLAYER
  10864. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  10865. {
  10866. $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  10867. }
  10868. else
  10869. {
  10870. $player = $player_parent;
  10871. }
  10872. // RATINGS
  10873. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
  10874. {
  10875. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
  10876. {
  10877. $rating_scheme = null;
  10878. $rating_value = null;
  10879. if (isset($rating['attribs']['']['scheme']))
  10880. {
  10881. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  10882. }
  10883. else
  10884. {
  10885. $rating_scheme = 'urn:simple';
  10886. }
  10887. if (isset($rating['data']))
  10888. {
  10889. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10890. }
  10891. $ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
  10892. }
  10893. if (is_array($ratings))
  10894. {
  10895. $ratings = array_values(array_unique($ratings));
  10896. }
  10897. }
  10898. else
  10899. {
  10900. $ratings = $ratings_parent;
  10901. }
  10902. // RESTRICTIONS
  10903. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
  10904. {
  10905. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
  10906. {
  10907. $restriction_relationship = null;
  10908. $restriction_type = null;
  10909. $restriction_value = null;
  10910. if (isset($restriction['attribs']['']['relationship']))
  10911. {
  10912. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  10913. }
  10914. if (isset($restriction['attribs']['']['type']))
  10915. {
  10916. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  10917. }
  10918. if (isset($restriction['data']))
  10919. {
  10920. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10921. }
  10922. $restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
  10923. }
  10924. if (is_array($restrictions))
  10925. {
  10926. $restrictions = array_values(array_unique($restrictions));
  10927. }
  10928. }
  10929. else
  10930. {
  10931. $restrictions = $restrictions_parent;
  10932. }
  10933. // THUMBNAILS
  10934. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
  10935. {
  10936. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
  10937. {
  10938. $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  10939. }
  10940. if (is_array($thumbnails))
  10941. {
  10942. $thumbnails = array_values(array_unique($thumbnails));
  10943. }
  10944. }
  10945. else
  10946. {
  10947. $thumbnails = $thumbnails_parent;
  10948. }
  10949. // TITLES
  10950. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
  10951. {
  10952. $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  10953. }
  10954. else
  10955. {
  10956. $title = $title_parent;
  10957. }
  10958. $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width));
  10959. }
  10960. }
  10961. }
  10962. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
  10963. {
  10964. if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
  10965. {
  10966. // Attributes
  10967. $bitrate = null;
  10968. $channels = null;
  10969. $duration = null;
  10970. $expression = null;
  10971. $framerate = null;
  10972. $height = null;
  10973. $javascript = null;
  10974. $lang = null;
  10975. $length = null;
  10976. $medium = null;
  10977. $samplingrate = null;
  10978. $type = null;
  10979. $url = null;
  10980. $width = null;
  10981. $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  10982. if (isset($link['attribs']['']['type']))
  10983. {
  10984. $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  10985. }
  10986. if (isset($link['attribs']['']['length']))
  10987. {
  10988. $length = ceil($link['attribs']['']['length']);
  10989. }
  10990. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  10991. $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width));
  10992. }
  10993. }
  10994. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
  10995. {
  10996. if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
  10997. {
  10998. // Attributes
  10999. $bitrate = null;
  11000. $channels = null;
  11001. $duration = null;
  11002. $expression = null;
  11003. $framerate = null;
  11004. $height = null;
  11005. $javascript = null;
  11006. $lang = null;
  11007. $length = null;
  11008. $medium = null;
  11009. $samplingrate = null;
  11010. $type = null;
  11011. $url = null;
  11012. $width = null;
  11013. $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  11014. if (isset($link['attribs']['']['type']))
  11015. {
  11016. $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  11017. }
  11018. if (isset($link['attribs']['']['length']))
  11019. {
  11020. $length = ceil($link['attribs']['']['length']);
  11021. }
  11022. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  11023. $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width));
  11024. }
  11025. }
  11026. if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
  11027. {
  11028. if (isset($enclosure[0]['attribs']['']['url']))
  11029. {
  11030. // Attributes
  11031. $bitrate = null;
  11032. $channels = null;
  11033. $duration = null;
  11034. $expression = null;
  11035. $framerate = null;
  11036. $height = null;
  11037. $javascript = null;
  11038. $lang = null;
  11039. $length = null;
  11040. $medium = null;
  11041. $samplingrate = null;
  11042. $type = null;
  11043. $url = null;
  11044. $width = null;
  11045. $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
  11046. if (isset($enclosure[0]['attribs']['']['type']))
  11047. {
  11048. $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  11049. }
  11050. if (isset($enclosure[0]['attribs']['']['length']))
  11051. {
  11052. $length = ceil($enclosure[0]['attribs']['']['length']);
  11053. }
  11054. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  11055. $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width));
  11056. }
  11057. }
  11058. if (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width))
  11059. {
  11060. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  11061. $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width));
  11062. }
  11063. $this->data['enclosures'] = array_values(array_unique($this->data['enclosures']));
  11064. }
  11065. if (!empty($this->data['enclosures']))
  11066. {
  11067. return $this->data['enclosures'];
  11068. }
  11069. else
  11070. {
  11071. return null;
  11072. }
  11073. }
  11074. /**
  11075. * Get the latitude coordinates for the item
  11076. *
  11077. * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
  11078. *
  11079. * Uses `<geo:lat>` or `<georss:point>`
  11080. *
  11081. * @since 1.0
  11082. * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
  11083. * @link http://www.georss.org/ GeoRSS
  11084. * @return string|null
  11085. */
  11086. public function get_latitude()
  11087. {
  11088. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  11089. {
  11090. return (float) $return[0]['data'];
  11091. }
  11092. elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  11093. {
  11094. return (float) $match[1];
  11095. }
  11096. else
  11097. {
  11098. return null;
  11099. }
  11100. }
  11101. /**
  11102. * Get the longitude coordinates for the item
  11103. *
  11104. * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
  11105. *
  11106. * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
  11107. *
  11108. * @since 1.0
  11109. * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
  11110. * @link http://www.georss.org/ GeoRSS
  11111. * @return string|null
  11112. */
  11113. public function get_longitude()
  11114. {
  11115. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  11116. {
  11117. return (float) $return[0]['data'];
  11118. }
  11119. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  11120. {
  11121. return (float) $return[0]['data'];
  11122. }
  11123. elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  11124. {
  11125. return (float) $match[2];
  11126. }
  11127. else
  11128. {
  11129. return null;
  11130. }
  11131. }
  11132. /**
  11133. * Get the `<atom:source>` for the item
  11134. *
  11135. * @since 1.1
  11136. * @return SimplePie_Source|null
  11137. */
  11138. public function get_source()
  11139. {
  11140. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
  11141. {
  11142. return $this->registry->create('Source', array($this, $return[0]));
  11143. }
  11144. else
  11145. {
  11146. return null;
  11147. }
  11148. }
  11149. }
  11150. /**
  11151. * Used for feed auto-discovery
  11152. *
  11153. *
  11154. * This class can be overloaded with {@see SimplePie::set_locator_class()}
  11155. *
  11156. * @package SimplePie
  11157. */
  11158. class SimplePie_Locator
  11159. {
  11160. var $useragent;
  11161. var $timeout;
  11162. var $file;
  11163. var $local = array();
  11164. var $elsewhere = array();
  11165. var $cached_entities = array();
  11166. var $http_base;
  11167. var $base;
  11168. var $base_location = 0;
  11169. var $checked_feeds = 0;
  11170. var $max_checked_feeds = 10;
  11171. protected $registry;
  11172. public function __construct(SimplePie_File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10)
  11173. {
  11174. $this->file = $file;
  11175. $this->useragent = $useragent;
  11176. $this->timeout = $timeout;
  11177. $this->max_checked_feeds = $max_checked_feeds;
  11178. if (class_exists('DOMDocument'))
  11179. {
  11180. $this->dom = new DOMDocument();
  11181. set_error_handler(array('SimplePie_Misc', 'silence_errors'));
  11182. $this->dom->loadHTML($this->file->body);
  11183. restore_error_handler();
  11184. }
  11185. else
  11186. {
  11187. $this->dom = null;
  11188. }
  11189. }
  11190. public function set_registry(SimplePie_Registry $registry)
  11191. {
  11192. $this->registry = $registry;
  11193. }
  11194. public function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
  11195. {
  11196. if ($this->is_feed($this->file))
  11197. {
  11198. return $this->file;
  11199. }
  11200. if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
  11201. {
  11202. $sniffer = $this->registry->create('Content_Type_Sniffer', array($this->file));
  11203. if ($sniffer->get_type() !== 'text/html')
  11204. {
  11205. return null;
  11206. }
  11207. }
  11208. if ($type & ~SIMPLEPIE_LOCATOR_NONE)
  11209. {
  11210. $this->get_base();
  11211. }
  11212. if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
  11213. {
  11214. return $working[0];
  11215. }
  11216. if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
  11217. {
  11218. if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
  11219. {
  11220. return $working;
  11221. }
  11222. if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
  11223. {
  11224. return $working;
  11225. }
  11226. if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
  11227. {
  11228. return $working;
  11229. }
  11230. if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
  11231. {
  11232. return $working;
  11233. }
  11234. }
  11235. return null;
  11236. }
  11237. public function is_feed($file)
  11238. {
  11239. if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
  11240. {
  11241. $sniffer = $this->registry->create('Content_Type_Sniffer', array($file));
  11242. $sniffed = $sniffer->get_type();
  11243. if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
  11244. {
  11245. return true;
  11246. }
  11247. else
  11248. {
  11249. return false;
  11250. }
  11251. }
  11252. elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
  11253. {
  11254. return true;
  11255. }
  11256. else
  11257. {
  11258. return false;
  11259. }
  11260. }
  11261. public function get_base()
  11262. {
  11263. if ($this->dom === null)
  11264. {
  11265. throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
  11266. }
  11267. $this->http_base = $this->file->url;
  11268. $this->base = $this->http_base;
  11269. $elements = $this->dom->getElementsByTagName('base');
  11270. foreach ($elements as $element)
  11271. {
  11272. if ($element->hasAttribute('href'))
  11273. {
  11274. $base = $this->registry->call('Misc', 'absolutize_url', array(trim($element->getAttribute('href')), $this->http_base));
  11275. if ($base === false)
  11276. {
  11277. continue;
  11278. }
  11279. $this->base = $base;
  11280. $this->base_location = method_exists($element, 'getLineNo') ? $element->getLineNo() : 0;
  11281. break;
  11282. }
  11283. }
  11284. }
  11285. public function autodiscovery()
  11286. {
  11287. $done = array();
  11288. $feeds = array();
  11289. $feeds = array_merge($feeds, $this->search_elements_by_tag('link', $done, $feeds));
  11290. $feeds = array_merge($feeds, $this->search_elements_by_tag('a', $done, $feeds));
  11291. $feeds = array_merge($feeds, $this->search_elements_by_tag('area', $done, $feeds));
  11292. if (!empty($feeds))
  11293. {
  11294. return array_values($feeds);
  11295. }
  11296. else
  11297. {
  11298. return null;
  11299. }
  11300. }
  11301. protected function search_elements_by_tag($name, &$done, $feeds)
  11302. {
  11303. if ($this->dom === null)
  11304. {
  11305. throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
  11306. }
  11307. $links = $this->dom->getElementsByTagName($name);
  11308. foreach ($links as $link)
  11309. {
  11310. if ($this->checked_feeds === $this->max_checked_feeds)
  11311. {
  11312. break;
  11313. }
  11314. if ($link->hasAttribute('href') && $link->hasAttribute('rel'))
  11315. {
  11316. $rel = array_unique($this->registry->call('Misc', 'space_seperated_tokens', array(strtolower($link->getAttribute('rel')))));
  11317. $line = method_exists($link, 'getLineNo') ? $link->getLineNo() : 1;
  11318. if ($this->base_location < $line)
  11319. {
  11320. $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base));
  11321. }
  11322. else
  11323. {
  11324. $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base));
  11325. }
  11326. if ($href === false)
  11327. {
  11328. continue;
  11329. }
  11330. if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !in_array('stylesheet', $rel) && $link->hasAttribute('type') && in_array(strtolower($this->registry->call('Misc', 'parse_mime', array($link->getAttribute('type')))), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
  11331. {
  11332. $this->checked_feeds++;
  11333. $headers = array(
  11334. 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
  11335. );
  11336. $feed = $this->registry->create('File', array($href, $this->timeout, 5, $headers, $this->useragent));
  11337. if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
  11338. {
  11339. $feeds[$href] = $feed;
  11340. }
  11341. }
  11342. $done[] = $href;
  11343. }
  11344. }
  11345. return $feeds;
  11346. }
  11347. public function get_links()
  11348. {
  11349. if ($this->dom === null)
  11350. {
  11351. throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
  11352. }
  11353. $links = $this->dom->getElementsByTagName('a');
  11354. foreach ($links as $link)
  11355. {
  11356. if ($link->hasAttribute('href'))
  11357. {
  11358. $href = trim($link->getAttribute('href'));
  11359. $parsed = $this->registry->call('Misc', 'parse_url', array($href));
  11360. if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
  11361. {
  11362. if ($this->base_location < $link->getLineNo())
  11363. {
  11364. $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base));
  11365. }
  11366. else
  11367. {
  11368. $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base));
  11369. }
  11370. if ($href === false)
  11371. {
  11372. continue;
  11373. }
  11374. $current = $this->registry->call('Misc', 'parse_url', array($this->file->url));
  11375. if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
  11376. {
  11377. $this->local[] = $href;
  11378. }
  11379. else
  11380. {
  11381. $this->elsewhere[] = $href;
  11382. }
  11383. }
  11384. }
  11385. }
  11386. $this->local = array_unique($this->local);
  11387. $this->elsewhere = array_unique($this->elsewhere);
  11388. if (!empty($this->local) || !empty($this->elsewhere))
  11389. {
  11390. return true;
  11391. }
  11392. return null;
  11393. }
  11394. public function extension(&$array)
  11395. {
  11396. foreach ($array as $key => $value)
  11397. {
  11398. if ($this->checked_feeds === $this->max_checked_feeds)
  11399. {
  11400. break;
  11401. }
  11402. if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
  11403. {
  11404. $this->checked_feeds++;
  11405. $headers = array(
  11406. 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
  11407. );
  11408. $feed = $this->registry->create('File', array($value, $this->timeout, 5, $headers, $this->useragent));
  11409. if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
  11410. {
  11411. return $feed;
  11412. }
  11413. else
  11414. {
  11415. unset($array[$key]);
  11416. }
  11417. }
  11418. }
  11419. return null;
  11420. }
  11421. public function body(&$array)
  11422. {
  11423. foreach ($array as $key => $value)
  11424. {
  11425. if ($this->checked_feeds === $this->max_checked_feeds)
  11426. {
  11427. break;
  11428. }
  11429. if (preg_match('/(rss|rdf|atom|xml)/i', $value))
  11430. {
  11431. $this->checked_feeds++;
  11432. $headers = array(
  11433. 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
  11434. );
  11435. $feed = $this->registry->create('File', array($value, $this->timeout, 5, null, $this->useragent));
  11436. if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
  11437. {
  11438. return $feed;
  11439. }
  11440. else
  11441. {
  11442. unset($array[$key]);
  11443. }
  11444. }
  11445. }
  11446. return null;
  11447. }
  11448. }
  11449. /**
  11450. * Miscellanous utilities
  11451. *
  11452. * @package SimplePie
  11453. */
  11454. class SimplePie_Misc
  11455. {
  11456. public static function time_hms($seconds)
  11457. {
  11458. $time = '';
  11459. $hours = floor($seconds / 3600);
  11460. $remainder = $seconds % 3600;
  11461. if ($hours > 0)
  11462. {
  11463. $time .= $hours.':';
  11464. }
  11465. $minutes = floor($remainder / 60);
  11466. $seconds = $remainder % 60;
  11467. if ($minutes < 10 && $hours > 0)
  11468. {
  11469. $minutes = '0' . $minutes;
  11470. }
  11471. if ($seconds < 10)
  11472. {
  11473. $seconds = '0' . $seconds;
  11474. }
  11475. $time .= $minutes.':';
  11476. $time .= $seconds;
  11477. return $time;
  11478. }
  11479. public static function absolutize_url($relative, $base)
  11480. {
  11481. $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
  11482. if ($iri === false)
  11483. {
  11484. return false;
  11485. }
  11486. return $iri->get_uri();
  11487. }
  11488. /**
  11489. * Get a HTML/XML element from a HTML string
  11490. *
  11491. * @deprecated Use DOMDocument instead (parsing HTML with regex is bad!)
  11492. * @param string $realname Element name (including namespace prefix if applicable)
  11493. * @param string $string HTML document
  11494. * @return array
  11495. */
  11496. public static function get_element($realname, $string)
  11497. {
  11498. $return = array();
  11499. $name = preg_quote($realname, '/');
  11500. if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
  11501. {
  11502. for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
  11503. {
  11504. $return[$i]['tag'] = $realname;
  11505. $return[$i]['full'] = $matches[$i][0][0];
  11506. $return[$i]['offset'] = $matches[$i][0][1];
  11507. if (strlen($matches[$i][3][0]) <= 2)
  11508. {
  11509. $return[$i]['self_closing'] = true;
  11510. }
  11511. else
  11512. {
  11513. $return[$i]['self_closing'] = false;
  11514. $return[$i]['content'] = $matches[$i][4][0];
  11515. }
  11516. $return[$i]['attribs'] = array();
  11517. if (isset($matches[$i][2][0]) && preg_match_all('/[\x09\x0A\x0B\x0C\x0D\x20]+([^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*)(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"([^"]*)"|\'([^\']*)\'|([^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER))
  11518. {
  11519. for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
  11520. {
  11521. if (count($attribs[$j]) === 2)
  11522. {
  11523. $attribs[$j][2] = $attribs[$j][1];
  11524. }
  11525. $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
  11526. }
  11527. }
  11528. }
  11529. }
  11530. return $return;
  11531. }
  11532. public static function element_implode($element)
  11533. {
  11534. $full = "<$element[tag]";
  11535. foreach ($element['attribs'] as $key => $value)
  11536. {
  11537. $key = strtolower($key);
  11538. $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
  11539. }
  11540. if ($element['self_closing'])
  11541. {
  11542. $full .= ' />';
  11543. }
  11544. else
  11545. {
  11546. $full .= ">$element[content]</$element[tag]>";
  11547. }
  11548. return $full;
  11549. }
  11550. public static function error($message, $level, $file, $line)
  11551. {
  11552. if ((ini_get('error_reporting') & $level) > 0)
  11553. {
  11554. switch ($level)
  11555. {
  11556. case E_USER_ERROR:
  11557. $note = 'PHP Error';
  11558. break;
  11559. case E_USER_WARNING:
  11560. $note = 'PHP Warning';
  11561. break;
  11562. case E_USER_NOTICE:
  11563. $note = 'PHP Notice';
  11564. break;
  11565. default:
  11566. $note = 'Unknown Error';
  11567. break;
  11568. }
  11569. $log_error = true;
  11570. if (!function_exists('error_log'))
  11571. {
  11572. $log_error = false;
  11573. }
  11574. $log_file = @ini_get('error_log');
  11575. if (!empty($log_file) && ('syslog' !== $log_file) && !@is_writable($log_file))
  11576. {
  11577. $log_error = false;
  11578. }
  11579. if ($log_error)
  11580. {
  11581. @error_log("$note: $message in $file on line $line", 0);
  11582. }
  11583. }
  11584. return $message;
  11585. }
  11586. public static function fix_protocol($url, $http = 1)
  11587. {
  11588. $url = SimplePie_Misc::normalize_url($url);
  11589. $parsed = SimplePie_Misc::parse_url($url);
  11590. if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
  11591. {
  11592. return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
  11593. }
  11594. if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
  11595. {
  11596. return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
  11597. }
  11598. if ($http === 2 && $parsed['scheme'] !== '')
  11599. {
  11600. return "feed:$url";
  11601. }
  11602. elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
  11603. {
  11604. return substr_replace($url, 'podcast', 0, 4);
  11605. }
  11606. elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
  11607. {
  11608. return substr_replace($url, 'itpc', 0, 4);
  11609. }
  11610. else
  11611. {
  11612. return $url;
  11613. }
  11614. }
  11615. public static function parse_url($url)
  11616. {
  11617. $iri = new SimplePie_IRI($url);
  11618. return array(
  11619. 'scheme' => (string) $iri->scheme,
  11620. 'authority' => (string) $iri->authority,
  11621. 'path' => (string) $iri->path,
  11622. 'query' => (string) $iri->query,
  11623. 'fragment' => (string) $iri->fragment
  11624. );
  11625. }
  11626. public static function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
  11627. {
  11628. $iri = new SimplePie_IRI('');
  11629. $iri->scheme = $scheme;
  11630. $iri->authority = $authority;
  11631. $iri->path = $path;
  11632. $iri->query = $query;
  11633. $iri->fragment = $fragment;
  11634. return $iri->get_uri();
  11635. }
  11636. public static function normalize_url($url)
  11637. {
  11638. $iri = new SimplePie_IRI($url);
  11639. return $iri->get_uri();
  11640. }
  11641. public static function percent_encoding_normalization($match)
  11642. {
  11643. $integer = hexdec($match[1]);
  11644. if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
  11645. {
  11646. return chr($integer);
  11647. }
  11648. else
  11649. {
  11650. return strtoupper($match[0]);
  11651. }
  11652. }
  11653. /**
  11654. * Converts a Windows-1252 encoded string to a UTF-8 encoded string
  11655. *
  11656. * @static
  11657. * @param string $string Windows-1252 encoded string
  11658. * @return string UTF-8 encoded string
  11659. */
  11660. public static function windows_1252_to_utf8($string)
  11661. {
  11662. static $convert_table = array("\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF");
  11663. return strtr($string, $convert_table);
  11664. }
  11665. /**
  11666. * Change a string from one encoding to another
  11667. *
  11668. * @param string $data Raw data in $input encoding
  11669. * @param string $input Encoding of $data
  11670. * @param string $output Encoding you want
  11671. * @return string|boolean False if we can't convert it
  11672. */
  11673. public static function change_encoding($data, $input, $output)
  11674. {
  11675. $input = SimplePie_Misc::encoding($input);
  11676. $output = SimplePie_Misc::encoding($output);
  11677. // We fail to fail on non US-ASCII bytes
  11678. if ($input === 'US-ASCII')
  11679. {
  11680. static $non_ascii_octects = '';
  11681. if (!$non_ascii_octects)
  11682. {
  11683. for ($i = 0x80; $i <= 0xFF; $i++)
  11684. {
  11685. $non_ascii_octects .= chr($i);
  11686. }
  11687. }
  11688. $data = substr($data, 0, strcspn($data, $non_ascii_octects));
  11689. }
  11690. // This is first, as behaviour of this is completely predictable
  11691. if ($input === 'windows-1252' && $output === 'UTF-8')
  11692. {
  11693. return SimplePie_Misc::windows_1252_to_utf8($data);
  11694. }
  11695. // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
  11696. elseif (function_exists('mb_convert_encoding') && ($return = SimplePie_Misc::change_encoding_mbstring($data, $input, $output)))
  11697. {
  11698. return $return;
  11699. }
  11700. // This is last, as behaviour of this varies with OS userland and PHP version
  11701. elseif (function_exists('iconv') && ($return = SimplePie_Misc::change_encoding_iconv($data, $input, $output)))
  11702. {
  11703. return $return;
  11704. }
  11705. // If we can't do anything, just fail
  11706. else
  11707. {
  11708. return false;
  11709. }
  11710. }
  11711. protected static function change_encoding_mbstring($data, $input, $output)
  11712. {
  11713. if ($input === 'windows-949')
  11714. {
  11715. $input = 'EUC-KR';
  11716. }
  11717. if ($output === 'windows-949')
  11718. {
  11719. $output = 'EUC-KR';
  11720. }
  11721. if ($input === 'Windows-31J')
  11722. {
  11723. $input = 'SJIS';
  11724. }
  11725. if ($output === 'Windows-31J')
  11726. {
  11727. $output = 'SJIS';
  11728. }
  11729. // Check that the encoding is supported
  11730. if (@mb_convert_encoding("\x80", 'UTF-16BE', $input) === "\x00\x80")
  11731. {
  11732. return false;
  11733. }
  11734. if (!in_array($input, mb_list_encodings()))
  11735. {
  11736. return false;
  11737. }
  11738. // Let's do some conversion
  11739. if ($return = @mb_convert_encoding($data, $output, $input))
  11740. {
  11741. return $return;
  11742. }
  11743. return false;
  11744. }
  11745. protected static function change_encoding_iconv($data, $input, $output)
  11746. {
  11747. return @iconv($input, $output, $data);
  11748. }
  11749. /**
  11750. * Normalize an encoding name
  11751. *
  11752. * This is automatically generated by create.php
  11753. *
  11754. * To generate it, run `php create.php` on the command line, and copy the
  11755. * output to replace this function.
  11756. *
  11757. * @param string $charset Character set to standardise
  11758. * @return string Standardised name
  11759. */
  11760. public static function encoding($charset)
  11761. {
  11762. // Normalization from UTS #22
  11763. switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
  11764. {
  11765. case 'adobestandardencoding':
  11766. case 'csadobestandardencoding':
  11767. return 'Adobe-Standard-Encoding';
  11768. case 'adobesymbolencoding':
  11769. case 'cshppsmath':
  11770. return 'Adobe-Symbol-Encoding';
  11771. case 'ami1251':
  11772. case 'amiga1251':
  11773. return 'Amiga-1251';
  11774. case 'ansix31101983':
  11775. case 'csat5001983':
  11776. case 'csiso99naplps':
  11777. case 'isoir99':
  11778. case 'naplps':
  11779. return 'ANSI_X3.110-1983';
  11780. case 'arabic7':
  11781. case 'asmo449':
  11782. case 'csiso89asmo449':
  11783. case 'iso9036':
  11784. case 'isoir89':
  11785. return 'ASMO_449';
  11786. case 'big5':
  11787. case 'csbig5':
  11788. return 'Big5';
  11789. case 'big5hkscs':
  11790. return 'Big5-HKSCS';
  11791. case 'bocu1':
  11792. case 'csbocu1':
  11793. return 'BOCU-1';
  11794. case 'brf':
  11795. case 'csbrf':
  11796. return 'BRF';
  11797. case 'bs4730':
  11798. case 'csiso4unitedkingdom':
  11799. case 'gb':
  11800. case 'iso646gb':
  11801. case 'isoir4':
  11802. case 'uk':
  11803. return 'BS_4730';
  11804. case 'bsviewdata':
  11805. case 'csiso47bsviewdata':
  11806. case 'isoir47':
  11807. return 'BS_viewdata';
  11808. case 'cesu8':
  11809. case 'cscesu8':
  11810. return 'CESU-8';
  11811. case 'ca':
  11812. case 'csa71':
  11813. case 'csaz243419851':
  11814. case 'csiso121canadian1':
  11815. case 'iso646ca':
  11816. case 'isoir121':
  11817. return 'CSA_Z243.4-1985-1';
  11818. case 'csa72':
  11819. case 'csaz243419852':
  11820. case 'csiso122canadian2':
  11821. case 'iso646ca2':
  11822. case 'isoir122':
  11823. return 'CSA_Z243.4-1985-2';
  11824. case 'csaz24341985gr':
  11825. case 'csiso123csaz24341985gr':
  11826. case 'isoir123':
  11827. return 'CSA_Z243.4-1985-gr';
  11828. case 'csiso139csn369103':
  11829. case 'csn369103':
  11830. case 'isoir139':
  11831. return 'CSN_369103';
  11832. case 'csdecmcs':
  11833. case 'dec':
  11834. case 'decmcs':
  11835. return 'DEC-MCS';
  11836. case 'csiso21german':
  11837. case 'de':
  11838. case 'din66003':
  11839. case 'iso646de':
  11840. case 'isoir21':
  11841. return 'DIN_66003';
  11842. case 'csdkus':
  11843. case 'dkus':
  11844. return 'dk-us';
  11845. case 'csiso646danish':
  11846. case 'dk':
  11847. case 'ds2089':
  11848. case 'iso646dk':
  11849. return 'DS_2089';
  11850. case 'csibmebcdicatde':
  11851. case 'ebcdicatde':
  11852. return 'EBCDIC-AT-DE';
  11853. case 'csebcdicatdea':
  11854. case 'ebcdicatdea':
  11855. return 'EBCDIC-AT-DE-A';
  11856. case 'csebcdiccafr':
  11857. case 'ebcdiccafr':
  11858. return 'EBCDIC-CA-FR';
  11859. case 'csebcdicdkno':
  11860. case 'ebcdicdkno':
  11861. return 'EBCDIC-DK-NO';
  11862. case 'csebcdicdknoa':
  11863. case 'ebcdicdknoa':
  11864. return 'EBCDIC-DK-NO-A';
  11865. case 'csebcdices':
  11866. case 'ebcdices':
  11867. return 'EBCDIC-ES';
  11868. case 'csebcdicesa':
  11869. case 'ebcdicesa':
  11870. return 'EBCDIC-ES-A';
  11871. case 'csebcdicess':
  11872. case 'ebcdicess':
  11873. return 'EBCDIC-ES-S';
  11874. case 'csebcdicfise':
  11875. case 'ebcdicfise':
  11876. return 'EBCDIC-FI-SE';
  11877. case 'csebcdicfisea':
  11878. case 'ebcdicfisea':
  11879. return 'EBCDIC-FI-SE-A';
  11880. case 'csebcdicfr':
  11881. case 'ebcdicfr':
  11882. return 'EBCDIC-FR';
  11883. case 'csebcdicit':
  11884. case 'ebcdicit':
  11885. return 'EBCDIC-IT';
  11886. case 'csebcdicpt':
  11887. case 'ebcdicpt':
  11888. return 'EBCDIC-PT';
  11889. case 'csebcdicuk':
  11890. case 'ebcdicuk':
  11891. return 'EBCDIC-UK';
  11892. case 'csebcdicus':
  11893. case 'ebcdicus':
  11894. return 'EBCDIC-US';
  11895. case 'csiso111ecmacyrillic':
  11896. case 'ecmacyrillic':
  11897. case 'isoir111':
  11898. case 'koi8e':
  11899. return 'ECMA-cyrillic';
  11900. case 'csiso17spanish':
  11901. case 'es':
  11902. case 'iso646es':
  11903. case 'isoir17':
  11904. return 'ES';
  11905. case 'csiso85spanish2':
  11906. case 'es2':
  11907. case 'iso646es2':
  11908. case 'isoir85':
  11909. return 'ES2';
  11910. case 'cseucpkdfmtjapanese':
  11911. case 'eucjp':
  11912. case 'extendedunixcodepackedformatforjapanese':
  11913. return 'EUC-JP';
  11914. case 'cseucfixwidjapanese':
  11915. case 'extendedunixcodefixedwidthforjapanese':
  11916. return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
  11917. case 'gb18030':
  11918. return 'GB18030';
  11919. case 'chinese':
  11920. case 'cp936':
  11921. case 'csgb2312':
  11922. case 'csiso58gb231280':
  11923. case 'gb2312':
  11924. case 'gb231280':
  11925. case 'gbk':
  11926. case 'isoir58':
  11927. case 'ms936':
  11928. case 'windows936':
  11929. return 'GBK';
  11930. case 'cn':
  11931. case 'csiso57gb1988':
  11932. case 'gb198880':
  11933. case 'iso646cn':
  11934. case 'isoir57':
  11935. return 'GB_1988-80';
  11936. case 'csiso153gost1976874':
  11937. case 'gost1976874':
  11938. case 'isoir153':
  11939. case 'stsev35888':
  11940. return 'GOST_19768-74';
  11941. case 'csiso150':
  11942. case 'csiso150greekccitt':
  11943. case 'greekccitt':
  11944. case 'isoir150':
  11945. return 'greek-ccitt';
  11946. case 'csiso88greek7':
  11947. case 'greek7':
  11948. case 'isoir88':
  11949. return 'greek7';
  11950. case 'csiso18greek7old':
  11951. case 'greek7old':
  11952. case 'isoir18':
  11953. return 'greek7-old';
  11954. case 'cshpdesktop':
  11955. case 'hpdesktop':
  11956. return 'HP-DeskTop';
  11957. case 'cshplegal':
  11958. case 'hplegal':
  11959. return 'HP-Legal';
  11960. case 'cshpmath8':
  11961. case 'hpmath8':
  11962. return 'HP-Math8';
  11963. case 'cshppifont':
  11964. case 'hppifont':
  11965. return 'HP-Pi-font';
  11966. case 'cshproman8':
  11967. case 'hproman8':
  11968. case 'r8':
  11969. case 'roman8':
  11970. return 'hp-roman8';
  11971. case 'hzgb2312':
  11972. return 'HZ-GB-2312';
  11973. case 'csibmsymbols':
  11974. case 'ibmsymbols':
  11975. return 'IBM-Symbols';
  11976. case 'csibmthai':
  11977. case 'ibmthai':
  11978. return 'IBM-Thai';
  11979. case 'cp37':
  11980. case 'csibm37':
  11981. case 'ebcdiccpca':
  11982. case 'ebcdiccpnl':
  11983. case 'ebcdiccpus':
  11984. case 'ebcdiccpwt':
  11985. case 'ibm37':
  11986. return 'IBM037';
  11987. case 'cp38':
  11988. case 'csibm38':
  11989. case 'ebcdicint':
  11990. case 'ibm38':
  11991. return 'IBM038';
  11992. case 'cp273':
  11993. case 'csibm273':
  11994. case 'ibm273':
  11995. return 'IBM273';
  11996. case 'cp274':
  11997. case 'csibm274':
  11998. case 'ebcdicbe':
  11999. case 'ibm274':
  12000. return 'IBM274';
  12001. case 'cp275':
  12002. case 'csibm275':
  12003. case 'ebcdicbr':
  12004. case 'ibm275':
  12005. return 'IBM275';
  12006. case 'csibm277':
  12007. case 'ebcdiccpdk':
  12008. case 'ebcdiccpno':
  12009. case 'ibm277':
  12010. return 'IBM277';
  12011. case 'cp278':
  12012. case 'csibm278':
  12013. case 'ebcdiccpfi':
  12014. case 'ebcdiccpse':
  12015. case 'ibm278':
  12016. return 'IBM278';
  12017. case 'cp280':
  12018. case 'csibm280':
  12019. case 'ebcdiccpit':
  12020. case 'ibm280':
  12021. return 'IBM280';
  12022. case 'cp281':
  12023. case 'csibm281':
  12024. case 'ebcdicjpe':
  12025. case 'ibm281':
  12026. return 'IBM281';
  12027. case 'cp284':
  12028. case 'csibm284':
  12029. case 'ebcdiccpes':
  12030. case 'ibm284':
  12031. return 'IBM284';
  12032. case 'cp285':
  12033. case 'csibm285':
  12034. case 'ebcdiccpgb':
  12035. case 'ibm285':
  12036. return 'IBM285';
  12037. case 'cp290':
  12038. case 'csibm290':
  12039. case 'ebcdicjpkana':
  12040. case 'ibm290':
  12041. return 'IBM290';
  12042. case 'cp297':
  12043. case 'csibm297':
  12044. case 'ebcdiccpfr':
  12045. case 'ibm297':
  12046. return 'IBM297';
  12047. case 'cp420':
  12048. case 'csibm420':
  12049. case 'ebcdiccpar1':
  12050. case 'ibm420':
  12051. return 'IBM420';
  12052. case 'cp423':
  12053. case 'csibm423':
  12054. case 'ebcdiccpgr':
  12055. case 'ibm423':
  12056. return 'IBM423';
  12057. case 'cp424':
  12058. case 'csibm424':
  12059. case 'ebcdiccphe':
  12060. case 'ibm424':
  12061. return 'IBM424';
  12062. case '437':
  12063. case 'cp437':
  12064. case 'cspc8codepage437':
  12065. case 'ibm437':
  12066. return 'IBM437';
  12067. case 'cp500':
  12068. case 'csibm500':
  12069. case 'ebcdiccpbe':
  12070. case 'ebcdiccpch':
  12071. case 'ibm500':
  12072. return 'IBM500';
  12073. case 'cp775':
  12074. case 'cspc775baltic':
  12075. case 'ibm775':
  12076. return 'IBM775';
  12077. case '850':
  12078. case 'cp850':
  12079. case 'cspc850multilingual':
  12080. case 'ibm850':
  12081. return 'IBM850';
  12082. case '851':
  12083. case 'cp851':
  12084. case 'csibm851':
  12085. case 'ibm851':
  12086. return 'IBM851';
  12087. case '852':
  12088. case 'cp852':
  12089. case 'cspcp852':
  12090. case 'ibm852':
  12091. return 'IBM852';
  12092. case '855':
  12093. case 'cp855':
  12094. case 'csibm855':
  12095. case 'ibm855':
  12096. return 'IBM855';
  12097. case '857':
  12098. case 'cp857':
  12099. case 'csibm857':
  12100. case 'ibm857':
  12101. return 'IBM857';
  12102. case 'ccsid858':
  12103. case 'cp858':
  12104. case 'ibm858':
  12105. case 'pcmultilingual850euro':
  12106. return 'IBM00858';
  12107. case '860':
  12108. case 'cp860':
  12109. case 'csibm860':
  12110. case 'ibm860':
  12111. return 'IBM860';
  12112. case '861':
  12113. case 'cp861':
  12114. case 'cpis':
  12115. case 'csibm861':
  12116. case 'ibm861':
  12117. return 'IBM861';
  12118. case '862':
  12119. case 'cp862':
  12120. case 'cspc862latinhebrew':
  12121. case 'ibm862':
  12122. return 'IBM862';
  12123. case '863':
  12124. case 'cp863':
  12125. case 'csibm863':
  12126. case 'ibm863':
  12127. return 'IBM863';
  12128. case 'cp864':
  12129. case 'csibm864':
  12130. case 'ibm864':
  12131. return 'IBM864';
  12132. case '865':
  12133. case 'cp865':
  12134. case 'csibm865':
  12135. case 'ibm865':
  12136. return 'IBM865';
  12137. case '866':
  12138. case 'cp866':
  12139. case 'csibm866':
  12140. case 'ibm866':
  12141. return 'IBM866';
  12142. case 'cp868':
  12143. case 'cpar':
  12144. case 'csibm868':
  12145. case 'ibm868':
  12146. return 'IBM868';
  12147. case '869':
  12148. case 'cp869':
  12149. case 'cpgr':
  12150. case 'csibm869':
  12151. case 'ibm869':
  12152. return 'IBM869';
  12153. case 'cp870':
  12154. case 'csibm870':
  12155. case 'ebcdiccproece':
  12156. case 'ebcdiccpyu':
  12157. case 'ibm870':
  12158. return 'IBM870';
  12159. case 'cp871':
  12160. case 'csibm871':
  12161. case 'ebcdiccpis':
  12162. case 'ibm871':
  12163. return 'IBM871';
  12164. case 'cp880':
  12165. case 'csibm880':
  12166. case 'ebcdiccyrillic':
  12167. case 'ibm880':
  12168. return 'IBM880';
  12169. case 'cp891':
  12170. case 'csibm891':
  12171. case 'ibm891':
  12172. return 'IBM891';
  12173. case 'cp903':
  12174. case 'csibm903':
  12175. case 'ibm903':
  12176. return 'IBM903';
  12177. case '904':
  12178. case 'cp904':
  12179. case 'csibbm904':
  12180. case 'ibm904':
  12181. return 'IBM904';
  12182. case 'cp905':
  12183. case 'csibm905':
  12184. case 'ebcdiccptr':
  12185. case 'ibm905':
  12186. return 'IBM905';
  12187. case 'cp918':
  12188. case 'csibm918':
  12189. case 'ebcdiccpar2':
  12190. case 'ibm918':
  12191. return 'IBM918';
  12192. case 'ccsid924':
  12193. case 'cp924':
  12194. case 'ebcdiclatin9euro':
  12195. case 'ibm924':
  12196. return 'IBM00924';
  12197. case 'cp1026':
  12198. case 'csibm1026':
  12199. case 'ibm1026':
  12200. return 'IBM1026';
  12201. case 'ibm1047':
  12202. return 'IBM1047';
  12203. case 'ccsid1140':
  12204. case 'cp1140':
  12205. case 'ebcdicus37euro':
  12206. case 'ibm1140':
  12207. return 'IBM01140';
  12208. case 'ccsid1141':
  12209. case 'cp1141':
  12210. case 'ebcdicde273euro':
  12211. case 'ibm1141':
  12212. return 'IBM01141';
  12213. case 'ccsid1142':
  12214. case 'cp1142':
  12215. case 'ebcdicdk277euro':
  12216. case 'ebcdicno277euro':
  12217. case 'ibm1142':
  12218. return 'IBM01142';
  12219. case 'ccsid1143':
  12220. case 'cp1143':
  12221. case 'ebcdicfi278euro':
  12222. case 'ebcdicse278euro':
  12223. case 'ibm1143':
  12224. return 'IBM01143';
  12225. case 'ccsid1144':
  12226. case 'cp1144':
  12227. case 'ebcdicit280euro':
  12228. case 'ibm1144':
  12229. return 'IBM01144';
  12230. case 'ccsid1145':
  12231. case 'cp1145':
  12232. case 'ebcdices284euro':
  12233. case 'ibm1145':
  12234. return 'IBM01145';
  12235. case 'ccsid1146':
  12236. case 'cp1146':
  12237. case 'ebcdicgb285euro':
  12238. case 'ibm1146':
  12239. return 'IBM01146';
  12240. case 'ccsid1147':
  12241. case 'cp1147':
  12242. case 'ebcdicfr297euro':
  12243. case 'ibm1147':
  12244. return 'IBM01147';
  12245. case 'ccsid1148':
  12246. case 'cp1148':
  12247. case 'ebcdicinternational500euro':
  12248. case 'ibm1148':
  12249. return 'IBM01148';
  12250. case 'ccsid1149':
  12251. case 'cp1149':
  12252. case 'ebcdicis871euro':
  12253. case 'ibm1149':
  12254. return 'IBM01149';
  12255. case 'csiso143iecp271':
  12256. case 'iecp271':
  12257. case 'isoir143':
  12258. return 'IEC_P27-1';
  12259. case 'csiso49inis':
  12260. case 'inis':
  12261. case 'isoir49':
  12262. return 'INIS';
  12263. case 'csiso50inis8':
  12264. case 'inis8':
  12265. case 'isoir50':
  12266. return 'INIS-8';
  12267. case 'csiso51iniscyrillic':
  12268. case 'iniscyrillic':
  12269. case 'isoir51':
  12270. return 'INIS-cyrillic';
  12271. case 'csinvariant':
  12272. case 'invariant':
  12273. return 'INVARIANT';
  12274. case 'iso2022cn':
  12275. return 'ISO-2022-CN';
  12276. case 'iso2022cnext':
  12277. return 'ISO-2022-CN-EXT';
  12278. case 'csiso2022jp':
  12279. case 'iso2022jp':
  12280. return 'ISO-2022-JP';
  12281. case 'csiso2022jp2':
  12282. case 'iso2022jp2':
  12283. return 'ISO-2022-JP-2';
  12284. case 'csiso2022kr':
  12285. case 'iso2022kr':
  12286. return 'ISO-2022-KR';
  12287. case 'cswindows30latin1':
  12288. case 'iso88591windows30latin1':
  12289. return 'ISO-8859-1-Windows-3.0-Latin-1';
  12290. case 'cswindows31latin1':
  12291. case 'iso88591windows31latin1':
  12292. return 'ISO-8859-1-Windows-3.1-Latin-1';
  12293. case 'csisolatin2':
  12294. case 'iso88592':
  12295. case 'iso885921987':
  12296. case 'isoir101':
  12297. case 'l2':
  12298. case 'latin2':
  12299. return 'ISO-8859-2';
  12300. case 'cswindows31latin2':
  12301. case 'iso88592windowslatin2':
  12302. return 'ISO-8859-2-Windows-Latin-2';
  12303. case 'csisolatin3':
  12304. case 'iso88593':
  12305. case 'iso885931988':
  12306. case 'isoir109':
  12307. case 'l3':
  12308. case 'latin3':
  12309. return 'ISO-8859-3';
  12310. case 'csisolatin4':
  12311. case 'iso88594':
  12312. case 'iso885941988':
  12313. case 'isoir110':
  12314. case 'l4':
  12315. case 'latin4':
  12316. return 'ISO-8859-4';
  12317. case 'csisolatincyrillic':
  12318. case 'cyrillic':
  12319. case 'iso88595':
  12320. case 'iso885951988':
  12321. case 'isoir144':
  12322. return 'ISO-8859-5';
  12323. case 'arabic':
  12324. case 'asmo708':
  12325. case 'csisolatinarabic':
  12326. case 'ecma114':
  12327. case 'iso88596':
  12328. case 'iso885961987':
  12329. case 'isoir127':
  12330. return 'ISO-8859-6';
  12331. case 'csiso88596e':
  12332. case 'iso88596e':
  12333. return 'ISO-8859-6-E';
  12334. case 'csiso88596i':
  12335. case 'iso88596i':
  12336. return 'ISO-8859-6-I';
  12337. case 'csisolatingreek':
  12338. case 'ecma118':
  12339. case 'elot928':
  12340. case 'greek':
  12341. case 'greek8':
  12342. case 'iso88597':
  12343. case 'iso885971987':
  12344. case 'isoir126':
  12345. return 'ISO-8859-7';
  12346. case 'csisolatinhebrew':
  12347. case 'hebrew':
  12348. case 'iso88598':
  12349. case 'iso885981988':
  12350. case 'isoir138':
  12351. return 'ISO-8859-8';
  12352. case 'csiso88598e':
  12353. case 'iso88598e':
  12354. return 'ISO-8859-8-E';
  12355. case 'csiso88598i':
  12356. case 'iso88598i':
  12357. return 'ISO-8859-8-I';
  12358. case 'cswindows31latin5':
  12359. case 'iso88599windowslatin5':
  12360. return 'ISO-8859-9-Windows-Latin-5';
  12361. case 'csisolatin6':
  12362. case 'iso885910':
  12363. case 'iso8859101992':
  12364. case 'isoir157':
  12365. case 'l6':
  12366. case 'latin6':
  12367. return 'ISO-8859-10';
  12368. case 'iso885913':
  12369. return 'ISO-8859-13';
  12370. case 'iso885914':
  12371. case 'iso8859141998':
  12372. case 'isoceltic':
  12373. case 'isoir199':
  12374. case 'l8':
  12375. case 'latin8':
  12376. return 'ISO-8859-14';
  12377. case 'iso885915':
  12378. case 'latin9':
  12379. return 'ISO-8859-15';
  12380. case 'iso885916':
  12381. case 'iso8859162001':
  12382. case 'isoir226':
  12383. case 'l10':
  12384. case 'latin10':
  12385. return 'ISO-8859-16';
  12386. case 'iso10646j1':
  12387. return 'ISO-10646-J-1';
  12388. case 'csunicode':
  12389. case 'iso10646ucs2':
  12390. return 'ISO-10646-UCS-2';
  12391. case 'csucs4':
  12392. case 'iso10646ucs4':
  12393. return 'ISO-10646-UCS-4';
  12394. case 'csunicodeascii':
  12395. case 'iso10646ucsbasic':
  12396. return 'ISO-10646-UCS-Basic';
  12397. case 'csunicodelatin1':
  12398. case 'iso10646':
  12399. case 'iso10646unicodelatin1':
  12400. return 'ISO-10646-Unicode-Latin1';
  12401. case 'csiso10646utf1':
  12402. case 'iso10646utf1':
  12403. return 'ISO-10646-UTF-1';
  12404. case 'csiso115481':
  12405. case 'iso115481':
  12406. case 'isotr115481':
  12407. return 'ISO-11548-1';
  12408. case 'csiso90':
  12409. case 'isoir90':
  12410. return 'iso-ir-90';
  12411. case 'csunicodeibm1261':
  12412. case 'isounicodeibm1261':
  12413. return 'ISO-Unicode-IBM-1261';
  12414. case 'csunicodeibm1264':
  12415. case 'isounicodeibm1264':
  12416. return 'ISO-Unicode-IBM-1264';
  12417. case 'csunicodeibm1265':
  12418. case 'isounicodeibm1265':
  12419. return 'ISO-Unicode-IBM-1265';
  12420. case 'csunicodeibm1268':
  12421. case 'isounicodeibm1268':
  12422. return 'ISO-Unicode-IBM-1268';
  12423. case 'csunicodeibm1276':
  12424. case 'isounicodeibm1276':
  12425. return 'ISO-Unicode-IBM-1276';
  12426. case 'csiso646basic1983':
  12427. case 'iso646basic1983':
  12428. case 'ref':
  12429. return 'ISO_646.basic:1983';
  12430. case 'csiso2intlrefversion':
  12431. case 'irv':
  12432. case 'iso646irv1983':
  12433. case 'isoir2':
  12434. return 'ISO_646.irv:1983';
  12435. case 'csiso2033':
  12436. case 'e13b':
  12437. case 'iso20331983':
  12438. case 'isoir98':
  12439. return 'ISO_2033-1983';
  12440. case 'csiso5427cyrillic':
  12441. case 'iso5427':
  12442. case 'isoir37':
  12443. return 'ISO_5427';
  12444. case 'iso5427cyrillic1981':
  12445. case 'iso54271981':
  12446. case 'isoir54':
  12447. return 'ISO_5427:1981';
  12448. case 'csiso5428greek':
  12449. case 'iso54281980':
  12450. case 'isoir55':
  12451. return 'ISO_5428:1980';
  12452. case 'csiso6937add':
  12453. case 'iso6937225':
  12454. case 'isoir152':
  12455. return 'ISO_6937-2-25';
  12456. case 'csisotextcomm':
  12457. case 'iso69372add':
  12458. case 'isoir142':
  12459. return 'ISO_6937-2-add';
  12460. case 'csiso8859supp':
  12461. case 'iso8859supp':
  12462. case 'isoir154':
  12463. case 'latin125':
  12464. return 'ISO_8859-supp';
  12465. case 'csiso10367box':
  12466. case 'iso10367box':
  12467. case 'isoir155':
  12468. return 'ISO_10367-box';
  12469. case 'csiso15italian':
  12470. case 'iso646it':
  12471. case 'isoir15':
  12472. case 'it':
  12473. return 'IT';
  12474. case 'csiso13jisc6220jp':
  12475. case 'isoir13':
  12476. case 'jisc62201969':
  12477. case 'jisc62201969jp':
  12478. case 'katakana':
  12479. case 'x2017':
  12480. return 'JIS_C6220-1969-jp';
  12481. case 'csiso14jisc6220ro':
  12482. case 'iso646jp':
  12483. case 'isoir14':
  12484. case 'jisc62201969ro':
  12485. case 'jp':
  12486. return 'JIS_C6220-1969-ro';
  12487. case 'csiso42jisc62261978':
  12488. case 'isoir42':
  12489. case 'jisc62261978':
  12490. return 'JIS_C6226-1978';
  12491. case 'csiso87jisx208':
  12492. case 'isoir87':
  12493. case 'jisc62261983':
  12494. case 'jisx2081983':
  12495. case 'x208':
  12496. return 'JIS_C6226-1983';
  12497. case 'csiso91jisc62291984a':
  12498. case 'isoir91':
  12499. case 'jisc62291984a':
  12500. case 'jpocra':
  12501. return 'JIS_C6229-1984-a';
  12502. case 'csiso92jisc62991984b':
  12503. case 'iso646jpocrb':
  12504. case 'isoir92':
  12505. case 'jisc62291984b':
  12506. case 'jpocrb':
  12507. return 'JIS_C6229-1984-b';
  12508. case 'csiso93jis62291984badd':
  12509. case 'isoir93':
  12510. case 'jisc62291984badd':
  12511. case 'jpocrbadd':
  12512. return 'JIS_C6229-1984-b-add';
  12513. case 'csiso94jis62291984hand':
  12514. case 'isoir94':
  12515. case 'jisc62291984hand':
  12516. case 'jpocrhand':
  12517. return 'JIS_C6229-1984-hand';
  12518. case 'csiso95jis62291984handadd':
  12519. case 'isoir95':
  12520. case 'jisc62291984handadd':
  12521. case 'jpocrhandadd':
  12522. return 'JIS_C6229-1984-hand-add';
  12523. case 'csiso96jisc62291984kana':
  12524. case 'isoir96':
  12525. case 'jisc62291984kana':
  12526. return 'JIS_C6229-1984-kana';
  12527. case 'csjisencoding':
  12528. case 'jisencoding':
  12529. return 'JIS_Encoding';
  12530. case 'cshalfwidthkatakana':
  12531. case 'jisx201':
  12532. case 'x201':
  12533. return 'JIS_X0201';
  12534. case 'csiso159jisx2121990':
  12535. case 'isoir159':
  12536. case 'jisx2121990':
  12537. case 'x212':
  12538. return 'JIS_X0212-1990';
  12539. case 'csiso141jusib1002':
  12540. case 'iso646yu':
  12541. case 'isoir141':
  12542. case 'js':
  12543. case 'jusib1002':
  12544. case 'yu':
  12545. return 'JUS_I.B1.002';
  12546. case 'csiso147macedonian':
  12547. case 'isoir147':
  12548. case 'jusib1003mac':
  12549. case 'macedonian':
  12550. return 'JUS_I.B1.003-mac';
  12551. case 'csiso146serbian':
  12552. case 'isoir146':
  12553. case 'jusib1003serb':
  12554. case 'serbian':
  12555. return 'JUS_I.B1.003-serb';
  12556. case 'koi7switched':
  12557. return 'KOI7-switched';
  12558. case 'cskoi8r':
  12559. case 'koi8r':
  12560. return 'KOI8-R';
  12561. case 'koi8u':
  12562. return 'KOI8-U';
  12563. case 'csksc5636':
  12564. case 'iso646kr':
  12565. case 'ksc5636':
  12566. return 'KSC5636';
  12567. case 'cskz1048':
  12568. case 'kz1048':
  12569. case 'rk1048':
  12570. case 'strk10482002':
  12571. return 'KZ-1048';
  12572. case 'csiso19latingreek':
  12573. case 'isoir19':
  12574. case 'latingreek':
  12575. return 'latin-greek';
  12576. case 'csiso27latingreek1':
  12577. case 'isoir27':
  12578. case 'latingreek1':
  12579. return 'Latin-greek-1';
  12580. case 'csiso158lap':
  12581. case 'isoir158':
  12582. case 'lap':
  12583. case 'latinlap':
  12584. return 'latin-lap';
  12585. case 'csmacintosh':
  12586. case 'mac':
  12587. case 'macintosh':
  12588. return 'macintosh';
  12589. case 'csmicrosoftpublishing':
  12590. case 'microsoftpublishing':
  12591. return 'Microsoft-Publishing';
  12592. case 'csmnem':
  12593. case 'mnem':
  12594. return 'MNEM';
  12595. case 'csmnemonic':
  12596. case 'mnemonic':
  12597. return 'MNEMONIC';
  12598. case 'csiso86hungarian':
  12599. case 'hu':
  12600. case 'iso646hu':
  12601. case 'isoir86':
  12602. case 'msz77953':
  12603. return 'MSZ_7795.3';
  12604. case 'csnatsdano':
  12605. case 'isoir91':
  12606. case 'natsdano':
  12607. return 'NATS-DANO';
  12608. case 'csnatsdanoadd':
  12609. case 'isoir92':
  12610. case 'natsdanoadd':
  12611. return 'NATS-DANO-ADD';
  12612. case 'csnatssefi':
  12613. case 'isoir81':
  12614. case 'natssefi':
  12615. return 'NATS-SEFI';
  12616. case 'csnatssefiadd':
  12617. case 'isoir82':
  12618. case 'natssefiadd':
  12619. return 'NATS-SEFI-ADD';
  12620. case 'csiso151cuba':
  12621. case 'cuba':
  12622. case 'iso646cu':
  12623. case 'isoir151':
  12624. case 'ncnc1081':
  12625. return 'NC_NC00-10:81';
  12626. case 'csiso69french':
  12627. case 'fr':
  12628. case 'iso646fr':
  12629. case 'isoir69':
  12630. case 'nfz62010':
  12631. return 'NF_Z_62-010';
  12632. case 'csiso25french':
  12633. case 'iso646fr1':
  12634. case 'isoir25':
  12635. case 'nfz620101973':
  12636. return 'NF_Z_62-010_(1973)';
  12637. case 'csiso60danishnorwegian':
  12638. case 'csiso60norwegian1':
  12639. case 'iso646no':
  12640. case 'isoir60':
  12641. case 'no':
  12642. case 'ns45511':
  12643. return 'NS_4551-1';
  12644. case 'csiso61norwegian2':
  12645. case 'iso646no2':
  12646. case 'isoir61':
  12647. case 'no2':
  12648. case 'ns45512':
  12649. return 'NS_4551-2';
  12650. case 'osdebcdicdf3irv':
  12651. return 'OSD_EBCDIC_DF03_IRV';
  12652. case 'osdebcdicdf41':
  12653. return 'OSD_EBCDIC_DF04_1';
  12654. case 'osdebcdicdf415':
  12655. return 'OSD_EBCDIC_DF04_15';
  12656. case 'cspc8danishnorwegian':
  12657. case 'pc8danishnorwegian':
  12658. return 'PC8-Danish-Norwegian';
  12659. case 'cspc8turkish':
  12660. case 'pc8turkish':
  12661. return 'PC8-Turkish';
  12662. case 'csiso16portuguese':
  12663. case 'iso646pt':
  12664. case 'isoir16':
  12665. case 'pt':
  12666. return 'PT';
  12667. case 'csiso84portuguese2':
  12668. case 'iso646pt2':
  12669. case 'isoir84':
  12670. case 'pt2':
  12671. return 'PT2';
  12672. case 'cp154':
  12673. case 'csptcp154':
  12674. case 'cyrillicasian':
  12675. case 'pt154':
  12676. case 'ptcp154':
  12677. return 'PTCP154';
  12678. case 'scsu':
  12679. return 'SCSU';
  12680. case 'csiso10swedish':
  12681. case 'fi':
  12682. case 'iso646fi':
  12683. case 'iso646se':
  12684. case 'isoir10':
  12685. case 'se':
  12686. case 'sen850200b':
  12687. return 'SEN_850200_B';
  12688. case 'csiso11swedishfornames':
  12689. case 'iso646se2':
  12690. case 'isoir11':
  12691. case 'se2':
  12692. case 'sen850200c':
  12693. return 'SEN_850200_C';
  12694. case 'csiso102t617bit':
  12695. case 'isoir102':
  12696. case 't617bit':
  12697. return 'T.61-7bit';
  12698. case 'csiso103t618bit':
  12699. case 'isoir103':
  12700. case 't61':
  12701. case 't618bit':
  12702. return 'T.61-8bit';
  12703. case 'csiso128t101g2':
  12704. case 'isoir128':
  12705. case 't101g2':
  12706. return 'T.101-G2';
  12707. case 'cstscii':
  12708. case 'tscii':
  12709. return 'TSCII';
  12710. case 'csunicode11':
  12711. case 'unicode11':
  12712. return 'UNICODE-1-1';
  12713. case 'csunicode11utf7':
  12714. case 'unicode11utf7':
  12715. return 'UNICODE-1-1-UTF-7';
  12716. case 'csunknown8bit':
  12717. case 'unknown8bit':
  12718. return 'UNKNOWN-8BIT';
  12719. case 'ansix341968':
  12720. case 'ansix341986':
  12721. case 'ascii':
  12722. case 'cp367':
  12723. case 'csascii':
  12724. case 'ibm367':
  12725. case 'iso646irv1991':
  12726. case 'iso646us':
  12727. case 'isoir6':
  12728. case 'us':
  12729. case 'usascii':
  12730. return 'US-ASCII';
  12731. case 'csusdk':
  12732. case 'usdk':
  12733. return 'us-dk';
  12734. case 'utf7':
  12735. return 'UTF-7';
  12736. case 'utf8':
  12737. return 'UTF-8';
  12738. case 'utf16':
  12739. return 'UTF-16';
  12740. case 'utf16be':
  12741. return 'UTF-16BE';
  12742. case 'utf16le':
  12743. return 'UTF-16LE';
  12744. case 'utf32':
  12745. return 'UTF-32';
  12746. case 'utf32be':
  12747. return 'UTF-32BE';
  12748. case 'utf32le':
  12749. return 'UTF-32LE';
  12750. case 'csventurainternational':
  12751. case 'venturainternational':
  12752. return 'Ventura-International';
  12753. case 'csventuramath':
  12754. case 'venturamath':
  12755. return 'Ventura-Math';
  12756. case 'csventuraus':
  12757. case 'venturaus':
  12758. return 'Ventura-US';
  12759. case 'csiso70videotexsupp1':
  12760. case 'isoir70':
  12761. case 'videotexsuppl':
  12762. return 'videotex-suppl';
  12763. case 'csviqr':
  12764. case 'viqr':
  12765. return 'VIQR';
  12766. case 'csviscii':
  12767. case 'viscii':
  12768. return 'VISCII';
  12769. case 'csshiftjis':
  12770. case 'cswindows31j':
  12771. case 'mskanji':
  12772. case 'shiftjis':
  12773. case 'windows31j':
  12774. return 'Windows-31J';
  12775. case 'iso885911':
  12776. case 'tis620':
  12777. return 'windows-874';
  12778. case 'cseuckr':
  12779. case 'csksc56011987':
  12780. case 'euckr':
  12781. case 'isoir149':
  12782. case 'korean':
  12783. case 'ksc5601':
  12784. case 'ksc56011987':
  12785. case 'ksc56011989':
  12786. case 'windows949':
  12787. return 'windows-949';
  12788. case 'windows1250':
  12789. return 'windows-1250';
  12790. case 'windows1251':
  12791. return 'windows-1251';
  12792. case 'cp819':
  12793. case 'csisolatin1':
  12794. case 'ibm819':
  12795. case 'iso88591':
  12796. case 'iso885911987':
  12797. case 'isoir100':
  12798. case 'l1':
  12799. case 'latin1':
  12800. case 'windows1252':
  12801. return 'windows-1252';
  12802. case 'windows1253':
  12803. return 'windows-1253';
  12804. case 'csisolatin5':
  12805. case 'iso88599':
  12806. case 'iso885991989':
  12807. case 'isoir148':
  12808. case 'l5':
  12809. case 'latin5':
  12810. case 'windows1254':
  12811. return 'windows-1254';
  12812. case 'windows1255':
  12813. return 'windows-1255';
  12814. case 'windows1256':
  12815. return 'windows-1256';
  12816. case 'windows1257':
  12817. return 'windows-1257';
  12818. case 'windows1258':
  12819. return 'windows-1258';
  12820. default:
  12821. return $charset;
  12822. }
  12823. }
  12824. public static function get_curl_version()
  12825. {
  12826. if (is_array($curl = curl_version()))
  12827. {
  12828. $curl = $curl['version'];
  12829. }
  12830. elseif (substr($curl, 0, 5) === 'curl/')
  12831. {
  12832. $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
  12833. }
  12834. elseif (substr($curl, 0, 8) === 'libcurl/')
  12835. {
  12836. $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
  12837. }
  12838. else
  12839. {
  12840. $curl = 0;
  12841. }
  12842. return $curl;
  12843. }
  12844. /**
  12845. * Strip HTML comments
  12846. *
  12847. * @param string $data Data to strip comments from
  12848. * @return string Comment stripped string
  12849. */
  12850. public static function strip_comments($data)
  12851. {
  12852. $output = '';
  12853. while (($start = strpos($data, '<!--')) !== false)
  12854. {
  12855. $output .= substr($data, 0, $start);
  12856. if (($end = strpos($data, '-->', $start)) !== false)
  12857. {
  12858. $data = substr_replace($data, '', 0, $end + 3);
  12859. }
  12860. else
  12861. {
  12862. $data = '';
  12863. }
  12864. }
  12865. return $output . $data;
  12866. }
  12867. public static function parse_date($dt)
  12868. {
  12869. $parser = SimplePie_Parse_Date::get();
  12870. return $parser->parse($dt);
  12871. }
  12872. /**
  12873. * Decode HTML entities
  12874. *
  12875. * @deprecated Use DOMDocument instead
  12876. * @param string $data Input data
  12877. * @return string Output data
  12878. */
  12879. public static function entities_decode($data)
  12880. {
  12881. $decoder = new SimplePie_Decode_HTML_Entities($data);
  12882. return $decoder->parse();
  12883. }
  12884. /**
  12885. * Remove RFC822 comments
  12886. *
  12887. * @param string $data Data to strip comments from
  12888. * @return string Comment stripped string
  12889. */
  12890. public static function uncomment_rfc822($string)
  12891. {
  12892. $string = (string) $string;
  12893. $position = 0;
  12894. $length = strlen($string);
  12895. $depth = 0;
  12896. $output = '';
  12897. while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
  12898. {
  12899. $output .= substr($string, $position, $pos - $position);
  12900. $position = $pos + 1;
  12901. if ($string[$pos - 1] !== '\\')
  12902. {
  12903. $depth++;
  12904. while ($depth && $position < $length)
  12905. {
  12906. $position += strcspn($string, '()', $position);
  12907. if ($string[$position - 1] === '\\')
  12908. {
  12909. $position++;
  12910. continue;
  12911. }
  12912. elseif (isset($string[$position]))
  12913. {
  12914. switch ($string[$position])
  12915. {
  12916. case '(':
  12917. $depth++;
  12918. break;
  12919. case ')':
  12920. $depth--;
  12921. break;
  12922. }
  12923. $position++;
  12924. }
  12925. else
  12926. {
  12927. break;
  12928. }
  12929. }
  12930. }
  12931. else
  12932. {
  12933. $output .= '(';
  12934. }
  12935. }
  12936. $output .= substr($string, $position);
  12937. return $output;
  12938. }
  12939. public static function parse_mime($mime)
  12940. {
  12941. if (($pos = strpos($mime, ';')) === false)
  12942. {
  12943. return trim($mime);
  12944. }
  12945. else
  12946. {
  12947. return trim(substr($mime, 0, $pos));
  12948. }
  12949. }
  12950. public static function atom_03_construct_type($attribs)
  12951. {
  12952. if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
  12953. {
  12954. $mode = SIMPLEPIE_CONSTRUCT_BASE64;
  12955. }
  12956. else
  12957. {
  12958. $mode = SIMPLEPIE_CONSTRUCT_NONE;
  12959. }
  12960. if (isset($attribs['']['type']))
  12961. {
  12962. switch (strtolower(trim($attribs['']['type'])))
  12963. {
  12964. case 'text':
  12965. case 'text/plain':
  12966. return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
  12967. case 'html':
  12968. case 'text/html':
  12969. return SIMPLEPIE_CONSTRUCT_HTML | $mode;
  12970. case 'xhtml':
  12971. case 'application/xhtml+xml':
  12972. return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
  12973. default:
  12974. return SIMPLEPIE_CONSTRUCT_NONE | $mode;
  12975. }
  12976. }
  12977. else
  12978. {
  12979. return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
  12980. }
  12981. }
  12982. public static function atom_10_construct_type($attribs)
  12983. {
  12984. if (isset($attribs['']['type']))
  12985. {
  12986. switch (strtolower(trim($attribs['']['type'])))
  12987. {
  12988. case 'text':
  12989. return SIMPLEPIE_CONSTRUCT_TEXT;
  12990. case 'html':
  12991. return SIMPLEPIE_CONSTRUCT_HTML;
  12992. case 'xhtml':
  12993. return SIMPLEPIE_CONSTRUCT_XHTML;
  12994. default:
  12995. return SIMPLEPIE_CONSTRUCT_NONE;
  12996. }
  12997. }
  12998. return SIMPLEPIE_CONSTRUCT_TEXT;
  12999. }
  13000. public static function atom_10_content_construct_type($attribs)
  13001. {
  13002. if (isset($attribs['']['type']))
  13003. {
  13004. $type = strtolower(trim($attribs['']['type']));
  13005. switch ($type)
  13006. {
  13007. case 'text':
  13008. return SIMPLEPIE_CONSTRUCT_TEXT;
  13009. case 'html':
  13010. return SIMPLEPIE_CONSTRUCT_HTML;
  13011. case 'xhtml':
  13012. return SIMPLEPIE_CONSTRUCT_XHTML;
  13013. }
  13014. if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
  13015. {
  13016. return SIMPLEPIE_CONSTRUCT_NONE;
  13017. }
  13018. else
  13019. {
  13020. return SIMPLEPIE_CONSTRUCT_BASE64;
  13021. }
  13022. }
  13023. else
  13024. {
  13025. return SIMPLEPIE_CONSTRUCT_TEXT;
  13026. }
  13027. }
  13028. public static function is_isegment_nz_nc($string)
  13029. {
  13030. return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string);
  13031. }
  13032. public static function space_seperated_tokens($string)
  13033. {
  13034. $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
  13035. $string_length = strlen($string);
  13036. $position = strspn($string, $space_characters);
  13037. $tokens = array();
  13038. while ($position < $string_length)
  13039. {
  13040. $len = strcspn($string, $space_characters, $position);
  13041. $tokens[] = substr($string, $position, $len);
  13042. $position += $len;
  13043. $position += strspn($string, $space_characters, $position);
  13044. }
  13045. return $tokens;
  13046. }
  13047. /**
  13048. * Converts a unicode codepoint to a UTF-8 character
  13049. *
  13050. * @static
  13051. * @param int $codepoint Unicode codepoint
  13052. * @return string UTF-8 character
  13053. */
  13054. public static function codepoint_to_utf8($codepoint)
  13055. {
  13056. $codepoint = (int) $codepoint;
  13057. if ($codepoint < 0)
  13058. {
  13059. return false;
  13060. }
  13061. else if ($codepoint <= 0x7f)
  13062. {
  13063. return chr($codepoint);
  13064. }
  13065. else if ($codepoint <= 0x7ff)
  13066. {
  13067. return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
  13068. }
  13069. else if ($codepoint <= 0xffff)
  13070. {
  13071. return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
  13072. }
  13073. else if ($codepoint <= 0x10ffff)
  13074. {
  13075. return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
  13076. }
  13077. else
  13078. {
  13079. // U+FFFD REPLACEMENT CHARACTER
  13080. return "\xEF\xBF\xBD";
  13081. }
  13082. }
  13083. /**
  13084. * Similar to parse_str()
  13085. *
  13086. * Returns an associative array of name/value pairs, where the value is an
  13087. * array of values that have used the same name
  13088. *
  13089. * @static
  13090. * @param string $str The input string.
  13091. * @return array
  13092. */
  13093. public static function parse_str($str)
  13094. {
  13095. $return = array();
  13096. $str = explode('&', $str);
  13097. foreach ($str as $section)
  13098. {
  13099. if (strpos($section, '=') !== false)
  13100. {
  13101. list($name, $value) = explode('=', $section, 2);
  13102. $return[urldecode($name)][] = urldecode($value);
  13103. }
  13104. else
  13105. {
  13106. $return[urldecode($section)][] = null;
  13107. }
  13108. }
  13109. return $return;
  13110. }
  13111. /**
  13112. * Detect XML encoding, as per XML 1.0 Appendix F.1
  13113. *
  13114. * @todo Add support for EBCDIC
  13115. * @param string $data XML data
  13116. * @param SimplePie_Registry $registry Class registry
  13117. * @return array Possible encodings
  13118. */
  13119. public static function xml_encoding($data, $registry)
  13120. {
  13121. // UTF-32 Big Endian BOM
  13122. if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
  13123. {
  13124. $encoding[] = 'UTF-32BE';
  13125. }
  13126. // UTF-32 Little Endian BOM
  13127. elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
  13128. {
  13129. $encoding[] = 'UTF-32LE';
  13130. }
  13131. // UTF-16 Big Endian BOM
  13132. elseif (substr($data, 0, 2) === "\xFE\xFF")
  13133. {
  13134. $encoding[] = 'UTF-16BE';
  13135. }
  13136. // UTF-16 Little Endian BOM
  13137. elseif (substr($data, 0, 2) === "\xFF\xFE")
  13138. {
  13139. $encoding[] = 'UTF-16LE';
  13140. }
  13141. // UTF-8 BOM
  13142. elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
  13143. {
  13144. $encoding[] = 'UTF-8';
  13145. }
  13146. // UTF-32 Big Endian Without BOM
  13147. elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C")
  13148. {
  13149. if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
  13150. {
  13151. $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8')));
  13152. if ($parser->parse())
  13153. {
  13154. $encoding[] = $parser->encoding;
  13155. }
  13156. }
  13157. $encoding[] = 'UTF-32BE';
  13158. }
  13159. // UTF-32 Little Endian Without BOM
  13160. elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00")
  13161. {
  13162. if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
  13163. {
  13164. $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8')));
  13165. if ($parser->parse())
  13166. {
  13167. $encoding[] = $parser->encoding;
  13168. }
  13169. }
  13170. $encoding[] = 'UTF-32LE';
  13171. }
  13172. // UTF-16 Big Endian Without BOM
  13173. elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
  13174. {
  13175. if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
  13176. {
  13177. $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8')));
  13178. if ($parser->parse())
  13179. {
  13180. $encoding[] = $parser->encoding;
  13181. }
  13182. }
  13183. $encoding[] = 'UTF-16BE';
  13184. }
  13185. // UTF-16 Little Endian Without BOM
  13186. elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
  13187. {
  13188. if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
  13189. {
  13190. $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8')));
  13191. if ($parser->parse())
  13192. {
  13193. $encoding[] = $parser->encoding;
  13194. }
  13195. }
  13196. $encoding[] = 'UTF-16LE';
  13197. }
  13198. // US-ASCII (or superset)
  13199. elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
  13200. {
  13201. if ($pos = strpos($data, "\x3F\x3E"))
  13202. {
  13203. $parser = $registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5)));
  13204. if ($parser->parse())
  13205. {
  13206. $encoding[] = $parser->encoding;
  13207. }
  13208. }
  13209. $encoding[] = 'UTF-8';
  13210. }
  13211. // Fallback to UTF-8
  13212. else
  13213. {
  13214. $encoding[] = 'UTF-8';
  13215. }
  13216. return $encoding;
  13217. }
  13218. public static function output_javascript()
  13219. {
  13220. if (function_exists('ob_gzhandler'))
  13221. {
  13222. ob_start('ob_gzhandler');
  13223. }
  13224. header('Content-type: text/javascript; charset: UTF-8');
  13225. header('Cache-Control: must-revalidate');
  13226. header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
  13227. ?>
  13228. function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
  13229. if (placeholder != '') {
  13230. document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
  13231. }
  13232. else {
  13233. document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
  13234. }
  13235. }
  13236. function embed_flash(bgcolor, width, height, link, loop, type) {
  13237. document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
  13238. }
  13239. function embed_flv(width, height, link, placeholder, loop, player) {
  13240. document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>');
  13241. }
  13242. function embed_wmedia(width, height, link) {
  13243. document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
  13244. }
  13245. <?php
  13246. }
  13247. /**
  13248. * Get the SimplePie build timestamp
  13249. *
  13250. * Uses the git index if it exists, otherwise uses the modification time
  13251. * of the newest file.
  13252. */
  13253. public static function get_build()
  13254. {
  13255. $root = dirname(dirname(__FILE__));
  13256. if (file_exists($root . '/.git/index'))
  13257. {
  13258. return filemtime($root . '/.git/index');
  13259. }
  13260. elseif (file_exists($root . '/SimplePie'))
  13261. {
  13262. $time = 0;
  13263. foreach (glob($root . '/SimplePie/*.php') as $file)
  13264. {
  13265. if (($mtime = filemtime($file)) > $time)
  13266. {
  13267. $time = $mtime;
  13268. }
  13269. }
  13270. return $time;
  13271. }
  13272. elseif (file_exists(dirname(__FILE__) . '/Core.php'))
  13273. {
  13274. return filemtime(dirname(__FILE__) . '/Core.php');
  13275. }
  13276. else
  13277. {
  13278. return filemtime(__FILE__);
  13279. }
  13280. }
  13281. /**
  13282. * Format debugging information
  13283. */
  13284. public static function debug(&$sp)
  13285. {
  13286. $info = 'SimplePie ' . SIMPLEPIE_VERSION . ' Build ' . SIMPLEPIE_BUILD . "\n";
  13287. $info .= 'PHP ' . PHP_VERSION . "\n";
  13288. if ($sp->error() !== null)
  13289. {
  13290. $info .= 'Error occurred: ' . $sp->error() . "\n";
  13291. }
  13292. else
  13293. {
  13294. $info .= "No error found.\n";
  13295. }
  13296. $info .= "Extensions:\n";
  13297. $extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml');
  13298. foreach ($extensions as $ext)
  13299. {
  13300. if (extension_loaded($ext))
  13301. {
  13302. $info .= " $ext loaded\n";
  13303. switch ($ext)
  13304. {
  13305. case 'pcre':
  13306. $info .= ' Version ' . PCRE_VERSION . "\n";
  13307. break;
  13308. case 'curl':
  13309. $version = curl_version();
  13310. $info .= ' Version ' . $version['version'] . "\n";
  13311. break;
  13312. case 'mbstring':
  13313. $info .= ' Overloading: ' . mb_get_info('func_overload') . "\n";
  13314. break;
  13315. case 'iconv':
  13316. $info .= ' Version ' . ICONV_VERSION . "\n";
  13317. break;
  13318. case 'xml':
  13319. $info .= ' Version ' . LIBXML_DOTTED_VERSION . "\n";
  13320. break;
  13321. }
  13322. }
  13323. else
  13324. {
  13325. $info .= " $ext not loaded\n";
  13326. }
  13327. }
  13328. return $info;
  13329. }
  13330. public static function silence_errors($num, $str)
  13331. {
  13332. // No-op
  13333. }
  13334. }
  13335. /**
  13336. * Class to validate and to work with IPv6 addresses.
  13337. *
  13338. * @package SimplePie
  13339. * @subpackage HTTP
  13340. * @copyright 2003-2005 The PHP Group
  13341. * @license http://www.opensource.org/licenses/bsd-license.php
  13342. * @link http://pear.php.net/package/Net_IPv6
  13343. * @author Alexander Merz <alexander.merz@web.de>
  13344. * @author elfrink at introweb dot nl
  13345. * @author Josh Peck <jmp at joshpeck dot org>
  13346. * @author Geoffrey Sneddon <geoffers@gmail.com>
  13347. */
  13348. class SimplePie_Net_IPv6
  13349. {
  13350. /**
  13351. * Uncompresses an IPv6 address
  13352. *
  13353. * RFC 4291 allows you to compress concecutive zero pieces in an address to
  13354. * '::'. This method expects a valid IPv6 address and expands the '::' to
  13355. * the required number of zero pieces.
  13356. *
  13357. * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
  13358. * ::1 -> 0:0:0:0:0:0:0:1
  13359. *
  13360. * @author Alexander Merz <alexander.merz@web.de>
  13361. * @author elfrink at introweb dot nl
  13362. * @author Josh Peck <jmp at joshpeck dot org>
  13363. * @copyright 2003-2005 The PHP Group
  13364. * @license http://www.opensource.org/licenses/bsd-license.php
  13365. * @param string $ip An IPv6 address
  13366. * @return string The uncompressed IPv6 address
  13367. */
  13368. public static function uncompress($ip)
  13369. {
  13370. $c1 = -1;
  13371. $c2 = -1;
  13372. if (substr_count($ip, '::') === 1)
  13373. {
  13374. list($ip1, $ip2) = explode('::', $ip);
  13375. if ($ip1 === '')
  13376. {
  13377. $c1 = -1;
  13378. }
  13379. else
  13380. {
  13381. $c1 = substr_count($ip1, ':');
  13382. }
  13383. if ($ip2 === '')
  13384. {
  13385. $c2 = -1;
  13386. }
  13387. else
  13388. {
  13389. $c2 = substr_count($ip2, ':');
  13390. }
  13391. if (strpos($ip2, '.') !== false)
  13392. {
  13393. $c2++;
  13394. }
  13395. // ::
  13396. if ($c1 === -1 && $c2 === -1)
  13397. {
  13398. $ip = '0:0:0:0:0:0:0:0';
  13399. }
  13400. // ::xxx
  13401. else if ($c1 === -1)
  13402. {
  13403. $fill = str_repeat('0:', 7 - $c2);
  13404. $ip = str_replace('::', $fill, $ip);
  13405. }
  13406. // xxx::
  13407. else if ($c2 === -1)
  13408. {
  13409. $fill = str_repeat(':0', 7 - $c1);
  13410. $ip = str_replace('::', $fill, $ip);
  13411. }
  13412. // xxx::xxx
  13413. else
  13414. {
  13415. $fill = ':' . str_repeat('0:', 6 - $c2 - $c1);
  13416. $ip = str_replace('::', $fill, $ip);
  13417. }
  13418. }
  13419. return $ip;
  13420. }
  13421. /**
  13422. * Compresses an IPv6 address
  13423. *
  13424. * RFC 4291 allows you to compress concecutive zero pieces in an address to
  13425. * '::'. This method expects a valid IPv6 address and compresses consecutive
  13426. * zero pieces to '::'.
  13427. *
  13428. * Example: FF01:0:0:0:0:0:0:101 -> FF01::101
  13429. * 0:0:0:0:0:0:0:1 -> ::1
  13430. *
  13431. * @see uncompress()
  13432. * @param string $ip An IPv6 address
  13433. * @return string The compressed IPv6 address
  13434. */
  13435. public static function compress($ip)
  13436. {
  13437. // Prepare the IP to be compressed
  13438. $ip = self::uncompress($ip);
  13439. $ip_parts = self::split_v6_v4($ip);
  13440. // Replace all leading zeros
  13441. $ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]);
  13442. // Find bunches of zeros
  13443. if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE))
  13444. {
  13445. $max = 0;
  13446. $pos = null;
  13447. foreach ($matches[0] as $match)
  13448. {
  13449. if (strlen($match[0]) > $max)
  13450. {
  13451. $max = strlen($match[0]);
  13452. $pos = $match[1];
  13453. }
  13454. }
  13455. $ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max);
  13456. }
  13457. if ($ip_parts[1] !== '')
  13458. {
  13459. return implode(':', $ip_parts);
  13460. }
  13461. else
  13462. {
  13463. return $ip_parts[0];
  13464. }
  13465. }
  13466. /**
  13467. * Splits an IPv6 address into the IPv6 and IPv4 representation parts
  13468. *
  13469. * RFC 4291 allows you to represent the last two parts of an IPv6 address
  13470. * using the standard IPv4 representation
  13471. *
  13472. * Example: 0:0:0:0:0:0:13.1.68.3
  13473. * 0:0:0:0:0:FFFF:129.144.52.38
  13474. *
  13475. * @param string $ip An IPv6 address
  13476. * @return array [0] contains the IPv6 represented part, and [1] the IPv4 represented part
  13477. */
  13478. private static function split_v6_v4($ip)
  13479. {
  13480. if (strpos($ip, '.') !== false)
  13481. {
  13482. $pos = strrpos($ip, ':');
  13483. $ipv6_part = substr($ip, 0, $pos);
  13484. $ipv4_part = substr($ip, $pos + 1);
  13485. return array($ipv6_part, $ipv4_part);
  13486. }
  13487. else
  13488. {
  13489. return array($ip, '');
  13490. }
  13491. }
  13492. /**
  13493. * Checks an IPv6 address
  13494. *
  13495. * Checks if the given IP is a valid IPv6 address
  13496. *
  13497. * @param string $ip An IPv6 address
  13498. * @return bool true if $ip is a valid IPv6 address
  13499. */
  13500. public static function check_ipv6($ip)
  13501. {
  13502. $ip = self::uncompress($ip);
  13503. list($ipv6, $ipv4) = self::split_v6_v4($ip);
  13504. $ipv6 = explode(':', $ipv6);
  13505. $ipv4 = explode('.', $ipv4);
  13506. if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4)
  13507. {
  13508. foreach ($ipv6 as $ipv6_part)
  13509. {
  13510. // The section can't be empty
  13511. if ($ipv6_part === '')
  13512. return false;
  13513. // Nor can it be over four characters
  13514. if (strlen($ipv6_part) > 4)
  13515. return false;
  13516. // Remove leading zeros (this is safe because of the above)
  13517. $ipv6_part = ltrim($ipv6_part, '0');
  13518. if ($ipv6_part === '')
  13519. $ipv6_part = '0';
  13520. // Check the value is valid
  13521. $value = hexdec($ipv6_part);
  13522. if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF)
  13523. return false;
  13524. }
  13525. if (count($ipv4) === 4)
  13526. {
  13527. foreach ($ipv4 as $ipv4_part)
  13528. {
  13529. $value = (int) $ipv4_part;
  13530. if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF)
  13531. return false;
  13532. }
  13533. }
  13534. return true;
  13535. }
  13536. else
  13537. {
  13538. return false;
  13539. }
  13540. }
  13541. /**
  13542. * Checks if the given IP is a valid IPv6 address
  13543. *
  13544. * @codeCoverageIgnore
  13545. * @deprecated Use {@see SimplePie_Net_IPv6::check_ipv6()} instead
  13546. * @see check_ipv6
  13547. * @param string $ip An IPv6 address
  13548. * @return bool true if $ip is a valid IPv6 address
  13549. */
  13550. public static function checkIPv6($ip)
  13551. {
  13552. return self::check_ipv6($ip);
  13553. }
  13554. }
  13555. /**
  13556. * Date Parser
  13557. *
  13558. * @package SimplePie
  13559. * @subpackage Parsing
  13560. */
  13561. class SimplePie_Parse_Date
  13562. {
  13563. /**
  13564. * Input data
  13565. *
  13566. * @access protected
  13567. * @var string
  13568. */
  13569. var $date;
  13570. /**
  13571. * List of days, calendar day name => ordinal day number in the week
  13572. *
  13573. * @access protected
  13574. * @var array
  13575. */
  13576. var $day = array(
  13577. // English
  13578. 'mon' => 1,
  13579. 'monday' => 1,
  13580. 'tue' => 2,
  13581. 'tuesday' => 2,
  13582. 'wed' => 3,
  13583. 'wednesday' => 3,
  13584. 'thu' => 4,
  13585. 'thursday' => 4,
  13586. 'fri' => 5,
  13587. 'friday' => 5,
  13588. 'sat' => 6,
  13589. 'saturday' => 6,
  13590. 'sun' => 7,
  13591. 'sunday' => 7,
  13592. // Dutch
  13593. 'maandag' => 1,
  13594. 'dinsdag' => 2,
  13595. 'woensdag' => 3,
  13596. 'donderdag' => 4,
  13597. 'vrijdag' => 5,
  13598. 'zaterdag' => 6,
  13599. 'zondag' => 7,
  13600. // French
  13601. 'lundi' => 1,
  13602. 'mardi' => 2,
  13603. 'mercredi' => 3,
  13604. 'jeudi' => 4,
  13605. 'vendredi' => 5,
  13606. 'samedi' => 6,
  13607. 'dimanche' => 7,
  13608. // German
  13609. 'montag' => 1,
  13610. 'dienstag' => 2,
  13611. 'mittwoch' => 3,
  13612. 'donnerstag' => 4,
  13613. 'freitag' => 5,
  13614. 'samstag' => 6,
  13615. 'sonnabend' => 6,
  13616. 'sonntag' => 7,
  13617. // Italian
  13618. 'lunedì' => 1,
  13619. 'martedì' => 2,
  13620. 'mercoledì' => 3,
  13621. 'giovedì' => 4,
  13622. 'venerdì' => 5,
  13623. 'sabato' => 6,
  13624. 'domenica' => 7,
  13625. // Spanish
  13626. 'lunes' => 1,
  13627. 'martes' => 2,
  13628. 'miércoles' => 3,
  13629. 'jueves' => 4,
  13630. 'viernes' => 5,
  13631. 'sábado' => 6,
  13632. 'domingo' => 7,
  13633. // Finnish
  13634. 'maanantai' => 1,
  13635. 'tiistai' => 2,
  13636. 'keskiviikko' => 3,
  13637. 'torstai' => 4,
  13638. 'perjantai' => 5,
  13639. 'lauantai' => 6,
  13640. 'sunnuntai' => 7,
  13641. // Hungarian
  13642. 'hétfő' => 1,
  13643. 'kedd' => 2,
  13644. 'szerda' => 3,
  13645. 'csütörtok' => 4,
  13646. 'péntek' => 5,
  13647. 'szombat' => 6,
  13648. 'vasárnap' => 7,
  13649. // Greek
  13650. 'Δευ' => 1,
  13651. 'Τρι' => 2,
  13652. 'Τετ' => 3,
  13653. 'Πεμ' => 4,
  13654. 'Παρ' => 5,
  13655. 'Σαβ' => 6,
  13656. 'Κυρ' => 7,
  13657. );
  13658. /**
  13659. * List of months, calendar month name => calendar month number
  13660. *
  13661. * @access protected
  13662. * @var array
  13663. */
  13664. var $month = array(
  13665. // English
  13666. 'jan' => 1,
  13667. 'january' => 1,
  13668. 'feb' => 2,
  13669. 'february' => 2,
  13670. 'mar' => 3,
  13671. 'march' => 3,
  13672. 'apr' => 4,
  13673. 'april' => 4,
  13674. 'may' => 5,
  13675. // No long form of May
  13676. 'jun' => 6,
  13677. 'june' => 6,
  13678. 'jul' => 7,
  13679. 'july' => 7,
  13680. 'aug' => 8,
  13681. 'august' => 8,
  13682. 'sep' => 9,
  13683. 'september' => 8,
  13684. 'oct' => 10,
  13685. 'october' => 10,
  13686. 'nov' => 11,
  13687. 'november' => 11,
  13688. 'dec' => 12,
  13689. 'december' => 12,
  13690. // Dutch
  13691. 'januari' => 1,
  13692. 'februari' => 2,
  13693. 'maart' => 3,
  13694. 'april' => 4,
  13695. 'mei' => 5,
  13696. 'juni' => 6,
  13697. 'juli' => 7,
  13698. 'augustus' => 8,
  13699. 'september' => 9,
  13700. 'oktober' => 10,
  13701. 'november' => 11,
  13702. 'december' => 12,
  13703. // French
  13704. 'janvier' => 1,
  13705. 'février' => 2,
  13706. 'mars' => 3,
  13707. 'avril' => 4,
  13708. 'mai' => 5,
  13709. 'juin' => 6,
  13710. 'juillet' => 7,
  13711. 'août' => 8,
  13712. 'septembre' => 9,
  13713. 'octobre' => 10,
  13714. 'novembre' => 11,
  13715. 'décembre' => 12,
  13716. // German
  13717. 'januar' => 1,
  13718. 'februar' => 2,
  13719. 'märz' => 3,
  13720. 'april' => 4,
  13721. 'mai' => 5,
  13722. 'juni' => 6,
  13723. 'juli' => 7,
  13724. 'august' => 8,
  13725. 'september' => 9,
  13726. 'oktober' => 10,
  13727. 'november' => 11,
  13728. 'dezember' => 12,
  13729. // Italian
  13730. 'gennaio' => 1,
  13731. 'febbraio' => 2,
  13732. 'marzo' => 3,
  13733. 'aprile' => 4,
  13734. 'maggio' => 5,
  13735. 'giugno' => 6,
  13736. 'luglio' => 7,
  13737. 'agosto' => 8,
  13738. 'settembre' => 9,
  13739. 'ottobre' => 10,
  13740. 'novembre' => 11,
  13741. 'dicembre' => 12,
  13742. // Spanish
  13743. 'enero' => 1,
  13744. 'febrero' => 2,
  13745. 'marzo' => 3,
  13746. 'abril' => 4,
  13747. 'mayo' => 5,
  13748. 'junio' => 6,
  13749. 'julio' => 7,
  13750. 'agosto' => 8,
  13751. 'septiembre' => 9,
  13752. 'setiembre' => 9,
  13753. 'octubre' => 10,
  13754. 'noviembre' => 11,
  13755. 'diciembre' => 12,
  13756. // Finnish
  13757. 'tammikuu' => 1,
  13758. 'helmikuu' => 2,
  13759. 'maaliskuu' => 3,
  13760. 'huhtikuu' => 4,
  13761. 'toukokuu' => 5,
  13762. 'kesäkuu' => 6,
  13763. 'heinäkuu' => 7,
  13764. 'elokuu' => 8,
  13765. 'suuskuu' => 9,
  13766. 'lokakuu' => 10,
  13767. 'marras' => 11,
  13768. 'joulukuu' => 12,
  13769. // Hungarian
  13770. 'január' => 1,
  13771. 'február' => 2,
  13772. 'március' => 3,
  13773. 'április' => 4,
  13774. 'május' => 5,
  13775. 'június' => 6,
  13776. 'július' => 7,
  13777. 'augusztus' => 8,
  13778. 'szeptember' => 9,
  13779. 'október' => 10,
  13780. 'november' => 11,
  13781. 'december' => 12,
  13782. // Greek
  13783. 'Ιαν' => 1,
  13784. 'Φεβ' => 2,
  13785. 'Μάώ' => 3,
  13786. 'Μαώ' => 3,
  13787. 'Απρ' => 4,
  13788. 'Μάι' => 5,
  13789. 'Μαϊ' => 5,
  13790. 'Μαι' => 5,
  13791. 'Ιούν' => 6,
  13792. 'Ιον' => 6,
  13793. 'Ιούλ' => 7,
  13794. 'Ιολ' => 7,
  13795. 'Αύγ' => 8,
  13796. 'Αυγ' => 8,
  13797. 'Σεπ' => 9,
  13798. 'Οκτ' => 10,
  13799. 'Νοέ' => 11,
  13800. 'Δεκ' => 12,
  13801. );
  13802. /**
  13803. * List of timezones, abbreviation => offset from UTC
  13804. *
  13805. * @access protected
  13806. * @var array
  13807. */
  13808. var $timezone = array(
  13809. 'ACDT' => 37800,
  13810. 'ACIT' => 28800,
  13811. 'ACST' => 34200,
  13812. 'ACT' => -18000,
  13813. 'ACWDT' => 35100,
  13814. 'ACWST' => 31500,
  13815. 'AEDT' => 39600,
  13816. 'AEST' => 36000,
  13817. 'AFT' => 16200,
  13818. 'AKDT' => -28800,
  13819. 'AKST' => -32400,
  13820. 'AMDT' => 18000,
  13821. 'AMT' => -14400,
  13822. 'ANAST' => 46800,
  13823. 'ANAT' => 43200,
  13824. 'ART' => -10800,
  13825. 'AZOST' => -3600,
  13826. 'AZST' => 18000,
  13827. 'AZT' => 14400,
  13828. 'BIOT' => 21600,
  13829. 'BIT' => -43200,
  13830. 'BOT' => -14400,
  13831. 'BRST' => -7200,
  13832. 'BRT' => -10800,
  13833. 'BST' => 3600,
  13834. 'BTT' => 21600,
  13835. 'CAST' => 18000,
  13836. 'CAT' => 7200,
  13837. 'CCT' => 23400,
  13838. 'CDT' => -18000,
  13839. 'CEDT' => 7200,
  13840. 'CET' => 3600,
  13841. 'CGST' => -7200,
  13842. 'CGT' => -10800,
  13843. 'CHADT' => 49500,
  13844. 'CHAST' => 45900,
  13845. 'CIST' => -28800,
  13846. 'CKT' => -36000,
  13847. 'CLDT' => -10800,
  13848. 'CLST' => -14400,
  13849. 'COT' => -18000,
  13850. 'CST' => -21600,
  13851. 'CVT' => -3600,
  13852. 'CXT' => 25200,
  13853. 'DAVT' => 25200,
  13854. 'DTAT' => 36000,
  13855. 'EADT' => -18000,
  13856. 'EAST' => -21600,
  13857. 'EAT' => 10800,
  13858. 'ECT' => -18000,
  13859. 'EDT' => -14400,
  13860. 'EEST' => 10800,
  13861. 'EET' => 7200,
  13862. 'EGT' => -3600,
  13863. 'EKST' => 21600,
  13864. 'EST' => -18000,
  13865. 'FJT' => 43200,
  13866. 'FKDT' => -10800,
  13867. 'FKST' => -14400,
  13868. 'FNT' => -7200,
  13869. 'GALT' => -21600,
  13870. 'GEDT' => 14400,
  13871. 'GEST' => 10800,
  13872. 'GFT' => -10800,
  13873. 'GILT' => 43200,
  13874. 'GIT' => -32400,
  13875. 'GST' => 14400,
  13876. 'GST' => -7200,
  13877. 'GYT' => -14400,
  13878. 'HAA' => -10800,
  13879. 'HAC' => -18000,
  13880. 'HADT' => -32400,
  13881. 'HAE' => -14400,
  13882. 'HAP' => -25200,
  13883. 'HAR' => -21600,
  13884. 'HAST' => -36000,
  13885. 'HAT' => -9000,
  13886. 'HAY' => -28800,
  13887. 'HKST' => 28800,
  13888. 'HMT' => 18000,
  13889. 'HNA' => -14400,
  13890. 'HNC' => -21600,
  13891. 'HNE' => -18000,
  13892. 'HNP' => -28800,
  13893. 'HNR' => -25200,
  13894. 'HNT' => -12600,
  13895. 'HNY' => -32400,
  13896. 'IRDT' => 16200,
  13897. 'IRKST' => 32400,
  13898. 'IRKT' => 28800,
  13899. 'IRST' => 12600,
  13900. 'JFDT' => -10800,
  13901. 'JFST' => -14400,
  13902. 'JST' => 32400,
  13903. 'KGST' => 21600,
  13904. 'KGT' => 18000,
  13905. 'KOST' => 39600,
  13906. 'KOVST' => 28800,
  13907. 'KOVT' => 25200,
  13908. 'KRAST' => 28800,
  13909. 'KRAT' => 25200,
  13910. 'KST' => 32400,
  13911. 'LHDT' => 39600,
  13912. 'LHST' => 37800,
  13913. 'LINT' => 50400,
  13914. 'LKT' => 21600,
  13915. 'MAGST' => 43200,
  13916. 'MAGT' => 39600,
  13917. 'MAWT' => 21600,
  13918. 'MDT' => -21600,
  13919. 'MESZ' => 7200,
  13920. 'MEZ' => 3600,
  13921. 'MHT' => 43200,
  13922. 'MIT' => -34200,
  13923. 'MNST' => 32400,
  13924. 'MSDT' => 14400,
  13925. 'MSST' => 10800,
  13926. 'MST' => -25200,
  13927. 'MUT' => 14400,
  13928. 'MVT' => 18000,
  13929. 'MYT' => 28800,
  13930. 'NCT' => 39600,
  13931. 'NDT' => -9000,
  13932. 'NFT' => 41400,
  13933. 'NMIT' => 36000,
  13934. 'NOVST' => 25200,
  13935. 'NOVT' => 21600,
  13936. 'NPT' => 20700,
  13937. 'NRT' => 43200,
  13938. 'NST' => -12600,
  13939. 'NUT' => -39600,
  13940. 'NZDT' => 46800,
  13941. 'NZST' => 43200,
  13942. 'OMSST' => 25200,
  13943. 'OMST' => 21600,
  13944. 'PDT' => -25200,
  13945. 'PET' => -18000,
  13946. 'PETST' => 46800,
  13947. 'PETT' => 43200,
  13948. 'PGT' => 36000,
  13949. 'PHOT' => 46800,
  13950. 'PHT' => 28800,
  13951. 'PKT' => 18000,
  13952. 'PMDT' => -7200,
  13953. 'PMST' => -10800,
  13954. 'PONT' => 39600,
  13955. 'PST' => -28800,
  13956. 'PWT' => 32400,
  13957. 'PYST' => -10800,
  13958. 'PYT' => -14400,
  13959. 'RET' => 14400,
  13960. 'ROTT' => -10800,
  13961. 'SAMST' => 18000,
  13962. 'SAMT' => 14400,
  13963. 'SAST' => 7200,
  13964. 'SBT' => 39600,
  13965. 'SCDT' => 46800,
  13966. 'SCST' => 43200,
  13967. 'SCT' => 14400,
  13968. 'SEST' => 3600,
  13969. 'SGT' => 28800,
  13970. 'SIT' => 28800,
  13971. 'SRT' => -10800,
  13972. 'SST' => -39600,
  13973. 'SYST' => 10800,
  13974. 'SYT' => 7200,
  13975. 'TFT' => 18000,
  13976. 'THAT' => -36000,
  13977. 'TJT' => 18000,
  13978. 'TKT' => -36000,
  13979. 'TMT' => 18000,
  13980. 'TOT' => 46800,
  13981. 'TPT' => 32400,
  13982. 'TRUT' => 36000,
  13983. 'TVT' => 43200,
  13984. 'TWT' => 28800,
  13985. 'UYST' => -7200,
  13986. 'UYT' => -10800,
  13987. 'UZT' => 18000,
  13988. 'VET' => -14400,
  13989. 'VLAST' => 39600,
  13990. 'VLAT' => 36000,
  13991. 'VOST' => 21600,
  13992. 'VUT' => 39600,
  13993. 'WAST' => 7200,
  13994. 'WAT' => 3600,
  13995. 'WDT' => 32400,
  13996. 'WEST' => 3600,
  13997. 'WFT' => 43200,
  13998. 'WIB' => 25200,
  13999. 'WIT' => 32400,
  14000. 'WITA' => 28800,
  14001. 'WKST' => 18000,
  14002. 'WST' => 28800,
  14003. 'YAKST' => 36000,
  14004. 'YAKT' => 32400,
  14005. 'YAPT' => 36000,
  14006. 'YEKST' => 21600,
  14007. 'YEKT' => 18000,
  14008. );
  14009. /**
  14010. * Cached PCRE for SimplePie_Parse_Date::$day
  14011. *
  14012. * @access protected
  14013. * @var string
  14014. */
  14015. var $day_pcre;
  14016. /**
  14017. * Cached PCRE for SimplePie_Parse_Date::$month
  14018. *
  14019. * @access protected
  14020. * @var string
  14021. */
  14022. var $month_pcre;
  14023. /**
  14024. * Array of user-added callback methods
  14025. *
  14026. * @access private
  14027. * @var array
  14028. */
  14029. var $built_in = array();
  14030. /**
  14031. * Array of user-added callback methods
  14032. *
  14033. * @access private
  14034. * @var array
  14035. */
  14036. var $user = array();
  14037. /**
  14038. * Create new SimplePie_Parse_Date object, and set self::day_pcre,
  14039. * self::month_pcre, and self::built_in
  14040. *
  14041. * @access private
  14042. */
  14043. public function __construct()
  14044. {
  14045. $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
  14046. $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
  14047. static $cache;
  14048. if (!isset($cache[get_class($this)]))
  14049. {
  14050. $all_methods = get_class_methods($this);
  14051. foreach ($all_methods as $method)
  14052. {
  14053. if (strtolower(substr($method, 0, 5)) === 'date_')
  14054. {
  14055. $cache[get_class($this)][] = $method;
  14056. }
  14057. }
  14058. }
  14059. foreach ($cache[get_class($this)] as $method)
  14060. {
  14061. $this->built_in[] = $method;
  14062. }
  14063. }
  14064. /**
  14065. * Get the object
  14066. *
  14067. * @access public
  14068. */
  14069. public static function get()
  14070. {
  14071. static $object;
  14072. if (!$object)
  14073. {
  14074. $object = new SimplePie_Parse_Date;
  14075. }
  14076. return $object;
  14077. }
  14078. /**
  14079. * Parse a date
  14080. *
  14081. * @final
  14082. * @access public
  14083. * @param string $date Date to parse
  14084. * @return int Timestamp corresponding to date string, or false on failure
  14085. */
  14086. public function parse($date)
  14087. {
  14088. foreach ($this->user as $method)
  14089. {
  14090. if (($returned = call_user_func($method, $date)) !== false)
  14091. {
  14092. return $returned;
  14093. }
  14094. }
  14095. foreach ($this->built_in as $method)
  14096. {
  14097. if (($returned = call_user_func(array($this, $method), $date)) !== false)
  14098. {
  14099. return $returned;
  14100. }
  14101. }
  14102. return false;
  14103. }
  14104. /**
  14105. * Add a callback method to parse a date
  14106. *
  14107. * @final
  14108. * @access public
  14109. * @param callback $callback
  14110. */
  14111. public function add_callback($callback)
  14112. {
  14113. if (is_callable($callback))
  14114. {
  14115. $this->user[] = $callback;
  14116. }
  14117. else
  14118. {
  14119. trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
  14120. }
  14121. }
  14122. /**
  14123. * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
  14124. * well as allowing any of upper or lower case "T", horizontal tabs, or
  14125. * spaces to be used as the time seperator (including more than one))
  14126. *
  14127. * @access protected
  14128. * @return int Timestamp
  14129. */
  14130. public function date_w3cdtf($date)
  14131. {
  14132. static $pcre;
  14133. if (!$pcre)
  14134. {
  14135. $year = '([0-9]{4})';
  14136. $month = $day = $hour = $minute = $second = '([0-9]{2})';
  14137. $decimal = '([0-9]*)';
  14138. $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
  14139. $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
  14140. }
  14141. if (preg_match($pcre, $date, $match))
  14142. {
  14143. /*
  14144. Capturing subpatterns:
  14145. 1: Year
  14146. 2: Month
  14147. 3: Day
  14148. 4: Hour
  14149. 5: Minute
  14150. 6: Second
  14151. 7: Decimal fraction of a second
  14152. 8: Zulu
  14153. 9: Timezone ±
  14154. 10: Timezone hours
  14155. 11: Timezone minutes
  14156. */
  14157. // Fill in empty matches
  14158. for ($i = count($match); $i <= 3; $i++)
  14159. {
  14160. $match[$i] = '1';
  14161. }
  14162. for ($i = count($match); $i <= 7; $i++)
  14163. {
  14164. $match[$i] = '0';
  14165. }
  14166. // Numeric timezone
  14167. if (isset($match[9]) && $match[9] !== '')
  14168. {
  14169. $timezone = $match[10] * 3600;
  14170. $timezone += $match[11] * 60;
  14171. if ($match[9] === '-')
  14172. {
  14173. $timezone = 0 - $timezone;
  14174. }
  14175. }
  14176. else
  14177. {
  14178. $timezone = 0;
  14179. }
  14180. // Convert the number of seconds to an integer, taking decimals into account
  14181. $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
  14182. return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
  14183. }
  14184. else
  14185. {
  14186. return false;
  14187. }
  14188. }
  14189. /**
  14190. * Remove RFC822 comments
  14191. *
  14192. * @access protected
  14193. * @param string $data Data to strip comments from
  14194. * @return string Comment stripped string
  14195. */
  14196. public function remove_rfc2822_comments($string)
  14197. {
  14198. $string = (string) $string;
  14199. $position = 0;
  14200. $length = strlen($string);
  14201. $depth = 0;
  14202. $output = '';
  14203. while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
  14204. {
  14205. $output .= substr($string, $position, $pos - $position);
  14206. $position = $pos + 1;
  14207. if ($string[$pos - 1] !== '\\')
  14208. {
  14209. $depth++;
  14210. while ($depth && $position < $length)
  14211. {
  14212. $position += strcspn($string, '()', $position);
  14213. if ($string[$position - 1] === '\\')
  14214. {
  14215. $position++;
  14216. continue;
  14217. }
  14218. elseif (isset($string[$position]))
  14219. {
  14220. switch ($string[$position])
  14221. {
  14222. case '(':
  14223. $depth++;
  14224. break;
  14225. case ')':
  14226. $depth--;
  14227. break;
  14228. }
  14229. $position++;
  14230. }
  14231. else
  14232. {
  14233. break;
  14234. }
  14235. }
  14236. }
  14237. else
  14238. {
  14239. $output .= '(';
  14240. }
  14241. }
  14242. $output .= substr($string, $position);
  14243. return $output;
  14244. }
  14245. /**
  14246. * Parse RFC2822's date format
  14247. *
  14248. * @access protected
  14249. * @return int Timestamp
  14250. */
  14251. public function date_rfc2822($date)
  14252. {
  14253. static $pcre;
  14254. if (!$pcre)
  14255. {
  14256. $wsp = '[\x09\x20]';
  14257. $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
  14258. $optional_fws = $fws . '?';
  14259. $day_name = $this->day_pcre;
  14260. $month = $this->month_pcre;
  14261. $day = '([0-9]{1,2})';
  14262. $hour = $minute = $second = '([0-9]{2})';
  14263. $year = '([0-9]{2,4})';
  14264. $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
  14265. $character_zone = '([A-Z]{1,5})';
  14266. $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
  14267. $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';
  14268. }
  14269. if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
  14270. {
  14271. /*
  14272. Capturing subpatterns:
  14273. 1: Day name
  14274. 2: Day
  14275. 3: Month
  14276. 4: Year
  14277. 5: Hour
  14278. 6: Minute
  14279. 7: Second
  14280. 8: Timezone ±
  14281. 9: Timezone hours
  14282. 10: Timezone minutes
  14283. 11: Alphabetic timezone
  14284. */
  14285. // Find the month number
  14286. $month = $this->month[strtolower($match[3])];
  14287. // Numeric timezone
  14288. if ($match[8] !== '')
  14289. {
  14290. $timezone = $match[9] * 3600;
  14291. $timezone += $match[10] * 60;
  14292. if ($match[8] === '-')
  14293. {
  14294. $timezone = 0 - $timezone;
  14295. }
  14296. }
  14297. // Character timezone
  14298. elseif (isset($this->timezone[strtoupper($match[11])]))
  14299. {
  14300. $timezone = $this->timezone[strtoupper($match[11])];
  14301. }
  14302. // Assume everything else to be -0000
  14303. else
  14304. {
  14305. $timezone = 0;
  14306. }
  14307. // Deal with 2/3 digit years
  14308. if ($match[4] < 50)
  14309. {
  14310. $match[4] += 2000;
  14311. }
  14312. elseif ($match[4] < 1000)
  14313. {
  14314. $match[4] += 1900;
  14315. }
  14316. // Second is optional, if it is empty set it to zero
  14317. if ($match[7] !== '')
  14318. {
  14319. $second = $match[7];
  14320. }
  14321. else
  14322. {
  14323. $second = 0;
  14324. }
  14325. return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
  14326. }
  14327. else
  14328. {
  14329. return false;
  14330. }
  14331. }
  14332. /**
  14333. * Parse RFC850's date format
  14334. *
  14335. * @access protected
  14336. * @return int Timestamp
  14337. */
  14338. public function date_rfc850($date)
  14339. {
  14340. static $pcre;
  14341. if (!$pcre)
  14342. {
  14343. $space = '[\x09\x20]+';
  14344. $day_name = $this->day_pcre;
  14345. $month = $this->month_pcre;
  14346. $day = '([0-9]{1,2})';
  14347. $year = $hour = $minute = $second = '([0-9]{2})';
  14348. $zone = '([A-Z]{1,5})';
  14349. $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
  14350. }
  14351. if (preg_match($pcre, $date, $match))
  14352. {
  14353. /*
  14354. Capturing subpatterns:
  14355. 1: Day name
  14356. 2: Day
  14357. 3: Month
  14358. 4: Year
  14359. 5: Hour
  14360. 6: Minute
  14361. 7: Second
  14362. 8: Timezone
  14363. */
  14364. // Month
  14365. $month = $this->month[strtolower($match[3])];
  14366. // Character timezone
  14367. if (isset($this->timezone[strtoupper($match[8])]))
  14368. {
  14369. $timezone = $this->timezone[strtoupper($match[8])];
  14370. }
  14371. // Assume everything else to be -0000
  14372. else
  14373. {
  14374. $timezone = 0;
  14375. }
  14376. // Deal with 2 digit year
  14377. if ($match[4] < 50)
  14378. {
  14379. $match[4] += 2000;
  14380. }
  14381. else
  14382. {
  14383. $match[4] += 1900;
  14384. }
  14385. return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
  14386. }
  14387. else
  14388. {
  14389. return false;
  14390. }
  14391. }
  14392. /**
  14393. * Parse C99's asctime()'s date format
  14394. *
  14395. * @access protected
  14396. * @return int Timestamp
  14397. */
  14398. public function date_asctime($date)
  14399. {
  14400. static $pcre;
  14401. if (!$pcre)
  14402. {
  14403. $space = '[\x09\x20]+';
  14404. $wday_name = $this->day_pcre;
  14405. $mon_name = $this->month_pcre;
  14406. $day = '([0-9]{1,2})';
  14407. $hour = $sec = $min = '([0-9]{2})';
  14408. $year = '([0-9]{4})';
  14409. $terminator = '\x0A?\x00?';
  14410. $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
  14411. }
  14412. if (preg_match($pcre, $date, $match))
  14413. {
  14414. /*
  14415. Capturing subpatterns:
  14416. 1: Day name
  14417. 2: Month
  14418. 3: Day
  14419. 4: Hour
  14420. 5: Minute
  14421. 6: Second
  14422. 7: Year
  14423. */
  14424. $month = $this->month[strtolower($match[2])];
  14425. return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
  14426. }
  14427. else
  14428. {
  14429. return false;
  14430. }
  14431. }
  14432. /**
  14433. * Parse dates using strtotime()
  14434. *
  14435. * @access protected
  14436. * @return int Timestamp
  14437. */
  14438. public function date_strtotime($date)
  14439. {
  14440. $strtotime = strtotime($date);
  14441. if ($strtotime === -1 || $strtotime === false)
  14442. {
  14443. return false;
  14444. }
  14445. else
  14446. {
  14447. return $strtotime;
  14448. }
  14449. }
  14450. }
  14451. /**
  14452. * Parses XML into something sane
  14453. *
  14454. *
  14455. * This class can be overloaded with {@see SimplePie::set_parser_class()}
  14456. *
  14457. * @package SimplePie
  14458. * @subpackage Parsing
  14459. */
  14460. class SimplePie_Parser
  14461. {
  14462. var $error_code;
  14463. var $error_string;
  14464. var $current_line;
  14465. var $current_column;
  14466. var $current_byte;
  14467. var $separator = ' ';
  14468. var $namespace = array('');
  14469. var $element = array('');
  14470. var $xml_base = array('');
  14471. var $xml_base_explicit = array(false);
  14472. var $xml_lang = array('');
  14473. var $data = array();
  14474. var $datas = array(array());
  14475. var $current_xhtml_construct = -1;
  14476. var $encoding;
  14477. protected $registry;
  14478. public function set_registry(SimplePie_Registry $registry)
  14479. {
  14480. $this->registry = $registry;
  14481. }
  14482. public function parse(&$data, $encoding)
  14483. {
  14484. // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
  14485. if (strtoupper($encoding) === 'US-ASCII')
  14486. {
  14487. $this->encoding = 'UTF-8';
  14488. }
  14489. else
  14490. {
  14491. $this->encoding = $encoding;
  14492. }
  14493. // Strip BOM:
  14494. // UTF-32 Big Endian BOM
  14495. if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
  14496. {
  14497. $data = substr($data, 4);
  14498. }
  14499. // UTF-32 Little Endian BOM
  14500. elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
  14501. {
  14502. $data = substr($data, 4);
  14503. }
  14504. // UTF-16 Big Endian BOM
  14505. elseif (substr($data, 0, 2) === "\xFE\xFF")
  14506. {
  14507. $data = substr($data, 2);
  14508. }
  14509. // UTF-16 Little Endian BOM
  14510. elseif (substr($data, 0, 2) === "\xFF\xFE")
  14511. {
  14512. $data = substr($data, 2);
  14513. }
  14514. // UTF-8 BOM
  14515. elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
  14516. {
  14517. $data = substr($data, 3);
  14518. }
  14519. if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
  14520. {
  14521. $declaration = $this->registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5)));
  14522. if ($declaration->parse())
  14523. {
  14524. $data = substr($data, $pos + 2);
  14525. $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
  14526. }
  14527. else
  14528. {
  14529. $this->error_string = 'SimplePie bug! Please report this!';
  14530. return false;
  14531. }
  14532. }
  14533. $return = true;
  14534. static $xml_is_sane = null;
  14535. if ($xml_is_sane === null)
  14536. {
  14537. $parser_check = xml_parser_create();
  14538. xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
  14539. xml_parser_free($parser_check);
  14540. $xml_is_sane = isset($values[0]['value']);
  14541. }
  14542. // Create the parser
  14543. if ($xml_is_sane)
  14544. {
  14545. $xml = xml_parser_create_ns($this->encoding, $this->separator);
  14546. xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
  14547. xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
  14548. xml_set_object($xml, $this);
  14549. xml_set_character_data_handler($xml, 'cdata');
  14550. xml_set_element_handler($xml, 'tag_open', 'tag_close');
  14551. // Parse!
  14552. if (!xml_parse($xml, $data, true))
  14553. {
  14554. $this->error_code = xml_get_error_code($xml);
  14555. $this->error_string = xml_error_string($this->error_code);
  14556. $return = false;
  14557. }
  14558. $this->current_line = xml_get_current_line_number($xml);
  14559. $this->current_column = xml_get_current_column_number($xml);
  14560. $this->current_byte = xml_get_current_byte_index($xml);
  14561. xml_parser_free($xml);
  14562. return $return;
  14563. }
  14564. else
  14565. {
  14566. libxml_clear_errors();
  14567. $xml = new XMLReader();
  14568. $xml->xml($data);
  14569. while (@$xml->read())
  14570. {
  14571. switch ($xml->nodeType)
  14572. {
  14573. case constant('XMLReader::END_ELEMENT'):
  14574. if ($xml->namespaceURI !== '')
  14575. {
  14576. $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
  14577. }
  14578. else
  14579. {
  14580. $tagName = $xml->localName;
  14581. }
  14582. $this->tag_close(null, $tagName);
  14583. break;
  14584. case constant('XMLReader::ELEMENT'):
  14585. $empty = $xml->isEmptyElement;
  14586. if ($xml->namespaceURI !== '')
  14587. {
  14588. $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
  14589. }
  14590. else
  14591. {
  14592. $tagName = $xml->localName;
  14593. }
  14594. $attributes = array();
  14595. while ($xml->moveToNextAttribute())
  14596. {
  14597. if ($xml->namespaceURI !== '')
  14598. {
  14599. $attrName = $xml->namespaceURI . $this->separator . $xml->localName;
  14600. }
  14601. else
  14602. {
  14603. $attrName = $xml->localName;
  14604. }
  14605. $attributes[$attrName] = $xml->value;
  14606. }
  14607. $this->tag_open(null, $tagName, $attributes);
  14608. if ($empty)
  14609. {
  14610. $this->tag_close(null, $tagName);
  14611. }
  14612. break;
  14613. case constant('XMLReader::TEXT'):
  14614. case constant('XMLReader::CDATA'):
  14615. $this->cdata(null, $xml->value);
  14616. break;
  14617. }
  14618. }
  14619. if ($error = libxml_get_last_error())
  14620. {
  14621. $this->error_code = $error->code;
  14622. $this->error_string = $error->message;
  14623. $this->current_line = $error->line;
  14624. $this->current_column = $error->column;
  14625. return false;
  14626. }
  14627. else
  14628. {
  14629. return true;
  14630. }
  14631. }
  14632. }
  14633. public function get_error_code()
  14634. {
  14635. return $this->error_code;
  14636. }
  14637. public function get_error_string()
  14638. {
  14639. return $this->error_string;
  14640. }
  14641. public function get_current_line()
  14642. {
  14643. return $this->current_line;
  14644. }
  14645. public function get_current_column()
  14646. {
  14647. return $this->current_column;
  14648. }
  14649. public function get_current_byte()
  14650. {
  14651. return $this->current_byte;
  14652. }
  14653. public function get_data()
  14654. {
  14655. return $this->data;
  14656. }
  14657. public function tag_open($parser, $tag, $attributes)
  14658. {
  14659. list($this->namespace[], $this->element[]) = $this->split_ns($tag);
  14660. $attribs = array();
  14661. foreach ($attributes as $name => $value)
  14662. {
  14663. list($attrib_namespace, $attribute) = $this->split_ns($name);
  14664. $attribs[$attrib_namespace][$attribute] = $value;
  14665. }
  14666. if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
  14667. {
  14668. $base = $this->registry->call('Misc', 'absolutize_url', array($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base)));
  14669. if ($base !== false)
  14670. {
  14671. $this->xml_base[] = $base;
  14672. $this->xml_base_explicit[] = true;
  14673. }
  14674. }
  14675. else
  14676. {
  14677. $this->xml_base[] = end($this->xml_base);
  14678. $this->xml_base_explicit[] = end($this->xml_base_explicit);
  14679. }
  14680. if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
  14681. {
  14682. $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
  14683. }
  14684. else
  14685. {
  14686. $this->xml_lang[] = end($this->xml_lang);
  14687. }
  14688. if ($this->current_xhtml_construct >= 0)
  14689. {
  14690. $this->current_xhtml_construct++;
  14691. if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
  14692. {
  14693. $this->data['data'] .= '<' . end($this->element);
  14694. if (isset($attribs['']))
  14695. {
  14696. foreach ($attribs[''] as $name => $value)
  14697. {
  14698. $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
  14699. }
  14700. }
  14701. $this->data['data'] .= '>';
  14702. }
  14703. }
  14704. else
  14705. {
  14706. $this->datas[] =& $this->data;
  14707. $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
  14708. $this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang));
  14709. if ((end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml')
  14710. || (end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml')
  14711. || (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_20 && in_array(end($this->element), array('title')))
  14712. || (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_090 && in_array(end($this->element), array('title')))
  14713. || (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_10 && in_array(end($this->element), array('title'))))
  14714. {
  14715. $this->current_xhtml_construct = 0;
  14716. }
  14717. }
  14718. }
  14719. public function cdata($parser, $cdata)
  14720. {
  14721. if ($this->current_xhtml_construct >= 0)
  14722. {
  14723. $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
  14724. }
  14725. else
  14726. {
  14727. $this->data['data'] .= $cdata;
  14728. }
  14729. }
  14730. public function tag_close($parser, $tag)
  14731. {
  14732. if ($this->current_xhtml_construct >= 0)
  14733. {
  14734. $this->current_xhtml_construct--;
  14735. if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param')))
  14736. {
  14737. $this->data['data'] .= '</' . end($this->element) . '>';
  14738. }
  14739. }
  14740. if ($this->current_xhtml_construct === -1)
  14741. {
  14742. $this->data =& $this->datas[count($this->datas) - 1];
  14743. array_pop($this->datas);
  14744. }
  14745. array_pop($this->element);
  14746. array_pop($this->namespace);
  14747. array_pop($this->xml_base);
  14748. array_pop($this->xml_base_explicit);
  14749. array_pop($this->xml_lang);
  14750. }
  14751. public function split_ns($string)
  14752. {
  14753. static $cache = array();
  14754. if (!isset($cache[$string]))
  14755. {
  14756. if ($pos = strpos($string, $this->separator))
  14757. {
  14758. static $separator_length;
  14759. if (!$separator_length)
  14760. {
  14761. $separator_length = strlen($this->separator);
  14762. }
  14763. $namespace = substr($string, 0, $pos);
  14764. $local_name = substr($string, $pos + $separator_length);
  14765. if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
  14766. {
  14767. $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
  14768. }
  14769. // Normalize the Media RSS namespaces
  14770. if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG ||
  14771. $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2 ||
  14772. $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3 ||
  14773. $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4 ||
  14774. $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5 )
  14775. {
  14776. $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
  14777. }
  14778. $cache[$string] = array($namespace, $local_name);
  14779. }
  14780. else
  14781. {
  14782. $cache[$string] = array('', $string);
  14783. }
  14784. }
  14785. return $cache[$string];
  14786. }
  14787. }
  14788. /**
  14789. * Handles `<media:rating>` or `<itunes:explicit>` tags as defined in Media RSS and iTunes RSS respectively
  14790. *
  14791. * Used by {@see SimplePie_Enclosure::get_rating()} and {@see SimplePie_Enclosure::get_ratings()}
  14792. *
  14793. * This class can be overloaded with {@see SimplePie::set_rating_class()}
  14794. *
  14795. * @package SimplePie
  14796. * @subpackage API
  14797. */
  14798. class SimplePie_Rating
  14799. {
  14800. /**
  14801. * Rating scheme
  14802. *
  14803. * @var string
  14804. * @see get_scheme()
  14805. */
  14806. var $scheme;
  14807. /**
  14808. * Rating value
  14809. *
  14810. * @var string
  14811. * @see get_value()
  14812. */
  14813. var $value;
  14814. /**
  14815. * Constructor, used to input the data
  14816. *
  14817. * For documentation on all the parameters, see the corresponding
  14818. * properties and their accessors
  14819. */
  14820. public function __construct($scheme = null, $value = null)
  14821. {
  14822. $this->scheme = $scheme;
  14823. $this->value = $value;
  14824. }
  14825. /**
  14826. * String-ified version
  14827. *
  14828. * @return string
  14829. */
  14830. public function __toString()
  14831. {
  14832. // There is no $this->data here
  14833. return md5(serialize($this));
  14834. }
  14835. /**
  14836. * Get the organizational scheme for the rating
  14837. *
  14838. * @return string|null
  14839. */
  14840. public function get_scheme()
  14841. {
  14842. if ($this->scheme !== null)
  14843. {
  14844. return $this->scheme;
  14845. }
  14846. else
  14847. {
  14848. return null;
  14849. }
  14850. }
  14851. /**
  14852. * Get the value of the rating
  14853. *
  14854. * @return string|null
  14855. */
  14856. public function get_value()
  14857. {
  14858. if ($this->value !== null)
  14859. {
  14860. return $this->value;
  14861. }
  14862. else
  14863. {
  14864. return null;
  14865. }
  14866. }
  14867. }
  14868. /**
  14869. * Handles creating objects and calling methods
  14870. *
  14871. * Access this via {@see SimplePie::get_registry()}
  14872. *
  14873. * @package SimplePie
  14874. */
  14875. class SimplePie_Registry
  14876. {
  14877. /**
  14878. * Default class mapping
  14879. *
  14880. * Overriding classes *must* subclass these.
  14881. *
  14882. * @var array
  14883. */
  14884. protected $default = array(
  14885. 'Cache' => 'SimplePie_Cache',
  14886. 'Locator' => 'SimplePie_Locator',
  14887. 'Parser' => 'SimplePie_Parser',
  14888. 'File' => 'SimplePie_File',
  14889. 'Sanitize' => 'SimplePie_Sanitize',
  14890. 'Item' => 'SimplePie_Item',
  14891. 'Author' => 'SimplePie_Author',
  14892. 'Category' => 'SimplePie_Category',
  14893. 'Enclosure' => 'SimplePie_Enclosure',
  14894. 'Caption' => 'SimplePie_Caption',
  14895. 'Copyright' => 'SimplePie_Copyright',
  14896. 'Credit' => 'SimplePie_Credit',
  14897. 'Rating' => 'SimplePie_Rating',
  14898. 'Restriction' => 'SimplePie_Restriction',
  14899. 'Content_Type_Sniffer' => 'SimplePie_Content_Type_Sniffer',
  14900. 'Source' => 'SimplePie_Source',
  14901. 'Misc' => 'SimplePie_Misc',
  14902. 'XML_Declaration_Parser' => 'SimplePie_XML_Declaration_Parser',
  14903. 'Parse_Date' => 'SimplePie_Parse_Date',
  14904. );
  14905. /**
  14906. * Class mapping
  14907. *
  14908. * @see register()
  14909. * @var array
  14910. */
  14911. protected $classes = array();
  14912. /**
  14913. * Legacy classes
  14914. *
  14915. * @see register()
  14916. * @var array
  14917. */
  14918. protected $legacy = array();
  14919. /**
  14920. * Constructor
  14921. *
  14922. * No-op
  14923. */
  14924. public function __construct() { }
  14925. /**
  14926. * Register a class
  14927. *
  14928. * @param string $type See {@see $default} for names
  14929. * @param string $class Class name, must subclass the corresponding default
  14930. * @param bool $legacy Whether to enable legacy support for this class
  14931. * @return bool Successfulness
  14932. */
  14933. public function register($type, $class, $legacy = false)
  14934. {
  14935. if (!is_subclass_of($class, $this->default[$type]))
  14936. {
  14937. return false;
  14938. }
  14939. $this->classes[$type] = $class;
  14940. if ($legacy)
  14941. {
  14942. $this->legacy[] = $class;
  14943. }
  14944. return true;
  14945. }
  14946. /**
  14947. * Get the class registered for a type
  14948. *
  14949. * Where possible, use {@see create()} or {@see call()} instead
  14950. *
  14951. * @param string $type
  14952. * @return string|null
  14953. */
  14954. public function get_class($type)
  14955. {
  14956. if (!empty($this->classes[$type]))
  14957. {
  14958. return $this->classes[$type];
  14959. }
  14960. if (!empty($this->default[$type]))
  14961. {
  14962. return $this->default[$type];
  14963. }
  14964. return null;
  14965. }
  14966. /**
  14967. * Create a new instance of a given type
  14968. *
  14969. * @param string $type
  14970. * @param array $parameters Parameters to pass to the constructor
  14971. * @return object Instance of class
  14972. */
  14973. public function &create($type, $parameters = array())
  14974. {
  14975. $class = $this->get_class($type);
  14976. if (in_array($class, $this->legacy))
  14977. {
  14978. switch ($type)
  14979. {
  14980. case 'locator':
  14981. // Legacy: file, timeout, useragent, file_class, max_checked_feeds, content_type_sniffer_class
  14982. // Specified: file, timeout, useragent, max_checked_feeds
  14983. $replacement = array($this->get_class('file'), $parameters[3], $this->get_class('content_type_sniffer'));
  14984. array_splice($parameters, 3, 1, $replacement);
  14985. break;
  14986. }
  14987. }
  14988. if (!method_exists($class, '__construct'))
  14989. {
  14990. $instance = new $class;
  14991. }
  14992. else
  14993. {
  14994. $reflector = new ReflectionClass($class);
  14995. $instance = $reflector->newInstanceArgs($parameters);
  14996. }
  14997. if (method_exists($instance, 'set_registry'))
  14998. {
  14999. $instance->set_registry($this);
  15000. }
  15001. return $instance;
  15002. }
  15003. /**
  15004. * Call a static method for a type
  15005. *
  15006. * @param string $type
  15007. * @param string $method
  15008. * @param array $parameters
  15009. * @return mixed
  15010. */
  15011. public function &call($type, $method, $parameters = array())
  15012. {
  15013. $class = $this->get_class($type);
  15014. if (in_array($class, $this->legacy))
  15015. {
  15016. switch ($type)
  15017. {
  15018. case 'Cache':
  15019. // For backwards compatibility with old non-static
  15020. // Cache::create() methods
  15021. if ($method === 'get_handler')
  15022. {
  15023. $result = @call_user_func_array(array($class, 'create'), $parameters);
  15024. return $result;
  15025. }
  15026. break;
  15027. }
  15028. }
  15029. $result = call_user_func_array(array($class, $method), $parameters);
  15030. return $result;
  15031. }
  15032. }
  15033. /**
  15034. * Handles `<media:restriction>` as defined in Media RSS
  15035. *
  15036. * Used by {@see SimplePie_Enclosure::get_restriction()} and {@see SimplePie_Enclosure::get_restrictions()}
  15037. *
  15038. * This class can be overloaded with {@see SimplePie::set_restriction_class()}
  15039. *
  15040. * @package SimplePie
  15041. * @subpackage API
  15042. */
  15043. class SimplePie_Restriction
  15044. {
  15045. /**
  15046. * Relationship ('allow'/'deny')
  15047. *
  15048. * @var string
  15049. * @see get_relationship()
  15050. */
  15051. var $relationship;
  15052. /**
  15053. * Type of restriction
  15054. *
  15055. * @var string
  15056. * @see get_type()
  15057. */
  15058. var $type;
  15059. /**
  15060. * Restricted values
  15061. *
  15062. * @var string
  15063. * @see get_value()
  15064. */
  15065. var $value;
  15066. /**
  15067. * Constructor, used to input the data
  15068. *
  15069. * For documentation on all the parameters, see the corresponding
  15070. * properties and their accessors
  15071. */
  15072. public function __construct($relationship = null, $type = null, $value = null)
  15073. {
  15074. $this->relationship = $relationship;
  15075. $this->type = $type;
  15076. $this->value = $value;
  15077. }
  15078. /**
  15079. * String-ified version
  15080. *
  15081. * @return string
  15082. */
  15083. public function __toString()
  15084. {
  15085. // There is no $this->data here
  15086. return md5(serialize($this));
  15087. }
  15088. /**
  15089. * Get the relationship
  15090. *
  15091. * @return string|null Either 'allow' or 'deny'
  15092. */
  15093. public function get_relationship()
  15094. {
  15095. if ($this->relationship !== null)
  15096. {
  15097. return $this->relationship;
  15098. }
  15099. else
  15100. {
  15101. return null;
  15102. }
  15103. }
  15104. /**
  15105. * Get the type
  15106. *
  15107. * @return string|null
  15108. */
  15109. public function get_type()
  15110. {
  15111. if ($this->type !== null)
  15112. {
  15113. return $this->type;
  15114. }
  15115. else
  15116. {
  15117. return null;
  15118. }
  15119. }
  15120. /**
  15121. * Get the list of restricted things
  15122. *
  15123. * @return string|null
  15124. */
  15125. public function get_value()
  15126. {
  15127. if ($this->value !== null)
  15128. {
  15129. return $this->value;
  15130. }
  15131. else
  15132. {
  15133. return null;
  15134. }
  15135. }
  15136. }
  15137. /**
  15138. * Used for data cleanup and post-processing
  15139. *
  15140. *
  15141. * This class can be overloaded with {@see SimplePie::set_sanitize_class()}
  15142. *
  15143. * @package SimplePie
  15144. * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags
  15145. */
  15146. class SimplePie_Sanitize
  15147. {
  15148. // Private vars
  15149. var $base;
  15150. // Options
  15151. var $remove_div = true;
  15152. var $image_handler = '';
  15153. var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
  15154. var $encode_instead_of_strip = false;
  15155. var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
  15156. var $strip_comments = false;
  15157. var $output_encoding = 'UTF-8';
  15158. var $enable_cache = true;
  15159. var $cache_location = './cache';
  15160. var $cache_name_function = 'md5';
  15161. var $timeout = 10;
  15162. var $useragent = '';
  15163. var $force_fsockopen = false;
  15164. var $replace_url_attributes = null;
  15165. public function __construct()
  15166. {
  15167. // Set defaults
  15168. $this->set_url_replacements(null);
  15169. }
  15170. public function remove_div($enable = true)
  15171. {
  15172. $this->remove_div = (bool) $enable;
  15173. }
  15174. public function set_image_handler($page = false)
  15175. {
  15176. if ($page)
  15177. {
  15178. $this->image_handler = (string) $page;
  15179. }
  15180. else
  15181. {
  15182. $this->image_handler = false;
  15183. }
  15184. }
  15185. public function set_registry(SimplePie_Registry $registry)
  15186. {
  15187. $this->registry = $registry;
  15188. }
  15189. public function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
  15190. {
  15191. if (isset($enable_cache))
  15192. {
  15193. $this->enable_cache = (bool) $enable_cache;
  15194. }
  15195. if ($cache_location)
  15196. {
  15197. $this->cache_location = (string) $cache_location;
  15198. }
  15199. if ($cache_name_function)
  15200. {
  15201. $this->cache_name_function = (string) $cache_name_function;
  15202. }
  15203. }
  15204. public function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
  15205. {
  15206. if ($timeout)
  15207. {
  15208. $this->timeout = (string) $timeout;
  15209. }
  15210. if ($useragent)
  15211. {
  15212. $this->useragent = (string) $useragent;
  15213. }
  15214. if ($force_fsockopen)
  15215. {
  15216. $this->force_fsockopen = (string) $force_fsockopen;
  15217. }
  15218. }
  15219. public function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
  15220. {
  15221. if ($tags)
  15222. {
  15223. if (is_array($tags))
  15224. {
  15225. $this->strip_htmltags = $tags;
  15226. }
  15227. else
  15228. {
  15229. $this->strip_htmltags = explode(',', $tags);
  15230. }
  15231. }
  15232. else
  15233. {
  15234. $this->strip_htmltags = false;
  15235. }
  15236. }
  15237. public function encode_instead_of_strip($encode = false)
  15238. {
  15239. $this->encode_instead_of_strip = (bool) $encode;
  15240. }
  15241. public function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
  15242. {
  15243. if ($attribs)
  15244. {
  15245. if (is_array($attribs))
  15246. {
  15247. $this->strip_attributes = $attribs;
  15248. }
  15249. else
  15250. {
  15251. $this->strip_attributes = explode(',', $attribs);
  15252. }
  15253. }
  15254. else
  15255. {
  15256. $this->strip_attributes = false;
  15257. }
  15258. }
  15259. public function strip_comments($strip = false)
  15260. {
  15261. $this->strip_comments = (bool) $strip;
  15262. }
  15263. public function set_output_encoding($encoding = 'UTF-8')
  15264. {
  15265. $this->output_encoding = (string) $encoding;
  15266. }
  15267. /**
  15268. * Set element/attribute key/value pairs of HTML attributes
  15269. * containing URLs that need to be resolved relative to the feed
  15270. *
  15271. * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
  15272. * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
  15273. * |q|@cite
  15274. *
  15275. * @since 1.0
  15276. * @param array|null $element_attribute Element/attribute key/value pairs, null for default
  15277. */
  15278. public function set_url_replacements($element_attribute = null)
  15279. {
  15280. if ($element_attribute === null)
  15281. {
  15282. $element_attribute = array(
  15283. 'a' => 'href',
  15284. 'area' => 'href',
  15285. 'blockquote' => 'cite',
  15286. 'del' => 'cite',
  15287. 'form' => 'action',
  15288. 'img' => array(
  15289. 'longdesc',
  15290. 'src'
  15291. ),
  15292. 'input' => 'src',
  15293. 'ins' => 'cite',
  15294. 'q' => 'cite'
  15295. );
  15296. }
  15297. $this->replace_url_attributes = (array) $element_attribute;
  15298. }
  15299. public function sanitize($data, $type, $base = '')
  15300. {
  15301. $data = trim($data);
  15302. if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
  15303. {
  15304. if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
  15305. {
  15306. if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data))
  15307. {
  15308. $type |= SIMPLEPIE_CONSTRUCT_HTML;
  15309. }
  15310. else
  15311. {
  15312. $type |= SIMPLEPIE_CONSTRUCT_TEXT;
  15313. }
  15314. }
  15315. if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
  15316. {
  15317. $data = base64_decode($data);
  15318. }
  15319. if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
  15320. {
  15321. $document = new DOMDocument();
  15322. $document->encoding = 'UTF-8';
  15323. $data = $this->preprocess($data, $type);
  15324. set_error_handler(array('SimplePie_Misc', 'silence_errors'));
  15325. $document->loadHTML($data);
  15326. restore_error_handler();
  15327. // Strip comments
  15328. if ($this->strip_comments)
  15329. {
  15330. $xpath = new DOMXPath($document);
  15331. $comments = $xpath->query('//comment()');
  15332. foreach ($comments as $comment)
  15333. {
  15334. $comment->parentNode->removeChild($comment);
  15335. }
  15336. }
  15337. // Strip out HTML tags and attributes that might cause various security problems.
  15338. // Based on recommendations by Mark Pilgrim at:
  15339. // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
  15340. if ($this->strip_htmltags)
  15341. {
  15342. foreach ($this->strip_htmltags as $tag)
  15343. {
  15344. $this->strip_tag($tag, $document, $type);
  15345. }
  15346. }
  15347. if ($this->strip_attributes)
  15348. {
  15349. foreach ($this->strip_attributes as $attrib)
  15350. {
  15351. $this->strip_attr($attrib, $document);
  15352. }
  15353. }
  15354. // Replace relative URLs
  15355. $this->base = $base;
  15356. foreach ($this->replace_url_attributes as $element => $attributes)
  15357. {
  15358. $this->replace_urls($document, $element, $attributes);
  15359. }
  15360. // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
  15361. if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
  15362. {
  15363. $images = $document->getElementsByTagName('img');
  15364. foreach ($images as $img)
  15365. {
  15366. if ($img->hasAttribute('src'))
  15367. {
  15368. $image_url = call_user_func($this->cache_name_function, $img->getAttribute('src'));
  15369. $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, $image_url, 'spi'));
  15370. if ($cache->load())
  15371. {
  15372. $img->setAttribute('src', $this->image_handler . $image_url);
  15373. }
  15374. else
  15375. {
  15376. $file = $this->registry->create('File', array($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen));
  15377. $headers = $file->headers;
  15378. if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
  15379. {
  15380. if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
  15381. {
  15382. $img->setAttribute('src', $this->image_handler . $image_url);
  15383. }
  15384. else
  15385. {
  15386. trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
  15387. }
  15388. }
  15389. }
  15390. }
  15391. }
  15392. }
  15393. // Remove the DOCTYPE
  15394. // Seems to cause segfaulting if we don't do this
  15395. if ($document->firstChild instanceof DOMDocumentType)
  15396. {
  15397. $document->removeChild($document->firstChild);
  15398. }
  15399. // Move everything from the body to the root
  15400. $real_body = $document->getElementsByTagName('body')->item(0)->childNodes->item(0);
  15401. $document->replaceChild($real_body, $document->firstChild);
  15402. // Finally, convert to a HTML string
  15403. $data = trim($document->saveHTML());
  15404. if ($this->remove_div)
  15405. {
  15406. $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
  15407. $data = preg_replace('/<\/div>$/', '', $data);
  15408. }
  15409. else
  15410. {
  15411. $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
  15412. }
  15413. }
  15414. if ($type & SIMPLEPIE_CONSTRUCT_IRI)
  15415. {
  15416. $absolute = $this->registry->call('Misc', 'absolutize_url', array($data, $base));
  15417. if ($absolute !== false)
  15418. {
  15419. $data = $absolute;
  15420. }
  15421. }
  15422. if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
  15423. {
  15424. $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
  15425. }
  15426. if ($this->output_encoding !== 'UTF-8')
  15427. {
  15428. $data = $this->registry->call('Misc', 'change_encoding', array($data, 'UTF-8', $this->output_encoding));
  15429. }
  15430. }
  15431. return $data;
  15432. }
  15433. protected function preprocess($html, $type)
  15434. {
  15435. $ret = '';
  15436. if ($type & ~SIMPLEPIE_CONSTRUCT_XHTML)
  15437. {
  15438. // Atom XHTML constructs are wrapped with a div by default
  15439. // Note: No protection if $html contains a stray </div>!
  15440. $html = '<div>' . $html . '</div>';
  15441. $ret .= '<!DOCTYPE html>';
  15442. $content_type = 'text/html';
  15443. }
  15444. else
  15445. {
  15446. $ret .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
  15447. $content_type = 'application/xhtml+xml';
  15448. }
  15449. $ret .= '<html><head>';
  15450. $ret .= '<meta http-equiv="Content-Type" content="' . $content_type . '; charset=utf-8" />';
  15451. $ret .= '</head><body>' . $html . '</body></html>';
  15452. return $ret;
  15453. }
  15454. public function replace_urls($document, $tag, $attributes)
  15455. {
  15456. if (!is_array($attributes))
  15457. {
  15458. $attributes = array($attributes);
  15459. }
  15460. if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
  15461. {
  15462. $elements = $document->getElementsByTagName($tag);
  15463. foreach ($elements as $element)
  15464. {
  15465. foreach ($attributes as $attribute)
  15466. {
  15467. if ($element->hasAttribute($attribute))
  15468. {
  15469. $value = $this->registry->call('Misc', 'absolutize_url', array($element->getAttribute($attribute), $this->base));
  15470. if ($value !== false)
  15471. {
  15472. $element->setAttribute($attribute, $value);
  15473. }
  15474. }
  15475. }
  15476. }
  15477. }
  15478. }
  15479. public function do_strip_htmltags($match)
  15480. {
  15481. if ($this->encode_instead_of_strip)
  15482. {
  15483. if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
  15484. {
  15485. $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
  15486. $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
  15487. return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
  15488. }
  15489. else
  15490. {
  15491. return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
  15492. }
  15493. }
  15494. elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
  15495. {
  15496. return $match[4];
  15497. }
  15498. else
  15499. {
  15500. return '';
  15501. }
  15502. }
  15503. protected function strip_tag($tag, $document, $type)
  15504. {
  15505. $xpath = new DOMXPath($document);
  15506. $elements = $xpath->query('body//' . $tag);
  15507. if ($this->encode_instead_of_strip)
  15508. {
  15509. foreach ($elements as $element)
  15510. {
  15511. $fragment = $document->createDocumentFragment();
  15512. // For elements which aren't script or style, include the tag itself
  15513. if (!in_array($tag, array('script', 'style')))
  15514. {
  15515. $text = '<' . $tag;
  15516. if ($element->hasAttributes())
  15517. {
  15518. $attrs = array();
  15519. foreach ($element->attributes as $name => $attr)
  15520. {
  15521. $value = $attr->value;
  15522. // In XHTML, empty values should never exist, so we repeat the value
  15523. if (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_XHTML))
  15524. {
  15525. $value = $name;
  15526. }
  15527. // For HTML, empty is fine
  15528. elseif (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_HTML))
  15529. {
  15530. $attrs[] = $name;
  15531. continue;
  15532. }
  15533. // Standard attribute text
  15534. $attrs[] = $name . '="' . $attr->value . '"';
  15535. }
  15536. $text .= ' ' . implode(' ', $attrs);
  15537. }
  15538. $text .= '>';
  15539. $fragment->appendChild(new DOMText($text));
  15540. }
  15541. $number = $element->childNodes->length;
  15542. for ($i = $number; $i > 0; $i--)
  15543. {
  15544. $child = $element->childNodes->item(0);
  15545. $fragment->appendChild($child);
  15546. }
  15547. if (!in_array($tag, array('script', 'style')))
  15548. {
  15549. $fragment->appendChild(new DOMText('</' . $tag . '>'));
  15550. }
  15551. $element->parentNode->replaceChild($fragment, $element);
  15552. }
  15553. return;
  15554. }
  15555. elseif (in_array($tag, array('script', 'style')))
  15556. {
  15557. foreach ($elements as $element)
  15558. {
  15559. $element->parentNode->removeChild($element);
  15560. }
  15561. return;
  15562. }
  15563. else
  15564. {
  15565. foreach ($elements as $element)
  15566. {
  15567. $fragment = $document->createDocumentFragment();
  15568. $number = $element->childNodes->length;
  15569. for ($i = $number; $i > 0; $i--)
  15570. {
  15571. $child = $element->childNodes->item(0);
  15572. $fragment->appendChild($child);
  15573. }
  15574. $element->parentNode->replaceChild($fragment, $element);
  15575. }
  15576. }
  15577. }
  15578. protected function strip_attr($attrib, $document)
  15579. {
  15580. $xpath = new DOMXPath($document);
  15581. $elements = $xpath->query('//*[@' . $attrib . ']');
  15582. foreach ($elements as $element)
  15583. {
  15584. $element->removeAttribute($attrib);
  15585. }
  15586. }
  15587. }
  15588. /**
  15589. * Handles `<atom:source>`
  15590. *
  15591. * Used by {@see SimplePie_Item::get_source()}
  15592. *
  15593. * This class can be overloaded with {@see SimplePie::set_source_class()}
  15594. *
  15595. * @package SimplePie
  15596. * @subpackage API
  15597. */
  15598. class SimplePie_Source
  15599. {
  15600. var $item;
  15601. var $data = array();
  15602. protected $registry;
  15603. public function __construct($item, $data)
  15604. {
  15605. $this->item = $item;
  15606. $this->data = $data;
  15607. }
  15608. public function set_registry(SimplePie_Registry $registry)
  15609. {
  15610. $this->registry = $registry;
  15611. }
  15612. public function __toString()
  15613. {
  15614. return md5(serialize($this->data));
  15615. }
  15616. public function get_source_tags($namespace, $tag)
  15617. {
  15618. if (isset($this->data['child'][$namespace][$tag]))
  15619. {
  15620. return $this->data['child'][$namespace][$tag];
  15621. }
  15622. else
  15623. {
  15624. return null;
  15625. }
  15626. }
  15627. public function get_base($element = array())
  15628. {
  15629. return $this->item->get_base($element);
  15630. }
  15631. public function sanitize($data, $type, $base = '')
  15632. {
  15633. return $this->item->sanitize($data, $type, $base);
  15634. }
  15635. public function get_item()
  15636. {
  15637. return $this->item;
  15638. }
  15639. public function get_title()
  15640. {
  15641. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  15642. {
  15643. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  15644. }
  15645. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  15646. {
  15647. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  15648. }
  15649. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  15650. {
  15651. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  15652. }
  15653. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  15654. {
  15655. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  15656. }
  15657. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  15658. {
  15659. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  15660. }
  15661. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  15662. {
  15663. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  15664. }
  15665. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  15666. {
  15667. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  15668. }
  15669. else
  15670. {
  15671. return null;
  15672. }
  15673. }
  15674. public function get_category($key = 0)
  15675. {
  15676. $categories = $this->get_categories();
  15677. if (isset($categories[$key]))
  15678. {
  15679. return $categories[$key];
  15680. }
  15681. else
  15682. {
  15683. return null;
  15684. }
  15685. }
  15686. public function get_categories()
  15687. {
  15688. $categories = array();
  15689. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  15690. {
  15691. $term = null;
  15692. $scheme = null;
  15693. $label = null;
  15694. if (isset($category['attribs']['']['term']))
  15695. {
  15696. $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  15697. }
  15698. if (isset($category['attribs']['']['scheme']))
  15699. {
  15700. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  15701. }
  15702. if (isset($category['attribs']['']['label']))
  15703. {
  15704. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  15705. }
  15706. $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
  15707. }
  15708. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  15709. {
  15710. // This is really the label, but keep this as the term also for BC.
  15711. // Label will also work on retrieving because that falls back to term.
  15712. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  15713. if (isset($category['attribs']['']['domain']))
  15714. {
  15715. $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  15716. }
  15717. else
  15718. {
  15719. $scheme = null;
  15720. }
  15721. $categories[] = $this->registry->create('Category', array($term, $scheme, null));
  15722. }
  15723. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  15724. {
  15725. $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  15726. }
  15727. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  15728. {
  15729. $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  15730. }
  15731. if (!empty($categories))
  15732. {
  15733. return array_unique($categories);
  15734. }
  15735. else
  15736. {
  15737. return null;
  15738. }
  15739. }
  15740. public function get_author($key = 0)
  15741. {
  15742. $authors = $this->get_authors();
  15743. if (isset($authors[$key]))
  15744. {
  15745. return $authors[$key];
  15746. }
  15747. else
  15748. {
  15749. return null;
  15750. }
  15751. }
  15752. public function get_authors()
  15753. {
  15754. $authors = array();
  15755. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  15756. {
  15757. $name = null;
  15758. $uri = null;
  15759. $email = null;
  15760. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  15761. {
  15762. $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  15763. }
  15764. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  15765. {
  15766. $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  15767. }
  15768. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  15769. {
  15770. $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  15771. }
  15772. if ($name !== null || $email !== null || $uri !== null)
  15773. {
  15774. $authors[] = $this->registry->create('Author', array($name, $uri, $email));
  15775. }
  15776. }
  15777. if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  15778. {
  15779. $name = null;
  15780. $url = null;
  15781. $email = null;
  15782. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  15783. {
  15784. $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  15785. }
  15786. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  15787. {
  15788. $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  15789. }
  15790. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  15791. {
  15792. $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  15793. }
  15794. if ($name !== null || $email !== null || $url !== null)
  15795. {
  15796. $authors[] = $this->registry->create('Author', array($name, $url, $email));
  15797. }
  15798. }
  15799. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  15800. {
  15801. $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  15802. }
  15803. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  15804. {
  15805. $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  15806. }
  15807. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  15808. {
  15809. $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  15810. }
  15811. if (!empty($authors))
  15812. {
  15813. return array_unique($authors);
  15814. }
  15815. else
  15816. {
  15817. return null;
  15818. }
  15819. }
  15820. public function get_contributor($key = 0)
  15821. {
  15822. $contributors = $this->get_contributors();
  15823. if (isset($contributors[$key]))
  15824. {
  15825. return $contributors[$key];
  15826. }
  15827. else
  15828. {
  15829. return null;
  15830. }
  15831. }
  15832. public function get_contributors()
  15833. {
  15834. $contributors = array();
  15835. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  15836. {
  15837. $name = null;
  15838. $uri = null;
  15839. $email = null;
  15840. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  15841. {
  15842. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  15843. }
  15844. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  15845. {
  15846. $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  15847. }
  15848. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  15849. {
  15850. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  15851. }
  15852. if ($name !== null || $email !== null || $uri !== null)
  15853. {
  15854. $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
  15855. }
  15856. }
  15857. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  15858. {
  15859. $name = null;
  15860. $url = null;
  15861. $email = null;
  15862. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  15863. {
  15864. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  15865. }
  15866. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  15867. {
  15868. $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  15869. }
  15870. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  15871. {
  15872. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  15873. }
  15874. if ($name !== null || $email !== null || $url !== null)
  15875. {
  15876. $contributors[] = $this->registry->create('Author', array($name, $url, $email));
  15877. }
  15878. }
  15879. if (!empty($contributors))
  15880. {
  15881. return array_unique($contributors);
  15882. }
  15883. else
  15884. {
  15885. return null;
  15886. }
  15887. }
  15888. public function get_link($key = 0, $rel = 'alternate')
  15889. {
  15890. $links = $this->get_links($rel);
  15891. if (isset($links[$key]))
  15892. {
  15893. return $links[$key];
  15894. }
  15895. else
  15896. {
  15897. return null;
  15898. }
  15899. }
  15900. /**
  15901. * Added for parity between the parent-level and the item/entry-level.
  15902. */
  15903. public function get_permalink()
  15904. {
  15905. return $this->get_link(0);
  15906. }
  15907. public function get_links($rel = 'alternate')
  15908. {
  15909. if (!isset($this->data['links']))
  15910. {
  15911. $this->data['links'] = array();
  15912. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
  15913. {
  15914. foreach ($links as $link)
  15915. {
  15916. if (isset($link['attribs']['']['href']))
  15917. {
  15918. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  15919. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  15920. }
  15921. }
  15922. }
  15923. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
  15924. {
  15925. foreach ($links as $link)
  15926. {
  15927. if (isset($link['attribs']['']['href']))
  15928. {
  15929. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  15930. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  15931. }
  15932. }
  15933. }
  15934. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  15935. {
  15936. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  15937. }
  15938. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  15939. {
  15940. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  15941. }
  15942. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  15943. {
  15944. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  15945. }
  15946. $keys = array_keys($this->data['links']);
  15947. foreach ($keys as $key)
  15948. {
  15949. if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
  15950. {
  15951. if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  15952. {
  15953. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  15954. $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  15955. }
  15956. else
  15957. {
  15958. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  15959. }
  15960. }
  15961. elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  15962. {
  15963. $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  15964. }
  15965. $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  15966. }
  15967. }
  15968. if (isset($this->data['links'][$rel]))
  15969. {
  15970. return $this->data['links'][$rel];
  15971. }
  15972. else
  15973. {
  15974. return null;
  15975. }
  15976. }
  15977. public function get_description()
  15978. {
  15979. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
  15980. {
  15981. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  15982. }
  15983. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
  15984. {
  15985. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  15986. }
  15987. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  15988. {
  15989. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  15990. }
  15991. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
  15992. {
  15993. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  15994. }
  15995. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  15996. {
  15997. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  15998. }
  15999. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  16000. {
  16001. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  16002. }
  16003. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  16004. {
  16005. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  16006. }
  16007. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  16008. {
  16009. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  16010. }
  16011. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  16012. {
  16013. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  16014. }
  16015. else
  16016. {
  16017. return null;
  16018. }
  16019. }
  16020. public function get_copyright()
  16021. {
  16022. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  16023. {
  16024. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  16025. }
  16026. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
  16027. {
  16028. return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  16029. }
  16030. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
  16031. {
  16032. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  16033. }
  16034. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  16035. {
  16036. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  16037. }
  16038. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  16039. {
  16040. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  16041. }
  16042. else
  16043. {
  16044. return null;
  16045. }
  16046. }
  16047. public function get_language()
  16048. {
  16049. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
  16050. {
  16051. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  16052. }
  16053. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
  16054. {
  16055. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  16056. }
  16057. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
  16058. {
  16059. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  16060. }
  16061. elseif (isset($this->data['xml_lang']))
  16062. {
  16063. return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  16064. }
  16065. else
  16066. {
  16067. return null;
  16068. }
  16069. }
  16070. public function get_latitude()
  16071. {
  16072. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  16073. {
  16074. return (float) $return[0]['data'];
  16075. }
  16076. elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  16077. {
  16078. return (float) $match[1];
  16079. }
  16080. else
  16081. {
  16082. return null;
  16083. }
  16084. }
  16085. public function get_longitude()
  16086. {
  16087. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  16088. {
  16089. return (float) $return[0]['data'];
  16090. }
  16091. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  16092. {
  16093. return (float) $return[0]['data'];
  16094. }
  16095. elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  16096. {
  16097. return (float) $match[2];
  16098. }
  16099. else
  16100. {
  16101. return null;
  16102. }
  16103. }
  16104. public function get_image_url()
  16105. {
  16106. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
  16107. {
  16108. return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
  16109. }
  16110. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
  16111. {
  16112. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  16113. }
  16114. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
  16115. {
  16116. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  16117. }
  16118. else
  16119. {
  16120. return null;
  16121. }
  16122. }
  16123. }
  16124. /**
  16125. * Parses the XML Declaration
  16126. *
  16127. * @package SimplePie
  16128. * @subpackage Parsing
  16129. */
  16130. class SimplePie_XML_Declaration_Parser
  16131. {
  16132. /**
  16133. * XML Version
  16134. *
  16135. * @access public
  16136. * @var string
  16137. */
  16138. var $version = '1.0';
  16139. /**
  16140. * Encoding
  16141. *
  16142. * @access public
  16143. * @var string
  16144. */
  16145. var $encoding = 'UTF-8';
  16146. /**
  16147. * Standalone
  16148. *
  16149. * @access public
  16150. * @var bool
  16151. */
  16152. var $standalone = false;
  16153. /**
  16154. * Current state of the state machine
  16155. *
  16156. * @access private
  16157. * @var string
  16158. */
  16159. var $state = 'before_version_name';
  16160. /**
  16161. * Input data
  16162. *
  16163. * @access private
  16164. * @var string
  16165. */
  16166. var $data = '';
  16167. /**
  16168. * Input data length (to avoid calling strlen() everytime this is needed)
  16169. *
  16170. * @access private
  16171. * @var int
  16172. */
  16173. var $data_length = 0;
  16174. /**
  16175. * Current position of the pointer
  16176. *
  16177. * @var int
  16178. * @access private
  16179. */
  16180. var $position = 0;
  16181. /**
  16182. * Create an instance of the class with the input data
  16183. *
  16184. * @access public
  16185. * @param string $data Input data
  16186. */
  16187. public function __construct($data)
  16188. {
  16189. $this->data = $data;
  16190. $this->data_length = strlen($this->data);
  16191. }
  16192. /**
  16193. * Parse the input data
  16194. *
  16195. * @access public
  16196. * @return bool true on success, false on failure
  16197. */
  16198. public function parse()
  16199. {
  16200. while ($this->state && $this->state !== 'emit' && $this->has_data())
  16201. {
  16202. $state = $this->state;
  16203. $this->$state();
  16204. }
  16205. $this->data = '';
  16206. if ($this->state === 'emit')
  16207. {
  16208. return true;
  16209. }
  16210. else
  16211. {
  16212. $this->version = '';
  16213. $this->encoding = '';
  16214. $this->standalone = '';
  16215. return false;
  16216. }
  16217. }
  16218. /**
  16219. * Check whether there is data beyond the pointer
  16220. *
  16221. * @access private
  16222. * @return bool true if there is further data, false if not
  16223. */
  16224. public function has_data()
  16225. {
  16226. return (bool) ($this->position < $this->data_length);
  16227. }
  16228. /**
  16229. * Advance past any whitespace
  16230. *
  16231. * @return int Number of whitespace characters passed
  16232. */
  16233. public function skip_whitespace()
  16234. {
  16235. $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
  16236. $this->position += $whitespace;
  16237. return $whitespace;
  16238. }
  16239. /**
  16240. * Read value
  16241. */
  16242. public function get_value()
  16243. {
  16244. $quote = substr($this->data, $this->position, 1);
  16245. if ($quote === '"' || $quote === "'")
  16246. {
  16247. $this->position++;
  16248. $len = strcspn($this->data, $quote, $this->position);
  16249. if ($this->has_data())
  16250. {
  16251. $value = substr($this->data, $this->position, $len);
  16252. $this->position += $len + 1;
  16253. return $value;
  16254. }
  16255. }
  16256. return false;
  16257. }
  16258. public function before_version_name()
  16259. {
  16260. if ($this->skip_whitespace())
  16261. {
  16262. $this->state = 'version_name';
  16263. }
  16264. else
  16265. {
  16266. $this->state = false;
  16267. }
  16268. }
  16269. public function version_name()
  16270. {
  16271. if (substr($this->data, $this->position, 7) === 'version')
  16272. {
  16273. $this->position += 7;
  16274. $this->skip_whitespace();
  16275. $this->state = 'version_equals';
  16276. }
  16277. else
  16278. {
  16279. $this->state = false;
  16280. }
  16281. }
  16282. public function version_equals()
  16283. {
  16284. if (substr($this->data, $this->position, 1) === '=')
  16285. {
  16286. $this->position++;
  16287. $this->skip_whitespace();
  16288. $this->state = 'version_value';
  16289. }
  16290. else
  16291. {
  16292. $this->state = false;
  16293. }
  16294. }
  16295. public function version_value()
  16296. {
  16297. if ($this->version = $this->get_value())
  16298. {
  16299. $this->skip_whitespace();
  16300. if ($this->has_data())
  16301. {
  16302. $this->state = 'encoding_name';
  16303. }
  16304. else
  16305. {
  16306. $this->state = 'emit';
  16307. }
  16308. }
  16309. else
  16310. {
  16311. $this->state = false;
  16312. }
  16313. }
  16314. public function encoding_name()
  16315. {
  16316. if (substr($this->data, $this->position, 8) === 'encoding')
  16317. {
  16318. $this->position += 8;
  16319. $this->skip_whitespace();
  16320. $this->state = 'encoding_equals';
  16321. }
  16322. else
  16323. {
  16324. $this->state = 'standalone_name';
  16325. }
  16326. }
  16327. public function encoding_equals()
  16328. {
  16329. if (substr($this->data, $this->position, 1) === '=')
  16330. {
  16331. $this->position++;
  16332. $this->skip_whitespace();
  16333. $this->state = 'encoding_value';
  16334. }
  16335. else
  16336. {
  16337. $this->state = false;
  16338. }
  16339. }
  16340. public function encoding_value()
  16341. {
  16342. if ($this->encoding = $this->get_value())
  16343. {
  16344. $this->skip_whitespace();
  16345. if ($this->has_data())
  16346. {
  16347. $this->state = 'standalone_name';
  16348. }
  16349. else
  16350. {
  16351. $this->state = 'emit';
  16352. }
  16353. }
  16354. else
  16355. {
  16356. $this->state = false;
  16357. }
  16358. }
  16359. public function standalone_name()
  16360. {
  16361. if (substr($this->data, $this->position, 10) === 'standalone')
  16362. {
  16363. $this->position += 10;
  16364. $this->skip_whitespace();
  16365. $this->state = 'standalone_equals';
  16366. }
  16367. else
  16368. {
  16369. $this->state = false;
  16370. }
  16371. }
  16372. public function standalone_equals()
  16373. {
  16374. if (substr($this->data, $this->position, 1) === '=')
  16375. {
  16376. $this->position++;
  16377. $this->skip_whitespace();
  16378. $this->state = 'standalone_value';
  16379. }
  16380. else
  16381. {
  16382. $this->state = false;
  16383. }
  16384. }
  16385. public function standalone_value()
  16386. {
  16387. if ($standalone = $this->get_value())
  16388. {
  16389. switch ($standalone)
  16390. {
  16391. case 'yes':
  16392. $this->standalone = true;
  16393. break;
  16394. case 'no':
  16395. $this->standalone = false;
  16396. break;
  16397. default:
  16398. $this->state = false;
  16399. return;
  16400. }
  16401. $this->skip_whitespace();
  16402. if ($this->has_data())
  16403. {
  16404. $this->state = false;
  16405. }
  16406. else
  16407. {
  16408. $this->state = 'emit';
  16409. }
  16410. }
  16411. else
  16412. {
  16413. $this->state = false;
  16414. }
  16415. }
  16416. }