JFIFXX    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222"4 ,PG"Z_4˷kjزZ,F+_z,© zh6٨icfu#ډb_N?wQ5-~I8TK<5oIv-k_U_~bMdӜUHh?]EwQk{_}qFW7HTՑYF?_'ϔ_Ջt=||I 6έ"D/[k9Y8ds|\Ҿp6Ҵ].6znopM[mei$[soᘨ˸ nɜG-ĨUycP3.DBli;hjx7Z^NhN3u{:jx힞#M&jL P@_ P&o89@Sz6t7#Oߋ s}YfTlmrZ)'Nk۞pw\Tȯ?8`Oi{wﭹW[r Q4F׊3m&L=h3z~#\l :F,j@ ʱwQT8"kJO6֚l}R>ډK]y&p}b;N1mr$|7>e@BTM*-iHgD) Em|ؘbҗaҾt4oG*oCNrPQ@z,|?W[0:n,jWiEW$~/hp\?{(0+Y8rΟ+>S-SVN;}s?. w9˟<Mq4Wv'{)01mBVW[8/< %wT^5b)iM pgN&ݝVO~qu9 !J27$O-! :%H ـyΠM=t{!S oK8txA& j0 vF Y|y ~6@c1vOpIg4lODL Rcj_uX63?nkWyf;^*B @~a`Eu+6L.ü>}y}_O6͐:YrGXkGl^w~㒶syIu! W XN7BVO!X2wvGRfT#t/?%8^WaTGcLMI(J1~8?aT ]ASE(*E} 2#I/׍qz^t̔bYz4xt){ OH+(EA&NXTo"XC')}Jzp ~5}^+6wcQ|LpdH}(.|kc4^"Z?ȕ a<L!039C EuCFEwç ;n?*oB8bʝ'#RqfM}7]s2tcS{\icTx;\7KPʇ Z O-~c>"?PEO8@8GQgaՎ󁶠䧘_%#r>1zaebqcPѵn#L =׀t L7`VA{C:ge@w1 Xp3c3ġpM"'-@n4fGB3DJ8[JoߐgK)ƛ$ 83+ 6ʻ SkI*KZlT _`?KQKdB`s}>`*>,*@JdoF*弝O}ks]yߘc1GV<=776qPTtXԀ!9*44Tހ3XΛex46YD  BdemDa\_l,G/֌7Y](xTt^%GE4}bTڹ;Y)BQu>J/J ⮶.XԄjݳ+Ed r5_D1 o Bx΢#<W8R6@gM. drD>(otU@x=~v2 ӣdoBd3eO6㣷ݜ66YQz`S{\P~z m5{J/L1xO\ZFu>ck#&:`$ai>2ΔloF[hlEܺΠk:)` $[69kOw\|8}ބ:񶐕IA1/=2[,!.}gN#ub ~݊}34qdELc$"[qU硬g^%B zrpJru%v\h1Yne`ǥ:gpQM~^Xi `S:V29.PV?Bk AEvw%_9CQwKekPؠ\;Io d{ ߞoc1eP\ `E=@KIRYK2NPlLɀ)&eB+ь( JTx_?EZ }@ 6U뙢طzdWIn` D噥[uV"G&Ú2g}&m?ċ"Om# {ON"SXNeysQ@FnVgdX~nj]J58up~.`r\O,ư0oS _Ml4kv\JSdxSW<AeIX$Iw:Sy›R9Q[,5;@]%u@ *rolbI  +%m:͇ZVủθau,RW33 dJeTYE.Mϧ-oj3+yy^cVO9NV\nd1 !͕_)av;թMlWR1)ElP;yوÏu 3k5Pr6<⒲l!˞*u־n!l:UNW %Chx8vL'X@*)̮ˍ D-M+JUkvK+x8cY?Ԡ~3mo|u@[XeYC\Kpx8oCC&N~3-H MXsu<`~"WL$8ξ3a)|:@m\^`@ҷ)5p+6p%i)P Mngc#0AruzRL+xSS?ʮ}()#tmˇ!0}}y$6Lt;$ʳ{^6{v6ķܰgVcnn ~zx«,2u?cE+ȘH؎%Za)X>uWTzNyosFQƤ$*&LLXL)1" LeOɟ9=:tZcŽY?ӭVwv~,Yrۗ|yGaFC.+ v1fήJ]STBn5sW}y$~z'c 8  ,! pVNSNNqy8z˱A4*'2n<s^ǧ˭PJޮɏUGLJ*#i}K%,)[z21z ?Nin1?TIR#m-1lA`fT5+ܐcq՝ʐ,3f2Uեmab#ŠdQy>\)SLYw#.ʑf ,"+w~N'cO3FN<)j&,- љ֊_zSTǦw>?nU仆Ve0$CdrP m׈eXmVu L.bֹ [Դaզ*\y8Է:Ez\0KqC b̘cөQ=0YsNS.3.Oo:#v7[#߫ 5܎LEr49nCOWlG^0k%;YߝZǓ:S#|}y,/kLd TA(AI$+I3;Y*Z}|ӧOdv..#:nf>>ȶITX 8y"dR|)0=n46ⲑ+ra ~]R̲c?6(q;5% |uj~z8R=XIV=|{vGj\gcqz؋%Mߍ1y#@f^^>N#x#۹6Y~?dfPO{P4Vu1E1J *|%JN`eWuzk M6q t[ gGvWIGu_ft5j"Y:Tɐ*; e54q$C2d} _SL#mYpO.C;cHi#֩%+) ӍƲVSYźg |tj38r|V1#;.SQA[S#`n+$$I P\[@s(EDzP])8G#0B[ىXIIq<9~[Z멜Z⊔IWU&A>P~#dp]9 "cP Md?٥Ifتuk/F9c*9Ǎ:ØFzn*@|Iށ9N3{'['ͬҲ4#}!V Fu,,mTIkv C7vB6kT91*l '~ƞFlU'M ][ΩũJ_{iIn$L jOdxkza۪#EClx˘oVɞljr)/,߬hL#^Lф,íMƁe̩NBLiLq}(q6IçJ$WE$:=#(KBzђ xlx?>Պ+>W,Ly!_DŌlQ![ SJ1ƐY}b,+Loxɓ)=yoh@꥟/Iѭ=Py9 ۍYӘe+pJnϱ?V\SO%(t =?MR[Șd/ nlB7j !;ӥ/[-A>dNsLj ,ɪv=1c.SQO3UƀܽE̻9GϷD7(}Ävӌ\y_0[w <΍>a_[0+LF.޺f>oNTq;y\bՃyjH<|q-eɏ_?_9+PHp$[uxK wMwNی'$Y2=qKBP~Yul:[<F12O5=d]Ysw:ϮEj,_QXz`H1,#II dwrP˂@ZJVy$\y{}^~[:NߌUOdؾe${p>G3cĖlʌ ת[`ϱ-WdgIig2 }s ؤ(%#sS@~3XnRG~\jc3vӍLM[JBTs3}jNʖW;7ç?=XF=-=qߚ#='c7ڑWI(O+=:uxqe2zi+kuGR0&eniT^J~\jyp'dtGsO39* b#Ɋ p[BwsT>d4ۧsnvnU_~,vƜJ1s QIz)(lv8MU=;56Gs#KMP=LvyGd}VwWBF'à ?MHUg2 !p7Qjڴ=ju JnA suMeƆҔ!)'8Ϣٔޝ(Vpצ֖d=ICJǠ{qkԭ߸i@Ku|p=..*+xz[Aqġ#s2aƊRR)*HRsi~a &fMP-KL@ZXy'x{}Zm+:)) IJ-iu ܒH'L(7yGӜq j 6ߌg1go,kرtY?W,pefOQS!K۟cҒA|սj>=⬒˧L[ ߿2JaB~Ru:Q] 0H~]7ƼI(}cq 'ήETq?fabӥvr )o-Q_'ᴎoK;Vo%~OK *bf:-ťIR`B5!RB@ï u ̯e\_U_ gES3QTaxU<~c?*#]MW,[8Oax]1bC|踤Plw5V%){t<d50iXSUm:Z┵i"1^B-PhJ&)O*DcWvM)}Pܗ-q\mmζZ-l@}aE6F@&Sg@ݚM ȹ 4#p\HdYDoH"\..RBHz_/5˘6KhJRPmƶim3,#ccoqa)*PtRmk7xDE\Y閣_X<~)c[[BP6YqS0%_;Àv~| VS؇ 'O0F0\U-d@7SJ*z3nyPOm~P3|Yʉr#CSN@ ƮRN)r"C:: #qbY. 6[2K2uǦHYRQMV G$Q+.>nNHq^ qmMVD+-#*U̒ p욳u:IBmPV@Or[b= 1UE_NmyKbNOU}the`|6֮P>\2PVIDiPO;9rmAHGWS]J*_G+kP2KaZH'KxWMZ%OYDRc+o?qGhmdSoh\D|:WUAQc yTq~^H/#pCZTI1ӏT4"ČZ}`w#*,ʹ 0i課Om*da^gJ݅{le9uF#Tֲ̲ٞC"qߍ ոޑo#XZTp@ o8(jdxw],f`~|,s^f1t|m򸄭/ctr5s79Q4H1꠲BB@l9@C+wpxu£Yc9?`@#omHs2)=2.ljg9$YS%*LRY7Z,*=䷘$armoϰUW.|rufIGwtZwo~5 YյhO+=8fF)W7L9lM̘·Y֘YLf큹pRF99.A "wz=E\Z'a 2Ǚ#;'}G*l^"q+2FQ hjkŦ${ޮ-T٭cf|3#~RJt$b(R(rdx >U b&9,>%E\ Άe$'q't*אެb-|dSBOO$R+H)܎K1m`;J2Y~9Og8=vqD`K[F)k[1m޼cn]skz$@)!I x՝"v9=ZA=`Ɠi :E)`7vI}dYI_ o:obo 3Q&D&2= Ά;>hy.*ⅥSӬ+q&j|UƧ}J0WW< ۋS)jQRjƯrN)Gű4Ѷ(S)Ǣ8iW52No˓ ۍ%5brOnL;n\G=^UdI8$&h'+(cȁ߫klS^cƗjԌEꭔgFȒ@}O*;evWVYJ\]X'5ղkFb 6Ro՜mi Ni>J?lPmU}>_Z&KKqrIDՉ~q3fL:Se>E-G{L6pe,8QIhaXaUA'ʂs+טIjP-y8ۈZ?J$WP Rs]|l(ԓsƊio(S0Y 8T97.WiLc~dxcE|2!XKƘਫ਼$((6~|d9u+qd^389Y6L.I?iIq9)O/뚅OXXVZF[یgQLK1RҖr@v#XlFНyS87kF!AsM^rkpjPDyS$Nqnxҍ!Uf!ehi2m`YI9r6 TFC}/y^Η5d'9A-J>{_l+`A['յϛ#w:݅%X}&PStQ"-\縵/$ƗhXb*yBS;Wջ_mcvt?2}1;qSdd~u:2k52R~z+|HE!)Ǟl7`0<,2*Hl-x^'_TVgZA'j ^2ΪN7t?w x1fIzC-ȖK^q;-WDvT78Z hK(P:Q- 8nZ܃e貾<1YT<,"6{/ ?͟|1:#gW>$dJdB=jf[%rE^il:BxSּ1հ,=*7 fcG#q eh?27,!7x6nLC4x},GeǝtC.vS F43zz\;QYC,6~;RYS/6|25vTimlv& nRh^ejRLGf? ۉҬܦƩ|Ȱ>3!viʯ>vオX3e_1zKȗ\qHS,EW[㺨uch⍸O}a>q6n6N6qN ! 1AQaq0@"2BRb#Pr3C`Scst$4D%Td ?Na3mCwxAmqmm$4n淿t'C"wzU=D\R+wp+YT&պ@ƃ3ޯ?AﶂaŘ@-Q=9Dռѻ@MVP܅G5fY6# ?0UQ,IX(6ڵ[DIMNލc&υj\XR|,4 jThAe^db#$]wOӪ1y%LYm뭛CUƃߜ}Cy1XνmF8jI]HۺиE@Ii;r8ӭVFՇ| &?3|xBMuSGe=Ӕ#BE5GY!z_eqр/W>|-Ci߇t1ޯќdR3ug=0 5[?#͏qcfH{ ?u=??ǯ}ZzhmΔBFTWPxs}G93 )gGR<>r h$'nchPBjJҧH -N1N?~}-q!=_2hcMlvY%UE@|vM2.Y[|y"EïKZF,ɯ?,q?vM 80jx";9vk+ ֧ ȺU?%vcVmA6Qg^MA}3nl QRNl8kkn'(M7m9وq%ޟ*h$Zk"$9: ?U8Sl,,|ɒxH(ѷGn/Q4PG%Ա8N! &7;eKM749R/%lc>x;>C:th?aKXbheᜋ^$Iհ hr7%F$EFdt5+(M6tÜUU|zW=aTsTgdqPQb'm1{|YXNb P~F^F:k6"j! Ir`1&-$Bevk:y#ywI0x=D4tUPZHڠ底taP6b>xaQ# WeFŮNjpJ* mQN*I-*ȩFg3 5Vʊɮa5FO@{NX?H]31Ri_uѕ 0 F~:60p͈SqX#a5>`o&+<2D: ڝ$nP*)N|yEjF5ټeihyZ >kbHavh-#!Po=@k̆IEN@}Ll?jO߭ʞQ|A07xwt!xfI2?Z<ץTcUj]陎Ltl }5ϓ$,Omˊ;@OjEj(ا,LXLOЦ90O .anA7j4 W_ٓzWjcBy՗+EM)dNg6y1_xp$Lv:9"zpʙ$^JԼ*ϭo=xLj6Ju82AH3$ٕ@=Vv]'qEz;I˼)=ɯx /W(Vp$ mu񶤑OqˎTr㠚xsrGCbypG1ߠw e8$⿄/M{*}W]˷.CK\ުx/$WPwr |i&}{X >$-l?-zglΆ(FhvS*b߲ڡn,|)mrH[a3ר[13o_U3TC$(=)0kgP u^=4 WYCҸ:vQרXàtkm,t*^,}D* "(I9R>``[~Q]#afi6l86:,ssN6j"A4IuQ6E,GnHzSHOuk5$I4ؤQ9@CwpBGv[]uOv0I4\yQѸ~>Z8Taqޣ;za/SI:ܫ_|>=Z8:SUIJ"IY8%b8H:QO6;7ISJҌAά3>cE+&jf$eC+z;V rʺmyeaQf&6ND.:NTvm<- uǝ\MvZYNNT-A>jr!SnO 13Ns%3D@`ܟ 1^c< aɽ̲Xë#w|ycW=9I*H8p^(4՗karOcWtO\ƍR8'KIQ?5>[}yUײ -h=% qThG2)"ו3]!kB*pFDlA,eEiHfPs5H:Փ~H0DتDIhF3c2E9H5zԑʚiX=:mxghd(v׊9iSOd@0ڽ:p5h-t&Xqӕ,ie|7A2O%PEhtjY1wЃ!  ࢽMy7\a@ţJ 4ȻF@o̒?4wx)]P~u57X 9^ܩU;Iꭆ 5 eK27({|Y׎ V\"Z1 Z}(Ǝ"1S_vE30>p; ΝD%xW?W?vo^Vidr[/&>~`9Why;R ;;ɮT?r$g1KACcKl:'3 cﳯ*"t8~l)m+U,z`(>yJ?h>]vЍG*{`;y]IT ;cNUfo¾h/$|NS1S"HVT4uhǜ]v;5͠x'C\SBplh}N ABx%ޭl/Twʽ]D=Kžr㻠l4SO?=k M: cCa#ha)ѐxcsgPiG{+xQI= zԫ+ 8"kñj=|c yCF/*9жh{ ?4o kmQNx;Y4膚aw?6>e]Qr:g,i"ԩA*M7qB?ӕFhV25r[7 Y }LR}*sg+xr2U=*'WSZDW]WǞ<叓{$9Ou4y90-1'*D`c^o?(9uݐ'PI& fJݮ:wSjfP1F:X H9dԯ˝[_54 }*;@ܨ ðynT?ןd#4rGͨH1|-#MrS3G3).᧏3vz֑r$G"`j 1tx0<ƆWh6y6,œGagAyb)hDß_mü gG;evݝnQ C-*oyaMI><]obD":GA-\%LT8c)+y76oQ#*{(F⽕y=rW\p۩cA^e6KʐcVf5$'->ՉN"F"UQ@fGb~#&M=8טJNu9D[̤so~ G9TtW^g5y$bY'سǴ=U-2 #MCt(i lj@Q 5̣i*OsxKf}\M{EV{υƇ);HIfeLȣr2>WIȂ6ik 5YOxȺ>Yf5'|H+98pjn.OyjY~iw'l;s2Y:'lgꥴ)o#'SaaKZ m}`169n"xI *+ }FP"l45'ZgE8?[X7(.Q-*ތL@̲v.5[=t\+CNܛ,gSQnH}*FG16&:t4ُ"Ạ$b |#rsaT ]ӽDP7ո0y)e$ٕvIh'QEAm*HRI=: 4牢) %_iNݧl] NtGHL ɱg<1V,J~ٹ"KQ 9HS9?@kr;we݁]I!{ @G["`J:n]{cAEVʆ#U96j#Ym\qe4hB7Cdv\MNgmAyQL4uLjj9#44tl^}LnR!t±]rh6ٍ>yҏNfU  Fm@8}/ujb9he:AyծwGpΧh5l}3p468)Udc;Us/֔YX1O2uqs`hwgr~{ RmhN؎*q 42*th>#E#HvOq}6e\,Wk#Xb>p}դ3T5†6[@Py*n|'f֧>lư΂̺SU'*qp_SM 'c6m ySʨ;MrƋmKxo,GmPAG:iw9}M(^V$ǒѽ9| aJSQarB;}ٻ֢2%Uc#gNaݕ'v[OY'3L3;,p]@S{lsX'cjwk'a.}}& dP*bK=ɍ!;3ngΊUߴmt'*{,=SzfD Ako~Gaoq_mi}#mPXhύmxǍ΂巿zfQc|kc?WY$_Lvl߶c`?ljݲˏ!V6UЂ(A4y)HpZ_x>eR$/`^'3qˏ-&Q=?CFVR DfV9{8gnh(P"6[D< E~0<@`G6Hгcc cK.5DdB`?XQ2ٿyqo&+1^ DW0ꊩG#QnL3c/x 11[yxპCWCcUĨ80me4.{muI=f0QRls9f9~fǨa"@8ȁQ#cicG$Gr/$W(WV"m7[mAmboD j۳ l^kh׽ # iXnveTka^Y4BNĕ0 !01@Q"2AaPq3BR?@4QT3,㺠W[=JKϞ2r^7vc:9 EߴwS#dIxu:Hp9E! V 2;73|F9Y*ʬFDu&y؟^EAA(ɩ^GV:ݜDy`Jr29ܾ㝉[E;FzxYGUeYC v-txIsםĘqEb+P\ :>iC';k|zرny]#ǿbQw(r|ӹs[D2v-%@;8<a[\o[ϧwI!*0krs)[J9^ʜp1) "/_>o<1AEy^C`x1'ܣnps`lfQ):lb>MejH^?kl3(z:1ŠK&?Q~{ٺhy/[V|6}KbXmn[-75q94dmc^h X5G-}دBޟ |rtMV+]c?-#ڛ^ǂ}LkrOu>-Dry D?:ޞUǜ7V?瓮"#rչģVR;n/_ ؉vݶe5db9/O009G5nWJpA*r9>1.[tsFnQ V 77R]ɫ8_0<՜IFu(v4Fk3E)N:yڮeP`1}$WSJSQNjٺ޵#lј(5=5lǏmoWv-1v,Wmn߀$x_DȬ0¤#QR[Vkzmw"9ZG7'[=Qj8R?zf\a=OU*oBA|G254 p.w7  &ξxGHp B%$gtЏ򤵍zHNuЯ-'40;_3 !01"@AQa2Pq#3BR?ʩcaen^8F<7;EA{EÖ1U/#d1an.1ě0ʾRh|RAo3m3 % 28Q yφHTo7lW>#i`qca m,B-j݋'mR1Ήt>Vps0IbIC.1Rea]H64B>o]($Bma!=?B KǾ+Ծ"nK*+[T#{EJSQs5:U\wĐf3܆&)IԆwE TlrTf6Q|Rh:[K zc֧GC%\_a84HcObiؖV7H )*ģK~Xhչ04?0 E<}3#u? |gS6ꊤ|I#Hڛ աwX97Ŀ%SLy6č|Fa 8b$sקhb9RAu7˨pČ_\*w묦F 4D~f|("mNKiS>$d7SlA/²SL|6N}S˯g]6; #. 403WebShell
403Webshell
Server IP : 51.79.149.130  /  Your IP : 216.73.216.210
Web Server : LiteSpeed
System : Linux linux.firevps.net 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64
User : digit4868 ( 1088)
PHP Version : 8.2.30
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /tmp/wsgi-lsapi-2.1/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /tmp/wsgi-lsapi-2.1/wsgi.c
/*-
 * Copyright (c) 2006 Allan Saddi <allan@saddi.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
 *
 * $Id$
 */

