PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /opt/alt/php53/usr/share/pear/Mail
Viewing File: /opt/alt/php53/usr/share/pear/Mail/mimeDecode.php
<?php /** * The Mail_mimeDecode class is used to decode mail/mime messages * * This class will parse a raw mime email and return * the structure. Returned structure is similar to * that returned by imap_fetchstructure(). * * +----------------------------- IMPORTANT ------------------------------+ * | Usage of this class compared to native php extensions such as | * | mailparse or imap, is slow and may be feature deficient. If available| * | you are STRONGLY recommended to use the php extensions. | * +----------------------------------------------------------------------+ * * Compatible with PHP versions 4 and 5 * * LICENSE: This LICENSE is in the BSD license style. * Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org> * Copyright (c) 2003-2006, PEAR <pear-group@php.net> * All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name of the authors, nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * * @category Mail * @package Mail_Mime * @author Richard Heyes <richard@phpguru.org> * @author George Schlossnagle <george@omniti.com> * @author Cipriano Groenendal <cipri@php.net> * @author Sean Coates <sean@php.net> * @copyright 2003-2006 PEAR <pear-group@php.net> * @license http://www.opensource.org/licenses/bsd-license.php BSD License * @version CVS: $Id: mimeDecode.php 337165 2015-07-15 09:42:08Z alan_k $ * @link http://pear.php.net/package/Mail_mime */ /** * require PEAR * * This package depends on PEAR to raise errors. */ require_once 'PEAR.php'; /** * The Mail_mimeDecode class is used to decode mail/mime messages * * This class will parse a raw mime email and return the structure. * Returned structure is similar to that returned by imap_fetchstructure(). * * +----------------------------- IMPORTANT ------------------------------+ * | Usage of this class compared to native php extensions such as | * | mailparse or imap, is slow and may be feature deficient. If available| * | you are STRONGLY recommended to use the php extensions. | * +----------------------------------------------------------------------+ * * @category Mail * @package Mail_Mime * @author Richard Heyes <richard@phpguru.org> * @author George Schlossnagle <george@omniti.com> * @author Cipriano Groenendal <cipri@php.net> * @author Sean Coates <sean@php.net> * @copyright 2003-2006 PEAR <pear-group@php.net> * @license http://www.opensource.org/licenses/bsd-license.php BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/Mail_mime */ class Mail_mimeDecode extends PEAR { /** * The raw email to decode * * @var string * @access private */ var $_input; /** * The header part of the input * * @var string * @access private */ var $_header; /** * The body part of the input * * @var string * @access private */ var $_body; /** * If an error occurs, this is used to store the message * * @var string * @access private */ var $_error; /** * Flag to determine whether to include bodies in the * returned object. * * @var boolean * @access private */ var $_include_bodies; /** * Flag to determine whether to decode bodies * * @var boolean * @access private */ var $_decode_bodies; /** * Flag to determine whether to decode headers * (set to UTF8 to iconv convert headers) * @var mixed * @access private */ var $_decode_headers; /** * Flag to determine whether to include attached messages * as body in the returned object. Depends on $_include_bodies * * @var boolean * @access private */ var $_rfc822_bodies; /** * Constructor. * * Sets up the object, initialise the variables, and splits and * stores the header and body of the input. * * @param string The input to decode * @access public */ function __construct($input) { list($header, $body) = $this->_splitBodyHeader($input); $this->_input = $input; $this->_header = $header; $this->_body = $body; $this->_decode_bodies = false; $this->_include_bodies = true; $this->_rfc822_bodies = false; } // BC function Mail_mimeDecode($input) { $this->__construct($input); } /** * Begins the decoding process. If called statically * it will create an object and call the decode() method * of it. * * @param array An array of various parameters that determine * various things: * include_bodies - Whether to include the body in the returned * object. * decode_bodies - Whether to decode the bodies * of the parts. (Transfer encoding) * decode_headers - Whether to decode headers, * - use "UTF8//IGNORE" to convert charset. * * input - If called statically, this will be treated * as the input * @return object Decoded results * @access public */ function decode($params = null) { // determine if this method has been called statically $isStatic = empty($this) || !is_a($this, __CLASS__); // Have we been called statically? // If so, create an object and pass details to that. if ($isStatic AND isset($params['input'])) { $obj = new Mail_mimeDecode($params['input']); $structure = $obj->decode($params); // Called statically but no input } elseif ($isStatic) { return PEAR::raiseError('Called statically and no input given'); // Called via an object } else { $this->_include_bodies = isset($params['include_bodies']) ? $params['include_bodies'] : false; $this->_decode_bodies = isset($params['decode_bodies']) ? $params['decode_bodies'] : false; $this->_decode_headers = isset($params['decode_headers']) ? $params['decode_headers'] : false; $this->_rfc822_bodies = isset($params['rfc_822bodies']) ? $params['rfc_822bodies'] : false; if (is_string($this->_decode_headers) && !function_exists('iconv')) { PEAR::raiseError('header decode conversion requested, however iconv is missing'); } $structure = $this->_decode($this->_header, $this->_body); if ($structure === false) { $structure = $this->raiseError($this->_error); } } return $structure; } /** * Performs the decoding. Decodes the body string passed to it * If it finds certain content-types it will call itself in a * recursive fashion * * @param string Header section * @param string Body section * @return object Results of decoding process * @access private */ function _decode($headers, $body, $default_ctype = 'text/plain') { $return = new stdClass; $return->headers = array(); $headers = $this->_parseHeaders($headers); foreach ($headers as $value) { $value['value'] = $this->_decodeHeader($value['value']); if (isset($return->headers[strtolower($value['name'])]) AND !is_array($return->headers[strtolower($value['name'])])) { $return->headers[strtolower($value['name'])] = array($return->headers[strtolower($value['name'])]); $return->headers[strtolower($value['name'])][] = $value['value']; } elseif (isset($return->headers[strtolower($value['name'])])) { $return->headers[strtolower($value['name'])][] = $value['value']; } else { $return->headers[strtolower($value['name'])] = $value['value']; } } foreach ($headers as $key => $value) { $headers[$key]['name'] = strtolower($headers[$key]['name']); switch ($headers[$key]['name']) { case 'content-type': $content_type = $this->_parseHeaderValue($headers[$key]['value']); if (preg_match('/([0-9a-z+.-]+)\/([0-9a-z+.-]+)/i', $content_type['value'], $regs)) { $return->ctype_primary = $regs[1]; $return->ctype_secondary = $regs[2]; } if (isset($content_type['other'])) { foreach($content_type['other'] as $p_name => $p_value) { $return->ctype_parameters[$p_name] = $p_value; } } break; case 'content-disposition': $content_disposition = $this->_parseHeaderValue($headers[$key]['value']); $return->disposition = $content_disposition['value']; if (isset($content_disposition['other'])) { foreach($content_disposition['other'] as $p_name => $p_value) { $return->d_parameters[$p_name] = $p_value; } } break; case 'content-transfer-encoding': $content_transfer_encoding = $this->_parseHeaderValue($headers[$key]['value']); break; } } if (isset($content_type)) { switch (strtolower($content_type['value'])) { case 'text/plain': $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null; break; case 'text/html': $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null; break; case 'multipart/signed': // PGP $parts = $this->_boundarySplit($body, $content_type['other']['boundary'], true); $return->parts['msg_body'] = $parts[0]; list($part_header, $part_body) = $this->_splitBodyHeader($parts[1]); $return->parts['sig_hdr'] = $part_header; $return->parts['sig_body'] = $part_body; break; case 'multipart/parallel': case 'multipart/appledouble': // Appledouble mail case 'multipart/report': // RFC1892 case 'multipart/signed': // PGP case 'multipart/digest': case 'multipart/alternative': case 'multipart/related': case 'multipart/relative': //#20431 - android case 'multipart/mixed': case 'application/vnd.wap.multipart.related': if(!isset($content_type['other']['boundary'])){ $this->_error = 'No boundary found for ' . $content_type['value'] . ' part'; return false; } $default_ctype = (strtolower($content_type['value']) === 'multipart/digest') ? 'message/rfc822' : 'text/plain'; $parts = $this->_boundarySplit($body, $content_type['other']['boundary']); for ($i = 0; $i < count($parts); $i++) { list($part_header, $part_body) = $this->_splitBodyHeader($parts[$i]); $part = $this->_decode($part_header, $part_body, $default_ctype); if($part === false) $part = $this->raiseError($this->_error); $return->parts[] = $part; } break; case 'message/rfc822': case 'message/delivery-status': // #bug #18693 if ($this->_rfc822_bodies) { $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body); } $obj = new Mail_mimeDecode($body); $return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies, 'decode_bodies' => $this->_decode_bodies, 'decode_headers' => $this->_decode_headers)); unset($obj); break; default: if(!isset($content_transfer_encoding['value'])) $content_transfer_encoding['value'] = '7bit'; $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $content_transfer_encoding['value']) : $body) : null; break; } } else { $ctype = explode('/', $default_ctype); $return->ctype_primary = $ctype[0]; $return->ctype_secondary = $ctype[1]; $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body) : $body) : null; } return $return; } /** * Given the output of the above function, this will return an * array of references to the parts, indexed by mime number. * * @param object $structure The structure to go through * @param string $mime_number Internal use only. * @return array Mime numbers */ function &getMimeNumbers(&$structure, $no_refs = false, $mime_number = '', $prepend = '') { $return = array(); if (!empty($structure->parts)) { if ($mime_number != '') { $structure->mime_id = $prepend . $mime_number; $return[$prepend . $mime_number] = &$structure; } for ($i = 0; $i < count($structure->parts); $i++) { if (!empty($structure->headers['content-type']) AND substr(strtolower($structure->headers['content-type']), 0, 8) == 'message/') { $prepend = $prepend . $mime_number . '.'; $_mime_number = ''; } else { $_mime_number = ($mime_number == '' ? $i + 1 : sprintf('%s.%s', $mime_number, $i + 1)); } $arr = &Mail_mimeDecode::getMimeNumbers($structure->parts[$i], $no_refs, $_mime_number, $prepend); foreach ($arr as $key => $val) { $no_refs ? $return[$key] = '' : $return[$key] = &$arr[$key]; } } } else { if ($mime_number == '') { $mime_number = '1'; } $structure->mime_id = $prepend . $mime_number; $no_refs ? $return[$prepend . $mime_number] = '' : $return[$prepend . $mime_number] = &$structure; } return $return; } /** * Given a string containing a header and body * section, this function will split them (at the first * blank line) and return them. * * @param string Input to split apart * @return array Contains header and body section * @access private */ function _splitBodyHeader($input) { if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) { return array($match[1], $match[2]); } // bug #17325 - empty bodies are allowed. - we just check that at least one line // of headers exist.. if (count(explode("\n",$input))) { return array($input, ''); } $this->_error = 'Could not split header and body'; return false; } /** * Parse headers given in $input and return * as assoc array. * * @param string Headers to parse * @return array Contains parsed headers * @access private */ function _parseHeaders($input) { if ($input !== '') { // Unfold the input $input = preg_replace("/\r?\n/", "\r\n", $input); //#7065 - wrapping.. with encoded stuff.. - probably not needed, // wrapping space should only get removed if the trailing item on previous line is a // encoded character $input = preg_replace("/=\r\n(\t| )+/", '=', $input); $input = preg_replace("/\r\n(\t| )+/", ' ', $input); $headers = explode("\r\n", trim($input)); $got_start = false; foreach ($headers as $value) { if (!$got_start) { // munge headers for mbox style from if ($value[0] == '>') { $value = substring($value, 1); // remove mbox > } if (substr($value,0,5) == 'From ') { $value = 'Return-Path: ' . substr($value, 5); } else { $got_start = true; } } $hdr_name = substr($value, 0, $pos = strpos($value, ':')); $hdr_value = substr($value, $pos+1); if($hdr_value[0] == ' ') { $hdr_value = substr($hdr_value, 1); } $return[] = array( 'name' => $hdr_name, 'value' => $hdr_value ); } } else { $return = array(); } return $return; } /** * Function to parse a header value, * extract first part, and any secondary * parts (after ;) This function is not as * robust as it could be. Eg. header comments * in the wrong place will probably break it. * * Extra things this can handle * filename*0=...... * filename*1=...... * * This is where lines are broken in, and need merging. * * filename*0*=ENC'lang'urlencoded data. * filename*1*=ENC'lang'urlencoded data. * * * * @param string Header value to parse * @return array Contains parsed result * @access private */ function _parseHeaderValue($input) { if (($pos = strpos($input, ';')) === false) { $input = $this->_decodeHeader($input); $return['value'] = trim($input); return $return; } $value = substr($input, 0, $pos); $value = $this->_decodeHeader($value); $return['value'] = trim($value); $input = trim(substr($input, $pos+1)); if (!strlen($input) > 0) { return $return; } // at this point input contains xxxx=".....";zzzz="...." // since we are dealing with quoted strings, we need to handle this properly.. $i = 0; $l = strlen($input); $key = ''; $val = false; // our string - including quotes.. $q = false; // in quote.. $lq = ''; // last quote.. while ($i < $l) { $c = $input[$i]; //var_dump(array('i'=>$i,'c'=>$c,'q'=>$q, 'lq'=>$lq, 'key'=>$key, 'val' =>$val)); $escaped = false; if ($c == '\\') { $i++; if ($i == $l-1) { // end of string. break; } $escaped = true; $c = $input[$i]; } // state - in key.. if ($val === false) { if (!$escaped && $c == '=') { $val = ''; $key = trim($key); $i++; continue; } if (!$escaped && $c == ';') { if ($key) { // a key without a value.. $key= trim($key); $return['other'][$key] = ''; } $key = ''; } $key .= $c; $i++; continue; } // state - in value.. (as $val is set..) if ($q === false) { // not in quote yet. if ((!strlen($val) || $lq !== false) && $c == ' ' || $c == "\t") { $i++; continue; // skip leading spaces after '=' or after '"' } // do not de-quote 'xxx*= itesm.. $key_is_trans = $key[strlen($key)-1] == '*'; if (!$key_is_trans && !$escaped && ($c == '"' || $c == "'")) { // start quoted area.. $q = $c; // in theory should not happen raw text in value part.. // but we will handle it as a merged part of the string.. $val = !strlen(trim($val)) ? '' : trim($val); $i++; continue; } // got end.... if (!$escaped && $c == ';') { $return['other'][$key] = trim($val); $val = false; $key = ''; $lq = false; $i++; continue; } $val .= $c; $i++; continue; } // state - in quote.. if (!$escaped && $c == $q) { // potential exit state.. // end of quoted string.. $lq = $q; $q = false; $i++; continue; } // normal char inside of quoted string.. $val.= $c; $i++; } // do we have anything left.. if (strlen(trim($key)) || $val !== false) { $val = trim($val); $return['other'][$key] = $val; } $clean_others = array(); // merge added values. eg. *1[*] foreach($return['other'] as $key =>$val) { if (preg_match('/\*[0-9]+\**$/', $key)) { $key = preg_replace('/(.*)\*[0-9]+(\**)$/', '\1\2', $key); if (isset($clean_others[$key])) { $clean_others[$key] .= $val; continue; } } $clean_others[$key] = $val; } // handle language translation of '*' ending others. foreach( $clean_others as $key =>$val) { if ( $key[strlen($key)-1] != '*') { $clean_others[strtolower($key)] = $val; continue; } unset($clean_others[$key]); $key = substr($key,0,-1); //extended-initial-value := [charset] "'" [language] "'" // extended-other-values $match = array(); $info = preg_match("/^([^']+)'([^']*)'(.*)$/", $val, $match); $clean_others[$key] = urldecode($match[3]); $clean_others[strtolower($key)] = $clean_others[$key]; $clean_others[strtolower($key).'-charset'] = $match[1]; $clean_others[strtolower($key).'-language'] = $match[2]; } $return['other'] = $clean_others; // decode values. foreach($return['other'] as $key =>$val) { $charset = isset($return['other'][$key . '-charset']) ? $return['other'][$key . '-charset'] : false; $return['other'][$key] = $this->_decodeHeader($val, $charset); } return $return; } /** * This function splits the input based * on the given boundary * * @param string Input to parse * @return array Contains array of resulting mime parts * @access private */ function _boundarySplit($input, $boundary, $eatline = false) { $parts = array(); $bs_possible = substr($boundary, 2, -2); $bs_check = '\"' . $bs_possible . '\"'; if ($boundary == $bs_check) { $boundary = $bs_possible; } // eatline is used by multipart/signed. $tmp = $eatline ? preg_split("/\r?\n--".preg_quote($boundary, '/')."(|--)\n/", $input) : preg_split("/--".preg_quote($boundary, '/')."((?=\s)|--)/", $input); $len = count($tmp) -1; for ($i = 1; $i < $len; $i++) { if (strlen(trim($tmp[$i]))) { $parts[] = $tmp[$i]; } } // add the last part on if it does not end with the 'closing indicator' if (!empty($tmp[$len]) && strlen(trim($tmp[$len])) && $tmp[$len][0] != '-') { $parts[] = $tmp[$len]; } return $parts; } /** * Given a header, this function will decode it * according to RFC2047. Probably not *exactly* * conformant, but it does pass all the given * examples (in RFC2047). * * @param string Input header value to decode * @return string Decoded header value * @access private */ function _decodeHeader($input, $default_charset=false) { if (!$this->_decode_headers) { return $input; } // Remove white space between encoded-words $input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input); // For each encoded-word... while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) { $encoded = $matches[1]; $charset = $matches[2]; $encoding = $matches[3]; $text = $matches[4]; switch (strtolower($encoding)) { case 'b': $text = base64_decode($text); break; case 'q': $text = str_replace('_', ' ', $text); preg_match_all('/=([a-f0-9]{2})/i', $text, $matches); foreach($matches[1] as $value) $text = str_replace('='.$value, chr(hexdec($value)), $text); break; } if (is_string($this->_decode_headers)) { $conv = @iconv($charset, $this->_decode_headers, $text); $text = ($conv === false) ? $text : $conv; } $input = str_replace($encoded, $text, $input); } if ($default_charset && is_string($this->_decode_headers)) { $conv = @iconv($charset, $this->_decode_headers, $input); $input = ($conv === false) ? $input : $conv; } return $input; } /** * Given a body string and an encoding type, * this function will decode and return it. * * @param string Input body to decode * @param string Encoding type to use. * @return string Decoded body * @access private */ function _decodeBody($input, $encoding = '7bit') { switch (strtolower($encoding)) { case '7bit': return $input; break; case 'quoted-printable': return $this->_quotedPrintableDecode($input); break; case 'base64': return base64_decode($input); break; default: return $input; } } /** * Given a quoted-printable string, this * function will decode and return it. * * @param string Input body to decode * @return string Decoded body * @access private */ function _quotedPrintableDecode($input) { // Remove soft line breaks $input = preg_replace("/=\r?\n/", '', $input); // Replace encoded characters $cb = create_function('$matches', ' return chr(hexdec($matches[0]));'); $input = preg_replace_callback( '/=([a-f0-9]{2})/i', $cb, $input); return $input; } /** * Checks the input for uuencoded files and returns * an array of them. Can be called statically, eg: * * $files =& Mail_mimeDecode::uudecode($some_text); * * It will check for the begin 666 ... end syntax * however and won't just blindly decode whatever you * pass it. * * @param string Input body to look for attahcments in * @return array Decoded bodies, filenames and permissions * @access public * @author Unknown */ function &uudecode($input) { // Find all uuencoded sections preg_match_all("/begin ([0-7]{3}) (.+)\r?\n(.+)\r?\nend/Us", $input, $matches); for ($j = 0; $j < count($matches[3]); $j++) { $str = $matches[3][$j]; $filename = $matches[2][$j]; $fileperm = $matches[1][$j]; $file = ''; $str = preg_split("/\r?\n/", trim($str)); $strlen = count($str); for ($i = 0; $i < $strlen; $i++) { $pos = 1; $d = 0; $len=(int)(((ord(substr($str[$i],0,1)) -32) - ' ') & 077); while (($d + 3 <= $len) AND ($pos + 4 <= strlen($str[$i]))) { $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20); $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20); $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20); $c3 = (ord(substr($str[$i],$pos+3,1)) ^ 0x20); $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4)); $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2)); $file .= chr(((($c2 - ' ') & 077) << 6) | (($c3 - ' ') & 077)); $pos += 4; $d += 3; } if (($d + 2 <= $len) && ($pos + 3 <= strlen($str[$i]))) { $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20); $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20); $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20); $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4)); $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2)); $pos += 3; $d += 2; } if (($d + 1 <= $len) && ($pos + 2 <= strlen($str[$i]))) { $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20); $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20); $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4)); } } $files[] = array('filename' => $filename, 'fileperm' => $fileperm, 'filedata' => $file); } return $files; } /** * getSendArray() returns the arguments required for Mail::send() * used to build the arguments for a mail::send() call * * Usage: * $mailtext = Full email (for example generated by a template) * $decoder = new Mail_mimeDecode($mailtext); * $parts = $decoder->getSendArray(); * if (!PEAR::isError($parts) { * list($recipents,$headers,$body) = $parts; * $mail = Mail::factory('smtp'); * $mail->send($recipents,$headers,$body); * } else { * echo $parts->message; * } * @return mixed array of recipeint, headers,body or Pear_Error * @access public * @author Alan Knowles <alan@akbkhome.com> */ function getSendArray() { // prevent warning if this is not set $this->_decode_headers = FALSE; $headerlist =$this->_parseHeaders($this->_header); $to = ""; if (!$headerlist) { return $this->raiseError("Message did not contain headers"); } foreach($headerlist as $item) { $header[$item['name']] = $item['value']; switch (strtolower($item['name'])) { case "to": case "cc": case "bcc": $to .= ",".$item['value']; default: break; } } if ($to == "") { return $this->raiseError("Message did not contain any recipents"); } $to = substr($to,1); return array($to,$header,$this->_body); } /** * Returns a xml copy of the output of * Mail_mimeDecode::decode. Pass the output in as the * argument. This function can be called statically. Eg: * * $output = $obj->decode(); * $xml = Mail_mimeDecode::getXML($output); * * The DTD used for this should have been in the package. Or * alternatively you can get it from cvs, or here: * http://www.phpguru.org/xmail/xmail.dtd. * * @param object Input to convert to xml. This should be the * output of the Mail_mimeDecode::decode function * @return string XML version of input * @access public */ function getXML($input) { $crlf = "\r\n"; $output = '<?xml version=\'1.0\'?>' . $crlf . '<!DOCTYPE email SYSTEM "http://www.phpguru.org/xmail/xmail.dtd">' . $crlf . '<email>' . $crlf . Mail_mimeDecode::_getXML($input) . '</email>'; return $output; } /** * Function that does the actual conversion to xml. Does a single * mimepart at a time. * * @param object Input to convert to xml. This is a mimepart object. * It may or may not contain subparts. * @param integer Number of tabs to indent * @return string XML version of input * @access private */ function _getXML($input, $indent = 1) { $htab = "\t"; $crlf = "\r\n"; $output = ''; $headers = @(array)$input->headers; foreach ($headers as $hdr_name => $hdr_value) { // Multiple headers with this name if (is_array($headers[$hdr_name])) { for ($i = 0; $i < count($hdr_value); $i++) { $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value[$i], $indent); } // Only one header of this sort } else { $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value, $indent); } } if (!empty($input->parts)) { for ($i = 0; $i < count($input->parts); $i++) { $output .= $crlf . str_repeat($htab, $indent) . '<mimepart>' . $crlf . Mail_mimeDecode::_getXML($input->parts[$i], $indent+1) . str_repeat($htab, $indent) . '</mimepart>' . $crlf; } } elseif (isset($input->body)) { $output .= $crlf . str_repeat($htab, $indent) . '<body><![CDATA[' . $input->body . ']]></body>' . $crlf; } return $output; } /** * Helper function to _getXML(). Returns xml of a header. * * @param string Name of header * @param string Value of header * @param integer Number of tabs to indent * @return string XML version of input * @access private */ function _getXML_helper($hdr_name, $hdr_value, $indent) { $htab = "\t"; $crlf = "\r\n"; $return = ''; $new_hdr_value = ($hdr_name != 'received') ? Mail_mimeDecode::_parseHeaderValue($hdr_value) : array('value' => $hdr_value); $new_hdr_name = str_replace(' ', '-', ucwords(str_replace('-', ' ', $hdr_name))); // Sort out any parameters if (!empty($new_hdr_value['other'])) { foreach ($new_hdr_value['other'] as $paramname => $paramvalue) { $params[] = str_repeat($htab, $indent) . $htab . '<parameter>' . $crlf . str_repeat($htab, $indent) . $htab . $htab . '<paramname>' . htmlspecialchars($paramname) . '</paramname>' . $crlf . str_repeat($htab, $indent) . $htab . $htab . '<paramvalue>' . htmlspecialchars($paramvalue) . '</paramvalue>' . $crlf . str_repeat($htab, $indent) . $htab . '</parameter>' . $crlf; } $params = implode('', $params); } else { $params = ''; } $return = str_repeat($htab, $indent) . '<header>' . $crlf . str_repeat($htab, $indent) . $htab . '<headername>' . htmlspecialchars($new_hdr_name) . '</headername>' . $crlf . str_repeat($htab, $indent) . $htab . '<headervalue>' . htmlspecialchars($new_hdr_value['value']) . '</headervalue>' . $crlf . $params . str_repeat($htab, $indent) . '</header>' . $crlf; return $return; } } // End of class