Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: Extract phpweb\Spam\Challenge #664

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions manual/add-note.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
<?php

use phpweb\Spam\Challenge;

$ip_spam_lookup_url = 'http://www.dnsbl.info/dnsbl-database-check.php?IP=';

$_SERVER['BASE_PAGE'] = 'manual/add-note.php';

require_once __DIR__ . '/../autoload.php';
include_once __DIR__ . '/../include/prepend.inc';
include_once __DIR__ . '/../include/posttohost.inc';
include_once __DIR__ . '/../include/shared-manual.inc';
include __DIR__ . '/spam_challenge.php';

use phpweb\UserNotes\UserNote;

Expand Down Expand Up @@ -55,7 +59,7 @@
}

// SPAM challenge failed
elseif (!test_answer($_POST['func'], $_POST['arga'], $_POST['argb'], $_POST['answer'])) {
elseif (!Challenge::isValidAnswer($_POST['func'], $_POST['arga'], $_POST['argb'], $_POST['answer'])) {
$error = 'SPAM challenge failed.';
}

Expand Down Expand Up @@ -366,14 +370,14 @@
</tr>
<tr>
<th class="subr"><label for="form-answer">Answer to this simple question (SPAM challenge)</label>:<br>
<?php $c = gen_challenge(); echo $c[3]; ?>?</th>
<?php $c = Challenge::create(); echo $c->question; ?>?</th>
<td><input id="form-answer" type="text" name="answer" size="60" maxlength="10" required> (Example: nine)</td>
</tr>
<tr>
<th colspan="2">
<input type="hidden" name="func" value="<?php echo $c[0]; ?>">
<input type="hidden" name="arga" value="<?php echo $c[1]; ?>">
<input type="hidden" name="argb" value="<?php echo $c[2]; ?>">
<input type="hidden" name="func" value="<?php echo $c->function; ?>">
<input type="hidden" name="arga" value="<?php echo $c->argumentOne; ?>">
<input type="hidden" name="argb" value="<?php echo $c->argumentTwo; ?>">
<input type="submit" name="action" value="Preview">
<input type="submit" name="action" value="Add Note">
</th>
Expand Down
66 changes: 0 additions & 66 deletions manual/spam_challenge.php

This file was deleted.

24 changes: 14 additions & 10 deletions manual/vote-note.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
<?php

use phpweb\Spam\Challenge;

$_SERVER['BASE_PAGE'] = 'manual/vote-note.php';

require_once __DIR__ . '/../autoload.php';
include_once __DIR__ . '/../include/prepend.inc';
include_once __DIR__ . '/../include/posttohost.inc';
include_once __DIR__ . '/../include/shared-manual.inc';
include_once __DIR__ . '/spam_challenge.php';

// Initialize global variables
$error = false;
Expand Down Expand Up @@ -53,7 +57,7 @@
}
if (!empty($_REQUEST['id']) && !empty($_REQUEST['page']) && ($N = manual_notes_load($_REQUEST['page'])) && array_key_exists($_REQUEST['id'], $N) && !empty($_REQUEST['vote']) && ($_REQUEST['vote'] === 'up' || $_REQUEST['vote'] === 'down')) {
if (!empty($_POST['challenge']) && !empty($_POST['func']) || empty($_POST['arga']) || empty($_POST['argb'])) {
if (!test_answer($_POST['func'], $_POST['arga'], $_POST['argb'], $_POST['challenge'])) {
if (!Challenge::isValidAnswer($_POST['func'], $_POST['arga'], $_POST['argb'], $_POST['challenge'])) {
$error = "Incorrect answer! Please try again.";
}
else {
Expand Down Expand Up @@ -109,13 +113,13 @@
<div style="background-color: #f5f5ff; border: 1px solid black; padding: 15px; width: 90%; margin: auto;">
<form action="" method="post">
<div>
<p><label for="form-challenge">Please answer this simple SPAM challenge</label>: <strong><?php $c = gen_challenge(); echo $c[3]; ?></strong>?<br>
<p><label for="form-challenge">Please answer this simple SPAM challenge</label>: <strong><?php $c = Challenge::create(); echo $c->question; ?></strong>?<br>
<input id="form-challenge" type="text" name="challenge" maxlength="10" required> (Example: nine)</p>
<p><input type="submit" value="Vote" name="votenote"></p>
</div>
<input type="hidden" name="func" value="<?php echo $c[0]; ?>">
<input type="hidden" name="arga" value="<?php echo $c[1]; ?>">
<input type="hidden" name="argb" value="<?php echo $c[2]; ?>">
<input type="hidden" name="func" value="<?php echo $c->function; ?>">
<input type="hidden" name="arga" value="<?php echo $c->argumentOne; ?>">
<input type="hidden" name="argb" value="<?php echo $c->argumentTwo; ?>">
</form>
</div>
</div>
Expand Down Expand Up @@ -158,13 +162,13 @@
<div style="background-color: #f5f5ff; border: 1px solid black; padding: 15px; width: 90%; margin: auto;">
<form action="" method="post">
<div>
<p><label for="form-challenge">Please answer this simple SPAM challenge</label>: <strong><?php $c = gen_challenge(); echo $c[3]; ?></strong>?<br>
<p><label for="form-challenge">Please answer this simple SPAM challenge</label>: <strong><?php $c = Challenge::create(); echo $c->question; ?></strong>?<br>
<input id="form-challenge" type="text" name="challenge" maxlength="10" required> (Example: nine)</p>
<p><input type="submit" value="Vote" name="votenote"></p>
</div>
<input type="hidden" name="func" value="<?php echo $c[0]; ?>">
<input type="hidden" name="arga" value="<?php echo $c[1]; ?>">
<input type="hidden" name="argb" value="<?php echo $c[2]; ?>">
<input type="hidden" name="func" value="<?php echo $c->function; ?>">
<input type="hidden" name="arga" value="<?php echo $c->argumentOne; ?>">
<input type="hidden" name="argb" value="<?php echo $c->argumentTwo; ?>">
</form>
<?php echo $error_div; ?>
</div>
Expand Down
160 changes: 160 additions & 0 deletions src/Spam/Challenge.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php

declare(strict_types=1);

namespace phpweb\Spam;

final readonly class Challenge
{
private const NUMBERS = [
0 => 'zero',
1 => 'one',
2 => 'two',
3 => 'three',
4 => 'four',
5 => 'five',
6 => 'six',
7 => 'seven',
8 => 'eight',
9 => 'nine',
];

private const CHALLENGES = [
// name, print, generator
'max' => [
'max',
[
self::class,
'print_prefix',
],
],
'min' => [
'min',
[
self::class,
'print_prefix',
],
],
'minus' => [
[
self::class,
'minus',
],
[
self::class,
'print_infix',
],
[
self::class,
'gen_minus',
],
],
'plus' => [
[
self::class,
'plus',
],
[
self::class,
'print_infix',
],
[
self::class,
'gen_plus',
],
],
];

private function __construct(
public string $function,
public string $argumentOne,
public string $argumentTwo,
public string $question,
) {
}

public static function create(): self
{
$function = array_rand(self::CHALLENGES);

$challenge = self::CHALLENGES[$function];

$a = mt_rand(0, 9);
$argumentOne = self::NUMBERS[$a];

$b = isset($challenge[2]) ? $challenge[2]($a) : mt_rand(0, 9);
$argumentTwo = self::NUMBERS[$b];

$question = $challenge[1](
$function,
$argumentOne,
$argumentTwo,
);

return new self(
$function,
$argumentOne,
$argumentTwo,
$question,
);
}

public static function isValidAnswer(
string $function,
string $argumentOne,
string $argumentTwo,
string $answer,
): bool {
if (!array_key_exists($function, self::CHALLENGES)) {
return false;
}

$challenge = self::CHALLENGES[$function];

$a = array_search($argumentOne, self::NUMBERS, true);

if (!is_int($a)) {
return false;
}

$b = array_search($argumentTwo, self::NUMBERS, true);

if (!is_int($b)) {
return false;
}

$expected = self::NUMBERS[$challenge[0]($a, $b)];

return $expected === $answer;
}

private static function plus(int $a, int $b): int
{
return $a + $b;
}

private static function gen_plus(int $a): int
{
return mt_rand(0, 9 - $a);
}

private static function minus(int $a, int $b): int
{
return $a - $b;
}

private static function gen_minus(int $a): int
{
return mt_rand(0, $a);
}

private static function print_infix(string $name, string $a, string $b): string
{
return "$a $name $b";
}

private static function print_prefix(string $name, string $a, string $b): string
{
return "$name($a, $b)";
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
--TEST--
test_answer() returns true when answer to spam challenge is valid
Challenge::isValidAnswer() returns true when answer to spam challenge is valid
--FILE--
<?php

require_once __DIR__ . '/../manual/spam_challenge.php';
declare(strict_types=1);

use phpweb\Spam\Challenge;

require_once __DIR__ . '/../../../src/autoload.php';

$answers = [
[
Expand Down Expand Up @@ -73,7 +77,7 @@ $answers = [
];

$results = array_map(static function (array $answer): array {
$answer['isValid'] = test_answer(
$answer['isValid'] = Challenge::isValidAnswer(
$answer['function'],
$answer['argumentOne'],
$answer['argumentTwo'],
Expand Down
18 changes: 11 additions & 7 deletions tests/gen-challenge.phpt → tests/Spam/Challenge/random.phpt
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
--TEST--
gen_challenge() generates a spam challenge
Challenge::random() generates a spam challenge
--FILE--
<?php

require_once __DIR__ . '/../manual/spam_challenge.php';
declare(strict_types=1);

use phpweb\Spam\Challenge;

require_once __DIR__ . '/../../../src/autoload.php';

mt_srand(9001);

$challenges = array_map(static function (): array {
[$function, $argumentOne, $argumentTwo, $question] = gen_challenge();
$challenge = Challenge::create();

return [
'function' => $function,
'argumentOne' => $argumentOne,
'argumentTwo' => $argumentTwo,
'question' => $question,
'function' => $challenge->function,
'argumentOne' => $challenge->argumentOne,
'argumentTwo' => $challenge->argumentTwo,
'question' => $challenge->question,
];
}, range(1, 20));

Expand Down