#include <Python.h>
#include <locale.h>
#include <wchar.h>

#include <assert.h>
#include <ctype.h>

#include "wsgi-int.h"
#include "lsapilib.h"

#include "interp.h"

const char *wsgiPyVersion = PY_VERSION;
PyObject *wsgiStderr;
const char *wsgiScriptName = "";
int wsgiScriptNameLen = 0;

static PyThreadState *_main;

#define LOG_FLAG   (LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_FLAG_ERROR|LSAPI_LOG_PID)
#define LOG_ERR(...)   LSAPI_Log(LOG_FLAG, __VA_ARGS__)


/* Assumes c is a valid hex digit */
static inline int toxdigit(int c)
{
    if (c >= '0' && c <= '9')
        return c - '0';
    else if (c >= 'A' && c <= 'F')
        return c - 'A' + 10;
    else if (c >= 'a' && c <= 'f')
        return c - 'a' + 10;
    return -1;
}


/* Unquote an escaped path */
const char *wsgiUnquote(const char *s)
{
    int len = strlen(s);
    char *result, *t;

    if ((result = PyMem_Malloc(len + 1)) == NULL)
        return NULL;

    t = result;
    while (*s)
    {
        if (*s == '%')
        {
            if (s[1] && s[2] && isxdigit(s[1]) && isxdigit(s[2]))
            {
                * (t++) = (toxdigit(s[1]) << 4) | toxdigit(s[2]);
                s += 3;
            }
            else
                * (t++) = * (s++);
        }
        else
            * (t++) = * (s++);
    }
    *t = '\0';

    return result;
}


int wsgiPutEnv(Request *self, const char *key, const char *value)
{
    PyObject *val;
    int ret;

#if PY_MAJOR_VERSION < 3
    if ((val = PyBytes_FromString(value)) == NULL)
#else
    if ((val = PyUnicode_DecodeLatin1(value, strlen(value), NULL)) == NULL)
#endif        
        return -1;
    ret = PyDict_SetItemString(self->environ, key, val);
    Py_DECREF(val);
    if (ret)
        return -1;
    return 0;
}


static void sendResponse500(void *ctxt)
{
    static const char *headers[] =
    {
        "Content-Type", "text/html; charset=iso-8859-1",
    };
    static const char *body =
        "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
        "<html><head>\n"
        "<title>500 Internal Error</title>\n"
        "</head><body>\n"
        "<h1>Internal Error</h1>\n"
        "<p>The server encountered an unexpected condition which\n"
        "prevented it from fulfilling the request.</p>\n"
        "</body></html>\n";

    if (!wsgiSendHeaders(ctxt, 500, 1, headers))
        wsgiSendBody(ctxt, (uint8_t *) body, strlen(body));
}


static void Request_clear(Request *self)
{
    PyObject *tmp;

    tmp = self->result;
    self->result = NULL;
    Py_XDECREF(tmp);

    tmp = self->headers;
    self->headers = NULL;
    Py_XDECREF(tmp);

    tmp = self->input;
    self->input = NULL;
    Py_XDECREF(tmp);

    tmp = self->environ;
    self->environ = NULL;
    Py_XDECREF(tmp);
}


static void Request_dealloc(Request *self)
{
    Request_clear(self);
    Py_TYPE(self)->tp_free((PyObject *) self);
}


static PyObject *Request_new(PyTypeObject *type, PyObject *args,
                             PyObject *kwds)
{
    Request *self;

    self = (Request *) type->tp_alloc(type, 0);
    if (self != NULL)
    {
        self->environ = PyDict_New();
        if (self->environ == NULL)
        {
            Py_DECREF(self);
            return NULL;
        }

        self->input = NULL;
        self->statusCode = 200;
        self->headers = NULL;
        self->result = NULL;
        self->headers_sent = 0;
    }

    return (PyObject *) self;
}


/* Constructor. Accepts the context CObject as its sole argument. */
static int Request_init(Request *self, PyObject *args, PyObject *kwds)
{
    PyObject *context_obj, *args2;

    if (!PyArg_ParseTuple(args, "O!", &PyCapsule_Type, &context_obj))
        return -1;

    self->context = PyCapsule_GetPointer(context_obj, "Request");

    if ((args2 = Py_BuildValue("(Oi)", self,
                               wsgiGetContentLength(self->context))) == NULL)
        return -1;

    self->input = PyObject_CallObject((PyObject *) &InputStream_Type, args2);
    Py_DECREF(args2);
    if (self->input == NULL)
        return -1;

    return wsgiPopulateEnviron(self);
}


/* start_response() callable implementation */
static PyObject *Request_start_response(Request *self, PyObject *args)
{
    char *psStatus;
    PyObject *headers, *exc_info = NULL;
    PyObject *tmp;

    if (!PyArg_ParseTuple(args, "sO!|O:start_response", &psStatus,
                          &PyList_Type, &headers, &exc_info))
    {
        LOG_ERR(
                "Request_start_response() ParseTuple 'sO!|O:start_response' failed.\n");
        return NULL;
    }

    if (exc_info != NULL && exc_info != Py_None)
    {
        /* If the headers have already been sent, just propagate the
           exception. */
        if (self->headers_sent)
        {
            PyObject *type, *value, *tb;
            if (!PyArg_ParseTuple(exc_info, "OOO", &type, &value, &tb))
            {
                LOG_ERR("Request_start_response() ParseTuple 'OOO' failed.\n");
                return NULL;
            }
            Py_INCREF(type);
            Py_INCREF(value);
            Py_INCREF(tb);
            PyErr_Restore(type, value, tb);
            return NULL;
        }
    }
    else if (self->headers != NULL)
    {
        LOG_ERR("Request_start_response headers already set.\n");
        PyErr_SetString(PyExc_AssertionError, "headers already set");
        return NULL;
    }

    /* TODO validation of status and headers */

    self->statusCode = strtol(psStatus, NULL, 10);

    tmp = self->headers;
    Py_INCREF(headers);
    self->headers = headers;
    Py_XDECREF(tmp);

    return PyObject_GetAttrString((PyObject *) self, "write");
}


/* Sends headers. Assumes self->status and self->headers are valid. */
static int _wsgiSendHeaders(Request *self)
{
    int headerCount;
    const char **headers;
    int i, j;

    headerCount = PyList_Size(self->headers);
    if (PyErr_Occurred())
        return -1;

    /* NB: 1 extra header for Content-Length */
    if ((headers = PyMem_Malloc(sizeof(*headers) *
                                (headerCount * 2 + 2))) == NULL)
        return -1;

    for (i = 0, j = 0; i < headerCount; i++)
    {
        PyObject *item;
        const char *header, *value;

        if ((item = PyList_GetItem(self->headers, i)) == NULL)
            goto bad;

        if (!PyArg_ParseTuple(item, "ss", &header, &value))
            goto bad;

        headers[j++] = header;
        headers[j++] = value;
    }

    if (wsgiSendHeaders(self->context, self->statusCode,
                        headerCount, headers))
        goto bad;

    PyMem_Free(headers);
    return 0;

bad:
    PyMem_Free(headers);
    return -1;
}


/* Send a chunk of data */
static inline int wsgiWrite(Request *self, const char *data, int len)
{
    if (len)
    {
        if (wsgiSendBody(self->context, (uint8_t *) data, len))
            return -1;
    }
    return 0;
}


/* write() callable implementation */
static PyObject *Request_write(Request *self, PyObject *args)
{
    const char *data;
    int dataLen;

    if (self->headers == NULL)
    {
        PyErr_SetString(PyExc_AssertionError, "write() before start_response()");
        return NULL;
    }

    if (!PyArg_ParseTuple(args, "s#:write", &data, &dataLen))
        return NULL;

    /* Send headers if necessary */
    if (!self->headers_sent)
    {
        if (_wsgiSendHeaders(self))
            return NULL;
        self->headers_sent = 1;
    }

    if (wsgiWrite(self, data, dataLen))
        return NULL;

    Py_INCREF(Py_None);
    return Py_None;
}

/* Send a wrapped file using wsgiSendFile */
static int
wsgiSendFileWrapper(Request *self, FileWrapper *wrapper)
{
    PyObject *pFileno, *args, *pFD;
    int fd;

    /* file-like must have fileno */
    if (!PyObject_HasAttrString((PyObject *) wrapper->filelike, "fileno"))
        return 1;

    if ((pFileno = PyObject_GetAttrString((PyObject *) wrapper->filelike,
                                          "fileno")) == NULL)
        return -1;

    if ((args = PyTuple_New(0)) == NULL)
    {
        Py_DECREF(pFileno);
        return -1;
    }

    pFD = PyObject_CallObject(pFileno, args);
    Py_DECREF(args);
    Py_DECREF(pFileno);
    if (pFD == NULL)
        return -1;

#if PY_MAJOR_VERSION >= 3
    fd = PyLong_AsLong(pFD);
#else
    fd = PyInt_AsLong(pFD);
#endif
    Py_DECREF(pFD);
    if (PyErr_Occurred())
        return -1;

    /* Send headers if necessary */
    if (!self->headers_sent)
    {
        if (_wsgiSendHeaders(self))
            return -1;
        self->headers_sent = 1;
    }

    if (wsgiSendFile(self->context, fd))
        return -1;

    return 0;
}


