root/wp-hashcash/trunk/wp-hashcash.php

Revision 59343, 23.1 KB (checked in by ecb29, 18 months ago)

Fixing a typo!

Line 
1<?php
2/*
3 Plugin Name: WordPress Hashcash
4 Plugin URI: http://wordpress-plugins.feifei.us/hashcash/
5 Description: Client-side javascript blocks all spam bots.  XHTML 1.1 compliant.
6 Author: Elliott Back
7 Author URI: http://elliottback.com
8 Version: 4.3
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 */
21
22function wphc_option($save = false){
23        if($save) {
24                if( function_exists( 'update_site_option' ) ) {
25                        update_site_option('plugin_wp-hashcash', $save);
26                } else {
27                        update_option('plugin_wp-hashcash', $save);
28                }
29
30                return $save;
31        } else {
32                if( function_exists( 'get_site_option' ) ) {
33                        $options = get_site_option('plugin_wp-hashcash');
34                } else {
35                        $options = get_option('plugin_wp-hashcash');
36                }
37
38                if(!is_array($options))
39                        $options = array();
40
41                return $options;
42        }
43}
44
45/**
46 * Install WP Hashcash
47 */
48
49function wphc_install () {
50        // set our default options
51        $options = wphc_option();
52        $options['comments-spam'] = $options['comments-spam'] || 0;
53        $options['comments-ham'] = $options['comments-ham'] || 0;
54        $options['signups-spam'] = $options['signups-spam'] || 0;
55        $options['signups-ham'] = $options['signups-ham'] || 0;
56        $options['key'] = array();
57        $options['key-date'] = 0;
58        $options['refresh'] = 60 * 60 * 24 * 7;
59        $options['signup_active'] = 1;
60        $options['comments_active'] = 1;
61
62        // akismet compat check
63        if(function_exists('akismet_init')){
64                $options['moderation'] = 'akismet';
65        } else {
66                $options['moderation'] = 'moderate';
67        }
68       
69        // validate ip / url
70        $options['validate-ip'] = true;
71        $options['validate-url'] = true;
72
73        // logging
74        $options['logging'] = true;
75
76        // update the key
77        wphc_option($options);
78        wphc_refresh();
79}
80
81add_action('activate_wp-hashcash/wp-hashcash.php', 'wphc_install');
82add_action('activate_wp-hashcash.php', 'wphc_install');
83
84/**
85 * Update the key, if needed
86 */
87
88function wphc_refresh(){
89        $options = wphc_option();
90
91        if( !isset( $options[ 'signup_active' ] ) ) {
92                wphc_install();
93                return;
94        }
95
96        if(time() - $options['key-date'] > $options['refresh']) {
97                if(count($options['key']) >= 5)
98                        array_shift($options['key']);
99
100                array_push($options['key'], rand(21474836, 2126008810));
101
102                $options['key-date'] = time();
103                wphc_option($options);
104        }
105}
106
107add_action('shutdown', 'wphc_refresh');
108
109/**
110 * Our plugin can also have a widget
111 */
112
113function get_spam_ratio( $ham, $spam ) {
114        if($spam + $ham == 0)
115                $ratio = 0;
116        else
117                $ratio = round(100 * ($spam/($ham+$spam)),2);
118
119        return $ratio;
120}
121
122function widget_ratio($options){
123        $signups_ham = (int)$options['signups-ham'];
124        $signups_spam = (int)$options['signups-spam'];
125        $ham = (int)$options['comments-ham'];
126        $spam = (int)$options['comments-spam'];
127        $ratio = get_spam_ratio( $ham, $spam );
128        $signups_ratio = get_spam_ratio( $signups_ham, $signups_spam );
129
130        $msg = "<p>$spam spam comments blocked out of $ham human comments.  " . $ratio ."% of your comments are spam!</p>";
131        if( $signups_ham && $signups_spam )
132                $msg = "<p>$signups_spam spam signups blocked out of $signups_ham human signups.  " . $signups_ratio ."% of your signups are spam!</p>";
133
134        return $msg;
135}
136
137function wphc_widget_init () {
138        if(!function_exists('register_sidebar_widget'))
139                return;
140
141        function widget_wphc($args) {
142                extract($args);
143                $options = wphc_option();
144
145                echo $before_widget . $before_title . '<a href="http://wordpress-plugins.feifei.us/hashcash/">WP Hashcash</a>' . $after_title;
146                echo '<ul>';
147                echo '<li><small>By <a href="http://elliottback.com">Elliott Back</a></small></li>';
148                echo "<li>".widget_ratio($options)."</li>";
149                echo '</ul>';
150                echo $after_widget;
151        }
152       
153        register_sidebar_widget(array('WP Hashcash', 'widgets'), 'widget_wphc');
154}
155
156add_action('widgets_init', 'wphc_widget_init');
157
158/**
159 * Admin Options
160 */
161
162add_action('admin_menu', 'wphc_add_options_to_admin');
163
164function wphc_add_options_to_admin() {
165        if( function_exists( 'is_site_admin' ) && !is_site_admin() )
166                return;
167
168        if (function_exists('add_options_page')) {
169                if( function_exists( 'is_site_admin' ) ) {
170                        add_submenu_page('wpmu-admin.php', __('WordPress Hashcash'), __('WordPress Hashcash'), 'manage_options', 'wphc_admin', 'wphc_admin_options');
171                } else {
172                        add_options_page('Wordpress Hashcash', 'Wordpress Hashcash', 8, basename(__FILE__), 'wphc_admin_options');
173                }
174        }
175}
176
177function wphc_admin_options() {
178        if( function_exists( 'is_site_admin' ) && !is_site_admin() )
179                return;
180
181        $options = wphc_option();
182
183        if( !isset( $options[ 'signup_active' ] ) ) {
184                wphc_install(); // MU has no activation hook
185                $options = wphc_option();
186        }
187
188        // POST HANDLER
189        if($_POST['wphc-submit']){
190                check_admin_referer( 'wphc-options' );
191                if ( function_exists('current_user_can') && !current_user_can('manage_options') )
192                        die('Current user not authorized to managed options');
193
194                $options['refresh'] = strip_tags(stripslashes($_POST['wphc-refresh']));
195                $options['moderation'] = strip_tags(stripslashes($_POST['wphc-moderation']));
196                $options['validate-ip'] = strip_tags(stripslashes($_POST['wphc-validate-ip']));
197                $options['validate-url'] = strip_tags(stripslashes($_POST['wphc-validate-url']));
198                $options['logging'] = strip_tags(stripslashes($_POST['wphc-logging']));
199                $options['signup_active'] = (int)$_POST['signup_active'];
200                $options['comments_active'] = (int)$_POST['comments_active'];
201                wphc_option($options);
202        }
203       
204        // MAIN FORM
205        echo '<style type="text/css">
206                .wrap h3 { color: black; background-color: #e5f3ff; padding: 4px 8px; }
207
208                .sidebar {
209                        border-right: 2px solid #e5f3ff;
210                        width: 200px;
211                        float: left;
212                        padding: 0px 20px 0px 10px;
213                        margin: 0px 20px 0px 0px;
214                }
215
216                .sidebar input {
217                        background-color: #FFF;
218                        border: none;
219                }
220
221                .main {
222                        float: left;
223                        width: 600px;
224                }
225
226                .clear { clear: both; }
227        </style>';
228
229        echo '<div class="wrap">';
230
231        echo '<div class="sidebar">';
232        echo '<h3>Plugin</h3>';
233        echo '<ul>
234        <li><a href="http://wordpress-plugins.feifei.us/hashcash/">Plugin\'s Homepage</a></li>';
235        if( function_exists( 'is_site_admin' ) && is_site_admin() ) {
236                echo '<li><a href="http://mu.wordpress.org/forums/">WordPress MU Forums</a></li>';
237        }
238        echo '<li><a href="http://wordpress.org/tags/wp-hashcash">Plugin Support Forum</a></li>';
239        echo '</ul>';           
240        echo '<h3>Donation</h3>';
241        echo '<center><form action="https://www.paypal.com/cgi-bin/webscr" method="post">
242<input type="hidden" name="cmd" value="_s-xclick">
243<input style="border:none;" type="image" src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
244<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
245<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----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-----END PKCS7-----"></form></center>';
246        echo '<p>Any small donation would be highly appreciated.</p>';
247        echo '<h3>Miscellaneous</h3>';
248        echo '<ul>
249        <li><a href="http://wordpress-plugins.feifei.us/">Elliott\'s WP Plugins</a></li>
250        <li><a href="http://ocaoimh.ie/wordpress-plugins/">Donncha\'s WP Plugins</a></li>
251        </ul>';
252        echo '<h3>Statistics</h3>';
253        echo '<p>'.widget_ratio($options).'</p>';
254        echo '</div>';
255
256        echo '<div class="main">';
257        echo '<h2>WordPress Hashcash</h2>';
258        echo '<p>This is an antispam plugin that eradicates spam signups on WordPress sites. It works because your visitors must use obfuscated
259        javascript to submit a proof-of-work that indicates they opened your website in a web browser, not a robot.  You can read more about it on the
260        <a href="http://wordpress-plugins.feifei.us/hashcash/">WordPress Hashcash plugin page</a> of my site.</p>';
261
262        echo '<h3>Standard Options</h3>';
263        echo '<form method="POST" action="?page=' . $_GET[ 'page' ] . '&updated=true">';
264        wp_nonce_field('wphc-options');
265        if( function_exists( 'is_site_admin' ) ) { // MU only
266                $signup_active = (int)$options[ 'signup_active' ];
267                $comments_active = (int)$options[ 'comments_active' ];
268                echo "<p><label>Signup protection enabled: <input type='checkbox' name='signup_active' value='1' " . ( $signup_active == '1' ? ' checked' : '' ) . " /></label></p>";
269                echo "<p><label>Comments protection enabled: <input type='checkbox' name='comments_active' value='1' " . ( $comments_active == '1' ? ' checked' : '' ) . " /></label></p>";
270        }
271        // moderation options
272        $moderate = htmlspecialchars($options['moderation'], ENT_QUOTES);
273        echo '<p><label for="wphc-moderation">' . __('Moderation:', 'wp-hashcash') . '</label>';
274        echo '<select id="wphc-moderation" name="wphc-moderation">';
275        echo '<option value="moderate"'.($moderate=='moderate'?' selected':'').'>Moderate</option>';
276        echo '<option value="akismet"'.($moderate=='akismet'?' selected':'').'>Akismet</option>';
277        echo '<option value="delete"'.($moderate=='delete'?' selected':'').'>Delete</option>';
278        echo '</select>';
279        echo '<br/><span style="color: grey; font-size: 90%;">The default is to place spam comments into the
280        akismet/moderation queue. Otherwise, the delete option will immediately discard spam comments.</span>';
281        echo '</p>';
282
283        // refresh interval
284        $refresh = htmlspecialchars($options['refresh'], ENT_QUOTES);
285        echo '<p><label for="wphc-refresh">' . __('Key Expiry:', 'wp-hashcash').'</label>
286                <input style="width: 200px;" id="wphc-refresh" name="wphc-refresh" type="text" value="'.$refresh.'" />
287                <br/><span style="color: grey; font-size: 90%;">Default is one week, or <strong>604800</strong> seconds.</p>';
288
289        // current key
290        echo '<p>Your current key is <strong>' . $options['key'][count($options['key']) - 1] . '</strong>.';
291        if(count($options['key']) > 1)
292                echo ' Previously you had keys '. join(', ', array_reverse(array_slice($options['key'], 0, count($options['key']) - 1))).'.';
293        echo '</p>';
294
295        // additional options
296        echo '<h3>Additional options:</h3>';
297
298        $validate_ip = htmlspecialchars($options['validate-ip'], ENT_QUOTES);
299        echo '<p><label for="wphc-validate-ip">Validate IP Address</label>
300                <input name="wphc-validate-ip" type="checkbox" id="wphc-validate-ip"'.($validate_ip?' checked':'').'/>
301                <br /><span style="color: grey; font-size: 90%;">
302                Checks if the IP address of the trackback sender is equal to the IP address of the webserver the trackback URL is referring to.</span></p>';
303
304        $validate_url = htmlspecialchars($options['validate-url'], ENT_QUOTES);
305        echo '<p><label for="wphc-validate-url">Validate URL</label>
306                <input name="wphc-validate-url" type="checkbox" id="wphc-validate-url"'.($validate_url?' checked':'').'/>
307                <br /><span style="color: grey; font-size: 90%;">Retrieves the web page located at the URL included
308                in the trackback to check if it contains a link to your blog.  If it does not, it is spam!</span></p>';
309
310        // logging options
311        echo '<h3>Logging:</h3>';
312
313        $logging = htmlspecialchars($options['logging'], ENT_QUOTES);
314        echo '<p><label for="wphc-logging">Logging</label>
315                <input name="wphc-logging" type="checkbox" id="wphc-logging"'.($logging?' checked':'').'/>
316                <br /><span style="color: grey; font-size: 90%;">Logs the reason why a given comment failed the spam
317                check into the comment body.  Works only if moderation / akismet mode is enabled.</span></p>';
318
319        echo '<input type="hidden" id="wphc-submit" name="wphc-submit" value="1" />';
320        echo '<input type="submit" id="wphc-submit-override" name="wphc-submit-override" value="Save WP Hashcash Settings"/>';
321        echo '</form>';
322        echo '</div>';
323
324        echo '<div class="clear">';
325        echo '<p style="text-align: center; font-size: .85em;">&copy; Copyright '.date('Y').' <a href="http://elliottback.com">Elliott B&auml;ck</a></p>';
326        echo '</div>';
327
328        echo '</div>';
329}
330
331/**
332 * Add JS to the header
333 */
334function wphc_posthead() {
335        if( function_exists( 'is_site_admin' ) ) {
336                $options = wphc_option();
337                if( !$options['comments_active'] )
338                        return;
339        }
340        if((is_single() || is_page()))
341                wphc_addhead();
342}
343add_action('wp_head', 'wphc_posthead');
344
345function wphc_signuphead() {
346        if( function_exists( 'is_site_admin' ) ) {
347                $options = wphc_option();
348                if( !$options['signup_active'] )
349                        return;
350        }
351        wphc_addhead();
352}
353add_action('signup_header', 'wphc_signuphead');
354
355function wphc_addhead() {
356        echo "<script type=\"text/javascript\"><!--\n";
357        echo 'function addLoadEvent(func) {
358  var oldonload = window.onload;
359  if (typeof window.onload != \'function\') {
360    window.onload = func;
361  } else {
362    window.onload = function() {
363      if (oldonload) {
364        oldonload();
365      }
366      func();
367    }
368  }
369}
370';
371        echo  wphc_getjs() . "\n";
372        echo "addLoadEvent(function(){document.getElementById('wphc_value').value=wphc();});\n";
373        echo "//--></script>\n";
374}
375
376function wphc_getjs(){
377        $options = wphc_option();
378        $val = $options['key'][count($options['key']) - 1];
379        $js = 'function wphc_compute(){';
380
381        switch(rand(0, 3)){
382                /* Addition of n times of field value / n, + modulus:
383                 Time guarantee:  100 iterations or less */
384                case 0:
385                        $inc = rand($val / 100, $val - 1);
386                        $n = floor($val / $inc);
387                        $r = $val % $inc;
388               
389                        $js .= "var wphc_eax = $inc; ";
390                        for($i = 0; $i < $n - 1; $i++){
391                                $js .= "wphc_eax += $inc; ";
392                        }
393                       
394                        $js .= "wphc_eax += $r; ";
395                        $js .= 'return wphc_eax; ';
396                        break;
397
398                        /* Conversion from binary:
399                Time guarantee:  log(n) iterations or less */
400                case 1:
401                        $binval = strrev(base_convert($val, 10, 2));
402                        $js .= "var wphc_eax = \"$binval\"; ";
403                        $js .= 'var wphc_ebx = 0; ';
404                        $js .= 'var wphc_ecx = 0; ';
405                        $js .= 'while(wphc_ecx < wphc_eax.length){ ';
406                        $js .= 'if(wphc_eax.charAt(wphc_ecx) == "1") { ';
407                        $js .= 'wphc_ebx += Math.pow(2, wphc_ecx); ';
408                        $js .= '} ';
409                        $js .= 'wphc_ecx++; ';
410                        $js .= '} ';
411                        $js .= 'return wphc_ebx;';
412                       
413                break;
414               
415                /* Multiplication of square roots:
416                Time guarantee:  constant time */
417                case 2:
418                        $sqrt = floor(sqrt($val));
419                        $r = $val - ($sqrt * $sqrt);
420                        $js .= "return $sqrt * $sqrt + $r; ";
421                break;
422               
423                /* Sum of random numbers to the final value:
424                Time guarantee:  log(n) expected value */
425                case 3:
426                        $js .= 'return ';
427       
428                        $i = 0;
429                        while($val > 0){
430                                if($i++ > 0)
431                                        $js .= '+';
432                               
433                                $temp = rand(1, $val);
434                                $val -= $temp;
435                                $js .= $temp;
436                        }
437       
438                        $js .= ';';
439                break;
440        }
441               
442        $js .= '} wphc_compute();';
443       
444        // pack bytes
445        if( !function_exists( 'strToLongs' ) ) {
446        function strToLongs($s) {
447                $l = array();
448           
449                // pad $s to some multiple of 4
450                $s = preg_split('//', $s, -1, PREG_SPLIT_NO_EMPTY);
451           
452                while(count($s) % 4 != 0){
453                        $s [] = ' ';
454                }
455       
456                for ($i = 0; $i < ceil(count($s)/4); $i++) {
457                        $l[$i] = ord($s[$i*4]) + (ord($s[$i*4+1]) << 8) + (ord($s[$i*4+2]) << 16) + (ord($s[$i*4+3]) << 24);
458                }
459       
460                return $l;
461        }
462        }
463       
464        // xor all the bytes with a random key
465        $key = rand(21474836, 2126008810);
466        $js = strToLongs($js);
467       
468        for($i = 0; $i < count($js); $i++){
469                $js[$i] = $js[$i] ^ $key;
470        }
471       
472        // libs function encapsulation
473        $libs = "function wphc(){\n";
474       
475        // write bytes to javascript, xor with key
476        $libs .= "\tvar wphc_data = [".join(',',$js)."]; \n";
477       
478        // do the xor with key
479        $libs .= "\n\tfor (var i=0; i<wphc_data.length; i++){\n";
480        $libs .= "\t\twphc_data[i]=wphc_data[i]^$key;\n";
481        $libs .= "\t}\n";
482       
483        // convert bytes back to string
484        $libs .= "\n\tvar a = new Array(wphc_data.length); \n";
485        $libs .= "\tfor (var i=0; i<wphc_data.length; i++) { \n";
486        $libs .= "\t\ta[i] = String.fromCharCode(wphc_data[i] & 0xFF, wphc_data[i]>>>8 & 0xFF, ";
487        $libs .= "wphc_data[i]>>>16 & 0xFF, wphc_data[i]>>>24 & 0xFF);\n";
488        $libs .= "\t}\n";
489       
490        $libs .= "\n\treturn eval(a.join('')); \n";
491       
492        // call libs function
493        $libs .= "}";
494       
495        // return code
496        return $libs;
497}
498
499/**
500 * Hook into the signups form
501 */
502function wphc_add_signupform(){
503        echo '<input type="hidden" id="wphc_value" name="wphc_value" value=""/>';
504}
505add_action( 'signup_hidden_fields', 'wphc_add_signupform' );
506
507function wphc_add_commentform(){
508        $options = wphc_option();
509       
510        switch($options['moderation']){
511                case 'delete':
512                        $verb = 'deleted';
513                        break;
514                case 'akismet':
515                        $verb = 'queued in Akismet';
516                        break;
517                case 'moderate':
518                default:
519                        $verb = 'placed in moderation';
520                        break;
521        }
522       
523        echo '<div><input type="hidden" id="wphc_value" name="wphc_value" value=""/></div>';
524        echo '<p>' . __('Powered by', 'wp-hashcash') . ' <a href="http://wordpress-plugins.feifei.us/hashcash/">WP Hashcash</a></p>';
525        echo '<noscript><div><small>Wordpress Hashcash needs javascript to work, but your browser has javascript disabled. Your comment will be '.$verb.'!</small></div></noscript>';
526}
527
528add_action('comment_form', 'wphc_add_commentform');
529
530/**
531 * Validate our tag
532 */
533
534function wphc_check_signup_hidden_tag( $result ) {
535        // get our options
536        $options = wphc_option();
537        $spam = false;
538        if( !strpos( $_SERVER[ 'PHP_SELF' ], 'wp-signup.php' ) )
539                return $result;
540
541        // Check the wphc values against the last five keys
542        $spam = !in_array($_POST["wphc_value"], $options['key']);
543       
544        if($spam){
545                $options['signups-spam'] = ((int) $options['signups-spam']) + 1;
546                wphc_option($options);
547                $result['errors']->add( 'blogname', __('You did not pass a spam check. Please enable JavaScript in your browser.') );
548        } else {
549                $options['signups-ham'] = ((int) $options['signups-ham']) + 1;
550                wphc_option($options);
551        }
552       
553        return $result;
554}
555add_filter( 'wpmu_validate_blog_signup', 'wphc_check_signup_hidden_tag' );
556add_filter( 'wpmu_validate_user_signup', 'wphc_check_signup_hidden_tag' );
557
558function wphc_check_hidden_tag($comment) {
559        // get our options
560        $type = $comment['comment_type'];
561        $options = wphc_option();
562        $spam = false;
563
564        if($type == "trackback" || $type == "pingback"){
565                // check the website's IP against the url it's sending as a trackback
566                if($options['validate-ip']){
567                        $server_ip = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
568                        $web_ip = gethostbyname(parse_url($comment['comment_author_url'], PHP_URL_HOST));
569                        $ipv = $server_ip != $web_ip;
570                        $spam = $spam || ($ipv);
571                       
572                        if($options['logging'] && $ipv) $comment['comment_content'] .= "\n\n[WORDPRESS HASHCASH] The comment's server IP (".$server_ip.") doesn't match the"
573                                . " comment's URL host IP (".$web_ip.") and so is spam.";
574                }
575
576                // look for our link in the page itself
577                if(!$spam && $options['validate-url']){
578                        if(!class_exists('Snoopy'))
579                                require_once( ABSPATH . WPINC . '/class-snoopy.php' );
580                               
581                        $permalink = get_permalink($comment['comment_post_ID']);
582                        $permalink = preg_replace('/\/$/', '', $permalink);
583                        $snoop = new Snoopy;
584                       
585                        if (@$snoop->fetchlinks($comment['comment_author_url'])){
586                                $found = false;
587                               
588                                if( !empty( $snoop->results ) )
589                                {
590                                        foreach($snoop->results as $url){
591                                                $url = preg_replace('/(\/|\/trackback|\/trackback\/)$/', '', $url);
592                                                if($url == $permalink)
593                                                        $found = true; 
594                                        }
595                                }
596                               
597                                if($options['logging'] && !$found) 
598                                        $comment['comment_content'] .= "\n\n[WORDPRESS HASHCASH] The comment's actual post text did not contain your blog url (".$permalink.") and so is spam.";
599                               
600                                $spam = $spam || !$found;
601                        } else {
602                                $spam = true;
603                                if($options['logging']) 
604                                        $comment['comment_content'] .= "\n\n[WORDPRESS HASHCASH] Snoopy failed to fetch results for the comment blog url (".$comment['comment_author_url'].") with error '".$snoop->error."' and so is spam.";
605                        }
606                }
607        } else {
608                // Check the wphc values against the last five keys
609                $spam = !in_array($_POST["wphc_value"], $options['key']);
610                if($options['logging'] && $spam)
611                        $comment['comment_content'] .= "\n\n[WORDPRESS HASHCASH] The poster sent us '".intval($_POST["wphc_value"])." which is not a hashcash value.";
612        }
613       
614        if($spam){
615                $options['comments-spam'] = ((int) $options['comments-spam']) + 1;
616                wphc_option($options);
617                       
618                switch($options['moderation']){
619                        case 'delete':
620                                add_filter('comment_post', create_function('$id', 'wp_delete_comment($id); die(\'This comment has been deleted by WP Hashcash\');'));
621                                break;
622                        case 'akismet':
623                                add_filter('pre_comment_approved', create_function('$a', 'return \'spam\';'));
624                                break;
625                        case 'moderate':
626                        default:
627                                add_filter('pre_comment_approved', create_function('$a', 'return 0;'));
628                                break;
629                }
630        } else {
631                $options['comments-ham'] = ((int) $options['comments-ham']) + 1;
632                wphc_option($options);
633        }
634       
635        return $comment;
636}
637
638add_filter('preprocess_comment', 'wphc_check_hidden_tag');
639?>
Note: See TracBrowser for help on using the browser.