import
[web.mtrack] / inc / captcha.php
1 <?php # vim:ts=2:sw=2:et:
2 /* For licensing and copyright terms, see the file named LICENSE */
3
4 interface IMTrackCaptchImplementation {
5   /** return the captcha content */
6   function emit($form);
7   /** check that the captcha is good
8    * Returns true/false */
9   function check($form);
10 }
11
12 class MTrackCaptcha {
13   static $impl = null;
14
15   static function register(IMTrackCaptchImplementation $impl)
16   {
17     self::$impl = $impl;
18   }
19
20   static function emit($form)
21   {
22     if (self::$impl !== null) {
23       return self::$impl->emit($form);
24     }
25     return '';
26   }
27
28   static function check($form)
29   {
30     if (self::$impl !== null) {
31       return self::$impl->check($form);
32     }
33     return true;
34   }
35 }
36
37 class MTrackCaptcha_Recaptcha implements IMTrackCaptchImplementation {
38   public $errcode = null;
39   public $pub;
40   public $priv;
41   public $userclass;
42
43   function __construct($pub, $priv, $userclass = 'anonymous|authenticated') {
44     $this->pub = $pub;
45     $this->priv = $priv;
46     $this->userclass = explode("|", $userclass);
47     MTrackCaptcha::register($this);
48   }
49
50   function emit($form)
51   {
52     $class = MTrackAuth::getUserClass();
53     if (!in_array($class, $this->userclass)) {
54       return '';
55     }
56     $pub = $this->pub;
57     $err = $this->errcode === null ? '' : "&error=$this->errcode";
58     return <<<HTML
59 <script type='text/javascript' src="https://api-secure.recaptcha.net/challenge?k=$pub$err"></script>
60 <noscript>
61   <iframe src="https://api-secure.recaptcha.net/noscript?k=$pub$err"
62     height="300" width="500" frameborder="0"></iframe>
63   <br/>
64   <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
65   <input type="hidden" name="recaptcha_response_field"
66     value="manual_challenge"/>
67 </noscript>
68 HTML;
69   }
70
71   function check($form)
72   {
73     $class = MTrackAuth::getUserClass();
74     if (!in_array($class, $this->userclass)) {
75       return true;
76     }
77     if (empty($_POST['recaptcha_challenge_field']) or
78         empty($_POST['recaptcha_response_field'])) {
79       return array('false', 'incorrect-captcha-sol');
80     }
81
82     $data = http_build_query(array(
83           'privatekey' => $this->priv,
84           'remoteip' => $_SERVER['REMOTE_ADDR'],
85           'challenge' => $_POST['recaptcha_challenge_field'],
86           'response' => $_POST['recaptcha_response_field'],
87           ));
88     $params = array(
89         'http' => array(
90           'method' => 'POST',
91           'content' => $data,
92           ),
93         );
94     $ctx = stream_context_create($params);
95
96     /* first line: true/false
97      * second line: error code
98      */
99     $res = array();
100     foreach (file('http://api-verify.recaptcha.net/verify', 0, $ctx) as $line) {
101       $res[] = trim($line);
102     }
103     if ($res[0] == 'true') {
104       return true;
105     }
106     $this->errcode = $res[1];
107     return false;
108   }
109
110 }
111