Skip to content

Commit

Permalink
Merge pull request #3 from aetiom/dev
Browse files Browse the repository at this point in the history
Push controller and security rework to v1.0
  • Loading branch information
aetiom authored Feb 5, 2019
2 parents eae9c63 + 84d56b7 commit ed8a66f
Show file tree
Hide file tree
Showing 12 changed files with 589 additions and 609 deletions.
202 changes: 129 additions & 73 deletions src/Captcha.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,29 @@
class Captcha {

/**
* @var Array $options : captcha options
* @var \VoightKampff\Opions $options : config options
*/
protected $options;

/**
* @var Collection $collection : captcha collection
* @var \VoightKampff\Collection $collection : captcha collection
*/
protected $collection = null;

/**
* @var \aetiom\PhpExt\Session $session : captcha session
* @var \VoightKampff\Security $security : captcha security
*/
protected $session = null;
protected $security = null;

/**
* @var \aetiom\PhpExt\MultiLang\Collection $directiveCol : directive collection
* @var \aetiom\PhpExt\MultiLang\Collection $errorCol : error collection
*/
protected $directiveCol = null;
protected $errorCol = null;

/**
* @var \aetiom\PhpExt\MultiLang\Collection $errorCol : error collection
* @var \VoightKampff\Directive $directive : directive container
*/
protected $errorCol = null;
protected $directive = null;

/**
* @var \aetiom\PhpExt\MultiLang\Container $error : error container
Expand All @@ -44,22 +44,43 @@ class Captcha {


/**
* Get captcha identifier
* @return string : captcha identifier
* Get posted images from HTML form
*
* @param integer $count : number of images to obtain
* @param string $prefix : checkbox prefix (id + cbPrefix)
*
* @return array : posted images identifiers
*/
public function getId()
static public function obtainPostedImages($count, $prefix)
{
return $this->collection->getId();
$postedImages = array();

for ($i = 0; $i < $count; $i++) {
$key = $prefix.$i;

if (!isset($_POST[$key])) {
continue;
}

$postedImages[] = filter_var($_POST[$key], FILTER_VALIDATE_INT);
}

return $postedImages;
}



/**
* Get collection of images to display
* @return array : image collection
*/
public function getImages()
{
return $this->collection->getImages();
if ($this->collection !== null) {
return $this->collection->getImages();
}

return array();
}

/**
Expand All @@ -69,9 +90,13 @@ public function getImages()
* @return string : selected language directive message if it exist
* default language directive otherwise
*/
public function getDirective($lang = '')
public function getDirective($lang = null)
{
return $this->formatDirective($lang);
if ($this->collection !== null) {
return $this->directive->getMessage($lang);
}

return '';
}

/**
Expand All @@ -83,6 +108,15 @@ public function getError()
return $this->error;
}

/**
* Get options
* @return \VoightKampff\Options : captcha options
*/
public function getOptions()
{
return $this->options;
}



/**
Expand All @@ -91,27 +125,19 @@ public function getError()
* @param string $id : captcha identifier
* @param array $param : optional parameters
*/
public function __construct($id, $param)
public function __construct($id, $param = array())
{
$this->options = $param;

$this->directiveCol = new \aetiom\PhpExt\MultiLang\Collection(
$this->options['directiveCollection'],
$this->options['defaultLang']);
$this->options = new Options($param);
$this->options->cbPrefix = $id.'-'.$this->options->cbPrefix;

$this->errorCol = new \aetiom\PhpExt\MultiLang\Collection(
$this->options['errorCollection'],
$this->options['defaultLang']);
$this->options->errorCollection,
$this->options->defaultLang);

$this->collection = new Collection($id, $this->options);
$this->security = new Security($this->options['security']);
$this->security = new Security($this->options);

if ($this->security->getTimeoutStatus()) {
$this->error = $this->errorCol->createContainer('timeout',
array('%TIME%' => $this->security->getTimeoutRemaining()));

$this->collection->clear();
}
$this->directive = new Directive($this->options, $this->collection);
}


