captcha-server

Gesponsorde koppelingen

PHP script bestanden

  1. captcha-server

« Lees de omschrijving en reacties

Server
De server output de data om een nieuwe Captcha te genereren. Er wordt een 'vraag' gesteld, en een aantal mogelijke afbeeldingen gegeven waarbij de bezoeker 0 of meer afbeeldingen moet selecteren.

Input

- Thema
Je kunt een captcha thema ID opgeven. Er wordt dan een vraag geselecteerd bij dit thema. In de testomgeving hebben we maar 1 thema beschikbaar; Thema 'dieren', met ID '1'.

- Aantal afbeeldingen
De voorkeur van het aantal te laden afbeeldingen (maximaal 9).

- Aantal antwoorden
De voorkeur van het aantal te selecteren afbeeldingen voor het goed beantwoorden van de captcha.



output
- Thema
Het thema (label + ID) die gebruikt is.

- Server path
Het pad waar de afbeeldingen gevonden kunnen worden. Deze optie is ingebouwd zodat ik, wanneer de captcha-server voor meerdere websites wordt gebruikt, de traffic van het laden van afbeeldingen kan spreiden over verschillende servers.

- Vraagstelling
De vraagstelling bij de captcha.

- Afbeeldingen
Per afbeelding een bestandsnaam, een alt text en een 'flag' of de afbeelding bij het beantwoorden wel of niet geselecteerd zou moeten zijn.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
"thema naam", "thema id"
"http://server path/"
"Vraag stelling"
"bestandsnaam", "Alt tekst", "true"
"bestandsnaam", "Alt tekst", "true"
"bestandsnaam", "Alt tekst", "false"
...


Bij een fout wordt er 1 regel ge-output met de gevonden foutmeling.


Database dump
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
CREATE TABLE `captcha_answers` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `question` int(10) unsigned NOT NULL default '0',
  `image` int(10) unsigned NOT NULL default '0',
  `value` varchar(5) NOT NULL default 'false',
  PRIMARY KEY  (`id`)
);

CREATE TABLE `captcha_images` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `file` varchar(255) NOT NULL default '',
  `description` text,
  PRIMARY KEY  (`id`)
);

CREATE TABLE `captcha_questions` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `theme` int(10) unsigned NOT NULL default '0',
  `lable` text NOT NULL,
  PRIMARY KEY  (`id`)
);

CREATE TABLE `captcha_themes` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`id`)
);




server.php
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?php

    define("LF", "\n", true);

    require_once(dirname(__FILE__) . '/library.php');

    // Load settings
    $theme_id = stringToInt(getGet("theme"));
    $number_of_images = stringToInt(getGet("images"));
    $number_of_answers = stringToInt(getGet("answers"));


    // Connect to database
    if(mysql_connect("localhost", "username", "password"))
    {

        if(mysql_select_db("database"))
        {

            $theme = false;

            // Validate requested theme
            $sql = "SELECT * FROM `captcha_themes` WHERE `id` = '" . $theme_id . "' LIMIT 1;";
            $rs = mysql_query($sql) or die(mysql_error());

            if($theme = mysql_fetch_assoc($rs)) // Theme found?
            {
                // $theme_id ok!
            }
            else
            {
                $sql = "SELECT * FROM `captcha_themes` ORDER BY rand() LIMIT 1;";
                $rs = mysql_query($sql) or die(mysql_error());
                $theme = mysql_fetch_assoc($rs) or die(mysql_error());
            }


            // Validate requested number of images
            if($number_of_images < 2)
            {

                $number_of_images = 2;
            }

            elseif($number_of_images > 9)
            {

                $number_of_images = 9;
            }


            // Validate requested number of answers
            if($number_of_answers < 1)
            {

                $number_of_answers = 1;
            }

            elseif($number_of_answers > $number_of_images)
            {

                $number_of_answers = 1;
            }


            if($theme) // Theme found
            {
                $answers = array();

                // lookup random question
                $sql = "SELECT * FROM `captcha_questions` WHERE `theme` = '" . $theme["id"] . "' ORDER BY rand() LIMIT 1;";
                $rs = mysql_query($sql) or die(mysql_error());

                if($question = mysql_fetch_assoc($rs)) // Question found?
                {
                    // Lookup random answers
                    $sql = "SELECT `i`.`file`, `i`.`description` FROM `captcha_images` AS `i` LEFT JOIN `captcha_answers` AS `a` ON `i`.`id` = `a`.`image` WHERE `question` = '" . $question["id"] . "' AND `value` = 'true' ORDER BY rand() LIMIT " . $number_of_answers . ";";
                    $rs = mysql_query($sql) or die(mysql_error());

                    while($a = mysql_fetch_assoc($rs))
                    {

                        $answers[] = array($a["file"], $a["description"], true);
                    }

                    
                    $sql = "SELECT `i`.`file`, `i`.`description` FROM `captcha_images` AS `i` LEFT JOIN `captcha_answers` AS `a` ON `i`.`id` = `a`.`image` WHERE `question` = '" . $question["id"] . "' AND `value` = 'false' ORDER BY rand() LIMIT " . ($number_of_images - $number_of_answers) . ";";
                    $rs = mysql_query($sql) or die(mysql_error());

                    while($a = mysql_fetch_assoc($rs))
                    {

                        $answers[] = array($a["file"], $a["description"], false);
                    }


                    // Shuffle answers
                    shuffle($answers);

                    // Create CSV output
                    $output = '"' . addslashes($theme["name"]) . '", "' . addslashes($theme["id"]) . '"' . LF // Theme & ID
                    . '"http://www.pholeron.com/projects/captcha/images/"' . LF // Server path
                    . '"' . addslashes($question["lable"]) . '", "' . $question["id"] . '"'; // Question & ID

                    for($i = 0; $i < sizeof($answers); $i++) // Answers
                    {
                        $output .= LF . '"' . addslashes($answers[$i][0]) . '", "' . addslashes($answers[$i][1]) . '", "' . ($answers[$i][2] ? 'true' : 'false') . '"';
                    }
                }

                else
                {
                    $output = 'Error: No questions found for theme "' . $theme["name"] . '".';
                }
            }

            else
            {
                $output = 'Error: Cannot find default theme.';
            }
        }

        else
        {
            $output = 'Error: Cannot connect to database.';
        }
    }

    else
    {
        $output = 'Error: Cannot connect to database server.';
    }


    echo $output;

