Created
November 6, 2011 04:55
-
-
Save elazar/1342491 to your computer and use it in GitHub Desktop.
Iterator to generate sequential passwords within a given length range
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Iterator to generate sequential passwords within a given length range. | |
*/ | |
class PasswordIterator implements Iterator | |
{ | |
/** | |
* Length of the next password to be generated | |
* @var int | |
*/ | |
protected $length; | |
/** | |
* Minimum password length | |
* @var int | |
*/ | |
protected $min; | |
/** | |
* Maximum password length | |
* @var int | |
*/ | |
protected $max; | |
/** | |
* Number of passwords that have been generated, returned by key() | |
* @var int | |
*/ | |
protected $counter; | |
/** | |
* Next password to be returned, stored in an array with one character | |
* per element to allow for easy incrementation, returned by current() | |
* @var array | |
*/ | |
protected $password; | |
/** | |
* Mapping of ASCII codes to corresponding characters, used for | |
* incrementation | |
* @var array | |
*/ | |
protected $chr; | |
/** | |
* Mapping of ASCII characters to corresponding codes, used for | |
* incrementation | |
* @var array | |
*/ | |
protected $ord; | |
/** | |
* First character to which a character position is reset when its | |
* preceding character is incremented | |
* @var string | |
*/ | |
protected $first; | |
/** | |
* Last character to which a character position is set before its | |
* preceding character is incremented | |
* @var string | |
*/ | |
protected $last; | |
/** | |
* Last character position for the current password length | |
* @var int | |
*/ | |
protected $end; | |
/** | |
* Last password of the current length that will be generated, used to | |
* indicate when the length must be incremented | |
* @var string | |
*/ | |
protected $stop; | |
/** | |
* Initializes properties used for password storage and incrementation. | |
* | |
* @param int $min Minimum password length, defaults to 1 | |
* @param int $max Maximum password length, defaults to none | |
* @return void | |
*/ | |
public function __construct($min = 1, $max = null) | |
{ | |
$this->min = $min; | |
$this->max = $max; | |
$this->chr = array_combine(range(32, 126), array_map('chr', range(32, 126))); | |
$this->ord = array_flip($this->chr); | |
$this->first = reset($this->chr); | |
$this->last = end($this->chr); | |
$this->rewind(); | |
} | |
/** | |
* Increments the password length and adjusts related properties | |
* accordingly. | |
* @return void | |
*/ | |
protected function increment() | |
{ | |
$this->length++; | |
$this->password = array_fill(0, $this->length, $this->first); | |
$this->stop = array_fill(0, $this->length, $this->last); | |
$this->end = $this->length - 1; | |
} | |
/** | |
* Reinitializes properties to begin generating passwords of the | |
* minimum length again. | |
* @return void | |
*/ | |
public function rewind() | |
{ | |
$this->length = $this->min - 1; | |
$this->counter = 1; | |
$this->increment(); | |
} | |
/** | |
* Returns the current password. | |
* @return string | |
*/ | |
public function current() | |
{ | |
return implode('', $this->password); | |
} | |
/** | |
* Returns the number of passwords generated. | |
* @return int | |
*/ | |
public function key() | |
{ | |
return $this->counter; | |
} | |
/** | |
* Generates a new password. | |
* @return void | |
*/ | |
public function next() | |
{ | |
$this->counter++; | |
if ($this->password == $this->stop) { | |
$this->increment(); | |
} else { | |
for ($left = $this->end; isset($this->password[$left]) && $this->password[$left] == $this->last; $left--); | |
if (isset($this->password[$left]) && $this->password[$left] != $this->last) { | |
$this->password[$left] = $this->chr[$this->ord[$this->password[$left]] + 1]; | |
for ($index = $left + 1; $index < $this->length; $index++) { | |
$this->password[$index] = $this->first; | |
} | |
} | |
} | |
} | |
/** | |
* Returns whether the next password is valid with respect to the | |
* given length range. | |
* @return boolean TRUE if the current password has a length under the | |
* maximum or no maximum is set | |
*/ | |
public function valid() | |
{ | |
return $this->max ? ($this->max >= $this->length) : true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment