2004-12-16 04:34:07 +00:00
|
|
|
|
# Copyright (C) 2004 Brock Wilcox <awwaiid@thelackthereof.org>
|
2015-07-28 22:44:53 +02:00
|
|
|
|
# Copyright (C) 2006–2015 Alex Schroeder <alex@gnu.org>
|
2004-12-16 04:34:07 +00:00
|
|
|
|
#
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
2007-08-17 00:30:31 +00:00
|
|
|
|
# the Free Software Foundation; either version 3 of the License, or
|
2004-12-16 04:34:07 +00:00
|
|
|
|
# (at your option) any later version.
|
|
|
|
|
|
#
|
|
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
|
|
#
|
|
|
|
|
|
# You should have received a copy of the GNU General Public License
|
2007-08-17 00:30:31 +00:00
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2004-12-16 04:34:07 +00:00
|
|
|
|
|
2015-03-29 23:20:37 +02:00
|
|
|
|
use strict;
|
2015-08-18 10:48:03 +02:00
|
|
|
|
use v5.10;
|
2015-03-27 03:01:01 +02:00
|
|
|
|
|
2014-08-21 22:23:23 +02:00
|
|
|
|
AddModuleDescription('questionasker.pl', 'QuestionAsker Extension');
|
2004-12-16 04:34:07 +00:00
|
|
|
|
|
PrintFooter relies on @MyFooters
We already called all the subs on @MyFooters and printed the result,
but this commit moves all the code from PrintFooters into subs and
puts those subs on @MyFooters. This allows us to write modules that
can better control where exactly their output should appear. In this
case the change was required in order to allow the Google +1 module to
coexist with code that maybe prints the comment form for all pages.
For example, knowing that the Google +1 sub is the first on one the
list because of unshift(@MyFooters, \&GooglePlusPrintFooter), we can
now write the following:
splice(@MyFooters, 1, 0, \&MyCommentsInTheFooter);
sub MyCommentsInTheFooter {
my ($id, $rev, $comment) = @_;
if (not $GooglePlusThisPagePrintedJournal
and (GetParam('action', 'browse') eq 'browse'
and $id and $CommentsPrefix
and $id ne $RCName
and $id !~ /^$CommentsPrefix(.*)/o)) {
my $target = $CommentsPrefix . $id;
my $page = '';
$page = PageHtml($target) if $IndexHash{$target};
return $q->div({-class=>'comment'},
$q->h2(T('Comments')),
$page)
. GetCommentForm("$CommentsPrefix$id", $rev, $comment);
}
}
The Google +1 extension was also fixed to not triger the EFF's Privacy
Badger. This is OK because we're using a two step button: The user
needs to click a button before we're loading the script from Google.
2015-08-17 13:39:34 +02:00
|
|
|
|
our ($q, $bol, $FreeLinks, $FreeLinkPattern, $LinkPattern, $WikiLinks,
|
2015-08-18 11:11:13 +02:00
|
|
|
|
@MyInitVariables, %AdminPages, %CookieParameters, @MyFormChanges);
|
PrintFooter relies on @MyFooters
We already called all the subs on @MyFooters and printed the result,
but this commit moves all the code from PrintFooters into subs and
puts those subs on @MyFooters. This allows us to write modules that
can better control where exactly their output should appear. In this
case the change was required in order to allow the Google +1 module to
coexist with code that maybe prints the comment form for all pages.
For example, knowing that the Google +1 sub is the first on one the
list because of unshift(@MyFooters, \&GooglePlusPrintFooter), we can
now write the following:
splice(@MyFooters, 1, 0, \&MyCommentsInTheFooter);
sub MyCommentsInTheFooter {
my ($id, $rev, $comment) = @_;
if (not $GooglePlusThisPagePrintedJournal
and (GetParam('action', 'browse') eq 'browse'
and $id and $CommentsPrefix
and $id ne $RCName
and $id !~ /^$CommentsPrefix(.*)/o)) {
my $target = $CommentsPrefix . $id;
my $page = '';
$page = PageHtml($target) if $IndexHash{$target};
return $q->div({-class=>'comment'},
$q->h2(T('Comments')),
$page)
. GetCommentForm("$CommentsPrefix$id", $rev, $comment);
}
}
The Google +1 extension was also fixed to not triger the EFF's Privacy
Badger. This is OK because we're using a two step button: The user
needs to click a button before we're loading the script from Google.
2015-08-17 13:39:34 +02:00
|
|
|
|
|
2015-04-10 13:31:28 +03:00
|
|
|
|
our (@QuestionaskerQuestions,
|
PrintFooter relies on @MyFooters
We already called all the subs on @MyFooters and printed the result,
but this commit moves all the code from PrintFooters into subs and
puts those subs on @MyFooters. This allows us to write modules that
can better control where exactly their output should appear. In this
case the change was required in order to allow the Google +1 module to
coexist with code that maybe prints the comment form for all pages.
For example, knowing that the Google +1 sub is the first on one the
list because of unshift(@MyFooters, \&GooglePlusPrintFooter), we can
now write the following:
splice(@MyFooters, 1, 0, \&MyCommentsInTheFooter);
sub MyCommentsInTheFooter {
my ($id, $rev, $comment) = @_;
if (not $GooglePlusThisPagePrintedJournal
and (GetParam('action', 'browse') eq 'browse'
and $id and $CommentsPrefix
and $id ne $RCName
and $id !~ /^$CommentsPrefix(.*)/o)) {
my $target = $CommentsPrefix . $id;
my $page = '';
$page = PageHtml($target) if $IndexHash{$target};
return $q->div({-class=>'comment'},
$q->h2(T('Comments')),
$page)
. GetCommentForm("$CommentsPrefix$id", $rev, $comment);
}
}
The Google +1 extension was also fixed to not triger the EFF's Privacy
Badger. This is OK because we're using a two step button: The user
needs to click a button before we're loading the script from Google.
2015-08-17 13:39:34 +02:00
|
|
|
|
$QuestionaskerRememberAnswer,
|
|
|
|
|
|
$QuestionaskerSecretKey,
|
|
|
|
|
|
$QuestionaskerRequiredList,
|
|
|
|
|
|
%QuestionaskerProtectedForms);
|
2004-12-16 04:34:07 +00:00
|
|
|
|
|
2006-05-28 22:20:21 +00:00
|
|
|
|
# A list of arrays. The first element in each array is a string, the
|
|
|
|
|
|
# question to be asked. The second element is a subroutine which is
|
|
|
|
|
|
# passed the answer as the first argument.
|
2006-05-26 23:08:16 +00:00
|
|
|
|
@QuestionaskerQuestions =
|
2006-05-30 20:05:14 +00:00
|
|
|
|
(['What is the first letter of this question?' => sub { shift =~ /^\s*W\s*$/i }],
|
|
|
|
|
|
['How many letters are in the word "four"?' => sub { shift =~ /^\s*(4|four)\s*$/i }],
|
|
|
|
|
|
['Tell me any number between 1 and 10' => sub { shift =~ /^\s*([1-9]|10|one|two|three|four|five|six|seven|eight|nine|ten)\s*$/ }],
|
2007-08-17 00:26:35 +00:00
|
|
|
|
["How many lives does a cat have?" => sub { shift =~ /^\s*(7|seven|9|nine)\s*$/i }],
|
2006-05-30 20:05:14 +00:00
|
|
|
|
["What is 2 + 4?" => sub { shift =~ /^\s*(6|six)\s*$/i }],
|
2006-05-26 23:08:16 +00:00
|
|
|
|
);
|
2004-12-16 04:34:07 +00:00
|
|
|
|
|
2006-05-28 22:20:21 +00:00
|
|
|
|
# The page name for exceptions, if defined. Every page linked to via
|
|
|
|
|
|
# WikiWord or [[free link]] is considered to be a page which needs
|
|
|
|
|
|
# questions asked. All other pages do not require questions asked. If
|
|
|
|
|
|
# not set, then all pages need questions asked.
|
|
|
|
|
|
$QuestionaskerRequiredList = '';
|
|
|
|
|
|
|
2006-06-05 21:28:14 +00:00
|
|
|
|
# If a user answers a question correctly, remember this in the cookie
|
2007-10-01 00:17:32 +00:00
|
|
|
|
# and don't ask any further questions. The name of the parameter in
|
|
|
|
|
|
# the cookie can be changed should a spam bot target this module
|
|
|
|
|
|
# specifically. Changing the secret key will force all users to answer
|
|
|
|
|
|
# another question.
|
2006-06-05 21:28:14 +00:00
|
|
|
|
$QuestionaskerRememberAnswer = 1;
|
2007-10-01 00:17:32 +00:00
|
|
|
|
$QuestionaskerSecretKey = 'question';
|
2006-06-05 21:28:14 +00:00
|
|
|
|
|
2006-05-28 22:20:21 +00:00
|
|
|
|
# Forms using one of the following classes are protected.
|
|
|
|
|
|
%QuestionaskerProtectedForms = ('comment' => 1,
|
|
|
|
|
|
'edit upload' => 1,
|
|
|
|
|
|
'edit text' => 1,);
|
|
|
|
|
|
|
2006-05-28 22:28:48 +00:00
|
|
|
|
push(@MyInitVariables, \&QuestionaskerInit);
|
|
|
|
|
|
|
|
|
|
|
|
sub QuestionaskerInit {
|
|
|
|
|
|
$QuestionaskerRequiredList = FreeToNormal($QuestionaskerRequiredList);
|
2006-07-15 23:14:02 +00:00
|
|
|
|
$AdminPages{$QuestionaskerRequiredList} = 1;
|
2007-10-01 00:17:32 +00:00
|
|
|
|
$CookieParameters{$QuestionaskerSecretKey} = '';
|
2006-05-28 22:28:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2015-04-11 23:41:33 +03:00
|
|
|
|
*OldQuestionaskerDoPost = \&DoPost;
|
|
|
|
|
|
*DoPost = \&NewQuestionaskerDoPost;
|
2005-12-18 00:07:36 +00:00
|
|
|
|
|
2004-12-16 04:34:07 +00:00
|
|
|
|
sub NewQuestionaskerDoPost {
|
|
|
|
|
|
my(@params) = @_;
|
2006-05-28 22:20:21 +00:00
|
|
|
|
my $id = FreeToNormal(GetParam('title', undef));
|
2006-05-30 20:05:14 +00:00
|
|
|
|
my $preview = GetParam('Preview', undef); # case matters!
|
2004-12-16 04:34:07 +00:00
|
|
|
|
my $question_num = GetParam('question_num', undef);
|
|
|
|
|
|
my $answer = GetParam('answer', undef);
|
2008-02-19 09:07:26 +00:00
|
|
|
|
unless (UserIsEditor()
|
2007-10-01 00:17:32 +00:00
|
|
|
|
or $QuestionaskerRememberAnswer && GetParam($QuestionaskerSecretKey, 0)
|
2006-05-30 20:05:14 +00:00
|
|
|
|
or $preview
|
|
|
|
|
|
or $QuestionaskerQuestions[$question_num][1]($answer)
|
|
|
|
|
|
or QuestionaskerException($id)) {
|
2006-05-26 23:08:16 +00:00
|
|
|
|
print GetHeader('', T('Edit Denied'), undef, undef, '403 FORBIDDEN');
|
|
|
|
|
|
print $q->p(T('You did not answer correctly.'));
|
2012-05-22 11:45:00 +02:00
|
|
|
|
print GetFormStart(), QuestionaskerGetQuestion(1),
|
2014-06-03 11:19:50 +02:00
|
|
|
|
(map { $q->input({-type=>'hidden', -name=>$_,
|
|
|
|
|
|
-value=>UnquoteHtml(GetParam($_))}) }
|
2007-11-11 10:25:29 +00:00
|
|
|
|
qw(title text oldtime summary recent_edit aftertext)), $q->end_form;
|
2006-05-30 20:05:14 +00:00
|
|
|
|
PrintFooter();
|
2006-06-05 20:21:35 +00:00
|
|
|
|
# logging to the error log file of the server
|
|
|
|
|
|
# warn "Q: '$QuestionaskerQuestions[$question_num][0]', A: '$answer'\n";
|
2006-05-26 23:08:16 +00:00
|
|
|
|
return;
|
2004-12-16 04:34:07 +00:00
|
|
|
|
}
|
2008-06-11 13:05:48 +00:00
|
|
|
|
# Set the secret key only if a question has in fact been answered
|
|
|
|
|
|
if (not GetParam($QuestionaskerSecretKey, 0)
|
|
|
|
|
|
and $QuestionaskerQuestions[$question_num][1]($answer)) {
|
|
|
|
|
|
SetParam($QuestionaskerSecretKey, 1)
|
|
|
|
|
|
}
|
2004-12-16 04:34:07 +00:00
|
|
|
|
return (OldQuestionaskerDoPost(@params));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-08-18 11:11:13 +02:00
|
|
|
|
push(@MyFormChanges, \&QuestionAddTo);
|
2008-01-28 16:01:24 +00:00
|
|
|
|
|
|
|
|
|
|
sub QuestionAddTo {
|
2015-08-18 11:11:13 +02:00
|
|
|
|
my ($form, $type, $upload) = @_;
|
2007-10-07 20:00:08 +00:00
|
|
|
|
if (not $upload
|
2006-05-28 22:20:21 +00:00
|
|
|
|
and not QuestionaskerException(GetId())
|
2008-04-14 11:25:23 +00:00
|
|
|
|
and not $QuestionaskerRememberAnswer && GetParam($QuestionaskerSecretKey, 0)
|
2008-02-19 09:07:26 +00:00
|
|
|
|
and not UserIsEditor()) {
|
2007-10-07 20:00:08 +00:00
|
|
|
|
my $question = QuestionaskerGetQuestion();
|
2009-05-25 11:40:46 +00:00
|
|
|
|
$form =~ s/(.*)<p>(.*?)<label for="username">/$1$question<p>$2<label for="username">/;
|
2006-05-28 22:20:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
return $form;
|
2005-12-18 00:07:36 +00:00
|
|
|
|
}
|
2004-12-16 04:34:07 +00:00
|
|
|
|
|
2005-12-18 00:07:36 +00:00
|
|
|
|
sub QuestionaskerGetQuestion {
|
2007-10-07 20:13:10 +00:00
|
|
|
|
my $need_button = shift;
|
|
|
|
|
|
my $button = $need_button ? $q->submit(-value=>T('Go!')) : '';
|
2005-12-18 00:07:36 +00:00
|
|
|
|
my $question_number = int(rand(scalar(@QuestionaskerQuestions)));
|
2006-05-28 22:20:21 +00:00
|
|
|
|
return $q->div({-class=>'question'},
|
|
|
|
|
|
$q->p(T('To save this page you must answer this question:')),
|
|
|
|
|
|
$q->blockquote($q->p($QuestionaskerQuestions[$question_number][0]),
|
|
|
|
|
|
$q->p($q->input({-type=>'text', -name=>'answer'}),
|
|
|
|
|
|
$q->input({-type=>'hidden', -name=>'question_num',
|
2007-10-07 20:13:10 +00:00
|
|
|
|
-value=>$question_number}),
|
|
|
|
|
|
$button)));
|
2004-12-16 04:34:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2006-05-26 23:08:16 +00:00
|
|
|
|
sub QuestionaskerException {
|
|
|
|
|
|
my $id = shift;
|
|
|
|
|
|
return 0 unless $QuestionaskerRequiredList and $id;
|
2006-05-26 23:13:55 +00:00
|
|
|
|
my $data = GetPageContent($QuestionaskerRequiredList);
|
2006-05-26 23:08:16 +00:00
|
|
|
|
if ($WikiLinks) {
|
|
|
|
|
|
while ($data =~ /$LinkPattern/g) {
|
2006-05-26 23:18:16 +00:00
|
|
|
|
return 0 if FreeToNormal($1) eq $id;
|
2006-05-26 23:08:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if ($FreeLinks) {
|
|
|
|
|
|
while ($data =~ /\[\[$FreeLinkPattern\]\]/g) {
|
2006-05-26 23:18:16 +00:00
|
|
|
|
return 0 if FreeToNormal($1) eq $id;
|
2006-05-26 23:08:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2006-05-26 23:18:16 +00:00
|
|
|
|
return 1;
|
2006-05-26 23:08:16 +00:00
|
|
|
|
}
|