root/wp-morph/trunk/wp-morph.php

Revision 11616, 7.7 kB (checked in by dsevilla, 1 year ago)

v1.6: Adapted to PHP5.

  • Property svn:keywords set to Id
Line 
1 <?php // -*- mode: php -*- vim: expandtab ts=8 sw=8
2 /*
3 Plugin Name: WP-Morph
4 Plugin URI: http://neuromancer.inf.um.es/blog/index.php?s=wp-morph&submit=Search
5 Description: Fool spammers by creating a complicated javascript program to be executed by a real browser.
6 Author: Diego Sevilla Ruiz
7 Version: 1.6
8 Author URI: http://neuromancer.inf.um.es/blog
9 Id: $Id$
10 */
11
12 ////// Config values:
13 // * form_valid_minutes is the number of minutes that the form is valid
14 //                      since the form appears in the screen till the user
15 //                      pushes the "submit" button. (15 minutes by default).
16 $form_valid_minutes = 15;
17 ////// End of config values.
18
19
20 // Check the result through the MD5 sum.
21 function morph_check_md5($comment) {
22         global $form_valid_minutes;
23
24         // Experimental: check only comments proper.
25         // Let pingbacks and trackbacks
26         if (!(get_comment_type() === 'comment'))
27                 return $comment;
28         
29         // Get rnd_val from WP option database
30         $rnd_val = get_option('wp_morph_seed');
31
32         // Check the fast check :)
33         if ('spammers_go_home' == trim(strip_tags($_POST['checkpoint'])) )
34         {
35                 // Check that md5 of check is the same than produced
36                 $v = $_POST['calc_value'];
37
38                 // This value cannot be known by spammers
39                 $v += $rnd_val;
40
41                 // Then, try at most "$form_valid_minutes" minutes back.
42                 $d = (integer)(time() / 60);
43                 $t = $d - $form_valid_minutes;
44
45                 while ($t <= $d)
46                 {
47                         $v2 = $v + $t;
48                         $v2 = md5($v2);
49
50                         if ($v2 == $_POST['result_md5'])
51                                 return $comment;
52                         $t++;
53                 }
54         }
55
56         die( "This weblog is protected by WP-Morph. This is to prevent
57              comment spam. You have to have JavaScript enhabled in order
58              to post comments here. Sorry for the inconvenience." );
59 }
60
61 global $wp_version;
62 if ($wp_version{0} == '2')
63         add_filter('pre_comment_approved', 'morph_check_md5');
64 else
65         add_filter('post_comment_text', 'morph_check_md5');
66
67 // Output form actions
68 function morph_output_form_items($page) {
69
70         // Check if we have to change the $rnd_val
71         $rnd_val = get_option('wp_morph_seed');
72         $rnd_val_last_updated = get_option('wp_morph_seed_last_updated');
73
74         // Change seed every day
75         if ( !$rnd_val || ((time () - $rnd_val_last_updated) > 86400) )
76         {
77                 $rnd_val = rand (1001, 60001);
78                 update_option('wp_morph_seed', $rnd_val);
79                 update_option('wp_morph_seed_last_updated', time());
80         }
81
82         // We have three arrays of random size. Complicated calculus can
83         // be made here.
84         // 6 to 20 variables
85         $nvars = rand(6,20);
86         $maxval = rand(1000,10000);
87         $vvv = array();
88
89         for ($i = 0 ; $i < $nvars; $i++)
90         {
91                 $v = rand(1,$maxval - 1);
92                 $js_str .= 'v' . $i . '=' . $v . ';';
93                 $vvv[$i] = $v;
94         }
95
96         $nops = rand(3,20);
97         for ($i = 0; $i < $nops; $i++)
98         {
99                 // Operator
100                 $op = rand(0,5);
101
102                 // Select two variables and result, random
103                 $v1 = rand(0, $nvars - 1);
104                 $v2 = rand(0, $nvars - 1);
105                 $v3 = rand(0, $nvars - 1);
106
107                 switch($op)
108                 {
109                         // +
110                 case '0':
111                         $vvv[$v3] = ($vvv[$v1] + $vvv[$v2]) % $maxval;
112                         $js_str .= 'v'.$v3.'=(v'.$v1
113                             . '+v'.$v2.')%'. $maxval .';';
114                         break;
115                         // -
116                 case '1':
117                         $vvv[$v3] = ($vvv[$v1] - $vvv[$v2]) % $maxval;
118                         $js_str .= 'v'.$v3.'=(v'.$v1
119                             . '-v'.$v2.')%'. $maxval .';';
120                         break;
121                         // *
122                 case '2':
123                         $vvv[$v3] = ($vvv[$v1] * $vvv[$v2]) % $maxval;
124                         $js_str .= 'v'.$v3.'=(v'.$v1
125                             . '*v'.$v2.')%'. $maxval .';';
126                         break;
127
128                         // if, >
129                 case '3':
130                         $v4 = rand (1, $maxval - 1);
131
132                         $js_str .= 'if ( v' . $v1 . ' > '. $v4 . ')
133                                     { v' . $v2 . ' = v' . $v3 . '; }';
134
135                         if ($vvv[$v1] > $v4)
136                         {
137                                 $vvv[$v2] = $vvv[$v3];
138                         }
139                         break;
140
141                         // if, <
142                 case '4':
143                         $v4 = rand (1, $maxval - 1);
144
145                         $js_str .= 'if ( v' . $v1 . ' < '. $v4 . ')
146                                     { v' . $v2 . ' = v' . $v3 . '; }';
147
148                         if ($vvv[$v1] < $v4)
149                         {
150                                 $vvv[$v2] = $vvv[$v3];
151                         }
152                         break;
153
154                         // while
155                 case '5':
156                         $v4 = rand (1, 100);
157
158                         // Quick and dirty check
159                         if ($v1 == $v2)
160                                 break;
161
162                         $js_str .= 'v'. $v1 .'=Math.abs(v'.$v1.');
163                                    v'. $v1 .'%='. $v4 .'; while (v'.$v1.'--) {
164                                    v'. $v2.'++; }';
165
166                         // Calc the final value
167                         $vvv[$v1] = abs ($vvv[$v1]);
168                         $vvv[$v2] += $vvv[$v1] % $v4;
169                         $vvv[$v1] = -1;
170                         break;
171                 }
172
173         }
174
175         $final_val = 0;
176
177         $js_str .= "eElement.value = (";
178         for ($i = 0 ; $i < $nvars; $i++)
179         {
180                 if ($i != 0)
181                 {
182                         $js_str .= '+';
183                 }
184                 $js_str .= 'v' . $i . '%' . $maxval;
185                 $final_val += ($vvv[$i] % $maxval);
186         }
187
188
189         $js_str .= ')%'. $maxval.';';
190
191         $final_val %= $maxval;
192
193         // Add the secret quantity
194         $final_val += $rnd_val;
195
196         // Add the epoh down to minutes
197         $final_val += (integer)(time() / 60);
198
199         // Calc the md5 of the value
200         $md5_value = md5($final_val);
201
202         // Write in hidden field
203         $page = str_replace('<input type="hidden" name="comment_post_ID"',
204            '<input type="hidden" name="checkpoint" value="spammers_go_home" />
205             <input type="hidden" name="result_md5" value="'
206                             . $md5_value . '" />
207             <input type="hidden" id="chk" name="calc_value" value="" />
208             <input type="hidden" name="comment_post_ID"', $page);
209
210         // The form action
211         $page = str_replace('<form',
212                             '<form onsubmit="go_anti_spam();" ',
213                             $page);
214
215         // The jscript
216         $page = str_replace('</head>', '<script type="text/javascript">
217 //<![CDATA[
218
219     function go_anti_spam()
220     {
221         eElement = document.getElementById("chk");
222         if(!eElement){ return false; }
223         else
224         {
225             '.$js_str.'
226             return true;
227         }
228     }//]]></script></head>', $page);
229
230         return $page;
231 }
232
233 function morph_call_output_items() {
234         ob_start('morph_output_form_items');
235 }
236
237 function morph_flush() {
238         ob_end_flush();
239 }
240
241 // Now we set that function up to execute when the wp_head action is called
242 add_action('wp_head', 'morph_call_output_items');
243
244 // This one needed to flush the buffer started in the output modification
245 add_action('shutdown', "morph_flush");
246
247 ?>
248
Note: See TracBrowser for help on using the browser.