/* Send the application's response */
static int wsgiSendResponse(Request *self, PyObject *result)
{
    PyObject *iter;
    PyObject *item;
    int ret;

    /* Check if it's a FileWrapper */
    if (result->ob_type == &FileWrapper_Type)
    {
        ret = wsgiSendFileWrapper(self, (FileWrapper *) result);
        if (ret < 0)
            return -1;
        if (!ret)
            return 0;
        /* Fallthrough */
    }

    iter = PyObject_GetIter(result);
    if (iter == NULL)
        return -1;

    while ((item = PyIter_Next(iter)))
    {
        int dataLen;
        const char *data;
        if (PyUnicode_Check(item))
        {
            PyObject *pBytes = PyUnicode_AsASCIIString(item);
            Py_DECREF(item);
            item = pBytes;
        }


        dataLen = PyBytes_Size(item);
        if (PyErr_Occurred())
        {
            Py_DECREF(item);
            break;
        }

        if (dataLen)
        {
            if ((data = PyBytes_AsString(item)) == NULL)
            {
                Py_DECREF(item);
                break;
            }

            /* Send headers if necessary */
            if (!self->headers_sent)
            {
                if (_wsgiSendHeaders(self))
                {
                    Py_DECREF(item);
                    break;
                }
                self->headers_sent = 1;
            }

            if (wsgiWrite(self, data, dataLen))
            {
                Py_DECREF(item);
                break;
            }
        }

        Py_DECREF(item);
    }

    Py_DECREF(iter);

    if (PyErr_Occurred())
        return -1;

    /* Send headers if they haven't been sent at this point */
    if (!self->headers_sent)
    {
        if (_wsgiSendHeaders(self))
            return -1;
        self->headers_sent = 1;
    }

    return 0;
}


/* Ensure application's iterator's close() method is called */
static void wsgiCallClose(PyObject *result)
{
    PyObject *type, *value, *traceback;
    PyObject *pClose, *args, *ret;

    /* Save exception state */
    PyErr_Fetch(&type, &value, &traceback);

    if (PyObject_HasAttrString(result, "close"))
    {
        pClose = PyObject_GetAttrString(result, "close");
        if (pClose != NULL)
        {
            args = PyTuple_New(0);
            if (args != NULL)
            {
                ret = PyObject_CallObject(pClose, args);
                Py_DECREF(args);
                Py_XDECREF(ret);
            }
            Py_DECREF(pClose);
        }
    }

    /* Restore exception state */
    PyErr_Restore(type, value, traceback);
}


static PyMethodDef Request_methods[] =
{
    {
        "start_response", (PyCFunction) Request_start_response, METH_VARARGS,
        "WSGI start_response callable"
    },
    {
        "write", (PyCFunction) Request_write, METH_VARARGS,
        "WSGI write callable"
    },
    { NULL }
};


PyTypeObject Request_Type =
{
    PyVarObject_HEAD_INIT(NULL, 0)
    "lsapi_wsgi.Request",        /*tp_name*/
    sizeof(Request),           /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    (destructor) Request_dealloc,   /*tp_dealloc*/
    0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    0,                         /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    0,                         /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    0,                         /*tp_str*/
    0,                         /*tp_getattro*/
    0,                         /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT,        /*tp_flags*/
    "WSGI Request class",      /* tp_doc */
    0,                         /* tp_traverse */
    0,                         /* tp_clear */
    0,                         /* tp_richcompare */
    0,                         /* tp_weaklistoffset */
    0,                         /* tp_iter */
    0,                         /* tp_iternext */
    Request_methods,           /* tp_methods */
    0,                         /* tp_members */
    0,                         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    (initproc) Request_init,   /* tp_init */
    0,                         /* tp_alloc */
    Request_new,               /* tp_new */
};


static PyMethodDef wsgisup_methods[] =
{
    { NULL }
};


#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef wsgisup_moduledef =
{
    PyModuleDef_HEAD_INIT,
    "lsapi_wsgi",
    NULL,
    0,
    wsgisup_methods,
    NULL,
    NULL,
    NULL,
    NULL
};


#define INITERROR return NULL
#else

#define INITERROR return
#ifndef PyMODINIT_FUNC
#define PyMODINIT_FUNC void
#endif

#endif


PyMODINIT_FUNC init_wsgisup(void)
{
    PyObject *m = NULL;

    if (PyType_Ready(&Request_Type) < 0)
        INITERROR;
    if (PyType_Ready(&InputStream_Type) < 0)
        INITERROR;
    if (PyType_Ready(&FileWrapper_Type) < 0)
        INITERROR;

#if PY_MAJOR_VERSION >= 3
    m = PyModule_Create(&wsgisup_moduledef);
#else
    m = Py_InitModule3("lsapi_wsgi", wsgisup_methods,
                       "WSGI C support module");
#endif

    if (m == NULL)
        INITERROR;

    Py_INCREF(&Request_Type);
    PyModule_AddObject(m, "Request", (PyObject *) &Request_Type);

    Py_INCREF(&InputStream_Type);
    PyModule_AddObject(m, "InputStream", (PyObject *) &InputStream_Type);

    Py_INCREF(&FileWrapper_Type);
    PyModule_AddObject(m, "FileWrapper", (PyObject *) &FileWrapper_Type);

#if PY_MAJOR_VERSION >= 3
    return m;
#endif
}


void wsgiCleanup(void)
{
    PyEval_RestoreThread(_main);
    Py_XDECREF(wsgiStderr);
    Py_Finalize();
}


static PyObject *importModule(const char *name, const char *filename)
{
    PyObject *module = NULL;
    PyObject *code = NULL;
    PyObject *res = NULL;
    PyObject *io_module = NULL;
    PyObject *file_object = NULL;
    PyObject *source_object = NULL;
    const char *source_buf = NULL;

    io_module = PyImport_ImportModule("io");
    if (!io_module)
        goto end;

    file_object = PyObject_CallMethod(io_module, "open", "ss", filename, "rb");
    if (!file_object)
        goto end;

    source_object = PyObject_CallMethod(file_object, "read", "");
    if (!source_object)
        goto end;

    res = PyObject_CallMethod(file_object, "close", "");
    if (!res)
        goto end;

    source_buf = PyBytes_AsString(source_object);
    if (!source_buf)
        goto end;

    code = Py_CompileString(source_buf, filename, Py_file_input);
    if (code)
        module = PyImport_ExecCodeModuleEx((char *)name, code, (char *)filename);
end:
    if (PyErr_Occurred())
        PyErr_Print();
    Py_XDECREF(io_module);
    Py_XDECREF(file_object);
    Py_XDECREF(source_object);
    Py_XDECREF(res);
    Py_XDECREF(code);

    if (module)
        Py_XINCREF(module);
    return module;
}


#if PY_MAJOR_VERSION >= 3
wchar_t *to_wchar(const char *str)
{
    int len = strlen(str) + 1;
    wchar_t *ret = malloc(sizeof(wchar_t) * len);
    if (ret)
        mbstowcs(ret, str, len);
    return ret;
}
#else
#define to_wchar(str)  ((char *)str)
#endif


