honeypot.pl 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. use strict;
  2. use v5.10;
  3. =head1 NAME
  4. honeypot - an Oddmuse module that reduces wiki spam
  5. =head1 SYNOPSIS
  6. This module adds parameters to the page edit form. These parameters are special
  7. because they are invisible to humans (using style information). If a spam bot
  8. sets these parameters to anything, the edit will be rejected. Another hidden
  9. parameter contains a timestamp. If a spam bot plays back recorded actions and
  10. provides the timestamp of the recording, the edit will be rejected because it is
  11. too old.
  12. More information:
  13. L<http://nedbatchelder.com/text/stopbots.html>
  14. =head1 INSTALLATION
  15. Installing a module is easy: Create a modules subdirectory in your
  16. data directory, and put the Perl file in there. It will be loaded
  17. automatically.
  18. =cut
  19. AddModuleDescription('honeypot.pl', 'Comments on Monitor Extension');
  20. =head1 CONFIGURATION
  21. =head2 $HoneyPotOk and $HoneyPotTimestamp
  22. C<$HoneyPotOkThis> is used to hold the timestamp. If a form is posted with a
  23. timestamp older than C<$HoneyPotTimestamp> seconds, it will be rejected.
  24. Example:
  25. $HoneyPotOkThis = 'friend';
  26. $HoneyPotTimestamp = 6 * 60 * 60; # six hours
  27. By default, the parameter is called "ok" and the timestamp may not be older than
  28. one hour (3600 seconds).
  29. =head2 $HoneyPotIdiot1 and $HoneyPotIdiot2
  30. These two variables should not be posted or they should be empty. Providing any
  31. values will result in the form being rejected.
  32. Example:
  33. $HoneyPotIdiot1 = 'spam';
  34. $HoneyPotIdiot2 = 'scum';
  35. By default, these have the values of "idiot" and "looser", for obvious reasons.
  36. =cut
  37. our ($q, $Now, @MyInitVariables, $QuestionaskerRememberAnswer, $QuestionaskerSecretKey);
  38. our ($HoneyPotOk, $HoneyPotIdiot, $HoneyPotTimestamp, $HoneyPotIdiot1, $HoneyPotIdiot2);
  39. $HoneyPotOk = 'ok';
  40. $HoneyPotIdiot1 = 'idiot';
  41. $HoneyPotIdiot2 = 'looser';
  42. $HoneyPotTimestamp = 3600;
  43. *HoneyPotOldGetFormStart = \&GetFormStart;
  44. *GetFormStart = \&HoneyPotNewGetFormStart;
  45. my $HoneyPotWasHere = 0;
  46. sub HoneyPotNewGetFormStart {
  47. my $html = HoneyPotOldGetFormStart(@_);
  48. my ($ignore, $method) = @_;
  49. return $html unless not $method or lc($method) eq 'post';
  50. if (not $HoneyPotWasHere) {
  51. $HoneyPotWasHere = 1;
  52. $html .= '<div style="display: none">';
  53. $html .= $q->textfield({-name=>$HoneyPotOk, -id=>$HoneyPotOk,
  54. -default=>time,
  55. -size=>40, -maxlength=>250}) if $HoneyPotOk;
  56. $html .= $q->label({-for=>$HoneyPotIdiot1}, 'Leave empty:') . ' ' .
  57. $q->textfield({-name=>$HoneyPotIdiot1, -id=>$HoneyPotIdiot1,
  58. -size=>40, -maxlength=>250}) if $HoneyPotIdiot1;
  59. $html .= $q->textarea(-name=>$HoneyPotIdiot2, -id=>$HoneyPotIdiot2,
  60. -rows=>5, -columns=>78) if $HoneyPotIdiot2;
  61. $html .= '</div>';
  62. }
  63. return $html;
  64. }
  65. # kill requests that contain the idiot or looser parameters
  66. # and requests that have a timestamp that is too old
  67. push(@MyInitVariables, \&HoneyPotInspection);
  68. sub HoneyPotInspection {
  69. if (not UserIsEditor()
  70. # we're making an edit
  71. and GetParam('title', '')
  72. # override from questionasker.pl
  73. and not ($QuestionaskerRememberAnswer and GetParam($QuestionaskerSecretKey, 0))
  74. # the parameters we use in our form
  75. and (GetParam($HoneyPotIdiot1) or GetParam($HoneyPotIdiot2)
  76. or ($HoneyPotOk
  77. and $Now - GetParam($HoneyPotOk) > $HoneyPotTimestamp))) {
  78. ReportError(T('Edit Denied'), '403 FORBIDDEN');
  79. }
  80. }
  81. =head1 COPYRIGHT AND LICENSE
  82. Copyright (C) 2011 Alex Schroeder <alex@gnu.org>
  83. This program is free software: you can redistribute it and/or modify it under
  84. the terms of the GNU General Public License as published by the Free Software
  85. Foundation, either version 3 of the License, or (at your option) any later
  86. version.
  87. This program is distributed in the hope that it will be useful, but WITHOUT ANY
  88. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  89. PARTICULAR PURPOSE. See the GNU General Public License for more details.
  90. You should have received a copy of the GNU General Public License along with
  91. this program. If not, see <http://www.gnu.org/licenses/>.
  92. =cut