?>


==================================================

Bij een "server" hoort natuurlijk ook een "client". Deze heb ik dan ook uitgewerkt.
Ik heb de class 'Captcha' gebouwd om de gegevens te laden van de server en te verwerken. Deze class is simpel van opzet omdat het nu in hoofdzaak om de server gaat.

Ik maak gebruik van de functie file_get_contents() om de data van de server te lezen. Deze moet dan natuurlijk wel toestemming hebben om een URL te mogen openen (denk aan beveiliging instellingen van je server).

De captcha class leest de ontvangen data van de server uit en verwerkt deze. Ook biedt de class de functie toHtml() om de captcha op te bouwen in je formulier, en de functie validate() om na het POST'en van het formulier de captcha te controleren.


captcha.cls.php
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<?php

    class Captcha
    {
        var
$captcha_data;
        var
$captcha_path = 'http://www.pholeron.com/projects/captcha/server.php';

        function
Captcha($theme_id = '0', $number_of_images = 6, $number_of_answers = 1)
        {

            // Init captcha data
            $this->captcha_data = array();

            // Load captcha data
            $this->load_data($theme_id, $number_of_images, $number_of_answers);
        }

        function
load_data($theme, $images, $answers)
        {

            // Retrieve from captcha server
            $data = file_get_contents($this->captcha_path . '?theme=' . urlencode($theme) . '&images=' . urlencode($images) . '&answers=' . urlencode($answers));

            if($data)
            {

                // Parse recieved data
                $csv = csvToArray($data);

                if(sizeof($csv) > 1) // Validate data
                {
                    // Load captcha theme
                    $this->captcha_data["theme"]["lable"] = $csv[0][0];
                    $this->captcha_data["theme"]["id"] = $csv[0][1];

                    // Load captcha server path
                    $this->captcha_data["file_path"] = $csv[1][0];
                    
                    // Load captcha question
                    $this->captcha_data["question"]["lable"] = $csv[2][0];
                    $this->captcha_data["question"]["id"] = $csv[2][1];

                    // Load captcha images & answers
                    $this->captcha_data["alt"] = array();
                    $this->captcha_data["answers"] = array();
                    $this->captcha_data["images"] = array();

                    for($i = 3; $i < sizeof($csv); $i++)
                    {

                        $this->captcha_data["images"][] = $csv[$i][0];
                        $this->captcha_data["alt"][] = $csv[$i][1];
                        $this->captcha_data["answers"][] = (strcasecmp($csv[$i][2], "true") === 0);
                    }
                }

                else // Error in data
                {
                    die('Error from captcha server at ' . $this->captcha_path . '<br><br>' . $csv[0][0]);
                }
            }

            else
            {
                die('Cannot load data from captcha server at ' . $this->captcha_path);
            }
        }


        // Return captcha
        function toHtml()
        {

            $s = '<div class="captcha">'
            . '<h1>' . htmlentities($this->captcha_data["question"]["lable"]) . '</h1>'
            . '<table border="0" cellpadding="0" cellspacing="5">'
            . '<tr>';
            
            for($i = 0; $i < sizeof($this->captcha_data["images"]); $i++)
            {

                $s .= '<td><img alt="' . htmlentities($this->captcha_data["alt"][$i]) . '" border="0" src="' . htmlentities($this->captcha_data["file_path"] . $this->captcha_data["images"][$i]) . '"></td>';
            }


            $s .= '</tr>'
            . '<tr>';

            for($i = 0; $i < sizeof($this->captcha_data["images"]); $i++)
            {

                $s .= '<td align="center"><input class="checkbox" name="captcha[' . $i . ']" type="checkbox" value="true"></td>';
            }


            $s .= '</tr>'
            . '</table>'
            . '</div>';

            return $s;
        }


        // Validate answers from post
        function validate()
        {

            $answers = array_fill(0, sizeof($this->captcha_data["answers"]), false);

            for($i = 0; $i < sizeof($answers); $i++)
            {

                if(empty($_POST["captcha"][$i]) === false)
                {

                    $answers[$i] = true;
                }
            }


            for($i = 0; $i < sizeof($answers); $i++)
            {

                if($answers[$i] !== $this->captcha_data["answers"][$i])
                {

                    return false;
                }
            }


            return true;
        }
    }