void python_init()
{
#if PY_MAJOR_VERSION >= 3
    setlocale(LC_CTYPE, "");
#endif
    const char *python_home = getenv("PYTHONHOME");
    if (python_home)
        Py_SetPythonHome(to_wchar(python_home));
    const char *python_bin = getenv("LS_PYTHONBIN");
    if (python_bin)
        Py_SetProgramName(to_wchar(python_bin));
    Py_Initialize();
#if PY_VERSION_HEX < 0x03090000
    PyEval_InitThreads();
#endif
    const char *wsgi_root = getenv("WSGI_ROOT");
    if (wsgi_root)
        chdir(wsgi_root);
}


void wsgiInit()
{
    python_init();

    //init the Types, do it here???
    init_wsgisup();

    _main = PyEval_SaveThread();

    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();
    wsgi_interpreters = PyDict_New();
    PyGILState_Release(gstate);

}


PyObject *wsgiImport(const char *module_name, int deref)
{
    PyObject *name, *module;
    name = PyUnicode_FromString(module_name);
    if (name == NULL)
        return NULL;

    module = PyImport_Import(name);
    Py_XDECREF(name);
    if (deref && module)
        Py_XDECREF(module);
    return module;
}


//Just for sub interpreter init
int wsgiSubInit (const char *progName )
{
    PyObject *sys_module;

#if PY_MAJOR_VERSION >= 3
    wchar_t *argv[1];
    
    //setlocale(LC_CTYPE,"");
    argv[0] = to_wchar(progName);
    if (argv[0])
    {
        PySys_SetArgv( 1, argv ); /* make sure sys.argv gets set */
        free(argv[0]);
    }
#else
    char *argv[1];
    argv[0] = (char *)progName;
    PySys_SetArgv(1, argv); /* make sure sys.argv gets set */
#endif
    if (wsgiImport("threading", 1) != NULL 
        && (sys_module = wsgiImport("sys", 0)) != NULL)
    {
        wsgiStderr = PyObject_GetAttrString(sys_module, "stderr");
        Py_DECREF(sys_module);
        if (wsgiStderr != NULL)
            return 0;
    }

    PyErr_Print();
    return -1;
}


PyObject *wsgiLoadModule(const char *moduleName)
{
    PyObject *pModule;
    char baseName[PATH_MAX] = {0};
    int pos = -1;
    const char *p = strrchr(moduleName, '/');
    if (p)
        strncpy(baseName, p + 1, sizeof(baseName));
    else
        strncpy(baseName, moduleName, sizeof(baseName));

    p = strchr(baseName, '.');
    if (p)
    {
        pos = p - baseName;
        baseName[pos] = 0x00;
    }

    pModule = importModule(baseName, moduleName);
//  fprintf(stdout, "wsgiLoadModule %s %s\n", baseName, moduleName);
    return pModule;
}


int fixMainFile(const char *moduleName)
{
    PyObject *m, *d;
    m = PyImport_AddModule("__main__");
    if (m == NULL)
        return -1;
    Py_INCREF(m);
    d = PyModule_GetDict(m);
    if (PyDict_GetItemString(d, "__file__") == NULL) {
        PyObject *f;
#if PY_MAJOR_VERSION >= 3
        f = PyUnicode_DecodeFSDefault(moduleName);
#else
        f = PyString_FromString(moduleName);
#endif
        if (f != NULL)
            PyDict_SetItemString(d, "__file__", f);
        Py_DECREF(f);
    }
    Py_DECREF(m);
    return 0;
}


PyObject *wsgiInitModule(PyObject *modict, const char *moduleName,
                         const char *appName, int reload)
{
    PyObject *module, *app = NULL;
    
    char * p = (char *)strrchr(moduleName, '/');
    if (p)
    {
        *p = 0;
        chdir(moduleName);
        *p = '/';
    }

    module = PyDict_GetItemString(modict, moduleName);
    if (module != NULL)
    {
        if (reload)
        {
            Py_DECREF(module);
            module = NULL;
            PyDict_DelItemString(modict, moduleName);
        }
        else
        {
            Py_INCREF(module);
        }
    }
    if (!module)
        module = wsgiLoadModule(moduleName);
    if (module != NULL)
    {
        PyDict_SetItemString(modict, moduleName, module);
        if ( appName == NULL )
            appName = "application";
        app = PyObject_GetAttrString(module, (char *) appName);

        Py_XDECREF(module);

        if (app == NULL || !PyCallable_Check(app))
        {
            LOG_ERR("wsgiHandler getApp [%s] failed, pApp=%p.\n", appName,
                    app);
            if (app)
            {
                Py_XDECREF(app);
                app = NULL;
            }
        }
    }
    
    return app;
}


//The global modict
static PyObject *modict = NULL;


PyObject *preload_module(const char *moduleName, const char *appName, const char *progName)
{
    PyObject *app = NULL;
    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();
    if (wsgiSubInit(progName) != 0)
    {
        LOG_ERR("wsgiHandler wsgiSubInit ERROR.\n");
    }
    else
    {
        fixMainFile(moduleName);
        modict = PyDict_New();
        app = wsgiInitModule(modict, moduleName, appName, 0);
    }
    PyGILState_Release(gstate);
    return app;
}


