RxD2WƮ[Q*7,5@ Ai -!{whxCj׻.PHvgh?6 7̠ szJYJo|Wo(ʮlJ0+b~u'M8:i᪾G}Ӭ؋]df*pf N^h!D1E')!>- `wu#XWx~,˰PIƮ~& C}ZŖu}tZ6u0Ҋ$_=EMmUunm;`;X.6?Bǖ< y7AVƎ魔1cg0?(S5_Ӂ!XZ] r^"ɵ,FG&@Ų2ϙ 2F(ɻ(tD܈֊}1ۧwۮjA }if]@ܒ+_&w"k+ {PtƁ߅~@2m,)Mў찓NZu3-Le Mnw-LfH]i|7iF$z1h{w>1e`KWڸĩ#lH8#̦Ֆ\<)t6=عYQ.>'8Xi1n9lp@xn34{Ϋyx!cShg1 NP:&A>u>Efϔ ?4Կ>Qr#9լbBs\.WD{$H>E⯎"`nU/NOӃ:L 8Īì@RU+Un6<7 ,ǂ0w ?V ='0K7#=,u!{=\絤E. `^miVp6?IX T =+vuGv %Ḿ7/.Yų M6ômO ;[N \!eG4i׭dm_XARznwaBvlu["b14CH%kNNB/j$Pq)q9ۂ!Ja4կs7 HS^Q;[{: %خ,h_N B?օ>fO̠2>O0AG iba*@؊FM)^ %E{ffgzzh)F{|2O,qG캙@{..V)A׉D]ߪ$z8U&1:J0}[?2"f;Bcj%^|:ئHQmY0C!-ǐ%T^&D`N8xl^E{P`-_qm%*b=]5;NP ~?p]Pt_>Ay>]X>] ~Mj@yD 6ckQǧסzX`XP@;szWZAhKwv> xqEr;1p ].-6y4yVwr7B59󿝧9=Q 2]+H<~MszԻ_<2$q- D)6B-X$C $[~,f>{?)ef,1޼[JAܮq|d> +C{<B;,taה_ JyJo?= ui0'T/,y j/cfNh95U`~0SLgMĿ$(;Eb}FiG;wt3h1z~;"t X@*_:OCsUT?ٛlBt7O0@UUq eh:A0O@]+_r9YbKU:?=D"|0VA(I ܺgC(}"]w"Y0%^MP~nZI:J2$]S2,7u{]_= |xipK,':ɘAW!UNtzXW_!\N]mFܹ;PM\wk;Eϝ6VQVSE\VeQ 9%34q;s,(3r2HV J{ǙP̚=N9gkPhJB$,?ZP zK :$$l '|䩲ж;r|ӐyB;Qi-|({_zy =QE`#ע_f>~TVܷVn))WKAӖmᘎ P{:No~UӇLJ4-G\VVrtuz^x{;Sb"٦6Y?6/#Z=7a2ث:qϴMI="a芊 mQD3=DG !CqX1JHV#P젯I)Ocku)OnW%F,uHy]7rcA|.Ư/5I(/+|ʹa@#U¯O|d  Rk|g7@Öz,qy_ >d}aNSD=j䳟R`/ fÏ{ὠ߅"ƌuדCSYVʇ:.oN{?\av[p{V!KBY|x&wZL*&ܴ'F~u4 Zebl""[Jdb%FqH~r8b/,^^3+OIwۺ;-ez}$TUsj T'Ev;(2OQ7`_d7Bխ[ĸ:)Vێ8|URX5qAxoӃ/A {  M:cBS܏抍+hEk`3@ĉl׫/9o3m73KgFZvKNOOWkk;J>=/y"H)~(ֵ$b 6uTQT*fÀ& 9Y] Z܇^gaCkoA5FZG B${1i䅗c&߳$lE4ƈg4.I J^N 0tNF6 :X`f<G3i&4eԗqf|jLjަ#y)~AฯĘ46څfĎ$,9Tם@|z@:fJo):Ys&n?La\zpMz: EYf@L1-."Bt'̓˪c&yK:K}ᔚUUWxcF$\rtZ'n+ἾQ*J|X|V$hh$8_/ Bĺվ ܂1JՊv^uϲh=Oa Qڪ$1|Gq_UO,Kjp-YHxUB"p~\G(>FTloy\+{J ;B+vkZj&nom4V38sK+LyMGV"|p;I%˿w7wz+)>evgZn\KّYfH;k(&afmD@  G%oJuS}AA`CygNϝ_ 3lz_ t_q(o~ ?< A! ŬŠC*24VѝYBe&Bcb/ n_ b+ީ0pe ,RGQŧ>n35?PR$oku;*@t|EbL}i>kWr±?қ:zo!p.8)5'Gٮ>{7H3>)3}2\(%@~)?FPߝWYY'n\}V';ԙeV;E;F,hgc{i4LEDU q_Bo;͒7<{}xZ$h|G-x7uZCNŹ 3+]"~#x- NAf@>{\[)J[4C4GW6Vϻ:Ih{Ȝ/D'/aYgr~N^ QBMѭAKU58AK'eBx]\ٕe"0-~d:U7r[n^(TC ,؈9=?QȤSxRC& Etڲˮ#Q=;f&0tNhZiAҮ2*7YTdM*AtqSh,ĂH8i`s"yvpgHyVŬiԟZ&OxT7Gk m,s1553sLJH<2tc[xqf؞4yKQ|F]FX]g&~&I;`߼RcNw133 y'/kelt60l?.藭2Fz8=E\ɚܿ&@6Kh-ݿ߹ɞvK1%)e0ygy4̖i*h_NzFč75EL2\Њ8]"cL~)TsÇJ#U* ;۪*F"n/T@7#U @sTeKXp{>+]VwSfԎrS*Q,$#_3c_ƇtHm_)Ilh2;\Vtd tKd%1O<7@k*N[ZVA{f@elklBĠNDԒ7!(9*#ˮĂ>!|pU˅Һ7t r+(=LςzsQ4Cʮh|ueRȓ7miZOXf/nESӮX%9WdLDn{^rC6F2 wAN'RnsݸR 'B]?@3]<lP|卟BBY٦N~$9яmmϵ3L(LDI5B$+T'K.WwH$ܴz;hH\jDr`Ƒ#3m|?wSoh朡\HPή(YmQ}Oj>8냬uӁְD_̸f3\ȧ0d<:uL,GKᱼ0rk 6LFa / v(S4 SO~2Jbq C!bؾ-% po4(67S]?oxZ2Ůzc5lP줇{wW0&/50]1BUɄ0d5cQu71Yu<.aR(f줶d}dl "oI^،_RC.X–$aiX斝M K:Ɓd#Lxl`{⊵ra0c%δȓK vtouTrT%t0aPs4z.Up+r1flLlؐ⊘exu5詍Mֆp=-P`6vKZ΍]<%ULVїCiT76#P3ou%@v]!ҋ,FF|EBY.yί*-||`EsaS +v{+SI1Z>k2 :/F7 HzyҥȄxTdЯY[Nu H%?M W>I_WrC&aPXßdU 3R|:WـMIGmz:3{Q]";y;u{sQG_e";g !~ 6 DuJ͸%O~ZL-,M-G2m tMkmK>E%;PbUrՇy݂vkd wcRnj?;roc_M8[KԊ*i];M>\Mj73>j`-zFu`taI5t31{K_З$>>r5 `;Ӎ|5h¨v|EQ<6LT H4xq).[xc 0@jArtE/zIo +pd@Ҿ* hj-vjXBY"d wŕ| H1oA+^4  $Ќ` o/ 7H[I׾>NR+uB9jg]?&M+܊P:iql?TA]$6,KI(0U@`p( ϒMWd6^>J?p^3J#ޝFB2^W[8~"/6Iw$<è;^@7` ]0ڮRUӤÅσay&@ SoVvPb|C y |$XЖ9Ů\ _wS]+1ciWa=a`ӗ~^ zˀ'V~q\ovýܝΌ=۪&H4pu,tšқ4saKи%d`=p ]]D;2<'|N`0S|'8n!Wۋ V9.0cqEru=SU2mL"  XGHJϳ~æ{Eڽdy _Jo _]X_+O /Mz^`&>ӓk`X*S;v q@:nFپ|l's{#a:eR $2EEi8;igm͝(f^mt`H*&PXDBN6:i)PÂ;xg:ZZPm~XC h6`& B@@97G?H/:j"ưAga"Zr A҅w,%z9NYS&A(t@J:Q9?M+ U@Sٴp9x/ӣc(K0?c# eq׸g F)}slTN$/?/JWϣG<='# O{DzIpAO[\|Zd4gۯ>@yp|j^6A2}Įkb:x")ƶTC{,PaUEo|pEE+P,[xcXi5pmЏaיE~0s)P RfQ(wY:I>|H;VMa|lm1'3-lPρȭxb͉uɿp>'”ؐA.?`Gr\i&@=1+-Q_y_Gp03խL 94 Y_Jero `C^$h>&A@U $Kkq=~bVrS"P{bFX(T0O4ٍ]D}F(ܳ tuus/IĹ ,'m;!w -ĉZL58L1c4r%3ZX.hCs^ݷȑR$qI9;c=&xݽU*| Bma* yS7q7zD,%qlz+[ s*ŢkzKu2.!euÍ6( cKUShsQ,1-e:}98Q(Lォ ^#Rnؙ7=Q+(6]dD[y^m'oF lnDٔ u:mZXbLqbzNփũPѢiܸhf:ʔL|>cэƲ4~.L@Nc`cN-^[M p5M?5ݏqٿKNG]Gf *9ME&ϣ2}.&|&.kFo1ʙFsQ3,]Gf|@)myt1 iG`u1@<[*y˾LfxQ/FMʭ$RSףPC<:Uʕ+Oum< &hT;tM?"h(#j@3{@=ԭ TW0g@gJД AkW}kO%$j~hls.?JQ_6׼QۤW  hVu~Mg2\e]eоBЁ 5^?KQ1l>%dC褓'iN.9t/!@E^P> n^{(2F6׿ZkD kxo}T| 3DJote'2`(q:ߴ$ ;bWUG!^-AuYK\`aP`:X*аG#*J12)$Y,v[#=_5qt)X5V/=VMbMz:W\/R t;by:Q{vN F619u*QbDkzW3i'TUKK;3[D+R6DIa13asOGO0: gKg>$?٥j&*`x!E5X rY_|Srm~[c { ԧ wQ _Aiܾ+=I ˽^[Yu 3IVojj\/(tJK]X(;ÜaO:B/M (,TKE$u1|Ox}Ho6l ٠_&ZjՠkqAOhNi bc>- ׊i(I 1QZeޱұ"2\ ȫ>l:hU_ -]9'ͥ @Ɍr4g"/ߋ 4nsj+`#h]?a?liWym?D:M@w9 P/0il6-M}Jj˙3 tmC. Jl9(-w0>7"4ُ(>%%Sn B%!9vgТoMx,òƼujaZ 1" E%zb/u֋wsSd~FؓRO![JݤIy7!43.B2O/wX4MPxяaE:H|HYڔ15ᚯktzZ8f=Pe{.Wb$5ދpن^ wȖVoixyPkkFCe,(j$~^M v:THh2D:paGBIױ8f]c,H~oTs`Z)bR5Y=p,%9tX,!Ҙ2/|I^L9FChXF#a*pֺr`6zI϶/E/+_TY=~>6T1>*P!]1#=dp%zsD'_ky[87oEB]xIri~̧<ɔěVB9OJ_s ޙ.(>q%#w?^(NvɌu(/tQԪ!طk)xi0{O؎ I|Y~"Y%#_(G8ſY>n[R op+b_P Rt7(IioPUww@L t]J]G@C%zN ugyCKW.QOp; EV4/- .A$7L FMV,-ڼ>7Rوs&"ߚ"P$iS4w7H%(\q*;+Y(0ޫt(aIb"@yR"[&7!UxudߋO fP5y*T|'g|[Ȟ l]kX[.#y_6W: 9g`IwM4UJ<5ZęԪ" @^} ?n#\ߣ&Qr2 #!+e4 z!s*b%vOt8ڇaf'}yN;}r}/Ls}^iNF6*rif_JyQnqa2g(o;}&xN=Pս (?-mcRȯ/[|;` ;sbgNmG~-([m|@u g66ZЉX22I."d>&eHEwK| lњ6C<9xx~5_Nc;~$t]yĬ95+$ieV$rlhSij=mrח8AaƤ}z+>K|enM>{L/}IM!+E\nAݿKCUOnJ^Fdx0r.}o[cFe2F`h^QʫbڿTJ&]CF/b-UT3)4)Hi} s/Op>2b$$SSlYbA.A%¦Ι邿^5^㊬⇚nd-7\zEi; _g$ܝjn8Ff1 Թ4d,=N !bˊ[HJ@t m|Ua߾k,)8БVa\\؟C9[ 2)ApB^5^̴`'#_|yp7I1F"zX$(K.Iný>Sd{[z-l)O:A F$UGp_sfEր:5|mwHGֿ~_!秫 eΈatl۹BR70i3^3:D92^U9Hqr2:)&ޘ!G׳gLENkXqR6Ai߲E.Od`-P0(Ӵ/#99sFhJ̌9?#{{(CyY#7wkGB'-QE3٧9,;CSy S_ۮHZ`ADPMI/@1k#ܟmv=2wgfpa(&`?GpxpbC6xȂ3*g_`!u[zɞL*OH0-|iH֊MY$JPj >OY L9HېEEFp-~<%r'͏ cV9bPڧJPiAUۉr72cz}=m׸~Ubۏ ˆ%E(1 ||QPCIe>܊m+I+̖4Y_V%!^~in$|6ƻd-Иmλ(o692r%ж@Uey:8P l%O3Wd`IiB>f}VUw\AU(x@a1ں@#t ܉Z察hY+9( UjcW$ZbrXa3Kh2~Q@TS*.RU>|"-}s;09,( w;M\zb;$"U\lVxdaARR}U/z' mK?*M)4MO6d,EfZFQ͓N$)&㭝u𪐯"ې0$[iap dIVgbIV#Ǭ fYk>m;*@kczD5MFgZkFPw:z.QHζ$ ";ؙ!wPmqk7.߱BwL`-~Yr-<e:(ybOSdaq$Q-2Yj{] lj&뚯 eFg9ٯ4Hҽ_á"ͧ= 7f#+|:תzΓa.r~}9xK&HŌ v^~-nv`ʛ.q)Aor6K|5Y\éqW0jRec^5keH*1)"|* ,ԾDz5=d)GNĞ!).ՑPJRT/B+s]67{[}]LPT2T?BiVǚ-?ջŴt^Qf?)0$&ZPhI2)"E0״]==?EJ0^*&-qm9 ^/fQ@41REJeB4oHP}.۶A}k;:wuF9D7h.Y @uH]0 PȘh~8i@i׫B̻س{8JŅ"E^ FÓ{ⱬ2dⰑ->j슴5lNT};WUKsgˉe2>7y6ZD&T9 t`p3CUD[+G9djЭ?]EI=DeDV%vtO>+5s$,"~/*?%O45y~}T_αΙd{LgvĠU ؕ+\b K&0: Di+r"}LU whԯVAb 9*՞ ]q&d&̩k,%9H ݈&`[.X?E?(--ҥkOH_}Ɏ~"7w?NJ ⸂\ܕQOm5ޮn$TOVE! +YIr 54C_nj9gyioh6_7q|9*܀ FHBSz:l}̧0!td^1'*R⩒YA)gޑSp~|OaxuQiHpʧ;agB쟡6@ok[Z1;P6z~0̑(?GK:Lm-F\Qr:fBn64{/7ֳل^YR_`r8T4 !4~o5m LCflKwAD;C Uz/'3uFi"a_wYYZR'/$߄Lָ%!H "=n=( Z2>m>N}L[RAsb5l=K2JGS]'QWef uN -QCaMmr n2G)FaAVyGe~{FCA$Y9MOJ9 ;qpHߏ֊$֩>rԫA7#VNܒ/v싃qi,;Ls]7u紼L%B.Ov/|( kW'( !ak<}]kC 7&&kР,eJ}k$iKΤ1k+ԯ7<.`o"6]Mscz>U\ps]q~3ĔKe,} ZN)I5iS؏ FQ3L}ij n9Z3m9XtAd gӹmv7``K2qiB1CΘUP";6%Y,Ҧ] ή/ҶdQ֞=(|} Mm#(TŠA& Hwvס r@iN%׺Gr`FT%׭<Z:ů{s؟Hkd-gFPBwpY?m6+3ʔùԧ_Y,~{GP305R9e/!VN]:'Y.âw?CCdvզu&Dv*F,k~}h `Q_yYOOoy wu߾(- 䱳tJ >~_ee<oP^v5HiFh#7Pœ ǰAUz?fh?7ڣ@7bjl%&QڦR^Pmp]5F(J'stt8Hף0\݁RcwiCӞZ |=; 0</qlET!}p-I |.^}q AUxfAGV ld7kd\] BYWߚ yky-;fQɕ֕]FkNrP$yLzۤdTT_סSMZ;rkd$p᯻7C@$ 7Y>C{+ wiOH(e{m<Pc>FdN 2N5dQ:(~}Ӫv> l:GMnߖCoSؼ")d ca]'#slwJtq*-k~vWԴ޻$Ř0 #E٠,*ڶ9A5kVVҾ?>} ,W6z pEv'1%b62 *^Q'1FgS ew( Ʌ}nɕXu0hSi}|. ; "J\˽_/Ba{o3K+37-Swd^" P\dw=#+DzZ'6$5p-9\HOMۤ1eh^ YpPa]'*v7'kߗQAejYzy^bO9#OYk]d/UӢ zC/E4ҭܮ}Tk*wRʹ;/F ̏XVZc2UM(b"YU֭ݷl#[4;y n'2LOԫ6Bt}Ge~n("fhQiBȕV}1u _ḠܭÔf^qN[[PBVZ_5IM HoQb"0vm&%?/#*G!_MQXd 5܂iδGr}R] Sv6/ʸ(G?S87s?Sd!;W 8ײiXʜ1MEE!rDBb[ raj=u.@SZxM0w&- { 5nD 267Xi/kL??!6j0h8daK27ܜut~ d{u\L<cWMay$ `I4F_~dEp:Gq%FOjT ):H. ':(lBH3/s@Ya UY ɿwݺ{ 9CvIkv0ǭ^"׭_.kp\uEE0ZKs F8\o_RHZDp1]0W(+9lMLwT@? a{԰]㚻>ˏotvO64 t^MdkȆMKl#`US#&UBN?}MKO@Tl(KN4&/%۟tHQ# _ A|:/Qρ0_kvUʓRCt|,6hɦ0.Xឧ']=\wf6`6jj@qwN"{Ψ{,|6 XZ.eE29FRաͣIUScU!q^?2 ~G^zlPrx{ ˆFuHvnīc8ګ겶) Q,e±_8qi2wjf$Cֿ޳dtKqqFBpq:c5viш,B; N\ y>n~fe3^٩-#Mn?Fzj-e./@I"7J e]RR [>:j[BH:jgW\C461 p/X>i8Խ|)n8>U5כ5HSd2QҚ9''5|^#AĦJ ڋX bz  +R tݟD&)|dGͺZ8er>~nie$,titOy4έcqm"H7wO ?1=D#{HީQ$mKyd-Ա"`2ZLorܸ 0ZĶ Xy,c|.f#EkI=7GcNh 8|۝ʂW%L<ѝąGMzW;eh^V8~K}22<ü^wdz:GtM_[ }d<$웉Iȗ(oOH挓_͠IQ5ˏ}gKqs`- H@Wj)/vV$nf)'~MKUtCF&9ʤMuC}?NɊ]#d6K7-rdKQGe>+ @"ͬ Bj$qjY},Bۊlm@݊,E5CHaNۣЗ"FEt@;Yޛ_A|X/dz(j,ᡗY81J:AVٮ.H~77g}tL8Q߼\ay!u޺zp|<,Fa1o:<8硿JLm[IY;{\ԐGZ8iX*}#Oo}""_ T9@:)du0['w6rsP`pFk$S{jm;+<5 7䁼 ` HRh$bҹ%LUY-/)!H4Maymu<{~y=dm,!E{ox7 k 9#<̜*)[9_ n߲.:¢y  dح58Sg.:bijגgf+}h I:N4M(|^ƃ*ʾyVRpjT~U RҬ3e#Dcm>Rj8+EpnhyYM}Q왝Hn_K޼: iBJ0OOwxC[ gaS=RT!ɏ^ ??E{?x,Eoq{bE˳&Zv=dݧBc;>[a,6+=G?>*Q7m^]Uz> }òݹ?У/"27>Rϯ1蕝=сi?~^j,wMB}ЛfGc/Nๆtƃsh>O뒖i}c']\ƒT$IW\`ɷ!0*}}h]l10k_4,]X[]A(K"f7f"}PVTNeԚ5G+ s,6~pQ$t_V>4ĝKb}vEԳxA=|{}hD:v8x# %Bo5gA$֬{ VЩT0C}Dq]pXaSyPX_΁[憿CLs[|1 ?D2<#)=}TvcTe$7/IbP!AM=Ty;xUMhe{ALj_x,ݷ/ՉPofv] i_ĎN n"fʛŜ뙚8H5UtT32~!\};4@04_<@( i^C,pҜԙ)K e|p -Vy| 0{[?VWdUG󸁧+ 93rmL8.%Ac VS2l- A>:Nyե:YUS 5;;>`亂t.<}d^jZ>$j5]0)jd;uO=*53W$ Woowݔݼ/HD ou1Z66P.4ͤ% DQD4!3|g='r샶GGG/rTd= Ĩ$~u߸{}4 Sgyы,ILRǏ?T>RgP_Cm]'nLfolrHdtD-ufEQДeg"ͱ?.e:?vQPLtCe& "ҟU(Z5&~,#I!~S+.܀P.-;8>cÜ8읚[N5\Fq$n4'C>sw×ׇՐ?ĵ(-U Ke>1# @7\" :VT w(MfdYeSLl0d6לּ&UK-EID' Um(9y%6a-oѳGPܯr!/bag4= в}dMawo i͍%BoлVgNb$R$ >|sO{{"|5.ڗ𺵠^(=`opZ#k.)*"=DA\EyY^t@~ğ6 U[=]ͨѱ+cu̪ht@c{/=ݥp4˯QƧOF~xiv!'&9I;9UFWv{KF+""O/Puds ]<2h7r ˍrW)ꩶ(ael&\1 1 O5#oN u@8𰅜Vu"322v2soT j< r:ݚ H*BJ܋U'mPQsxWʫ̇'{4l\^u$^L<,Iڒv;߮ND(iZ0Dz+ʱtRqv \Pjc.H]έ1KrM|"i$*XvELqsxɒ@mZUWĕEP,{>=YlF ExE@Sv\lthMGk&ifX{u]wߐ{xh| 4~5!q娟$[|*h<6T^3-8% EGw Qa5ɢ\Ms1*;q~pL~FGmudu 1[+ 0]yhM}8ApN);5Qʰ@ᢞ j2jSc%a-z;ܭ HC7c.Ocv+*fX*9$@l<~Tn d[Vu-5ך?GݐaQzʂٟB-Ha-Q}K+#G{lnjPqk{Piv+sai';=|R-/)0" vt^x6Ipq%PX\/QYehQ)Y!H_oՑk}7Dܼ ~/8{{>3~!#uݿ5E0RU—M{ݚ< +#{AԞC1-lB$|ݶ>"Go y*Wlfrk~:$> #"j22$:"}.^F!ޗhVT+cӊbMubá.~B"c0(r 0L` (q dU%Zwꂻ핑掖UiQ' C1y-r$C|byUڒ㏫J4FtWάAbCq,8!ױ&}O]`hV?zZBÕ^/MKO1w Z.Ĵ{ʑa~s?\'qÿ«@*4Nku ӭ>Mnj^6Z{X^Ig;5Z|CSZG`̤o@#NM B˾42HpjӓP5@C,AI7Bq2kᣜ}N4Gd̲|lSv [ YʰKaZ>aR~2#ZJF߱YQGprzhř^ F | @.YX]dY֑rrWg8? 4go"ɾ'^ ,C5[Uocز8ω¯K׫WFhdCe|hrs+oO!fB!`<AR#;RUĽKlYt{Ef8p),,lS*D6zKNw6^<Ȫ@=`um`AϥlQJ"{dT5l=(^Elq.p8e\h͖Fs+: QVƄGYUb7 Cg&;>$yzy^ݫ~#vyy@|l'k#^0x &˨M G^nIBB*Ko jzl>GܑEO8YۉLݸ`},満B\4Nb-0P$IsYr%?cuTW5q;(6."֧uAѻ%yZ~]-"݇aysTWAD^z?XQA<[KBג},^W&8zVN3&CH,{oCuA $;׾I;(ezRF2-ȃ \Jx鷀e#~ bZ ֿ=2qaT;<۠$X嵈Mv:"I ף B&a } n?0Vh اm-뮷])]1L~@2`o*M˹֏7-$.8%l{ҵc= &BWn5z7< 8ao #hv!b&H5=Պ'~e_5=d2(pӼi D Őę}?ZQ6ƿI{HT}:5&_Z $ )_l8ս*KD!ӏ1|8t:nBTvhb_T;t)(x!~-i-Ki)fA;=zi:A(*tXk5U~jlE?z0~+s{5\x(yuzj̘?ÒRRҲ f9/-PZDuO~Nw2b?Hj6l?ݗC圗5="#1&ڦмR15^Iuа%腂v*"Tdm}Ա锷+3r՟ɦ8~jknW  "mokBBCyi' 0yMz=:Pu筚 if!\~hђuPw'x׸ȿw('O!R[7о9_zmfσaiFG=YfbІ?repS=|QvDZb,K+{ᢺwlv _RmKgmx[U :/&^Z N+\;!d^S@|eu&. \\4t` ֮ny98yac {LZ"3m_@M #v˗%N0(2ok 6#l[ԶvSdL4+y|yF9c})Lu/T\Zhd=$9't< dY.C46fi֨ˬHa 1kmvt}"[vDB$4jr=,A%p*rFIF-'K#oS#936\z@޻:M%繤T3?fjǀwD' j|_t$UK2l6tgM9s_h {3xxGN?H@Gqa܌G2tH Z_moςiٙV9b!!C",==6Sp9|OE(=pQc};#ʭtp EO9~uӿߤ,~%ů?0h_VSlD=x,&U ^Tm2rM%E[NKp\"=A=R]fLa&1Ob"*~)eĄߣ|Q?)7dӖ@CĔ !Nw"9CKW Ǵv^L&y5k !Gc<WiRcMVaQҙ-p鎥"jR|a۾btFDzSŹoN")-TFAZ@ʨ ɮU#b7VzTKi fqSVIh֍oKK}? , E~S>rC.Xu ˻$Pi>5}SM-Ae3#:_8zƤy`=q(0V_:Z w 32dJ,b#'>zD<_iVAU%t>kŗfGBk[|=m+֜$2gjW5[犊g7r]!xR: 9P֨4^q?C;vdu.5by6Qg$JzDTBR@XЗ묀E4l"z@2Z1=B2}K>E#ʼYP`mWn.+#W0!3?ȠC1H2\5] |vZĄ+"Α ϵ]6"oy%KW0-LW쟤8S`" kUr\ vy#"!u[c0S3)ռOIЍwY4sPxk{G~&_hA%Ԥ'wAt4_.1Y5"6Uo( CA@H[JgmQȁFNJ=Nrn B }IF*y.V.1κbz!~>$lRܘv)6*hŢ Uy{s=X{*' E>m%K!徲O!15=Z>Oh}jcd*U&[ g#vddc 7j+淉R2BSyz8awZ$dHru4z{PI̓pdVcIī|aQsUj;JŪ8ٽj tHa6鲙މ~oUD{!F~ oX72_ +/ٗOZƾKK bwd\9t.E:2rvOE[]onZsHMI;Izå-2`)Z_^-OU1P!{s{nqz&(k!JO1_L:0psMM#)v@[Ұg? JKO+>LB`]S+(O)^ss"#!9zLeMgߺB?/rN8P{C5(n ʻ ᶅC$GFVV w4^>5xW%U{GyPO \6iHr l#pFg0 2?N\DR*"C%ˋ ssP{+90 },9$LvIump^yuI PM8E#4+P:ԛ}|;qc?4u iMzU|ބKx%M VwcTw9OT &F4;l Eo7 R}&ʨ'@V[V|ڈ&ȻAHoWQǯ|j}!*5Fd7>ݱQ5?+׼aU&Nc7[GCAM"_7\Ij #hg? Hap2Jv69赴ҏKIb5 v]klWK otyߴvKp(X$Qkq|$x23TJ|QGٿ'oAe>eG衚a.<χgҼܴU1>/U~ 7~eH;6(6Un㌴e΃l`6 yv鷜2ެ^f6PD\널g;s8=]UUg=P!5#Ԡ:A;'`\w?'U \¡¶M7w[yxN39R C;M8”/dK:< Eq‘mv91r]׾yi"'-1>rfgwNՄjzq=K >ϋp``nHAW^ t;eV+*t/zE0&kri޼D[]*/d_ΞBo.xC7 bC/rFIQʂEl ${nߺm_BDC16 qSCEL(+1UcDzUA:RPN|/li,=3OS@44#$ " zQP0 MRh@폔],qπX,X{q>Z:"̴Ķ*BU,fpOvSP)GUTȁ`~-W{q@,8~ KYwaurl(+=꺵u[ȆV.82BY5~k1H;5P@uMQň8}"X|I%vu'EaصoFhR k,A/^ =ke0m\tnB՗{g,! ?t5-'0B^Wte[{Yz7Z81e AP؄U*`/:fwRþ߂ x/;)ar91,Pg2E @Q2QHqcVH3 }~#m':"5HMXM MؾrQi`ɭI_<qq|Sp\y{,^~,}EP5zPSDE XX{0u*ko^D-=UgѢ,^:Ka'Ό95d+:!XBERb뫷]_ :MZıg>?zXY*WtHbOI|[@.@vm4(ngtI(Ʌ+>"x$\5ʋf !^d[e.̯<<J'xf~Gʅ11Ӱp IY x{V\v\}ߣgjPyʫ2;>_K(~^jf!TKZ·\v zѻUWuAuP;@#a*9qY͑sPQL Z@ֆRoe"dGW58]Y'^I~?s<_`Zd &ZS })du.QOP:^"3ot Spi [?=˴ =ܘ՗⩊qiE>77s a~83?j,k"KF}$koe'J./nX{m .kbЮJ{}_u.ũ5 pXW"U?U.qy{cvZt@I. $Cq!ˁūN+ ~! g> DYz1f×~X9˴ 7;L1JH4~3^$AYOrߒꗲ$"SrC+\'ҒـP=b{Y4*-]BveӄJdKbў4Lm?vp밁 =ִ0Iv!ԧ~*瞁Y#;|8ID g.⫉2C^_kdLIbLG.A2ab1Lħ⩶|zpjy3"]q*L{ݢ6D,,k-u c 20슊:NL]KX"jR|<M+[G! E ˠl[`W6tc<:]K.3P{iS% &a z#)/sL=6:~M3sghYj SW׿a77ڍX"^" @ps!m>688lDCسgLa KymQ+$G];z.L4\Z4j${+Uíkjq \uޚ#J %v/0'8oOy ~[KV@SNMhs)6߱|jl搗V:݂ C`9)^3޽qN B="cIF_\\UιJv2*d'2p bF)m6AM!#/[e6!m?j;5:C/( ( J+Vuw*x)J;oC-k~ HbdHD 4LI x!D#f80 9#_)jwL[W}jrC콿oNn{v8mp$a*?g.} V5*CDjM%º*xBn$E⾊gY͏(dW^+ 5w}aݲRCPm ^anwMU64j>/_WMT[jD$z+.zh#'0v'8ܖ-eIoI G^/pBd]Fi֜aZy6/6~)b01!ёvy@?گ 7K{^ܶՕ/z$Frc*<ﶳ^}hL](7۫w8|O?pteE 9Sm ΅Y_hQ WrYxA3PZ7a'vOZiGW= EoAZgxZo>כ}~S~_+$댊 B;fWURt6X߼ [T潪߇:8ҿso$"I0( `6UPu׍ K־#гj f΋1{뿾ZbuGvd^SY61En;#.fa:EA|Z*v9E{lxQFU A朗;̒L$m(* 1T)4, #ZE]|YJL+jda 4Wme.2Z 谫>z4w( N>XA{X,ܵ0Jm|k><2Љ4hNC[$m𔀗~S@>Т JrzU˵)-YŒQ{ϿZ=;̋p$"50=@Mvc/Y=qk_-IVC_"5x[v:={t-#\4vK NBC,iɉ;kǖM6`"0*dQ'C Ofsbh`goUeWk{|ڴP0}48CU[Q&kYNpwv(VKٺ/(ʹmB01/h/8/[nA-eQn_v]J\`dqNRd|q wuaɏ@j6,vɗgSmW5{Ux AxB-@Ur}0eooÈA2eqősO*~IKȈGs%pfݹt oc\a<-:SP׿sӋߢ˫h3j!CW;cgEtX#qKE+5wks򜾐k&$vEt&ZTS@fKT-}uO}^GЋt][z9AqcrȡʲC̯Zd&((K-PU@Q/a[M7ڒ ?vKMŽ|l/ ;ʦe pQ'cuMDCEgVKǗeW/Iݰ#/ ɽ5t8:D&64-'}I O@Xiw]KեhtmmTAFg'{W= PbVkK̆""\YuyiRw^DX`U\=KRjbaďe)j krg'(xuYZ9 }MyOk^nxG\[s7 ڔbr`oDefLÖ ?p74sxnf2,DFJ e~9FR|^jֆ$uTfeY?UdO J Xg3UK6" 2~F)vp/7瀐R` ˊ2"hP+^p +lqSqA:qQi"jE6*Hηag'p[7jGi9_=٭α7|]9 /\Uj}-M"26%RҦl>P1:ޑ>z-7dn@-ܤ-_<8e^?燦81c6z.#ًO0<snHz<V5}.<3[|^leNcyu鮷RCUddQ?9Z!erb%,uOYS)"zys1Y9#u UT?9ZZҧ{y?IBMP /5TPiP451~0otUe"eIֵYy(.WnTGLUѓ'e媿DfA4<#c} s smw#F`:>mhgL2#8)ҲnS2WӦKCRvI{c)jSl?qJ#(?\؅{yZ8q 6g|j2zZ CFA.GuW)jON߶ѯmMsK^,NAB?Z9٠"t7 z5yהc[Ȳ#!/i!'z14"w4fԦa9㢥m{+@PZM)MهiQ)a)Թ"ʦL~P˪o)IrL!WvQʽ1Wu?fFD\@X5EPGz~minrpDfs^I8-JeCIs~sjcUã%iQQ?*hHɅ䩷ȋ2Dư-0GzgXvbS?XSC-($Nqx qnyc[6g@*^aDpfjnDŽ#)uY4)c4Wy2r iffx`q*0ԏEo{-j58]:y^uX"f[%֝8F H<1MlVqu=9ď8}6Gզ kSV]G 2>e +wR>J" 9M=,K(ǘFʾ}Ȋ]N"m=ք!H@&w{Lk9-yNI & ܪPC*C`!ioc<$U.@, $,Zkvhu>P}1m] A(SɣEg˦@kӉv57F-B^u ~"dn3gz& *]E/ѳ* +^y\cj_N ұl]-nj/Tܲ1vd2Źb7oL ~-M H-ʺ+ā/J;I^O(Lxj6g0I~06J.H?"}fdBפz#Yܙ.S04Su{yyUZs(K9X=w@ɣr֯y^6+ZNA}!gY-#Mg5Z>y 9yc ųRNg7!nܑ^OߩЯt& TcYT2X̕[xF*Ǿl'֕&3UmcLo}6:ƛ5&罎4@1()xSZ1M|}y/>ttAW2V8[tOw am:7[Om.soƝ/փq)6{zqgy|M^EQeOm]uf=]idW+;t(b0C,_ӖEJ#P4EY%_-=g-#xy֛D禍eJ_1u^jj }1Mr3wp326|zxeyk[eA'v9FaԳ9!6A%FIc>*y @Y3Ei 6vDJQ7nM !wPYaJqTg1$~~8q}(~ܲ9Ee_Bv7 fUk3Ŝe:8:N%a_Z5 ⅍6Tv9e B-?tHBx i'O/}}9% Z9@(`o?/GE#7IaD]U@af!|kAͣUfz9" ކQ R^!Y\ 7o#7LNHVM5^8yh$ci; DODJ/IH|Bã)8SFWUB2[h(ڢZ",-zԫfL[z}ɒ kK,y z+29BoW9ΑMmfx"z|^{H_#ث'ю>`\j'%PRi6YZ𱟲w2L 06,vJXb̓w08;!}ٰ&:q~ji74zO>?BZ3J)Ձq/'x`<↿܇;_*c( ij#D₮EI27ɡ&13Ө:m]|(Q0E n{PMԊAt3-\%Fä”6'Y4pg:Y`~|3_.Mz/FE[2q|uV<4Сؒ,ѫ w H.Xbyv'xʓ3Jddp5/y}nKW@MW-%=^R,ٶ\=ikل2JFZnń*^Pl#Cݙ߰EW8hkW.3 P(B{!'M>vr5'JQwm-BY^bb=nDEՒ}h c*c]ٰ,|`>WY{4+zh]wM3OI8kNXv K~Ē-#LO ; ?m Y|DW MQR\_1\ B^R?+SZ&U/ - l;cZˇ){;1Tʢʥ|'c r`"{ЎBV+ґI5 )|%4XfuZm7) uGis>XI? ԠvߤAQ }.^juKBb̭1J_^vCv=p[T&==!#'".z=χ?_.-ZCtǓ䕐XuXTK8:|[:TWS uc! ^Xtˎ[R)Ckڪr?a«Ǯ,P[t/@䞜 '}AcrLe/nbVe|ot/ C:YeЏ%W7$&N=0D4{WV XP:4|s2"Aꁎ!]LiWD Ap`JOrڡɑ}MP2tfTq_y'h0kdW/bdx_&Ya],H0~c8WoױDsH! ku0o bB(eC $PrNeyV >*4¸cy5iǡJ1Qq~HxuFp쁠bo7:n0e҈k(AXm >O8ɋ!$MCGݔe4i| t":3+;~ `Wa䷟k{ͬUXWMHdo|OM*Gzo1G"Kdz`=*S/; c!Ztx(/tӮ--}}&4չG@!L.~㸎{;C $2;[aR_ B/lŵ(v*.|Ol îS*'J/b0?|$Yi&YK5tW71ś·@vʰ!e~Y(4aWdLC6wTg ,P Cɷ*9!~.g>i@>[(?E~^2VDX@^S8z4ka_}ȵgU*ےUY1 E7vY(Qt--8֕|GaIIHADF$$+0e>`<4G [)m9WEܟ܊ E24G{#d A5'WXnŊ $siO@N,N\ n c[p1~>ױA~5B6-BG߾5IVa|8hΖիO"$KV6x3lQ'JҍN3?_ic%L!\]_ =}Wσ لO1*8L\wCi*%tF[dKj6ʮ ~LK _?N_1nb)zsXL +ট|NPTY~Į-I7խ@f/ J` Dϲ)+gYCRhr "VWVQb6kF;?vT5qef2i6j0xȝ$QZ.uxf閼1i!8D9_7-ל|"v[L!@Sb7,k/9fa*&~"5-U:g@yf==y޹`YWAk6!%Sڭy1qqvUZ gy 56߮1n@e0=v 3X͂|-(`.=6 #ίK[eܵ|(PwZCf@AIj1jE>n]C[f 7p]f o] lU!%11. ~69+ttw }O);\!}c nulm Om9xY3m+>noY]K'ܝTuۘb08@T>a{r+֥Ygw\h7ǍJMŞֱSHJd(nwvbvS'hat7-@x|2 3mɭĐUt1MJF⍟S`^)QM˷t[TUum!l)-sLl'D v)f B/ HbG65?0ZG ?,،'ѝh(}ğN9{y[uŬ "le2տ3[ Liڕ( qs˪5:3stvqF41c᯹Uk}4 . '!L@yZނP;ʣm# !e`]K4(\FQqbD8i˙3^# ],`Ѣ/R`a åujJ+f ^e.LH4TLRs\Z O^X`(-}cVd:>plө F N0ؘ-J(ШH bW{o\p 7t_tg.f7:ZkxvJB1/9'ʽ]c ^tN+?Ϭ@tJWh} *׵` )k)څiAhO s]mW"x=ґ#(/faG~T qrWǨ'^L!ݽ,}ʧe&.݅Ϭ= S|Ԏ׮æ,i-fmR뉙vv<{N+YlT(Z;.uC uJIߧc3Yc8T */XĜ=}9JI !}(jdlcC,[#؅`sߏx79Ͼw""-1m{ޖJIzo{i<,4{z[yd JMԙ?J@1>GX\=ԫv- hux?_"_$٫H|y6RRpD@<[&x$>O$]z6:zrJпn=pK@>6xV]ǁ*Yܨ_MFʼ~ހ'LD7H$@"L{ E0H q˂*h@@0/ɖkcLYt< P^ >U@w~-^<8'sR(.0T\LY&w&9pde> BZE&OTe*I<R}PÀ,yOD݆g!_q9tR481m&L+!Qqv*stb>ugIJ7 H/c ,ێ޹?Xuwc`J9lj;jgU^$5f8b.Vbuˏ<wYZ2An jbt*jA(`?-Q4LDs۵_Y$t?bMml !?Ũ f!W>Hc[\(~,CA07>3_Y"tFʐ@ly0 vׇby:Rl]^v.`7l/'ɳӗ_; >&S94=ڿ@Н~A-)܂*5; bJ87:o 4с썬4eȵG땪g^X^Z#5#7DoLov5u%Bg,g}[,:iK6=|f|U b'Gd&]u]V()IW !iJ T">/*x s> KKY,g^8+. u?AwqC԰Qu26[~M\'tMlNCtƒt8jP|VZΘv qqXcLZW-K;/- bH~]h[aBt0 ~YR,#1\ṕ"JYq"|HZQ#yMzu쳚vJ'|L~ Muö OCt)K7s--O@1g¢Z>߇?tdogf!K&3]88wB[>4x舿}`ʡ2~k%2I޳x˂jv9 ?LW6u<|e-1\qś iZUejn'qD:C1/f0 .&o=Z*99/ޛjgn vF%ZpCzHk񜤊E(77ɂ{϶tL\nsC0(~~=:\eqlE5 GZR@F yp<_w<ΡX SD~Og|)\ wf *j Ůc WţǗW ?UA'~bJ(w2q~&O ػ 񔯹"T&Kk:™ MO4 iD*f;(}SOD")ϱc5㝧->|kIU -ѐvXhMulIWFdZwyeyvwop9xB9<;7 0ìڿLRs7mKՈuetgYr SXڽ:e^Ɍ~9^{Ba[}re.a˙^]f^_h*ka֪Qa33 7(hDS-baTΩJlyk]]6Zg9~>(HүU:>`gMH;A|V/c7ϝ}z 7:>XF@ [I#T?!s ~q .uM,lNnRFfZy_{g UcKK^L@wCY/ԣo# 8U?gxmeڄI/KJp_y5`f#s Ө[;iu8z!c4$3NV3-\|// \ĸ*M֍Cp'X?~έ:HaaxTw b ~jQjimUB-~v0%io4׆|M;Y'h>c'Δ0J2*R⺾,vǮK}xUU`_+˞oTyutWe:j]R3w_V3[hI_]JcѲZ&E/"\d״Q_ݍgOiayj!U_>WHṮ s$2; Vm#c嬯B.{%3uL'A$c tӃhlXwNCǠ[2M(&dE;嫆~!_?U-nF;j <|.0&S(+g0u ^T-.f)wleKaɼݘ%`gU󊵰Ј!Lq~cLK\rw_Kz wTFl9aJc[˝ e:bp‰2[kɡmA)(aN!o8/Ks ` >N".ν,;b:]4'8J͞ .sǰXb+dRvH`bt~OuщpJqޏcI*0Ov [fku|\(F^$nʆW b`0)We^fdؒ@` Vo57tk/-SP[ϑۅ4:jx0t\ų0YF!l~,hcIƒM] p>C"鶬@Q-$aj| !zkiiX})Dt-H$?u+a0o^a@$mfiΎM\uKWq\gT3G8f㺅zάFcUt'w^b!BTP ?HY&љbYoէAv]hi}b@X1z+u9גYv:o,7m.~׈^lAΐŤP~]_m3J=}]L8.bAE̘/zmMo,= a_} B/ܐQQ)M3.Fշo#mz|x. `T}ZDJX,RhFy!.GRŏޡGey-"s}1W_K~\0 *BkGE1rt(kkZl}i/А7EeP"niz,ꉅVԛG/3Vs\К yGȣɶroN5}oJ㐭37Vrto+5]/^/z:6a.əzOqDd 6Q6ePo  SoL 'vRMf5 A;Pg\g6cvͳЕ)L[Ὑ`S`6 p ۉC" <ׇ+|ʞf- ͙˜!zK^0E@>zRnxa'YMab:2I1.u+P75&|srq/A`s)v`}Mʕ$ OL|R;DڶMgw.XCKvDMV '(-e疇bz?`&{ q'T~5Du^6v4|7Z$o$P?!ʔJJ).q LȵO'PVt^L~[<3 ŝxh@,U/I`($eLd ^ևCY夰EwDh3A??L[Q(#8ݥΗ%*8]tYjàXOb+nII$]# ͚岻]tݧ,(ZgBHy%㨄Ų (]Y`KrIkj zt\֖ I c.s.r?E V[r8i2%Wamp_˵[6vMQ؅b$ݖ$*52 ̙Kkf3%ID*no `f`c#Ejץ+˛32iM_âcI{hE Y&7b=R{Yf4?+LHos_j)kn~L(~ƺ;@3.?)lCs.(斥͗L1gX;w,3yIEs18Rɳ*"̣**`mg'% :}2DQ2Xok$:{켕&YVee$v?TlOqAE,OdRulfN^2ř-3y@#,4i4/ `1ɿh6eYֽ?vw/S|y/bj>g%+yv2>? y2EoԇJ6Za47gcԵ&j0IPYNV-὆)ߛnnp}}dTA&U fHM#,U03 gbe:a-9w_{fVe_jRm~L߶]֮ѤSExmDo6`5R~t7L9V{98sm7f?H#HU&%2^UwB"dž cqV3۩FO\ Cq8Rrc#\.-iXFkm ;SAT"$߈6.iTmAl;]KDt$z:6iIGx"J"et™GwX$ w5 ɽ7jA߄j\4s&/ıLY#S߳ƪs;R^_5Ջ A]QIܛ)ؔb*<#^o㾂ĕ}em(_lGlh/`((3PV($*sI ,QFDH_ÃouhSDx|ha{su)*@ YY-8(5nXsF{-]`拲i63Sv^c= lUTM^4#ѯ2Ig^0HD/$YjJiG|b?)1۲_7וLo]()ZO gKJͪ_!P`@xHYp)D8HJ$';gLUf'U2*%0Bq~VdiM>@ׁ ݯr'>'ȯ"Ôzщ_!~bUQ⧖ʘT _t?LahٲOi? &v$R B,G^ , #V}U|#,\TPF~o6!C"py& r;a07<т]q/6s{8I `JDž)>7'qnxyEt3jxURj1'JX`I4t$S.Bc4I0k%2N0KP!p~(B`ۗ$/ZeI 4,Cyߐk-w0g1EIDo= NN͛ D=vL}5j](IuJ< ﯆1;cA-h/Xu݅`|CPV׽< ~K?U8`ZqQ+;bhymLۣ4ō \0Q;Ϊۿ2 r4H8 cqxX?o.jxF!oL@ɣW EOv'z,<6 伉]鶟WŎPݧ3login($username, $password) ) return $this->error; do_action('xmlrpc_call', 'metaWeblog.editPost'); $cap = ( $publish ) ? 'publish_posts' : 'edit_posts'; $error_message = __( 'Sorry, you are not allowed to publish posts on this site.' ); $post_type = 'post'; $page_template = ''; if ( !empty( $content_struct['post_type'] ) ) { if ( $content_struct['post_type'] == 'page' ) { $cap = ( $publish ) ? 'publish_pages' : 'edit_pages'; $error_message = __( 'Sorry, you are not allowed to publish pages on this site.' ); $post_type = 'page'; if ( !empty( $content_struct['wp_page_template'] ) ) $page_template = $content_struct['wp_page_template']; } elseif ( $content_struct['post_type'] == 'post' ) { // This is the default, no changes needed } else { // No other post_type values are allowed here return new IXR_Error( 401, __( 'Invalid post type.' ) ); } } if ( !current_user_can( $cap ) ) return new IXR_Error( 401, $error_message ); $postdata = wp_get_single_post($post_ID, ARRAY_A); // If there is no post data for the give post id, stop // now and return an error. Other wise a new post will be // created (which was the old behavior). if ( empty($postdata["ID"]) ) return(new IXR_Error(404, __("Invalid post ID."))); $this->escape($postdata); extract($postdata, EXTR_SKIP); // Let WordPress manage slug if none was provided. $post_name = ""; if ( isset($content_struct["wp_slug"]) ) $post_name = $content_struct["wp_slug"]; // Only use a password if one was given. if ( isset($content_struct["wp_password"]) ) $post_password = $content_struct["wp_password"]; // Only set a post parent if one was given. if ( isset($content_struct["wp_page_parent_id"]) ) $post_parent = $content_struct["wp_page_parent_id"]; // Only set the menu_order if it was given. if ( isset($content_struct["wp_page_order"]) ) $menu_order = $content_struct["wp_page_order"]; $post_author = $postdata["post_author"]; // Only set the post_author if one is set. if ( isset($content_struct["wp_author_id"]) && ($user->ID != $content_struct["wp_author_id"]) ) { switch ( $post_type ) { case "post": if ( !current_user_can("edit_others_posts") ) return(new IXR_Error(401, __("You are not allowed to change the post author as this user."))); break; case "page": if ( !current_user_can("edit_others_pages") ) return(new IXR_Error(401, __("You are not allowed to change the page author as this user."))); break; default: return(new IXR_Error(401, __("Invalid post type."))); break; } $post_author = $content_struct["wp_author_id"]; } if ( isset($content_struct["mt_allow_comments"]) ) { if ( !is_numeric($content_struct["mt_allow_comments"]) ) { switch ( $content_struct["mt_allow_comments"] ) { case "closed": $comment_status = "closed"; break; case "open": $comment_status = "open"; break; default: $comment_status = get_option("default_comment_status"); break; } } else { switch ( (int) $content_struct["mt_allow_comments"] ) { case 0: case 2: $comment_status = "closed"; break; case 1: $comment_status = "open"; break; default: $comment_status = get_option("default_comment_status"); break; } } } if ( isset($content_struct["mt_allow_pings"]) ) { if ( !is_numeric($content_struct["mt_allow_pings"]) ) { switch ( $content_struct["mt_allow_pings"] ) { case "closed": $ping_status = "closed"; break; case "open": $ping_status = "open"; break; default: $ping_status = get_option("default_ping_status"); break; } } else { switch ( (int) $content_struct["mt_allow_pings"] ) { case 0: $ping_status = "closed"; break; case 1: $ping_status = "open"; break; default: $ping_status = get_option("default_ping_status"); break; } } } $post_title = $content_struct['title']; $post_content = $content_struct['description']; $catnames = $content_struct['categories']; $post_category = array(); if ( is_array($catnames) ) { foreach ($catnames as $cat) { $post_category[] = get_cat_ID($cat); } } $post_excerpt = $content_struct['mt_excerpt']; $post_more = $content_struct['mt_text_more']; $post_status = $publish ? 'publish' : 'draft'; if ( isset( $content_struct["{$post_type}_status"] ) ) { switch( $content_struct["{$post_type}_status"] ) { case 'draft': case 'private': case 'publish': $post_status = $content_struct["{$post_type}_status"]; break; case 'pending': // Pending is only valid for posts, not pages. if ( $post_type === 'post' ) $post_status = $content_struct["{$post_type}_status"]; break; default: $post_status = $publish ? 'publish' : 'draft'; break; } } $tags_input = $content_struct['mt_keywords']; if ( ('publish' == $post_status) ) { if ( ( 'page' == $post_type ) && !current_user_can('publish_pages') ) return new IXR_Error(401, __('Sorry, you do not have the right to publish this page.')); else if ( !current_user_can('publish_posts') ) return new IXR_Error(401, __('Sorry, you do not have the right to publish this post.')); } if ( $post_more ) $post_content = $post_content . "" . $post_more; $to_ping = $content_struct['mt_tb_ping_urls']; if ( is_array($to_ping) ) $to_ping = implode(' ', $to_ping); // Do some timestamp voodoo if ( !empty( $content_struct['date_created_gmt'] ) ) $dateCreated = str_replace( 'Z', '', $content_struct['date_created_gmt']->getIso() ) . 'Z'; // We know this is supposed to be GMT, so we're going to slap that Z on there by force elseif ( !empty( $content_struct['dateCreated']) ) $dateCreated = $content_struct['dateCreated']->getIso(); if ( !empty( $dateCreated ) ) { $post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); $post_date_gmt = iso8601_to_datetime($dateCreated, GMT); } else { $post_date = $postdata['post_date']; $post_date_gmt = $postdata['post_date_gmt']; } // We've got all the data -- post it: $newpost = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'post_date', 'post_date_gmt', 'to_ping', 'post_name', 'post_password', 'post_parent', 'menu_order', 'post_author', 'tags_input', 'page_template'); $result = wp_update_post($newpost, true); if ( is_wp_error( $result ) ) return new IXR_Error(500, $result->get_error_message()); if ( !$result ) return new IXR_Error(500, __('Sorry, your entry could not be edited. Something wrong happened.')); // Only posts can be sticky if ( $post_type == 'post' && isset( $content_struct['sticky'] ) ) { if ( $content_struct['sticky'] == true ) stick_post( $post_ID ); elseif ( $content_struct['sticky'] == false ) unstick_post( $post_ID ); } if ( isset($content_struct['custom_fields']) ) $this->set_custom_fields($post_ID, $content_struct['custom_fields']); // Handle enclosures $this->add_enclosure_if_new($post_ID, $content_struct['enclosure']); $this->attach_uploads( $ID, $post_content ); logIO('O',"(MW) Edited ! ID: $post_ID"); return true; } /** * Retrieve post. * * @since 1.5.0 * * @param array $args Method parameters. * @return array */ function mw_getPost($args) { $this->escape($args); $post_ID = (int) $args[0]; $username = $args[1]; $password = $args[2]; if ( !$user = $this->login($username, $password) ) return $this->error; if ( !current_user_can( 'edit_post', $post_ID ) ) return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) ); do_action('xmlrpc_call', 'metaWeblog.getPost'); $postdata = wp_get_single_post($post_ID, ARRAY_A); if ($postdata['post_date'] != '') { $post_date = mysql2date('Ymd\TH:i:s', $postdata['post_date'], false); $post_date_gmt = mysql2date('Ymd\TH:i:s', $postdata['post_date_gmt'], false); // For drafts use the GMT version of the post date if ( $postdata['post_status'] == 'draft' ) $post_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $postdata['post_date'] ), 'Ymd\TH:i:s' ); $categories = array(); $catids = wp_get_post_categories($post_ID); foreach($catids as $catid) $categories[] = get_cat_name($catid); $tagnames = array(); $tags = wp_get_post_tags( $post_ID ); if ( !empty( $tags ) ) { foreach ( $tags as $tag ) $tagnames[] = $tag->name; $tagnames = implode( ', ', $tagnames ); } else { $tagnames = ''; } $post = get_extended($postdata['post_content']); $link = post_permalink($postdata['ID']); // Get the author info. $author = get_userdata($postdata['post_author']); $allow_comments = ('open' == $postdata['comment_status']) ? 1 : 0; $allow_pings = ('open' == $postdata['ping_status']) ? 1 : 0; // Consider future posts as published if ( $postdata['post_status'] === 'future' ) $postdata['post_status'] = 'publish'; $sticky = false; if ( is_sticky( $post_ID ) ) $sticky = true; $enclosure = array(); foreach ( (array) get_post_custom($post_ID) as $key => $val) { if ($key == 'enclosure') { foreach ( (array) $val as $enc ) { $encdata = split("\n", $enc); $enclosure['url'] = trim(htmlspecialchars($encdata[0])); $enclosure['length'] = (int) trim($encdata[1]); $enclosure['type'] = trim($encdata[2]); break 2; } } } $resp = array( 'dateCreated' => new IXR_Date($post_date), 'userid' => $postdata['post_author'], 'postid' => $postdata['ID'], 'description' => $post['main'], 'title' => $postdata['post_title'], 'link' => $link, 'permaLink' => $link, // commented out because no other tool seems to use this // 'content' => $entry['post_content'], 'categories' => $categories, 'mt_excerpt' => $postdata['post_excerpt'], 'mt_text_more' => $post['extended'], 'mt_allow_comments' => $allow_comments, 'mt_allow_pings' => $allow_pings, 'mt_keywords' => $tagnames, 'wp_slug' => $postdata['post_name'], 'wp_password' => $postdata['post_password'], 'wp_author_id' => $author->ID, 'wp_author_display_name' => $author->display_name, 'date_created_gmt' => new IXR_Date($post_date_gmt), 'post_status' => $postdata['post_status'], 'custom_fields' => $this->get_custom_fields($post_ID), 'sticky' => $sticky ); if ( !empty($enclosure) ) $resp['enclosure'] = $enclosure; return $resp; } else { return new IXR_Error(404, __('Sorry, no such post.')); } } /** * Retrieve list of recent posts. * * @since 1.5.0 * * @param array $args Method parameters. * @return array */ function mw_getRecentPosts($args) { $this->escape($args); $blog_ID = (int) $args[0]; $username = $args[1]; $password = $args[2]; $num_posts = (int) $args[3]; if ( !$user = $this->login($username, $password) ) return $this->error; do_action('xmlrpc_call', 'metaWeblog.getRecentPosts'); $posts_list = wp_get_recent_posts($num_posts); if ( !$posts_list ) return array( ); foreach ($posts_list as $entry) { if ( !current_user_can( 'edit_post', $entry['ID'] ) ) continue; $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date'], false); $post_date_gmt = mysql2date('Ymd\TH:i:s', $entry['post_date_gmt'], false); // For drafts use the GMT version of the date if ( $entry['post_status'] == 'draft' ) $post_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $entry['post_date'] ), 'Ymd\TH:i:s' ); $categories = array(); $catids = wp_get_post_categories($entry['ID']); foreach( $catids as $catid ) $categories[] = get_cat_name($catid); $tagnames = array(); $tags = wp_get_post_tags( $entry['ID'] ); if ( !empty( $tags ) ) { foreach ( $tags as $tag ) { $tagnames[] = $tag->name; } $tagnames = implode( ', ', $tagnames ); } else { $tagnames = ''; } $post = get_extended($entry['post_content']); $link = post_permalink($entry['ID']); // Get the post author info. $author = get_userdata($entry['post_author']); $allow_comments = ('open' == $entry['comment_status']) ? 1 : 0; $allow_pings = ('open' == $entry['ping_status']) ? 1 : 0; // Consider future posts as published if ( $entry['post_status'] === 'future' ) $entry['post_status'] = 'publish'; $struct[] = array( 'dateCreated' => new IXR_Date($post_date), 'userid' => $entry['post_author'], 'postid' => $entry['ID'], 'description' => $post['main'], 'title' => $entry['post_title'], 'link' => $link, 'permaLink' => $link, // commented out because no other tool seems to use this // 'content' => $entry['post_content'], 'categories' => $categories, 'mt_excerpt' => $entry['post_excerpt'], 'mt_text_more' => $post['extended'], 'mt_allow_comments' => $allow_comments, 'mt_allow_pings' => $allow_pings, 'mt_keywords' => $tagnames, 'wp_slug' => $entry['post_name'], 'wp_password' => $entry['post_password'], 'wp_author_id' => $author->ID, 'wp_author_display_name' => $author->display_name, 'date_created_gmt' => new IXR_Date($post_date_gmt), 'post_status' => $entry['post_status'], 'custom_fields' => $this->get_custom_fields($entry['ID']) ); } $recent_posts = array(); for ( $j=0; $jescape($args); $blog_ID = (int) $args[0]; $username = $args[1]; $password = $args[2]; if ( !$user = $this->login($username, $password) ) return $this->error; if ( !current_user_can( 'edit_posts' ) ) return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this site in order to view categories.' ) ); do_action('xmlrpc_call', 'metaWeblog.getCategories'); $categories_struct = array(); if ( $cats = get_categories(array('get' => 'all')) ) { foreach ( $cats as $cat ) { $struct['categoryId'] = $cat->term_id; $struct['parentId'] = $cat->parent; $struct['description'] = $cat->name; $struct['categoryDescription'] = $cat->description; $struct['categoryName'] = $cat->name; $struct['htmlUrl'] = esc_html(get_category_link($cat->term_id)); $struct['rssUrl'] = esc_html(get_category_feed_link($cat->term_id, 'rss2')); $categories_struct[] = $struct; } } return $categories_struct; } /** * Uploads a file, following your settings. * * Adapted from a patch by Johann Richard. * * @link http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/ * * @since 1.5.0 * * @param array $args Method parameters. * @return array */ function mw_newMediaObject($args) { global $wpdb; $blog_ID = (int) $args[0]; $username = $wpdb->escape($args[1]); $password = $wpdb->escape($args[2]); $data = $args[3]; $name = sanitize_file_name( $data['name'] ); $type = $data['type']; $bits = $data['bits']; logIO('O', '(MW) Received '.strlen($bits).' bytes'); if ( !$user = $this->login($username, $password) ) return $this->error; do_action('xmlrpc_call', 'metaWeblog.newMediaObject'); if ( !current_user_can('upload_files') ) { logIO('O', '(MW) User does not have upload_files capability'); $this->error = new IXR_Error(401, __('You are not allowed to upload files to this site.')); return $this->error; } if ( $upload_err = apply_filters( "pre_upload_error", false ) ) return new IXR_Error(500, $upload_err); if ( !empty($data["overwrite"]) && ($data["overwrite"] == true) ) { // Get postmeta info on the object. $old_file = $wpdb->get_row(" SELECT ID FROM {$wpdb->posts} WHERE post_title = '{$name}' AND post_type = 'attachment' "); // Delete previous file. wp_delete_attachment($old_file->ID); // Make sure the new name is different by pre-pending the // previous post id. $filename = preg_replace("/^wpid\d+-/", "", $name); $name = "wpid{$old_file->ID}-{$filename}"; } $upload = wp_upload_bits($name, $type, $bits); if ( ! empty($upload['error']) ) { $errorString = sprintf(__('Could not write file %1$s (%2$s)'), $name, $upload['error']); logIO('O', '(MW) ' . $errorString); return new IXR_Error(500, $errorString); } // Construct the attachment array // attach to post_id 0 $post_id = 0; $attachment = array( 'post_title' => $name, 'post_content' => '', 'post_type' => 'attachment', 'post_parent' => $post_id, 'post_mime_type' => $type, 'guid' => $upload[ 'url' ] ); // Save the data $id = wp_insert_attachment( $attachment, $upload[ 'file' ], $post_id ); wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) ); return apply_filters( 'wp_handle_upload', array( 'file' => $name, 'url' => $upload[ 'url' ], 'type' => $type ), 'upload' ); } /* MovableType API functions * specs on http://www.movabletype.org/docs/mtmanual_programmatic.html */ /** * Retrieve the post titles of recent posts. * * @since 1.5.0 * * @param array $args Method parameters. * @return array */ function mt_getRecentPostTitles($args) { $this->escape($args); $blog_ID = (int) $args[0]; $username = $args[1]; $password = $args[2]; $num_posts = (int) $args[3]; if ( !$user = $this->login($username, $password) ) return $this->error; do_action('xmlrpc_call', 'mt.getRecentPostTitles'); $posts_list = wp_get_recent_posts($num_posts); if ( !$posts_list ) { $this->error = new IXR_Error(500, __('Either there are no posts, or something went wrong.')); return $this->error; } foreach ($posts_list as $entry) { if ( !current_user_can( 'edit_post', $entry['ID'] ) ) continue; $post_date = mysql2date('Ymd\TH:i:s', $entry['post_date'], false); $post_date_gmt = mysql2date('Ymd\TH:i:s', $entry['post_date_gmt'], false); // For drafts use the GMT version of the date if ( $entry['post_status'] == 'draft' ) $post_date_gmt = get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $entry['post_date'] ), 'Ymd\TH:i:s' ); $struct[] = array( 'dateCreated' => new IXR_Date($post_date), 'userid' => $entry['post_author'], 'postid' => $entry['ID'], 'title' => $entry['post_title'], 'date_created_gmt' => new IXR_Date($post_date_gmt) ); } $recent_posts = array(); for ( $j=0; $jescape($args); $blog_ID = (int) $args[0]; $username = $args[1]; $password = $args[2]; if ( !$user = $this->login($username, $password) ) return $this->error; if ( !current_user_can( 'edit_posts' ) ) return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this site in order to view categories.' ) ); do_action('xmlrpc_call', 'mt.getCategoryList'); $categories_struct = array(); if ( $cats = get_categories(array('hide_empty' => 0, 'hierarchical' => 0)) ) { foreach ( $cats as $cat ) { $struct['categoryId'] = $cat->term_id; $struct['categoryName'] = $cat->name; $categories_struct[] = $struct; } } return $categories_struct; } /** * Retrieve post categories. * * @since 1.5.0 * * @param array $args Method parameters. * @return array */ function mt_getPostCategories($args) { $this->escape($args); $post_ID = (int) $args[0]; $username = $args[1]; $password = $args[2]; if ( !$user = $this->login($username, $password) ) return $this->error; if ( !current_user_can( 'edit_post', $post_ID ) ) return new IXR_Error( 401, __( 'Sorry, you can not edit this post.' ) ); do_action('xmlrpc_call', 'mt.getPostCategories'); $categories = array(); $catids = wp_get_post_categories(intval($post_ID)); // first listed category will be the primary category $isPrimary = true; foreach ( $catids as $catid ) { $categories[] = array( 'categoryName' => get_cat_name($catid), 'categoryId' => (string) $catid, 'isPrimary' => $isPrimary ); $isPrimary = false; } return $categories; } /** * Sets categories for a post. * * @since 1.5.0 * * @param array $args Method parameters. * @return bool True on success. */ function mt_setPostCategories($args) { $this->escape($args); $post_ID = (int) $args[0]; $username = $args[1]; $password = $args[2]; $categories = $args[3]; if ( !$user = $this->login($username, $password) ) return $this->error; do_action('xmlrpc_call', 'mt.setPostCategories'); if ( !current_user_can('edit_post', $post_ID) ) return new IXR_Error(401, __('Sorry, you cannot edit this post.')); foreach ( $categories as $cat ) { $catids[] = $cat['categoryId']; } wp_set_post_categories($post_ID, $catids); return true; } /** * Retrieve an array of methods supported by this server. * * @since 1.5.0 * * @param array $args Method parameters. * @return array */ function mt_supportedMethods($args) { do_action('xmlrpc_call', 'mt.supportedMethods'); $supported_methods = array(); foreach ( $this->methods as $key => $value ) { $supported_methods[] = $key; } return $supported_methods; } /** * Retrieve an empty array because we don't support per-post text filters. * * @since 1.5.0 * * @param array $args Method parameters. */ function mt_supportedTextFilters($args) { do_action('xmlrpc_call', 'mt.supportedTextFilters'); return apply_filters('xmlrpc_text_filters', array()); } /** * Retrieve trackbacks sent to a given post. * * @since 1.5.0 * * @param array $args Method parameters. * @return mixed */ function mt_getTrackbackPings($args) { global $wpdb; $post_ID = intval($args); do_action('xmlrpc_call', 'mt.getTrackbackPings'); $actual_post = wp_get_single_post($post_ID, ARRAY_A); if ( !$actual_post ) return new IXR_Error(404, __('Sorry, no such post.')); $comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_ID) ); if ( !$comments ) return array(); $trackback_pings = array(); foreach ( $comments as $comment ) { if ( 'trackback' == $comment->comment_type ) { $content = $comment->comment_content; $title = substr($content, 8, (strpos($content, '') - 8)); $trackback_pings[] = array( 'pingTitle' => $title, 'pingURL' => $comment->comment_author_url, 'pingIP' => $comment->comment_author_IP ); } } return $trackback_pings; } /** * Sets a post's publish status to 'publish'. * * @since 1.5.0 * * @param array $args Method parameters. * @return int */ function mt_publishPost($args) { $this->escape($args); $post_ID = (int) $args[0]; $username = $args[1]; $password = $args[2]; if ( !$user = $this->login($username, $password) ) return $this->error; do_action('xmlrpc_call', 'mt.publishPost'); if ( !current_user_can('edit_post', $post_ID) ) return new IXR_Error(401, __('Sorry, you cannot edit this post.')); $postdata = wp_get_single_post($post_ID,ARRAY_A); $postdata['post_status'] = 'publish'; // retain old cats $cats = wp_get_post_categories($post_ID); $postdata['post_category'] = $cats; $this->escape($postdata); $result = wp_update_post($postdata); return $result; } /* PingBack functions * specs on www.hixie.ch/specs/pingback/pingback */ /** * Retrieves a pingback and registers it. * * @since 1.5.0 * * @param array $args Method parameters. * @return array */ function pingback_ping($args) { global $wpdb; do_action('xmlrpc_call', 'pingback.ping'); $this->escape($args); $pagelinkedfrom = $args[0]; $pagelinkedto = $args[1]; $title = ''; $pagelinkedfrom = str_replace('&', '&', $pagelinkedfrom); $pagelinkedto = str_replace('&', '&', $pagelinkedto); $pagelinkedto = str_replace('&', '&', $pagelinkedto); // Check if the page linked to is in our site $pos1 = strpos($pagelinkedto, str_replace(array('http://www.','http://','https://www.','https://'), '', get_option('home'))); if ( !$pos1 ) return new IXR_Error(0, __('Is there no link to us?')); // let's find which post is linked to // FIXME: does url_to_postid() cover all these cases already? // if so, then let's use it and drop the old code. $urltest = parse_url($pagelinkedto); if ( $post_ID = url_to_postid($pagelinkedto) ) { $way = 'url_to_postid()'; } elseif ( preg_match('#p/[0-9]{1,}#', $urltest['path'], $match) ) { // the path defines the post_ID (archives/p/XXXX) $blah = explode('/', $match[0]); $post_ID = (int) $blah[1]; $way = 'from the path'; } elseif ( preg_match('#p=[0-9]{1,}#', $urltest['query'], $match) ) { // the querystring defines the post_ID (?p=XXXX) $blah = explode('=', $match[0]); $post_ID = (int) $blah[1]; $way = 'from the querystring'; } elseif ( isset($urltest['fragment']) ) { // an #anchor is there, it's either... if ( intval($urltest['fragment']) ) { // ...an integer #XXXX (simpliest case) $post_ID = (int) $urltest['fragment']; $way = 'from the fragment (numeric)'; } elseif ( preg_match('/post-[0-9]+/',$urltest['fragment']) ) { // ...a post id in the form 'post-###' $post_ID = preg_replace('/[^0-9]+/', '', $urltest['fragment']); $way = 'from the fragment (post-###)'; } elseif ( is_string($urltest['fragment']) ) { // ...or a string #title, a little more complicated $title = preg_replace('/[^a-z0-9]/i', '.', $urltest['fragment']); $sql = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_title RLIKE %s", $title); if (! ($post_ID = $wpdb->get_var($sql)) ) { // returning unknown error '0' is better than die()ing return new IXR_Error(0, ''); } $way = 'from the fragment (title)'; } } else { // TODO: Attempt to extract a post ID from the given URL return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn’t exist, or it is not a pingback-enabled resource.')); } $post_ID = (int) $post_ID; logIO("O","(PB) URL='$pagelinkedto' ID='$post_ID' Found='$way'"); $post = get_post($post_ID); if ( !$post ) // Post_ID not found return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn’t exist, or it is not a pingback-enabled resource.')); if ( $post_ID == url_to_postid($pagelinkedfrom) ) return new IXR_Error(0, __('The source URL and the target URL cannot both point to the same resource.')); // Check if pings are on if ( !pings_open($post) ) return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn’t exist, or it is not a pingback-enabled resource.')); // Let's check that the remote site didn't already pingback this entry if ( $wpdb->get_results( $wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_author_url = %s", $post_ID, $pagelinkedfrom) ) ) return new IXR_Error( 48, __( 'The pingback has already been registered.' ) ); // very stupid, but gives time to the 'from' server to publish ! sleep(1); // Let's check the remote site $linea = wp_remote_fopen( $pagelinkedfrom ); if ( !$linea ) return new IXR_Error(16, __('The source URL does not exist.')); $linea = apply_filters('pre_remote_source', $linea, $pagelinkedto); // Work around bug in strip_tags(): $linea = str_replace(']*>/", "\n\n", $linea ); preg_match('|([^<]*?)|is', $linea, $matchtitle); $title = $matchtitle[1]; if ( empty( $title ) ) return new IXR_Error(32, __('We cannot find a title on that page.')); $linea = strip_tags( $linea, '' ); // just keep the tag we need $p = explode( "\n\n", $linea ); $preg_target = preg_quote($pagelinkedto, '|'); foreach ( $p as $para ) { if ( strpos($para, $pagelinkedto) !== false ) { // it exists, but is it a link? preg_match("|]+?".$preg_target."[^>]*>([^>]+?)|", $para, $context); // If the URL isn't in a link context, keep looking if ( empty($context) ) continue; // We're going to use this fake tag to mark the context in a bit // the marker is needed in case the link text appears more than once in the paragraph $excerpt = preg_replace('|\|', '', $para); // prevent really long link text if ( strlen($context[1]) > 100 ) $context[1] = substr($context[1], 0, 100) . '...'; $marker = ''.$context[1].''; // set up our marker $excerpt= str_replace($context[0], $marker, $excerpt); // swap out the link for our marker $excerpt = strip_tags($excerpt, ''); // strip all tags but our context marker $excerpt = trim($excerpt); $preg_marker = preg_quote($marker, '|'); $excerpt = preg_replace("|.*?\s(.{0,100}$preg_marker.{0,100})\s.*|s", '$1', $excerpt); $excerpt = strip_tags($excerpt); // YES, again, to remove the marker wrapper break; } } if ( empty($context) ) // Link to target not found return new IXR_Error(17, __('The source URL does not contain a link to the target URL, and so cannot be used as a source.')); $pagelinkedfrom = str_replace('&', '&', $pagelinkedfrom); $context = '[...] ' . esc_html( $excerpt ) . ' [...]'; $pagelinkedfrom = $wpdb->escape( $pagelinkedfrom ); $comment_post_ID = (int) $post_ID; $comment_author = $title; $this->escape($comment_author); $comment_author_url = $pagelinkedfrom; $comment_content = $context; $this->escape($comment_content); $comment_type = 'pingback'; $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_url', 'comment_content', 'comment_type'); $comment_ID = wp_new_comment($commentdata); do_action('pingback_post', $comment_ID); return sprintf(__('Pingback from %1$s to %2$s registered. Keep the web talking! :-)'), $pagelinkedfrom, $pagelinkedto); } /** * Retrieve array of URLs that pingbacked the given URL. * * Specs on http://www.aquarionics.com/misc/archives/blogite/0198.html * * @since 1.5.0 * * @param array $args Method parameters. * @return array */ function pingback_extensions_getPingbacks($args) { global $wpdb; do_action('xmlrpc_call', 'pingback.extensions.getPingbacks'); $this->escape($args); $url = $args; $post_ID = url_to_postid($url); if ( !$post_ID ) { // We aren't sure that the resource is available and/or pingback enabled return new IXR_Error(33, __('The specified target URL cannot be used as a target. It either doesn’t exist, or it is not a pingback-enabled resource.')); } $actual_post = wp_get_single_post($post_ID, ARRAY_A); if ( !$actual_post ) { // No such post = resource not found return new IXR_Error(32, __('The specified target URL does not exist.')); } $comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_ID) ); if ( !$comments ) return array(); $pingbacks = array(); foreach ( $comments as $comment ) { if ( 'pingback' == $comment->comment_type ) $pingbacks[] = $comment->comment_author_url; } return $pingbacks; } } $wp_xmlrpc_server = new wp_xmlrpc_server(); $wp_xmlrpc_server->serve_request(); ?>