lib/0000755000175000001440000000000011115114241010506 5ustar monsuserslib/picture_sender.cgi0000774000175000001440000000306111115113210014204 0ustar monsusers#!/usr/bin/perl use strict; our ( $TMP,$EXP,$USE_EXP,%IMG, $IOK, # OK $INX, # Not exists $IEX, # Expired $IWR, # Wrong ); BEGIN { $TMP = '/opt/tmp/captcha'; $EXP = 60 * 15; # 15 min $USE_EXP = 1; ($IWR,$IEX,$INX,$IOK) = -2..1; %IMG = ( $IWR => 'wrong', $IEX => 'expired', $INX => 'wrong', ); } sub data ($) { my $w = shift; my ($w1,$w2,$rest) = split //,$w,3; my $f = "$TMP/$w1/$w2/$rest.png"; unless ( (my $c = check($f)) > 0) { return $TMP . '/' . $IMG{$c} . '.png'; } return $f; } sub check ($) { my $f = shift; my $r; if ( ! -e $f ){ $r = $INX; } elsif ($USE_EXP and time - (stat($f))[9] > $EXP) { $r = $IEX; # expired } else { $r = $IOK; } return $r; } sub send_http_header ($) { printf "Content-type: %s\n\n",shift; } sub senderror { send_http_header('image/gif'); print(pack 'H*','4749463839613c000a00800000ff0000ffffff2c000000003c000a000002478c8fa9cbed7f400412da9b2875157bd8195a866c8d1948a6daa1ac888aa49c32d51dc6375c2e610d8b9546c0c86cd753fc5a8fe5cc08742a9f29e110091d663fdcaef70b461400003b'); } sub sendfile ($) { my $fn = shift; my $data = ''; eval { open my $f,'<',$fn or die "open failed ($fn): $!"; $data = do { local $/; <$f> }; close $f; 1; }; if (my $e = $@) { warn ($e); senderror(); #send_http_header('text/plain'); #print($e); }else{ send_http_header('image/png'); print($data); } } our $file = $ENV{REQUEST_URI}; our ($hash) = $file =~ m{^/captcha/([^/]+)$}; our $fn; if ($hash and -e ($fn = data($hash))) { sendfile($fn); }else{ warn "File ($fn) does not exists"; senderror(); } lib/Captcha/0000775000175000001440000000000011115113075012057 5ustar monsuserslib/Captcha/font.ttf0000664000175000001440000034444410715377541013600 0ustar monsusers DSIGCPLTSH]k'OS/2q@vVcmapӥ8Dcvt FLQ28rfpgmUE-, gasp glyf&a@}(hdmx,> ?headܹ,6hhea _d$hmtx@Z3 tkernfoT loca"|?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~*>~~ O\_   " & 0 3 : < > D  !!!!"!&!.!^!!"""""""")"+"H"a"e###!%%% %%%%%$%,%4%<%l%%%%%%%%%%%%%%%&<&@&B&`&c&f&k  ~Q^   & 0 2 9 < > D  !!!!"!&!.![!!"""""""")"+"H"`"d### %%% %%%%%$%,%4%<%P%%%%%%%%%%%%%%%&:&@&B&`&c&e&jR  x;.4jy߲ߠޖޢދާ!q_0NA2TSJGDA>70)"ۀܳjSPO20/,1vvhlznTTVR*,(bcdefghjikmlnoqprsutvwxzy{}|~RSTUVW   XYZ[\]  ^_`abcdefghijklmnopqrstuvwxyz{|}~ !"#$%&'()*+,-./0F:GIIKLMNQGnCS<8G>y  L q | 3 ; ~ Op4=wm3s,sd1bHca)m.Tkv i  ! !&!?!V!o!!!!!!""+"C"Z"q""""""##1#`#$I$%%& &'?'(P(n(()X)*F***+y+,1,,-#--.0./|0!010B0_01Z122c2n2~2~2223D3344+4O4}445Z5s556`667 7u7778"99939J9c9z99999::::4:K:b:}::;;:;O;;<<2<_<<===.=E=i=>O>f>}>??+??@@@@@ASAjAAAAAAB B"BBBBCC+CACWC{CCCCCCD@DDDDEEE2EIE`EwEEFF.FEF\FsFFFFFFGG/GHGiGGGGGGGGGGGGGGHH(HRHHIIIJ J&JBJ\JJJJKK9KNK\KrKKKKLLL4LKLbLyLLLLLMMM1MHM[MsMMMN_NvNNNNNO)OuOOOPPrPPPPQQcQzQQQQQQRRXRRRRSS,SCSSTT%TF#pFE: -,+%E%Ej@`%#D!!!-,+%E%Ej`%#D!!!-,+!!!-,+!!!-,CCe -, i@a ,b`+ d#da\XaY-,%EhTX%E%E`h %#D%#D% Eh #D%Eh`%#DY-,% Eh #D%Eh`%#D-, CX!CXE+G#DGzEi G#D QX+G#DGz!GzYYY-, E#Eh`D-,EjB-,/-,!!-,%E%Ed`j%Eja %Ej e%#D%#D!!-,Eh#Ei@a%Eja %Ej e%#D%#D!!-,Ed#EdadB-,%C@T%CTZX% E@aDY%CT%C@TZX% E@`DY!!!!-,KRXC%E#aD!!Y-,KRXC%E#`D!!Y-,KRXED!!Y-, %#I@` c RX#%8#%e8c8!!!!!Y-,KPXED!!Y-,%# `#-,%# a#-,%-,F#F`F# F`ab# #KKpE` PXaFY`h:-, E%FRX?!Y-, E%FPX?!Y-,CC -,KRX%%I%%Ia TX! CUXY@TX CTXY CTX%8YYYY!!!!-,KRXCe8!!Y-,KRXC8!!Y-,!! d#d@b-,!QX d#d b@/+Y`-,!QX d#dUb/+Y`-, d#d@b`#!-,&&&&Eh:-,&&&&Ehe:-,CXY-,CXY-, +# <+-,(+# #+CX....!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"...../0*#.2V&!!2,!!!!!!!!!!!!!!%''''$!**!*!/**$*'$$*'2''$!!!!!!!!!2!!!!!/!!'''$***!!!!!!!!!!!!!!!!!!!!!!!!!+!((0!2*!!!!!$)"+2!!!!!!2''*222!'!!!!2'$'$$**(****!$$'!'$!!!222**!$'!'!!'!'!'*'$!$!3!!!!*!*!+*!''$$$*!*!$$V22221$'!'!'!$!$!$!*!*!*!*!*!!*!!!*!)"*!*!'$$*!*!*!*!2/''!22*! '*0,0-''!'$$***'/*$**$$$'.'/*'"!!" !!!!!!#!%!, ./!!!/$2!($!==1%"*'''!*$6"**%(/***$'$".'+(8926'(:'!!!!."## $*$!!!!3!#!/0'-!1!"!33" !2/2/2/'&!C2222!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$#%2111134."!'2!6])$$60$$$$$$$$$$$$$$!(****'$--$-$3--'-*''-*6**'$$$$$$$$$6$$$$!$!3$!$***'---$$$$$$$$$$$$$$$$$$$$$$$$$.$++3$6- $$$$$',%.6$!$$$!$$6**-666$!* $$$$6*'*''--+----$'!'*$*!'$$$666--$'!*$*$$*$*$*.*'$'$8$$$$-$-$.-$**'!''"-$-$''!]6 6665' !!*$*$*$'$'$'$-$-$-$-$-$$-$$$-$,%-$-$*'!'-$-$-$-$63*!*$66-$ *.4040**$*''---*3-'--'''*2*3-*%$$%#!$$$$!$!$&$($0#13$$$3'6$+'$AA5'$-***$-';%--'+3---'*'$2*.+<=6:*+?*$$!$$2%&&#'.'$$$$!7$%$34*1"$5"$%$!77%#!$636363*!)$I 6666 $ &!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&' 65555 792$$ *6$:d,&':4 &''''''''''&&&#+----*'00'0'700*0-**0-:--*&'''''''':''''#'#7'# &---*000'''''''''''''''''''''''''1'..7&:0"&&&'')0(2:'#& '&#'':--0:::&#- '''':-*-**00.0000'*#* -'-#*'&&:::00'*#-'-''-'-'-1-*'*'<''''0'0'20'--*#**$0'0'* * #d:":::9*###-'-'-'*'*'*'0'0'0'0'0''0'''0'/(0'0'-*#*0'0'0'0':7-#-'::0' -18384--'-**000-70*00***-6-70-' '''%#' '''#'#')'+'4&57'''7*:'.*'FF9*'0---'1*?(00*/7000*-*'6-2/@B:?-.C-''$&'6'))%*1)''''#;'(&78-5$'9$'''#;;'%#' :7:7:7-#,'N#::::#&##)$)))))))))))))))))))))))))))))))))))))))))))))*#:9999###;=5 '&"-:&Cs2",-C<%,----------,,,)244440-88-8-?880840084C440,"--------C----)-)?-)%,4440888-------------------------"9-66@,C8',,,--"07.9C-),%-,)--C448CC"C"",!)4 ----"C404008858888-0)0%4-4)0-,,CCC88-0)4-4--"4-4-4940-0-E---"-$8-8-98-440)00*8-8-0%0%"#(sC'C"C"C""B0(((4-4-4-0-0-0-8-8-8-8-8--8---8-7.8-8-40)08-8-8-8-C?4)4-CC8- 4"9@";A<44-4008884?80880004>4?84-%---+)-%---)-)-/-#2"-<+=?---?0C-50-QQA1-8444-80I.8816?888040->4:6JLCI45N4--)",->-//+090----")D-.,@@4=*-A*---)DE-+)-%C?C?C?4)2"-Z(CCCC(,((0*00000000000000000000000000000000000000000000/1(CBBBB(((DF>%-$,("4C,K8&22KC*22222222222222.8::::62>>2>2G>>6>:66>:K::62&22222222K2222!.!2.G2.*2:::6>>>2222222222222222222222222&@2<,22222&5>4@K2.2)22.22K::>KK&K&&2%.: 2222&K:6:66>>;>>>>26.6*:2:.6222KKK?>26.:2:22&:2:2:?:6262M222&2(>2>2@>2:!:!6.6!6/>2>26*6*&'-!K,K&K&K&&I6---:2:2:2626262>2>2>2>2>22>222>2=3>2>2:!6.6!>2>2>2>2KG:.:2KK>2:&?H&BIC::2:66>>>:G>6>>666:E:G>:3)2230.2)#222.2.#252(8&2C1EG222G6K2<62[[I72>:::2?6Q4>>7>>6:62E:@*77SJ .777777777777773=AAAA<7EE 7E7NEE*7J6LO777O*7p2SSSS2722;3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=2SRRRR222UWL.8,71*@S!!!7\E.==\R$$3==============8DHHHHB=MM$=M=WMMBMHBBMH\HHB$$=.=====$===\====)8)=8W=83$$=HHHBMMM======================%===.N=JJW=\M6=====.BL?%%O\=8=3==8==\HHM\\.\..=-8H====.\HBHBB$$$$MMIMMMM=B8B3H=H8B===%%%\\\MM=$B8H=H==.$H=H=HNHB=B=_===.=1M=M=OM=H)H)B8B)B:M=M=B3B3.08(\6\.\.\..ZB78!!8!H=H=H=B=B=B=M=M=M=M=M=$$$$=M===M=K?M=M=H)B8B)M=M=M=M=\WH8$H=\\M=H.NX.RYRHH=HBBMM$MHWMBMMBBBHUHWM$H>2==>;8=2*===8=8*=A=1E/=RMHHH=MBd?MMCJWMMMBHB>UHOJfi\dGIkH==9/==U>AA;BNB====/8]=?=WYGT9=Z9=>)=8]^>;8=3+\W\W\WH8E.=|7\\\\7=77A9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7\[[[[777^aU3>1=6/G\%%%=dK!!!2BCdY''8B!!!CCCCCCCCCC!!BBB=JNNNNHCSS'CSC^SSHSNHHSNdNNH''B2!CCCCC'CC!!C!dCCCC,=,C=^C=8''BNNNHSSSCCCCCCCCCCC!!!!CCCCCCCCCCC(CCC2UCPP_!!BdS:BBBCC2GRE((UdC=!B7CB=CCd!NNSdd2d22B1=NC!!CCC!2dNHNHH''''SSOSSSS!!!!!!!!!!!C!H=H8NCN=HCBB(((dddSSC'H=NCNCC2!(NCNCNTNHCHCgCC!C2C5SCSCVSCN,N,H=H,H?SCSCH8H8!!!!!!!!!24<,d;d2d2d22bH<<##<#!NCNCNCHCHCHCSCSCSCSCSC'!'!'!'!C!SCCC!SCQDSCSCN,H=H,SCSCSCSCd^N='NCddSC!N2U`2YaY!NNCNHHSS'SN^SHSSHHHN\N_S'ND7C!CD@=C7.CC!C=C=.CGC5K3CYA\_!CCC_HdCPH''CyybICSNNNCTHmESSIP^SSSHNHC\NVPordlMPtNCC>3BC\DGG@HUGCCCC3=eCEB_`M[>Cb>CD,C=!!!efD@=C8/d^d^d^N=K2CGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGI54&'-40fa{H=Fʩ|@23?UOCaa;G7QZymz7 Ezd/cX"a8R cc<>*,A(W6/O"c!/?@V<&&4,08@P0?""""8)@6)A)o0  @l+/3/]+/+3/]9/]39/3?32#".%327654'&#"4>32#".%327654'&#"@pY}Ը}Y(22((22(X|Թ|X(22((22(fcүce|8%%8|{9$$8mgdӯde|8$$8||9$%8%0:@%f"&,9$1 7,79@4 6"9 $&)1/)@_54&#"327&>.*,<3jj⨿PN#T7~emGXjHi TF ,}MaJKVUk\>F+e-/AH1>&;T/IrUdU%@P0`p/]]99?3/10!!U@B)pQ 0@ &fw !P  /]2/<<??10]]3# 54:17PQW @$}@"    @16 6 "    p/]33//3/]9/9/99999+]+?3/<3/<99103676?'&''767&/7&'& *E*S8!hJ$' Kp/-.KHWӗ7F B ,$qT\q/!? 4T) 3@       /]3<<2//]/<3<2//]10!!!!!!C~|d/ 0@     h e++/9/3/9??910!'>7#|_tWR6kI-y}@ @/q//10!!-P|/@he++/?10!!|Mh?-@p/3/]3?5&#"T-4xE)I5;c^>[+cceZNIuVqvrQW$ <@! 6 6  ?/]3/9??9/+9]+10!>7ddA-L^+NC6k@ 6 @* 6gy?o l+/3/+/]3/9]]+??3/99+10)6%>54&#"%>32!:%dcKNch{S8|?م>C_b|!gb~UD7H.ٹ@ 6 6$, &#&6&@) 6&@!P!!!!!!!!w, 6 6@ 6  $#@06#####)@6?0o/l+/3/+/]3/+9/]+39]+++?3/9?]3/99/]++999+10+%6$3 #".'%32654&#"32654&#"0hiU-IQ(eNRmiZ0T"PkPFHZE֢_:-f^6{_xdfp#fFCPW*+ x@+   d     p  @6  p  @//]q33/]]+q<<23/]??3]9/32#".'%32654&#"%q#DAʑϑZnLUop];7)1 ʎ7mg-cgz72V(m@G&w  &@ 6&@ 6&  ##?*o)l+/+/]3/]9??9/+9/+99]]10.#">32#"$!232654&#"kK7c7(IeN(ˆ5xWPlpSUsp2UFdHJGב{IqQwzy|~[ 9@$  {   ?o  l+/+/]9/9]??910!!![h~I:j0,팣gT)5@  v ! 6!@+6!@3333 3@3P33333'-'06*@66x0(*$  0?7o*6l+/3/]+/]3/]9]9]++??9/]]q++9910]q&'&54763 #".54632654&#"32654&#"I`,<&8*Zwue|x4_OFZ^IJ]vLItuMLq3?VpuZcV@<9rnh1nքQL]\IL_]?a{}`a|xG(z@&x  6 & 6&@1 6&  g#?*o#)l+/3/]+/]9]??9/+9/+99+]]10%32767#"54>32!".4&#"326fL7b7(Ie دʆxVQkoSVrI3UFcIKF֒{sQwzz{~|/&)@? he++/<<??]10!!!!|MM&hh|d/&>@$?     he++/3<9/7#|M_tW&hR6kIkpI`@6 P`P/]7654&#"%6!2!!,WQABG] |چ^e5wi&ayd~B77=^u0[{UrPa>N9 6ֳ6@h6 6V<$$6J1C4>>J:::::&..C4=G>1>>>>@111 )?77777"/3/]/33/]3/]/99/33///]?2/]3/99]10]]++++327>5#"!2$73#"$54$3 #"&'#"&5432732654&#"}.:Vo˧kwRJmd;se @0I IVV      @96   O @@ p  /]33/]9/]]9]?$&r5!{IE@HSFAOaH@-  0`}} o}  l+/+/3/?3/]9?3/]9]10#"$! &'.#"326f(b=Mp&nDR>Wxr^lYC48|\ )@ '}o  k+/+/]??10!2#!32>54&#Hkmy_oxDl(n?i S@8P0@o  o k+/<+/33//??9/]qr]10!!!!!!?, J@2P0@   o k+/<+/3/??9/]qr]10!!!!!`g89^3!S@0 @ 6 } #o} " l+/+/3/9/??3/99/+9910!# $547632.#"32675wƿ(KdLY1c`c\GXNSX,5 4@o    n  k+/<+/<?$p@B  $  }&o$%k+/<+/3/999]?<54&+ވh[:eQ%_.$1>(Y-9Z|HÌz7#v WW"h J0GLGy,@6"###4#T## # ! #O@P6@ 6*&@6 ! #&@ 6}}&.&o@ 6}@6}-l+/3/+++/3/+9+?3/++]q9?3/]q99]10]]%32654'&'$'&546$3 .#" # G+Fai22'Um`OP! x)ui7Y[<9--(CooqscZC0#@x{ /@/32//??<10!!!!/a2;2P.@ Fnk+/+/?@ /]5}*@/]33/99/99?3/<910!! ! f///3/]10!! f@/2/3/?3/]10!#[I>)7 @ 63@ 6&*##3&@ 6&3@. 630X6 6#79h08f+/3/+/3<99++]??+?+9/9/+9/9+10%>7>32!.'#"&54767>74&#"32>5{SN8rJ4< POlGGL>Nd2'IT[|!"CADu1)fu+")A-K+KUB)+.M!,yNN&.%K< ! !*0=B_L}W@ ;[ 6@* 6 f ie+/99+/]????99++]10!>32#"'&'!32654&#"}=^t}kYCOgOIcaESi@@.$c{y~v{J> V@887XW0?8 ?"i ! f+/+/3/]?3/9/?3/]9/]]10#".547>763 .#"326 㯩\8)Kw7_Pe}|`Pm,yb?mP13DERHg@ ;[ 6@ 6   6 6 @ 6h  f+/+/99+++????99++]10!5#"5324&#"326PBXl_<jQG`cINhFd#.J@@\}{vyzH> ]@   @ 6@ 6 8  "i!f+/+/3/9]?+?+9/q9/9/10!32767#"&54!2%.#" *;_<6!&\?b gTa:% b0E0%w4ҕvfM0_Y^@%@ 6 66 6/+++3<<22//9/??<32&#"@hMk-I-70 &*0Ac= %(IQ>$0@g!2#R# 6$@ 6$.( 6 6 @) 6(.!i+2h %1f+/3/+/99]??/?+9/++9/99++]]10!# &547326=#"'&543232654&#"^}Uٌ-DXW<<^mՃ]|FbPLglNN]&/dp2"-7^uG 2Tasostt{q{Q 666@ 6   he+/<+/?32!4&#"!{SpgJCJ\iVJ]HdSp!(@ he++/<<???9/10!!!!iiQ#C@'  6       he++/3<%jг6 6 6@- 6B %$O%%%%&%e+/]9/9/?<32>32!4'&#"!4'.#"!~|Rv/`th)=HXh @+FZh&aRZYhKe]H#7hsIF(1jy{>L 66@ 6   he+/9+/?32!4&#"!{{U}gJCJ\i&j[]HdSpI > 2@ 6 78  if+/+/??]10]4! ! '&32654&#"IH?sWXqrTYt;ǂ}l>j@ 4T 6@ 6   6 @6  6  ie+/99+/+++????99++]10!67632#"&'32654&#"}}OBYl^=jQG`dHNhlc#/@?~zuyzHl>]@ 4T 6@/ 6 66 hf+/+/99++????99++]10!#"46325!4&#"326e<_t|kZBO}hgOIcaFRil?@ /#czyuz>K 6@$ 6 e+/]92/]9]???999++10!>32&#"!}7uVZk~H*P,?g&qU8B]3>.$ 6&@ 6  6&@#6 # %@6@ 6@666 6@:6,( (9 # %(@6@6@ 6(0(i66@ 6 /f+/3/++++/3/+++9]]]?+3/+++9/?+3/++9/9+10+++%327654'&'.54>32&'&#"# &3ZKR-#.!ԥqzִy(~#0DE?((io&&H>#',%?`iK:zh&3 1#'R[\g8UU@&    @ 60/]+q3<<22//9/??<=&54676763-?? %@CA.Ab~äF*OKMM(;4'CYr57M;$CR"U$$tb,W0cv"* l@ /]3/??103#QW^@c4@     //]/<3/3/10]]#".#">3232sL:uH]`1lX'\>"~ISFf>2$k@ %&+55+55>$!@=I iX WY!IVV!! !   @? 6 !     !  p  /]3/]9/]9//?2(k@ %&+5+5%21k@  %&+5+5]L22k@  %&+55+5528k@ %&+55+55I2DV@ :: %;&+5+5I2DCV@ ;; %;&+5+5I2DV@>>: %>&+5+]5I2DV@ ;> %;&+55+55I2DV@ F9 %F&+5+5Il2DV@ >8 %;&+55+55JQ>2FV@ 33 %$?5+5H2HV@###%$&+5+]5H2HCV@ $$%$&+5+5H2HV@''#%'&+5+]5H2HV@ $'%$&+55+552@%&+5+]5!2C@ %&+5+52@  % &+5+52@  %&+55+55{2QV@ "%"&+5+5I 2RV@ %&+5+5I 2RCV@ %&+5+5I 2RV@  % &+5+]5I 2RV@  %&+55+55I 2RV@ (%(&+5+5w2XV@  %&+5+5w2XCV@  %&+5+5w2XV@ %&+5+]5w2XV@  %&+55+55i *@    /]3<<2//??<32.#"/18(3RpC7QBcV^yL,Е&ٸɋK0:HMUD48 2&!,[% /}ZM,_o&EKi   2P2`2222>,J,f+/33/]/]+/]33//]]9999++?3/]9?3/]99]10].#"#".'%32654'&$&5467.54>7632654'&$C8C>2gfNW53k|}Q(x$\CEE)9Yl3.QC[x%4n-',904(".C`\]XK:vLhm*JaYL'ID@/()8mVL8lCVVEE* 2D)!&L @ /]3//3/10#"&54632LŠŠщÉiQ*@ //32//?32#"'&'732654&'&'&54654&#"whu,8&ƦzZCA#"#.7Nv=29Kx}R$1(wrPb* L,."RL;&0;;-;\v:11:@ * 6* 6ֳ 6@I 6""#2//1: *11#*06 *)O)O))))):011/]3/mjr/"uP( XXHES`bcii}iRx7[9--9:17@ * 6* 6ֳ 6@K 6*/++++.'`'''  5!o!!!+**1$$/]3//]3/3/?3/]3/]9?3/]3/]910++++#"$54$324#"32%#"&54632.#"3261bb͔iiJ&Ci_DNj$5a=abcii1yAeùzQO=XZ$I@]@ P    p   O _ o  @ P `   O_ @P @@P/3]2//3/]]3/]99999]]]?<<<2/<<<<9]10!!#!%!!###$!~eqwZݙmC@@@/2/3/?3/]10!#K^@ /3/?<<10!!%!!b@xv@AV        P p  _  /<3/]/]<3/99/3<<2/@" %-"  -'% **//9/33/3/]/9/10>32#"&'#"&5463232654&#"&#"3276$J_^Kb s@B   P` P`/]<32#".54>32654'&#".#"3276y*4sԄaaK{]HtG~Qe"oEFBVs<;ce~̽iNORYR-^:( gY=PaGu+Q|@A         /7Lc({n22FS9K(Q$%wah.Qh%G@'!  %'n & k+/32//<+/32//<?<<<32#"'&#"#"&5463232654' -.O%2K5'#) %@M-4B3'(: %$q=-C(/9$#*gfC5\zj,D5-6@!*N;!".X@3@ 6#+.O   (  /q33//]3<99?3/]3/99/9/+910#&'#"&54767674&#"'>323265 .,>R}54hV,951 FpoFE 94-?J$+vaX558+",+GQ*89|>9*$0PT '@  /3/?3/]10q4>32#".732654&#"V|ΨN+!@9JK<=K]_dΫmUl4(\ln]]S(m@EYVfv$'&'&?o * o%0%`%%&&%)l+/33//]9+/33//]9??<999910]]%&'.5!2%3!567>54&#"!53'tEec=9JH~a8LM岪WQ4\{b1?Z6~V/:PQ4+E?9@O@10,#J'&@ 6&&#A #@ @=@ 6=3#@ 6#, 6 J@4 6J60@ 0OOOOO:G :Qi&''GPf+/3/+/3/9/]<9+?+<+?+?+9/9/99/9/+99910!3267#"'&'#"&5467676$767.#"%67>32>32%.#"326765 $7Y2I#QץwZS{݇@1AL#'CY=QUTy'5ŞfIX\g݌'jYQHgy}cOB67t`/G-7#0$TZNEz$/ 4 P:=B-j6J[9:.XKcgrhqw)L).@89)DI #-@ @ 69@ 6@ 6 @W 6-$ # $#- ( (#$-+  !+/i!.f+/+/999??3??399999.+}ć<<<<<10+++]+!"'&''7.54!2&'&#"32654'h|EZqV;ZiULFpX;W'1eK!(0b^:| +a[t;,5I~3BIS&"& ?55|l/&W&@  ?55~<m@  //]/3/10!!!~DmTdM@B/33/9/9/99/32&#"?üIg3',;-QnI]<'-~;$+Q"U~D>'/Yc)@     6 @5 6  #((    /3232#".#">3232sL:uH]`1lX'sL:uH]`1lX']="~ISFf\>"~ISEek^@2_p/]33/]99/9?3/>2$Ck@ %&+5+5>%2$k@  %&+5+5]L%22k@ (%(&+5+5G+x@M $P0@ 8(   - o },l+/+/33//9/<<9]??9/]qr]?9?910!!!!!!5#"'&7632"32>54.<5@Jb慹KJy/?x;=|85w])6z~Ϯ[Y_ĤNUǢV;>!(4@"  62 ,(%@ 6%2@ 6 ,@$ 6 (0////")"6i)5f+/+/3/9/]9+?<+?<+9/9/999+10!3267#"'# 57632>3 %.#"32654&#" bO4L$Ccdɏpg\u 3g \LKeWST\\EXavd.4$vA5?p6E>=vaerVztst  ///10!!   ///10!! 76.@_   ? O  ??55/]5/]]576.@_   ? O   ??55/]5/]]5F -@   6/+9/2/9?3/910!4673M^sXOR6kIF -@    6 /+9/3/9?2/910!'>7#F_tWQ6kIiL F @" 6@ 6`  /3<<2//]/32/+q/+q10!!!!!!oCWoL[\/ @c         @/]<33/]9/]9?32&#"!!!! RgN-HB7]ss&*032&#"!! RgN-HB7]s&*0@      /]3<<<<2/7#F_tWR6kI7d6.@_?O   ??55/]5/]]5 '3?K@= 67@ 6% 6@ 6  6@& 6 1I77C==+% 666@5 6 (.o"""(@4`444F::Mo /3/]]3/3/]]9/]3/]9/9/+++3+?<<<3/<?<<3/++++++.+}104632#"&732654&#"%3#4632#"&732654&#"4632#"&732654&#"4'(44('4IJ4('44'(4览4((44((4QȺҺǔPPPPȺѻƔPPQQȺѻƔPPQQ>12$k@  %&+5+5i12(k@ %&+5+5>>2$k@  %&+5+5i2(k@ %&+55+55i>6(Ck@ %&+5+5>2,:k@ %&+5+512,:k@  % &+5+582,:k@  %&+55+55;n>2,C:k@ %&+5+5]L>62k@ %&+5+5]L122k@  % &+5+5]L>22Ck@ %&+5+5>28k@ %&+5+5128k@ %&+5+5>28Ck@ %&+5+5!&@he++/??10!!i&;@!@ 6/33/+99/99?3/]<910]q!#'#!zz♙1@ 6 @ 6 //+?<3/+2/103#"'&#"#&54632326pX@O vQ#>&!oz5 $.k~F%//?10!!y<@(F p //?<3/]]10]]q3#"&'3326N\JJWK_N:11/?10!!:dEl #@  /]3//3/10#"&546324&#"326Ecddc<++<<++<{dddc+<<++<<Qo3@    /33//9?3/3/3/9999107632#"'532654&#"t^R;~rhuV=25GvtO0f>{.%*.Q̳6@'6O@ 6/32/3//+q3/3/?<3/]<10++!#!#E5Hҿ'Ai)@    /3/99?3/3/991073327#"&54ȩJB/Q|XxW9LN.jY5@ 6/33/+99/99?<3/]910!373zz W@9        o   k+/3<yl\tr P@6         h e++/3<<2/54&#Gnnx_oxDl'n#?K +@TYkv )9    )#   & & - i ,f+/+/999???<99<<<<10]]]7.'!7!"$54>32&'32654&#"AAgC<5%㈄z<9&8D=}sRLLTtZ@M# (He6  "wRkˏt=>2<k@  % &+5+5Q2\@ %&+5+5p 5@  }o   k+/<<+/?3/]?3/10!2!#!32654&+*9oj\D[GDa}lO4T@* 6 6 f   iBe+/<+/]??9+?9+]?10!>32#"&'32654&#"}@b^=jQG`dHNhlNC<@?~zuyz; //]/10!!C} @U          II@6@ 6   6 /+3/3/++]33/]3]/3/3/33/3.+}ć.+}10   ' c>;=>;??;s ,@   /]3/9?3/]9/910!567s8[Oh!!-H@, {p0`/33//]3/9]]?33/9/]10!>767654&#"'67>32!oo-/1B+*+>][J$$&5<P(;G\E:;t)-@ $#?*$$$$##@6##** 6 @ 6 $#' /33//3/999++?3/]9/+]]9/99/]9910%67632#"'&'732654'&'72654&#"-1H`\A$APLIc̿f;:08?8 uV<)()!(^+8C0L5-fC^7KN-Y0*7&3,!#67N?567m ?55F6'7 <?55 6@H 6  P0@ k+/<2/<92/99/?32&#"!!!!!}8tWYk~H*P,?g9`gIqU8B]W^3>2*k@ *# %'&+5+5IQ2JV@ 92%6&+5+5n?2,:g@ %&+5+5GQy26@ ??&%0?5+53Q>2V@ AA(%2?5+5a>2&k@ !! %"&+5+5J2F@### %$&+5+]5a12&k@ !% % &+5+5J2Fj@ #' %"&+5+5H%v@ 0@; 6;[ 6#  6 6 'h & f+/+/3<<99/9/++??9+]?9+?9/]<<103#!5#"5325!5!5!4&#"326ٸPBXl_<2hjQG`cINhF]d#.J@@t\}{vyz? B?}0//10!!}Mh) X@6  )     &  p  /]3<<2/]/99]?3/]9/<<99]10!533##5hccIy>F2$s@  %&+5+5I2DW@ @9 %=&+5+5Ah2$@ % ?5+5IA9>2D@ F;%8?5+582'r-@"@p@P`%&+5+]]q5H6GQ3@  ?5/]q5Ai"(@  % ?5+5HA>"H@ /$%!?5+5i82(r@ % &+5+5H2HV@ #'%"&+5+5B@) n }` p   k?O]+/3/]+/? 6   h/_o?O]q/3<9//]r9+/?7#!!4#"!!3632aTfiOVh}C&jbnFHu%]LG62t@ & %+55+55I 6R@ & %+55+55>B25o@ ''%(&+5+52U@ %&+5+5>825r@ '+%&&+5+52U@ %&+5+5GyF26s@///%0&+5+]532V @ 11%2&+5+5/27Q@  %/5+58U2WQ@ %/5+5/827r@  % &+5+586WQ3@_`p?5/]528r@ %&+55+55wl2XV@  %&+55+55E28r'@ @%&+55+]]55w2X+@ 0Pp %&+55+]]q55"F2=s@  % &+5+5%G2]@  % &+5+]5"?2=g@  % &+5+5%G2]@  % &+5+5  @ 6/7ut7r+VgY^ۦۦZjjZg"*327632#"&547#"&5476732>54#"o8&-&]LZ4 D=ӟPVZs#(TP7`*-Q"97L$aoRd_JOl 3!!#&'56LQr;f`N߿lefX-GSh $73&'#G.WfeM`e=rQOl #67!5!&'M_f;rQlG-XfeSh 5367#&efW.GLQr>f_M߿On#67!#'563!&'3PE}}EPබPE}}EP-OO-OUg3&'67#&%55$-OO-OPE~~DOᶶOD~~EPg3&'67#&%55$!!-OO-O3PE~~DOᶶOD~~EPbjk3!!jdedh!#>32#4.#".n$S^{m`qr]0vۥxA6ˣrtN !5!5!5N111{{{{{{B!!!PLPdR!R10R! !R170K# 2#"54$kpf 2#"&546"32654&kehhgGhgHHghkhhhLdKIffIJe #@   /9/3/9/2/910!'67#YnGyzyl}0h6S>6$T@ & %+5+5I6DX@ ;&;: %+5+5aB6&|@ %&%! %+5+5J6Fh@ '&'# %+5+5aL6&t@ !& %+5+5J6F`@ $&$# %+5+5i6(T@ &%+5+5H6Hh@ $&$#%+5+5iO6(|@ & %+5+5H6HH@ &&)"%+5+5iL6(t@ &%+5+5H6H`@ $&$#%+5+5^3B6*|@ (&($ %+5+5IQ6JT@ 7&73%+5+5^3L6*t@ %&"# %+5+5IQ6JT@ 4&43%+5+5^Q36*P /( %+5IQ6JQ 0@ 2&21%+5+5B6+|@ &%+5+5{>6KXx@ & %+5+5]@   @( 6o n  k+/<<6-dx@ & %+5+5Qk @= 6 @ 6 @ 6 he++/33/9/33/]/+9999??9?36Q ! %+5R'N 6@( 6  }ok+/]9+/9/???9?3/++106$3 !"'32!"!!F?g=6"qbh<Qt#P pxtJfR=A@&H   ie+/9+/9/???9?99]10632#"'3264&#"!!+Χρ='!C4MOHKVySi#' t%]L62T@ &%+5+5I 6RT@ &%+5+5]LS62@ &"%+5+5I 6RL@ &"%+5+5Q>65 &+%+5Q>6U %+5GyF66@ 3&3/&%+5+536V@ 5&51(%+5+55N@/     PP/]r33NIuA6>6:x@ &%+5+56Zh@ &%+5+5=>6<x@ & %+5+5Q6\0@ &%+5+5w "@  e+/2/??92/10&#"!4!2;.&y1= >6c@ %%# %+54I6D7V &@SA;&SQ %>8 %+55+5+554O6D|@ &%+5+5E6@ S&SQ'9%+5+5#O6|@ +&+)%+5+5I 6T@ 1&1/%+5+5}@ @/3/99/10#}B+ ?@"@@ 6  ?@ 6 /33/+3/99/]/<<2/+10#!5!!5!-BX+>6$ %+5?5x/3//3/10!!:i7(  %+5?57+  %+5?5V7,@ %+5?562l@  %+5?57<@   %+5?56|@  !%+5?56@ & %+555+555>$%@ok+/+/??10!!!;<R;x@$962@! 6p/]33/99/99]?<54&'ddekvyhde|{JF=9Eoj"^mf=;R=Y@)BB  P   p@ 6@/]+qr3<<2//]??9/10!! !3!2>5!=;Z__[}VOeLLeO^LY@"  @6? }  o@60}l+/392/]+/+/392/]+/?<<<c# PLRN'~xWԃ4C_-5>ɉ%wj%X@7 6% @ 6"'i   & e+/]<+/9/+]99/???9/9+10#"'!4$32%>54#"32654&'jy jKLd@CDKVF{ô] iLi^[Sf j%@(6@! 66 60O ]/392/]++9/++9??<<<9/<9.+}ć.+}10 !!Ti\%5`J K@-9  i  f+/9/+/9/9]???999]10! 547%!265#"/ļ-biehg`X6;`w|@JZ=@p@ 6@6 @@"66 6  6@ 6 6 @ 6 f+/9/+9+3/]+3/9/99+++?39+}/]?3|/+9/+]910]%! $547&54$!2&#"3"327Zɼ"ojghRGM:P42:A^RNR<@"   0  f+/9/3/]3/9/??9]10 +254.547!!=_BqF2ّld! W][VxYY~voױ!&{N% @#       @,6  6    e+/<3/]33/+399]?<R% P@ @6@ 6  @ 6  ? ]3/+3/3/+3/+?54&#".x?@?TlX;80Z  .~[uhxZ^j!% @   @7 6 6     B O  ]/]q33/3//3/99]++?<<H&Lk|h;3^4H5QGKPJRhS6L@  & %+5+5^V@3@ 6?     oB}l+/+/3/9/?3/9?3/99/]+10! ! &# !!!27DyohC+F%>sdGy6n,82,:k@  %&+55+55#- Z V@4{   / _ o  }h"o !3/3/+/]9/]<?3/?9/10]3 #!!#"'3265!3254+DK#;J`D\L)R=z)Ql Zb@={o    @6 @6/  }ho   k+/<+/]9/]++<<?<?<9/]10]3 #!!!!!!3254+DK#H<)P5V=@!  h   /32$ =@! 6   }o k+/<+/9/??9/+103 )!!3254+\MB%@ok+/+/??10!!!;<R V@    @6    n+/3/3/]+3/99?3<7.+2!>7>3#"?F>R`GTGptg4EB<;BF3htpHSGaR{CDCaX64wN3Nw4Xa ;5!}@66@ 6@+ 6 } @6 }#o"l+/3/+/9/+]99/?3/+9?3/99/+9++10! %32654&+32654#"%! -}$^azj{aWckc6G ^TQe[Qw/}Գ O@.7 87      n k+/+/99?7>3#"?F><;BF3htpHSHbR{CNw4Xa 7@! 6 n  @3/]3/+/?9??+10)!#"'3265!;;J`D\LR=z)Ql0+]L2$@ nk+/+/?54&'ddekvyhde|{JF=9Epoj"^mf=; 1@    k+/3/3/?3/?<10!!!!!3TĞ?R,@ n k+/+/<??<9/10)#"5!327!;лf`P!s >ktj7L 7@"    @/]33/]/?%F+Cbqxssd@) i   } B@"6@6/}ok]+/<+/9/]++????9/]10! ! #!!265!  ;x*oz<xsaZbW5B@I>DJ "\@;P vy  $i # f+/9/+/9/9]]??]??]10]63 ! ?67!2654&#"I+9{Cݞbil[ehg7ItX$ G|{%p 6@ 6/_@% 6@6? ? ie+/]<+/]9/]+9+??9/]910++)!2%3254+32654+yzavgfla2>p5 r%zVX]K.,`%$@@e+/3/]??10!!!HZ31@/!.(' `  @6 O  ''@6@  @@ 6@/]+q3<<2/]+3//]+3/]?<7.+2!>3#"Z5#1/h.1$5Hhk5HNVXѵc\&..&\cWWNH5fiL%I!q J?S 3#"5%G4i20[HpRV4D-,U\]%F$q%8X, *3 9?%=@$ 6  h  3/3]/+/?2/9??+10)!#"'325!?iˑH&RdC-z;% @?      /     @$6PphO e]+/]qr+/]+qr9/9999?<<Rw%$@ he+/+/?SJ>F%;@P@ 60/]+qr32//??<10!!!!h)Q&\Lj$/y@7 %+% VY.O@"B (B@  6 @ 6 0 P  /]++q3<<3/]/]]??<3!5#"3i+1=FrgŖqiZ,/03 hg+h+'TH2HV@ $'%$&+55+55f$]!@4 6 6! ! &h%e+/3<<<2//+/2/???9?9/<<++10%#"'32654#"!#535!3#632*|>628OWhwwٱ5w#' Gku^^2U@ %&+5+5J=r@ @ 6 0@* 6   iBf+/+3]/]9/]?3+/]9?3+/99/10! 54>32&#"!!327m)Ъ9 ,3&1wp.u3Ѫ3>V!L2@  %&+55+55Q#M%n@  6 @ 6@ 6?i3/3]/+/]9/+]<+???99/+103 )!#"'325!32654+?5ˑH&Rd2>pC-z.,`%n@    @ 6 6@ 6 i  e+/<+/9/++]<<+?<?<9/9/103 )!!!!!32654+T6eh2?qo%k.,`[@ 6 P  @% 6  h   e+/3<<<2//+/? 6  O @/]]3/99/]]99/99/9/??+99?<<<9?3/+]<.+}ć.+}9910]!!#"'3267#"&'33267[HKjX XlHYĈ MV&=D`BUӑk+@w% _@ 0  @6  6 6/++]3]2/]+q/]?332&#"!!!!632327L][.+ )ʨo$-j:G+1 +5(34կ K K !!!!Dkkͯ; !!##)2}t #!!#!q|;t. !5!5!5!#llCXͯ !5!##*} !5!!5!#=*AůXH 3!!!kX;ͯH !333!ͯ2}}XH !!!!3qR+{H;tX.H !5!5!5!3.lXͯH !5!333֯ͯ}XH 3!5!3!5=R{H|H 3!!!!kk ;ͯ;H 3!!!3>)կ }} KH 33!!!¯ͯz) KAt;t;.H !5!5!5!3#llXͯKH !5!333*֯ͯK KH 3!5!!5!#={* K  !5!!5!!#(lkԯկ; !5!!##*)}t !5!!5!#!!!(*|)ԯկt;XH !5!3!!5!((ԯ;կH !5!333!(֯ͯ}}XH !5!3!3!!5!p{֯Sz(ԯt;կH!5!5!5!3!!!!#llkkXͯ;ͯ;H!5!333!!##*֯ͯ)}}}}H !!33!5!5!##!{ԯ{*,t;կ;tmH!!(mm!!(H! KH! KH! KhH #'+/37;?CGKOSW[_cgkosw3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#3#%3#%3#h}}}}}}}}||}}}} }}}}}}|| }}}}}}}}}}|| }}}}}}}}}}||}}}} }}}}}}||}}H}}}}}|}}}}}|}}}}}}|||||}}}}}}|}}}}}|}}}}}}|||||}}}}}}|}}}}}<H #'+/37;?CGKOSW[_cgkosw{=@Ի{|xsokgcplhd`WSOK_TPLH\C?;73@<840+'#($   Ծ{xvcu`Z_Y\F3E0.-zzרzzxz{`zc\z_0z3zz{{{cc__33{uEtDŕqAĔp@əm= Șl< ͝i9 ̜h8ѡe5Рd4եa1Ԥ`0@Y-X,U)T(Q%P$}M!|L IHy]x\ -,)(%$! yy y y yy-y,)y(%y$!y yy,,(( $$ 9/9/9/9/9/9/9/9/9/9/9/9/<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<</9/9/9/9/9/9/9/<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<103#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#%3#3#73#73#73#73#73#3#%3#73#73#73#%3#3#'3#'3#'3#'3#'3#3#73#73#73#73#73#3#'3#'3#'3#'3#'3#3#73#73#73#73#73#yxxxxyyyyxxxxyyyyyyxxyyyyxxxxyyyyxxxxyyyyxxyyyyJyyyxxxxyyyyxxxxyyyyxxyyyy;yy>xxxxyyyyxxxxyyyyyyyxxyyyyyxxxxyyyyxxxxyyyyyyyxxyyyyH}}}}}}}}}}}|}}}}}}}}}}}|}}}}}}}}}}}}|||||||||||}}}}}}}}}}}}|}}}}}}}}}}}|}}}}}}}}}}}}|||||||||||}}}}}}}}}}}}|}}}}}}}}}}}.H=AEIMQUY]aeimquy}#3#3#3#3!35#35#35#35#353353353353353353#%35335335335335#3'#3'#3'#3'#335335335335335#373533533533535!355#%353355##5##5##5##5#353353353353355##5##5##5##5#35335335335335||||||||)}}}}}}}}}|}|}}|}}|}||"|}|}}|}}|}}}}}||}}}}|}|}}|}}|}}|}}|}}|}"|v}|}}|}}|}}|}}|}||}|}}|}}|}}|}}|}}|}||}|}}|}}||}|}|u}v}u}v}u}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}||||||||||}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}||||||||||}}}}}}}}}}|}}}}}}}}}}>!!PP=!!~0! 0u   U,,0l ::lu UX #"54324&#"326L՗֗Bו|P3!4&#"326|vTRxwSTv,SwvTSwx&3!4#"32'#"&54632&L֖ז}A֖ #/9! ! 4#"32#"&54632#"&546327327#"wv\@A;/"!00!"//"!00!"/>ON?hu w@@d!00!"//"!00!"//$$ #-! ! 4&#"326%4&#"326327'#"'wv/"!00!"//"!00!"/gh?NOu w"//"!00!"//"!00$!IU'33!!#&''&'!5!677674#"32L6P6᧷L̏1}P1&$-.U7⮳E3}Qr3!Eǚ7 -.W#!!#!5!".54324&#"326M_6^Sړ6q6mkĹͰj\'&'#"54325>"32654&W#~InL^%桢\ * !|Z5]3ঠ㚤9#"'!72654'#"&5467$ ]z_Yd˯Z[iTRoU]%%̿ Z\D; +)7>5'#"&54632&54632632#"&'Nu6`ra?dCvsEj8ipNLX"!G}*tzwp3kKqo^]5oxcf;}..54632>32^ yeNmT"]mQzTn}dX?& 4UeD4V+3#"'&$'#"&54$32<(#7fݒEd^L9,B@zy…^0? #"&54632#"&54632@KqTtE;}|_n#딒`lu2R+{qw6Qo3@    /33//9?3/3/3/9999107632#"'532654&#"t^R;~rhuV=25GvtO0f>{.%*# @@6  @ 6  o@ 6 @p  /39/3/]9/+?3/]3/+]9/3+/q99.+}10632# '732654&#"'!!KgBH/8IG?!QA\N!l#+2>/28 PA@?o6@ 6)/32/3]+/+?39/]10!!5!#&dD]8' 6@+ 6 $@"6$@6$@ 6?o@6 6  !@ 6 & /33//+]q3/9+9+?3/]9/+++99++10#"&547&54632%2654&#"254&#"Ǹi6@7=yA6F=m(w}|x)+jfkkfi* (!I *e-5beb{#/@ " # @ 6'@. 6-@ 6  @ 6$  "#@ 6 */]33/+<9/]3/+<9/+33/+<9/]3/+<910>327'#"&''7.5467'4&#"32619o66p9Ӎӌ=q44n9֍pPOppOPp{я6m76p:ՏՌ4l89q8PppPOpp{      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~spaceexclamquotedbl numbersigndollarpercent ampersand quotesingle parenleft parenrightasteriskpluscommahyphenperiodslashzeroonetwothreefourfivesixseveneightninecolon semicolonlessequalgreaterquestionatABCDEFGHIJKLMNOPQRSTUVWXYZ bracketleft backslash bracketright asciicircum underscoregraveabcdefghijklmnopqrstuvwxyz braceleftbar braceright asciitilde AdieresisAringCcedillaEacuteNtilde Odieresis Udieresisaacuteagrave acircumflex adieresisatildearingccedillaeacuteegrave ecircumflex edieresisiacuteigrave icircumflex idieresisntildeoacuteograve ocircumflex odieresisotildeuacuteugrave ucircumflex udieresisdaggerdegreecentsterlingsectionbullet paragraph germandbls registered copyright trademarkacutedieresisnotequalAEOslashinfinity plusminus lessequal greaterequalyenmu1 partialdiff summationproductpi1integral ordfeminine ordmasculineOhmaeoslash questiondown exclamdown logicalnotradicalflorin approxequal increment guillemotleftguillemotrightellipsisnbspaceAgraveAtildeOtildeOEoeendashemdash quotedblleft quotedblright quoteleft quoterightdividelozenge ydieresis YdieresisfractionEuro guilsinglleftguilsinglrightfifl daggerdblperiodcenteredquotesinglbase quotedblbase perthousand Acircumflex EcircumflexAacute EdieresisEgraveIacute Icircumflex IdieresisIgraveOacute OcircumflexappleOgraveUacute UcircumflexUgravedotlessi circumflextildemacronbreve dotaccentringcedilla hungarumlautogonekcaronLslashlslashScaronscaronZcaronzcaron brokenbarEthethYacuteyacuteThornthornminusmultiply onesuperior twosuperior threesuperioronehalf onequarter threequartersfrancGbrevegbreveIdotScedillascedillaCacutecacuteCcaronccarondmacron overscoremiddot foursuperiorAbreveabreveAogonekaogonekDcarondcaronDslashEogonekeogonekEcaronecaronIJijLacutelacuteLcaronlcaronLdotldotNacutenacuteNcaronncaron napostrophe Odblacute odblacuteRacuteracuteRcaronrcaronSacutesacuteTcedillatcedillaTcarontcaronUringuring Udblacute udblacuteZacutezacuteZdotzdotnoGammanoThetanoPhinoalphanodelta noepsilonnosigmanotaunophi underscoredblminutesecond exclamdbl nsuperiorpeseta afii61248 afii61289 arrowleftarrowup arrowright arrowdown arrowboth arrowupdn arrowupdnbse orthogonal intersection equivalenceH22073H18543H18551H18533 openbullet commaaccentAmacronamacron Ccircumflex ccircumflexCdotcdotEmacronemacronEbreveebreveEdotedot Gcircumflex gcircumflexGdotgdotGcedillagcedilla Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonek Jcircumflex jcircumflexKcedillakcedilla kgreenlandicLcedillalcedillaNcedillancedillaEngengOmacronomacronObreveobreveRcedillarcedilla Scircumflex scircumflexTbartbarUtildeutildeUmacronumacronUbreveubreveUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexlongs Aringacute aringacuteAEacuteaeacute Oslashacute oslashacutetonos dieresistonos Alphatonos anoteleia EpsilontonosEtatonos Iotatonos Omicrontonos Upsilontonos OmegatonosiotadieresistonosAlphaBetaGammaDeltaEpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonPhiChiPsiOmega IotadieresisUpsilondieresis alphatonos epsilontonosetatonos iotatonosupsilondieresistonosalphabetagammadeltaepsilonzetaetathetaiotakappalambdamunuxiomicronpirhosigma1sigmatauupsilonphichipsiomega iotadieresisupsilondieresis omicrontonos upsilontonos omegatonos afii10023 afii10051 afii10052 afii10053 afii10054 afii10055 afii10056 afii10057 afii10058 afii10059 afii10060 afii10061 afii10062 afii10145 afii10017 afii10018 afii10019 afii10020 afii10021 afii10022 afii10024 afii10025 afii10026 afii10027 afii10028 afii10029 afii10030 afii10031 afii10032 afii10033 afii10034 afii10035 afii10036 afii10037 afii10038 afii10039 afii10040 afii10041 afii10042 afii10043 afii10044 afii10045 afii10046 afii10047 afii10048 afii10049 afii10065 afii10066 afii10067 afii10068 afii10069 afii10070 afii10072 afii10073 afii10074 afii10075 afii10076 afii10077 afii10078 afii10079 afii10080 afii10081 afii10082 afii10083 afii10084 afii10085 afii10086 afii10087 afii10088 afii10089 afii10090 afii10091 afii10092 afii10093 afii10094 afii10095 afii10096 afii10097 afii10071 afii10099 afii10100 afii10101 afii10102 afii10103 afii10104 afii10105 afii10106 afii10107 afii10108 afii10109 afii10110 afii10193 afii10050 afii10098WgravewgraveWacutewacute Wdieresis wdieresisYgraveygrave afii00208 quotereversed radicalex afii08941 afii61352 estimated oneeighth threeeighths fiveeighths seveneighthshouse revlogicalnot integraltp integralbtSF100000SF110000SF010000SF030000SF020000SF040000SF080000SF090000SF060000SF070000SF050000SF430000SF240000SF510000SF520000SF390000SF220000SF210000SF250000SF500000SF490000SF380000SF280000SF270000SF260000SF360000SF370000SF420000SF190000SF200000SF230000SF470000SF480000SF410000SF450000SF460000SF400000SF540000SF530000SF440000upblockdnblockblocklfblockrtblockltshadeshadedkshade filledbox filledrecttriaguptriagrttriagdntriaglfcircle invbullet invcircle smileface invsmilefacesunfemalemalespadeclubheartdiamond musicalnotemusicalnotedblundercommaaccent fivesuperior sevensuperior eightsuperiorcurrency $79:<$&$*$2$4$7s$8$9$:$>>0 0 *H CkSjy|oĠ?00)ъĽ5ǛSV0  *H 010U VeriSign Trust Network10U VeriSign, Inc.1,0*U #VeriSign Time Stamping Service Root1402U +NO LIABILITY ACCEPTED, (c)97 VeriSign, Inc.0 970512070000Z 991231070000Z010U VeriSign Trust Network10U VeriSign, Inc.1,0*U #VeriSign Time Stamping Service Root1402U +NO LIABILITY ACCEPTED, (c)97 VeriSign, Inc.00  *H 0. h|,-.  WSu3* [4 Z%}XsjxqX)X^-bXq"X/6MJ;"V~!lJGj6 -Ӵ90  *H :>{թy=q#+(ߌe,ZbVkbEƢ5"r-| CMlX 5ʉp*}a qfbB="2"d$006C!FXF%`0  *H 010U VeriSign Trust Network10U VeriSign, Inc.1,0*U #VeriSign Time Stamping Service Root1402U +NO LIABILITY ACCEPTED, (c)97 VeriSign, Inc.0 970512070000Z 991231070000Z01'0%U VeriSign Time Stamping Service10U VeriSign Trust Network1402U +NO LIABILITY ACCEPTED, (c)97 VeriSign, Inc.10U VeriSign, Inc.10UInternet00  *H 0aGܴ^i b1FI:?xZcEO n06- o' Q`5OTOз,B Ѝ^㖴"IBlӘV.:X"e匫xGBh[-}0  *H m`_i{p+b#D Q#tI'\q5+ൖ苧KsH ڋ %VNGWF8V!&;-%2Λ@GmGv0;~*1+ݰUApF-,~0 0 yfnжneq0  *H 0a10UInternet10U VeriSign, Inc.1301U *VeriSign Commercial Software Publishers CA0 980416000000Z 990416235959Z0]10UInternet10U VeriSign, Inc.1301U *VeriSign Commercial Software Publishers CA1F0DU =www.verisign.com/repository/CPS Incorp. by Ref.,LIAB.LTD(c)961>0<U 5Digital ID Class 3 - Microsoft Software Validation v21 0 UUS10U Washington10URedmond10UMicrosoft Corporation10U Microsoft Corporation0 0  *H  0&dm{AO o*q.S26h5IؖeS zpm̳*02X|k%gw #1,0(0u0a10UInternet10U VeriSign, Inc.1301U *VeriSign Commercial Software Publishers CAyfnжneq0 *H 0 *H  1  +70 +7 10  +70 *H  1|8ӛ C(0Z +7 1L0J" Arial Black font$"http://www.microsoft.com/truetype/0  *H $2p#& +GQrvDR$;M KưUm mGrI ]m m|鵠Vű".)'Q,mZ: Ō?AqE?7lхa}2Hc!o5e8C1`UۀKa:et&|LO6跟V+P>?9H|5Nm8j+ QW)~P|lp0 *H  100010U VeriSign Trust Network10U VeriSign, Inc.1,0*U #VeriSign Time Stamping Service Root1402U +NO LIABILITY ACCEPTED, (c)97 VeriSign, Inc.C!FXF%`0 *H Y0 *H  1  *H 0 *H  1 981110215215Z0 *H  1B*]7W-0  *H |4J: ۰$sz7$fjbpcxHĭ!:| ? ّ/슩fDeS\K(%Qʢ:.&] w5Kx#'lib/tmp/0000755000175000001440000000000011115113715011313 5ustar monsuserslib/tmp/wrong.png0001666000175000001440000001021210715421117013161 0ustar monsusersPNG  IHDR8z pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3gAMA|Q cHRMz%u0`:o_FIDATx\ۑ:nm8p8;B!p&:T~}tWQkF֌z^Ex$^(    $H@   H@$  p"?8 $ A(ң,Gj"c^Dֶ9D _?pY\l"]rv7q&(KJ?_.nاqnYzsi_g_4{_.߫:QU I_xxEյuz-d>յ~؁|zOfzm|4/cѾ6DL}z>:-"\{Zml[Oӈ:lISosQe4ms?k;ګkWhDb{l$l WBeY$9Htin,5$qN0M} g>z$uMs84M6b:&%4`sN'%P ضL{ET)C$5; $mT|P `֯׺ $ҶӇ{VjG$i3Ha5; $B'TV~ pOU5z=r\.0,+lIlqO_ң8iT_їe. F@ _ &Bf}L|ꍎ#  .& !:I m;|ZMt\$+.^,jhԁ¹mc ϰ{lkrt~]fl]cؠ/lRDguurշu/uSoys_S)qoUBk l&R9*a/az٪]B۞׶?WKчF.(?($c_*73Tsعpd [!QňU!~x+ QzQr)!ݤ~& m؈k!h :m뮗tKP0gYXrճ\5t:A|uAڴ?ƱX슶0H:c_b'>BؓGUMٽegիaO@ ݊TU5os~sQ@;> +k74nr;lPn!:w]l +)ز9ޙh<>fRBa"A o3ģ|=a:nln/>PTΦ`Ma*멂(kqt= 8d_|$C\|>ʬמ\c5w؝>;a !6L]w>C^x9&_    H@$  $H@  Wċw $.3"IENDB`lib/tmp/expired.png0001666000175000001440000001033010715421116013465 0ustar monsusersPNG  IHDR8z pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3gAMA|Q cHRMz%u0`:o_FIDATx[ѕ0 ll (KpK,AK(AJ}7C { !LnfD1!cLG@?H HA$ A H$ A Hύ"cf3zV|~:F]G e/Xz\ Fd\l䨪~lh0L"c~1&MݵՋU%acޏu?j5H9equζqns\k[/(6 1ݷ"˺Θ6|ґruq.w: ׍{LԵﻮ,|]iz"Gk]ؔ$2~tG9y s,S"&MQse=I\bfΘ忊~my~9^8  ";?xi<ꍎ#   x \0MߓC3瀻/EYa%},ʎлhHX4Ʊ\N﫭_ )4VTZi>[}pNUyX}jV-kŮV+xU̺=)b8e|۠V|ݎhLScw_)hiSZt(;pqOIZUZ}IgkWT#F"i#بߨCGtyN={|eKj]\@VbHo-OO ;&^NQ"Ct8*t:^jtr6"?\;c[ߡsn&` 3`6$_M!#=Bӄr(Dtmgz-2fpq~ضk!ૻ1" nQ&="PU i m81/!,R:r0zc`5rt]oӜiMU:8WO)ww<%SY~V*_|k4%4vPD,JS|Li`?j)PI"iSR^Oj?^W瀄(sxE@]ޔ=s@"j# H7nB$H@   H@$  $ ]0A<3b 3}IENDB`lib/usage.pl0000644000175000001440000000321411115114142012147 0ustar monsusersuse Captcha; #$TMP temp path for generated images; #$FONT_PATH where to search for font file #$FONT font name; #$EXP = 60 * 15; # 15 min expiration time #$USE_EXP = 1; do expiration checks # for ex: # $Captcha::TMP = '/the/path/should/point/to/captchas/tmp'; # Captcha check => my @t = Request->param('check'); @t = reverse @t if length($t[0]) == 40; my $r = Captcha->check(@t); if ($r != 1) { $self->set_error( captcha => $r == -1 ? 'Bad Code (not exists)' : $r == 0 ? 'Wrong word' : $r == -2 ? 'Code Expired' : 'Bad Code ('.$r.')' ); Trace->dbg(['Redirecting to %s',$ENV{REQUEST_URI}]); Response->redirect($ENV{REQUEST_URI}); return; } # <= Captcha check print Template->process(\q{ [% SET cp = Captcha; %] [% IF cp %]
Введите текст, который вы видите на этой картинке -»
(примечание: на картинке только заглавные английские буквы)
If you dont see picture, ask administrator
[% END %] },{ Captcha => sub { Captcha->make(); } });lib/Captcha.pm0000664000175000001440000001602310775672024012436 0ustar monsuserspackage Captcha; use strict; use Image::Imlib2; use Digest::SHA1 qw(sha1_hex); use constant pi => 3.141592; use Carp qw(croak carp); use File::Find qw(find); use IO::Handle; our ($FONT_PATH,$FONT,$TMP,$EXP,$USE_EXP); BEGIN { ( my $f = __FILE__ ) =~ s/\.pm$//i; $FONT_PATH = $f; $FONT = 'font'; $TMP = '/opt/tmp/captcha'; $EXP = 60 * 15; # 15 min $USE_EXP = 1; } { my $fdbg; sub d($) { local ($@,$!); unless (-d $TMP) { croak "CAPTCHA: Please, create temp dir ($TMP) for images or set it via \$".__PACKAGE__."::TMP"; } unless ($fdbg) { open $fdbg,'>>',"$TMP/log" or do { warn "CAPTCHA: log error: $!";return }; chmod oct(1664),"$TMP/log"; $fdbg->autoflush(1); } local $_=shift; s{\r?\n$}{}sg; s{\r?\n}{\\n}sg; printf $fdbg "%s [%s] %s (%s)\n",scalar(localtime),$ENV{REMOTE_ADDR},$_,$ENV{REQUEST_URI}; } } sub la() { open my $f,'<','/proc/loadavg'; local $/=' '; my $la = <$f>; close $f; return $la; } sub word (;$) { my $size = shift || 7; my %c; $c{0} = [qw(e u i o a oo ae)]; $c{1} = [qw(r s d l n m )]; $c{1} = [qw(r s l n m )]; $c{2} = [qw(q w t p f g h j k z x c v b)]; my $s = ''; my $nc = irnd(1,3); my $cs = 1; my %lc; @lc{0,1,2} = ('','',''); while (length($s) < $size) { if ($nc < 0) { $cs = $cs == 0 ? irnd(1,3) : 0; $nc = $cs == 0 ? 0 : $cs == 1 ? irnd(1,2) : 0; } my $set = $c{$cs}; my $char; do { $char = $set->[ irnd(0,0+@$set) ]; } while ( $char eq $lc{$cs} or ( $lc{$cs} and ( index($lc{$cs},$char) != -1 or index($char,$lc{$cs}) != -1 ) ) ); next if length($s) + length($char) > $size; $nc -= length($char); $lc{$cs} = $char; $s .= $char; $nc = -1 if length($char) > 1; } return uc($s); } sub rnd($$) { my ($min,$max) = @_; return $min + rand() * ( $max - $min ); } sub irnd($$) { my ($min,$max) = @_; return int rnd($min,$max); } sub rot (@) { @_[1..$#_],$_[0] } sub avg { my ($sx,$sy,$c,$cx,$cy) = @_; my @r; for (0..2) { $r[$_] = int( ( $$c[$_] * 0.95 + $$cx[$_] * 0.025 + $$cy[$_] * 0.025 ) ); } $r[3] = 255; return @r; } sub transform { my ($image,$fg,$bg) = @_; my $width = $image->width; my $height = $image->height; my $image2 = Image::Imlib2->new($width,$height); my (@fq,@ph,@am); my @bg = rot unpack 'C4',pack 'N',( $bg | 0xff000000 ); my @fg = rot unpack 'C4',pack 'N',( $fg | 0xff000000 ); $am[1] = rnd ( 6,8 ); $fq[1] = pi / $width * 1.05 * rnd( 0.95,1.05 ); $ph[1] = pi + rnd( -pi(),pi ); $fq[2] = pi / $height * 2.5 * rnd(0.95,1.05); $ph[2] = pi/2 + rnd( -pi()/4,pi/4 ); $am[2] = rnd( 6,8 ); $fq[3] = pi / $width * 3 * rnd( 0.95,1.05 ); $ph[3] = 0 + rnd( -pi(),pi ); $fq[4] = pi / $height * rnd( 0.95,1.05 ); $ph[4] = pi + rnd( -pi()/8,pi/8 ); for my $x ( 0 .. $width-1 ) { for my $y ( 0 .. $height-1 ) { my $sx = $x; my $sy = $y; my $sx = $x + ( sin($x * $fq[1] + $ph[1]) + sin($y * $fq[2] + $ph[2]) ) * $am[1]; my $sy = $y + ( sin($x * $fq[3] + $ph[3]) + sin($y * $fq[4] + $ph[4]) ) * $am[2]; my @c; if($sx < 0 || $sy < 0 || $sx > $width || $sy > $height ){ @c = @bg; }else{ @c = $image->query_pixel(int $sx,int $sy); } $image2->set_color(@c); $image2->draw_point($x,$y); } } my $nw = int ( $width * 0.8 ); my $nh = int ( $height * 0.8 ); return $image2->create_scaled_image($nw,$nh); } sub captcha() { unless (-d $TMP) { croak "CAPTCHA: Please, create temp dir ($TMP) for images or set it via \$".__PACKAGE__."::TMP"; } unless (-e "$FONT_PATH/${FONT}.ttf") { croak "CAPTCHA: Please, put font file to ($FONT_PATH/$FONT) or set path via \$".__PACKAGE__."::FONTPATH/\$".__PACKAGE__."::FONT"; } my ($w,$h) = (200,70); my $image = Image::Imlib2->new($w,$h); $image->add_font_path($FONT_PATH); $image->load_font("$FONT/24"); my $word = word(6); #warn "Creating captcha with word $word\n"; my $bg = int irnd (0,0x606060); my $fg = ~ $bg; my @bg = rot unpack 'C4',pack 'N',( $bg | 0xff000000 ); my @fg = rot unpack 'C4',pack 'N',( $fg | 0xff000000 ); $image->set_color(@bg); $image->fill_rectangle(0,0,200,70); $image->set_color(@fg); my ($tw,$th) = $image->get_text_size($word); $image->draw_text(int(($w - $tw)/2),int(($h - $th)/2)-4,$word); my $img2 = transform($image,$fg,$bg); my $sha = sha1_hex($word); d("Created captcha `$sha' for `$word'"); return ($sha,$img2); } sub save_file($$) { my $um = umask(0); eval { my ($w,$i) = @_; my ($w1,$w2,$rest) = split //,$w,3; unless (-d "$TMP/$w1") { mkdir "$TMP/$w1" , oct 1771 or croak "CAPTCHA: Cant create temp: $!" } unless (-d "$TMP/$w1/$w2") { mkdir "$TMP/$w1/$w2", oct 1771 or croak "CAPTCHA: Cant create temp: $!" } my $f = "$TMP/$w1/$w2/$rest.png"; $i->save($f); chmod oct(1664),$f; }; die $@ if $@; umask($um); } sub check ($$) { shift if @_ == 3; my $s = uc shift; my $hash = shift; $s =~ tr/015D/OLSO/; my $w = sha1_hex($s); my ($w1,$w2,$rest) = split //,$w,3; #warn "$hash\n$w\n"; if ($hash ne $w) { eval { d("Wrong hash: $w <=> $hash"); warn "CAPTCHA: ($s) Wrong hash: $w <=> $hash\n"; Trace->dbg(["CAPTCHA: ($s) Wrong hash: $w <=> $hash ($ENV{REMOTE_ADDR})"]); }; return 0 }; my $f = "$TMP/$w1/$w2/$rest.png"; my $r; if ( ! -e $f ){ eval { d("($s) Non-existing file $f"); warn "CAPTCHA: ($s) Non-existing file $f\n"; Trace->dbg(["CAPTCHA: ($s) Non-existing file $f"]); }; return -1; } elsif ($USE_EXP and time - (stat($f))[9] > $EXP) { eval { d("($s) Expired file $f"); warn "CAPTCHA: ($s) Expired file $f\n"; Trace->dbg(["CAPTCHA: ($s) Expired file $f"]); }; $r = -2; # expired } else { eval { d("($s) OK $f"); warn "CAPTCHA: ($s) OK $f\n"; Trace->dbg(["CAPTCHA: ($s) OK $f"]); }; $r = 1; } unlink $f or do { eval { d("($s) Can't delete used file $f: $!"); carp "CAPTCHA: ($s) Can't delete used file $f: $!"; Trace->dbg(["CAPTCHA: ($s) Can't delete used file $f: $!"]); }; $r = -1; }; rmdir "$TMP/$w1/$w2"; rmdir "$TMP/$w1"; return $r; } sub data { my $png = shift; my $w = shift; return unless $w =~ /^[\da-f]{40}$/; my ($w1,$w2,$rest) = split //,$w,3; open my $f, '<',"$TMP/$w1/$w2/$rest.png" or return; my $data = do { local $/; <$f> }; close $f; return $data; } sub get_old_unused() { #opendir(my $dir,$TMP); return unless $USE_EXP; my $found; my $t = time - int ( $EXP*0.5 ); SEARCH: { find ({ wanted => sub { return if !-f || length $_ < 40 || (stat)[9] > $t; $found = $_; last SEARCH; }, no_chdir => 1, },$TMP); } return unless $found; utime(time,time,$found); for($found){ #s{(?:^\Q$TMP/\E|\.png$|/)}{}g; # 3 different is much more faster s{^\Q$TMP/\E}{}; s{\.png$}{}; s{/}{}g; } #print $found."\n"; d("Found existing captcha `$found'"); return $found; } sub make { my $x; d("Making captcha"); return $x if $x = get_old_unused(); my ($w,$i) = captcha(); save_file($w,$i); return $w; } #my ($w,$i) = captcha(); #save_file($w,$i); #print $w."\n"; #my $w = 'afe6ddc40a17e763b14e8a7c7ce1149460258d92'; #my $s = 'snlidre'; #4f35e0f8797d3be905d8854c344da8dc8b1182ae #print check($s,$w)."\n"; #print $w."\n"; #print sha1_hex(uc $s)."\n"; #get_old_unused(); #print la; 1;