?>



client.php
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php

    require_once(dirname(__FILE__) . '/library.php');
    require_once(dirname(__FILE__) . '/captcha.cls.php');

    session_start();

    if(isset($_POST["submit"]) && isset($_SESSION["captcha"])) // Validate form
    {
        // Check form
        if($_SESSION["captcha"]->validate())
        {

            echo 'Your answer was valid!<br><br>';
        }

        else
        {
            echo 'Your answer was invalid!<br><br>';
        }
    }


    // Test for different sized captcha's
    $number_of_images = rand(1, 9);
    $number_of_answers = rand(1, $number_of_images - 1);

    // Load captcha in session (we need it's data to validate the POST)
    $_SESSION["captcha"] = new Captcha(1, $number_of_images, $number_of_answers);

    // Create some form..
    echo '<form action="" method="post">'
    . 'Some form fields..' // Additional formfields
    . $_SESSION["captcha"]->toHtml() // Captcha validator output
    . '<input name="submit" type="submit" value="submit">'
    . '</form>';

?>



library.php (wat algemene functies)
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php

    // Parse a CSV file to an 2D array
    function csvToArray($data)
    {

        // output
        $csv = array();
        $line = array();

        $escaped = false; // Flag: escape char
        $quoted = false; // Flag: quoted string

        $buffer = ''; // Buffer (quoted values)
        $junk = ''; // Junk buffer (unquoted values)

        for($i = 0; $i < strlen($data); $i++)
        {

            $char = $data[$i];

            if($quoted)
            {

                if(($char == '\\') && ($escaped === false))
                {

                    // Set flags
                    $escaped = true;
                }

                elseif(($char == '"') && ($escaped === false))
                {

                    // Set flags
                    $quoted = false;
                    $escaped = false;
                }

                else
                {
                    // Add char to buffer
                    $buffer .= $char;

                    // Set flags
                    $escaped = false;
                }
            }

            else
            {
                if($char == "\n") // Start a new line
                {
                    if(strlen($buffer) > 0)
                    {

                        // Add buffer to line
                        $line[] = $buffer;

                        // Clear buffer
                        $buffer = '';
                    }

                    else
                    {
                        $junk = trim($junk);

                        // Add junk to line (possible unquoted values?)
                        $line[] = $junk;
                    }


                    // Clear junk
                    $junk = '';

                    // Add line to CSV
                    $csv[] = $line;

                    // Clear line
                    $line = array();
                }

                elseif($char == '"') // Start new value
                {
                    // Set flags
                    $quoted = true;
                }

                elseif($char == ',')
                {

                    if(strlen($buffer) > 0)
                    {

                        // Add buffer to line
                        $line[] = $buffer;

                        // Clear buffer
                        $buffer = '';
                    }

                    else
                    {
                        $junk = trim($junk);

                        // Add junk to line (possible unquoted values?)
                        $line[] = $junk;
                    }


                    // Clear junk
                    $junk = '';
                }

                else // Add to junk char
                {
                    $junk .= $char;
                }
            }
        }


        // Clean up
        if(strlen($buffer) > 0)
        {

            // Add buffer to line
            $line[] = $buffer;

            // Clear buffer
            $buffer = '';
        }

        else
        {
            $junk = trim($junk);

            // Add junk to line (possible unquoted values?)
            $line[] = $junk;
        }


        $csv[] = $line;

        return $csv;
    }


    // Get a value from the $_GET array (case insensitive!!)
    function getGet($name)
    {

        if(isset($_GET) && is_array($_GET))
        {

            foreach($_GET AS $key => $val)
            {

                if(strcasecmp($key, $name) === 0)
                {

                    return urldecode($val);
                }
            }
        }

        
        return '';
    }


    // Parse a string to an integer
    function stringToInt($string)
    {

        if(is_numeric($string))
        {

            return intval($string);
        }


        return 0;
    }


?>

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.