Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 *  Equation driver for Text_CAPTCHA.
4
 *  Returns simple equations as string, e.g. "9 - 2"
5
 *
6
 *  @author  Christian Weiske <cweiske@php.net>
7
 *  @author  Christian Wenz <wenz@php.net>
8
 *  @license BSD License
9
 */
10
require_once 'Text/CAPTCHA.php';
11
 
12
class Text_CAPTCHA_Driver_Equation extends Text_CAPTCHA
13
{
14
    /**
15
     * Operators that may be used in the equation.
16
     * Two numbers have to be filled in, and
17
     *  %s is needed since number2text conversion
18
     *  may be applied and strings filled in.
19
     *
20
     * @access protected
21
     * @var array
22
     */
23
    var $_operators = array(
24
        '%s * %s',
25
        '%s + %s',
26
        '%s - %s',
27
        'min(%s, %s)',
28
        'max(%s, %s)'
29
    );
30
 
31
    /**
32
     * The equation to solve.
33
     *
34
     * @access protected
35
     * @var string
36
     */
37
    var $_equation = null;
38
 
39
    /**
40
     * Minimal number to use in an equation.
41
     *
42
     * @access protected
43
     * @var int
44
     */
45
    var $_min = 1;
46
 
47
    /**
48
     * Maximum number to use in an equation.
49
     *
50
     * @access protected
51
     * @var int
52
     */
53
    var $_max = 10;
54
 
55
    /**
56
     * Whether numbers shall be converted to text
57
     *
58
     * @access protected
59
     * @var bool
60
     */
61
    var $_numbersToText = false;
62
 
63
    /**
64
     * Complexity of the generated equations.
65
     * 1 - simple ones such as "1 + 10"
66
     * 2 - harder ones such as "(3-2)*(min(5,6))"
67
     *
68
     * @access protected
69
     * @var int
70
     */
71
    var $_severity = 1;
72
 
73
    /**
74
     * Last error
75
     *
76
     * @access protected
77
     * @var PEAR_Error
78
     */
79
    var $_error = null;
80
 
81
 
82
    /**
83
     * Initialize the driver.
84
     *
85
     * @param array $options Optionally supply options for the initialization phase
86
     *
87
     * @access public
88
     * @return true on success, PEAR_Error on error.
89
     */
90
    function init($options = array())
91
    {
92
        if (isset($options['min'])) {
93
            $this->_min = (int)$options['min'];
94
        } else {
95
            $this->_min = 1;
96
        }
97
        if (isset($options['max'])) {
98
            $this->_max = (int)$options['max'];
99
        } else {
100
            $this->_max = 10;
101
        }
102
        if (isset($options['numbersToText'])) {
103
            $this->_numbersToText = (bool)$options['numbersToText'];
104
        } else {
105
            $this->_numbersToText = false;
106
        }
107
        if (isset($options['severity'])) {
108
            $this->_severity = (int)$options['severity'];
109
        } else {
110
            $this->_severity = 1;
111
        }
112
 
113
        if ($this->_numbersToText) {
114
            include_once 'Numbers/Words.php';
115
            if (!class_exists('Numbers_Words')) {
116
                $this->_error = PEAR::raiseError('Number_Words package required', true);
117
                return $this->_error;
118
            }
119
        }
120
 
121
        return $this->_createPhrase();
122
    }
123
 
124
    /**
125
     * Create random CAPTCHA equation.
126
     *
127
     * This method creates a random equation. The equation is
128
     * stored in $this->_equation, the solution in $this->_phrase.
129
     *
130
     * @access protected
131
     * @return mixed    true on success, PEAR_Error on error
132
     */
133
    function _createPhrase()
134
    {
135
        switch ($this->_severity) {
136
            case 1:
137
                list($this->_equation, $this->_phrase) = $this->_createSimpleEquation();
138
                break;
139
 
140
            case 2:
141
                list($eq1, $sol1) = $this->_createSimpleEquation();
142
                list($eq2, $sol2) = $this->_createSimpleEquation();
143
                $op3 = $this->_operators[rand(0, count($this->_operators) - 1)];
144
                list($eq3, $this->_phrase) = $this->_solveSimpleEquation($sol1, $sol2, $op3);
145
                $this->_equation = sprintf($op3, '(' . $eq1 . ')', '(' . $eq2 . ')');
146
                break;
147
 
148
            default:
149
                $this->_error = PEAR::raiseError('Equation complexity of ' . $this->_severity . ' not supported', true);
150
                return $this->_error;
151
        }
152
        return true;
153
    }
154
 
155
    /**
156
     * Creates a simple equation of type (number operator number)
157
     *
158
     * @access protected
159
     * @return array    Array with equation and solution
160
     */
161
    function _createSimpleEquation()
162
    {
163
        $one = rand($this->_min, $this->_max);
164
        $two = rand($this->_min, $this->_max);
165
        $operator = $this->_operators[rand(0, count($this->_operators) - 1)];
166
 
167
        return $this->_solveSimpleEquation($one, $two, $operator);
168
    }
169
 
170
    /**
171
     * Solves a simple equation with two given numbers
172
     * and one operator as defined in $this->_operators.
173
     *
174
     * Also converts the numbers to words if required.
175
     *
176
     * @param int    $one      First number
177
     * @param int    $two      Second number
178
     * @param string $operator Operator
179
     *
180
     * @access protected
181
     * @return array    Array with equation and solution
182
     */
183
    function _solveSimpleEquation($one, $two, $operator)
184
    {
185
        $equation = sprintf($operator, $one, $two);
186
        $code = '$solution=' . $equation . ';';
187
        eval($code);
188
 
189
        if ($this->_numbersToText) {
190
            $equation = sprintf($operator, Numbers_Words::toWords($one), Numbers_Words::toWords($two));
191
        }
192
 
193
        return array($equation, $solution);
194
    }
195
 
196
    /**
197
     * Return the solution to the equation.
198
     *
199
     * This method returns the CAPTCHA phrase, which is
200
     *  the solution to the equation.
201
     *
202
     * @access  public
203
     * @return  string   secret phrase
204
     */
205
    function getPhrase()
206
    {
207
        return $this->_phrase;
208
    }
209
 
210
    /**
211
     * Creates the captcha. This method is a placeholder,
212
     *  since the equation is created in _createPhrase()
213
     *
214
     * @access protected
215
     * @return PEAR_Error
216
     */
217
    function _createCAPTCHA()
218
    {
219
        //is already done in _createPhrase();
220
    }
221
 
222
    /**
223
     * Returns the CAPTCHA (as a string)
224
     *
225
     * @access public
226
     * @return string
227
     */
228
    function getCAPTCHA()
229
    {
230
        return $this->_equation;
231
    }
232
 
233
}//class Text_CAPTCHA_Driver_TextEquation extends Text_CAPTCHA