Expand All @@ -122,13 +148,14 @@ public function __construct($id, $param)
* @param array $userAnswers : user answers to check and certifiates
* @return boolean true in case of success, false otherwise
*/
public function verify($userAnswers)
public function verify(array $userAnswers = null)
{
$answerList = $this->collection->getAnswers();
if ($userAnswers === null) {
$userAnswers = self::obtainPostedImages(
$this->options->imageCount, $this->options->cbPrefix);
}

if (!$this->security->isSessionActive()) {
$this->error = $this->errorCol->createContainer('inactive');
$this->collection->clear();
if ($this->checkInactivity()) {
return false;
}

Expand All @@ -137,34 +164,55 @@ public function verify($userAnswers)
return false;
}

if ($this->checkAnswers($userAnswers, $answerList)) {
$this->security->addAttempt();

if ($this->checkAnswers($userAnswers)) {
$this->collection->clear();
$this->security->clear();
return true;
}

if (!$this->security->addAttempt()) {
$this->collection->clear();
}

$this->error = $this->errorCol->createContainer('wrongAnswers');
return false;
}

/**
* Display captcha
*
* @param string $lang : display language
* @return string : html code
*
* @throws \Exception if captcha id does not exist
*/
public function display($lang = null)
{
if (!$this->checkTimeout()) {
$this->checkInactivity(true);
}

$error = '';
if ($this->error !== null) {
$error = $this->error->getMessage($lang);
}

$display = new Display($this->options, $this->getImages());
return $display->createHtml($this->getDirective($lang), $error);
}



/**
* Check user answers
*
* @param array $userAnswers : user answers
* @param array $expectedAnswers : system expected answers
*
* @param array $userAnswers : user answers
* @return boolean true if anwsers are those expected, false otherwise
*/
private function checkAnswers($userAnswers, $expectedAnswers)
private function checkAnswers($userAnswers)
{
$expectedAnswers = $this->collection->getAnswers();

// return false if user does not send count of expected answers
if (count($userAnswers) !== $this->options['requestCount']) {
if (count($userAnswers) !== $this->options->requestCount) {
return false;
}

Expand All @@ -178,45 +226,53 @@ private function checkAnswers($userAnswers, $expectedAnswers)
}
}

if ($count === $this->options['requestCount']) {
if ($count === $this->options->requestCount) {
return true;
}

return false;
}

/**
* Format directive
*
* @param string $lang : selected language
* @return string formated directive
* Check timeout status
* @return boolean true if user has been timeouted, false otherwise
*/
private function formatDirective($lang)
private function checkTimeout()
{
$start = $this->directiveCol->createContainer('start');
$link1 = $this->directiveCol->createContainer('linkSimple');
$link2 = $this->directiveCol->createContainer('linkMulti');
$end = $this->directiveCol->createContainer('end');
$kwIn = $this->directiveCol->createContainer('keywordIn');
$kwOut = $this->directiveCol->createContainer('keywordOut');

$dirStr = '';
foreach ($this->collection->getKeyWords() as $key => $q) {
if (!empty($dirStr)) {
if ($this->options['requestCount'] > 2
&& $key < $this->options['requestCount'] - 1) {
$dirStr .= $link2->getMessage($lang);
} else {
$dirStr .= $link1->getMessage($lang);
}
}
if ($this->security->getTimeoutRemaining() > 0) {
$this->error = $this->errorCol->createContainer('timeout',
array('%TIME%' => $this->security->getTimeoutRemaining()));


$dirStr .= $kwIn->getMessage($lang).$q[$lang].$kwOut->getMessage($lang);

$this->collection->clear();
return true;
}

if ($this->security->getTimeoutRemaining() < 0) {
$this->security->resetTimout();
$this->collection->reset();
}

return $start->getMessage($lang).$dirStr.$end->getMessage($lang);
return false;
}

/**
* Check inactivity status
*
* @param boolean $throwError : set false if error doesn't have to be throw
* @return boolean true if session is active, false otherwise
*/
private function checkInactivity(bool $throwError = true)
{
if ($this->security->isSessionActive()) {
return false;
}

if ($throwError) {
$this->error = $this->errorCol->createContainer('inactive');
}

$this->security->resetInactivity();
$this->collection->reset();
return true;
}
}
Loading

0 comments on commit ed8a66f

Please sign in to comment.