int wsgiHandler(void *ctxt, char *moduleName, char *appName,
                const char *progName)
{
    PyGILState_STATE gstate;
    PyObject *ctxt_c_obj, *args, *start_resp;
    Request *req_obj = NULL;
    PyObject *result;
    int renew = 0;
    InterpreterObject *interp = NULL;
    const char *app_group_name = NULL;
    char *reloading = NULL;
    int reload = 0;
    PyObject *pApp;

    //a pointer to global or sub
    PyObject **pmodict = NULL;

    app_group_name = LSAPI_GetEnv_r((LSAPI_Request *)ctxt, "WSGIApplicationGroup");
#ifdef __DEBUG__
    //LOG_ERR("lsapi_wsgi: interpreter '%s'.\n", app_group_name);
#endif

    if (!app_group_name || strcasecmp(app_group_name, "global") == 0)
    {
        pmodict = &modict;
        gstate = PyGILState_Ensure();
    }
    else
    {
        interp = wsgi_acquire_interpreter(app_group_name, &renew);
        if (!interp)
        {
            LOG_ERR("wsgi_acquire_interpreter ERROR for name %s. \n", app_group_name);
            goto out;
        }
        pmodict = &interp->modict;
    }

    if (*pmodict == NULL)
    {
        if (wsgiSubInit(progName) != 0)
        {
            LOG_ERR("wsgiHandler wsgiSubInit ERROR.\n");
            goto out;
        }
        *pmodict = PyDict_New();
    }

    if (moduleName == NULL)
    {
        moduleName = LSAPI_GetScriptFileName_r((LSAPI_Request *) ctxt );
        appName = LSAPI_GetEnv_r((LSAPI_Request*)ctxt, "WSGICallableObject");
        if (moduleName == NULL )
        {
            LOG_ERR("wsgiLoadModule Error, moduleName is NULL.");
            goto out;
        }
    }
    
    if (renew == 0)
    {
        //setting "WSGIScriptReloading"
        reloading = LSAPI_GetEnv_r((LSAPI_Request*)ctxt, "WSGIScriptReloading");
        if (reloading != NULL && strcmp(reloading, "ON") == 0)
            reload = 1;
    }

    pApp = wsgiInitModule(*pmodict, moduleName, appName, reload);
    if (pApp == NULL)
        goto out;

    /* Create Request object, passing it the context as a CObject */
    ctxt_c_obj = PyCapsule_New(ctxt, "Request", NULL);
    if (ctxt_c_obj == NULL)
    {
        LOG_ERR("wsgiHandler failed to create Request object.\n");
        goto out;
    }

    args = Py_BuildValue("(O)", ctxt_c_obj);
    Py_DECREF(ctxt_c_obj);
    if (args == NULL)
    {
        LOG_ERR("wsgiHandler failed to build args.\n");
        goto out;
    }

    req_obj = (Request *) PyObject_CallObject((PyObject *) &Request_Type,
              args);
    Py_DECREF(args);
    if (req_obj == NULL)
    {
        LOG_ERR("wsgiHandler failed to create req_obj.\n");
        goto out;
    }
    wsgiSetRequestData(ctxt, req_obj);


    /* Get start_response callable */
    start_resp = PyObject_GetAttrString((PyObject *) req_obj,
                                        "start_response");
    if (start_resp == NULL)
    {
        LOG_ERR("wsgiHandler missing start_response.\n");
        goto out;
    }

    /* Build arguments and call application object */
    args = Py_BuildValue("(OO)", req_obj->environ, start_resp);
    Py_DECREF(start_resp);
    if (args == NULL)
    {
        LOG_ERR("wsgiHandler failed to build start_resp args.\n");
        goto out;
    }

    result = PyObject_CallObject(pApp, args);
    Py_DECREF(args);
    Py_XDECREF(pApp);

    if (result != NULL)
    {
        /* Handle the application response */
        req_obj->result = result;
        /* result now owned by req_obj */
        wsgiSendResponse(req_obj, result);    /* ignore return */
        wsgiCallClose(result);
    }
    else
        LOG_ERR("wsgiHandler pApp->start_response() return NULL.\n");
out:
    if (PyErr_Occurred())
    {
        PyErr_Print();

        /* Display HTTP 500 error, if possible */
        if (req_obj == NULL || !req_obj->headers_sent)
            sendResponse500(ctxt);
    }

    if (req_obj != NULL)
    {
        wsgiSetRequestData(ctxt, NULL);

        /* Don't rely on cyclic GC. Clear circular references NOW. */
        Request_clear(req_obj);

        Py_DECREF(req_obj);
    }

    if (interp)
        wsgi_release_interpreter(interp);
    else
        PyGILState_Release(gstate);

    /* Always return success. */
    return 0;
}


int wsgiAppHandler(void *ctxt, PyObject *app)
{
    PyObject *ctxt_c_obj, *args, *start_resp;
    Request *req_obj = NULL;
    PyObject *result;

    //LOG_ERR("wsgiAppHandler(%p)\n", app);

    if (app == NULL)
        goto out;

    /* Create Request object, passing it the context as a CObject */
    ctxt_c_obj = PyCapsule_New(ctxt, "Request", NULL);
    if (ctxt_c_obj == NULL)
    {
        LOG_ERR("wsgiAppHandler failed to create Request object.\n");
        goto out;
    }

    args = Py_BuildValue("(O)", ctxt_c_obj);
    Py_DECREF(ctxt_c_obj);
    if (args == NULL)
    {
        LOG_ERR("wsgiAppHandler failed to build args.\n");
        goto out;
    }
    //LOG_ERR("wsgiAppHandler args created.\n");

    req_obj = (Request *) PyObject_CallObject((PyObject *) &Request_Type,
              args);
    Py_DECREF(args);
    if (req_obj == NULL)
    {
        LOG_ERR("wsgiAppHandler failed to create req_obj.\n");
        goto out;
    }
    wsgiSetRequestData(ctxt, req_obj);

    //LOG_ERR("wsgiAppHandler create start_response.\n");

    /* Get start_response callable */
    start_resp = PyObject_GetAttrString((PyObject *) req_obj,
                                        "start_response");
    if (start_resp == NULL)
    {
        LOG_ERR("wsgiHandler missing start_response.\n");
        goto out;
    }

    /* Build arguments and call application object */
    args = Py_BuildValue("(OO)", req_obj->environ, start_resp);
    Py_DECREF(start_resp);
    if (args == NULL)
    {
        LOG_ERR("wsgiAppHandler failed to build start_resp args.\n");
        goto out;
    }

    //LOG_ERR("wsgiAppHandler call app->start_response.\n");

    result = PyObject_CallObject(app, args);
    Py_DECREF(args);

    if (result != NULL)
    {
        /* Handle the application response */
        req_obj->result = result;
        /* result now owned by req_obj */
        wsgiSendResponse(req_obj, result);    /* ignore return */
        wsgiCallClose(result);
    }
    else
        LOG_ERR("wsgiAppHandler pApp->start_response() return NULL.\n");
out:
    if (PyErr_Occurred())
    {
        PyErr_Print();

        /* Display HTTP 500 error, if possible */
        if (req_obj == NULL || !req_obj->headers_sent)
            sendResponse500(ctxt);
    }

    if (req_obj != NULL)
    {
        wsgiSetRequestData(ctxt, NULL);

        /* Don't rely on cyclic GC. Clear circular references NOW. */
        Request_clear(req_obj);

        Py_DECREF(req_obj);
    }

    /* Always return success. */
    return 0;
}



Youez - 2016 - github.com/yon3zu
LinuXploit