Location: PHPKode > scripts > Enigma > enigma/core/enigma.class.php
<?
/**
 * This class represents an Enigma.
 *
 * 3 different models can be emulated with this class, each one has its own set of rotors and reflectors to be used with.
 * Depending on the model, 3 or 4 rotors are mounted, only the first three of them can be triggered by the advance mechanism.
 * A letter is encoded by sending its corresponding signal through the plugboard, rotor 1..3(4), the reflector,
 * rotor 3(4)..1 and the plugboard again.
 * After each encoded letter, the advance mechanism changes the internal setup by rotating the rotors.
 *
 * @author David Kargl <hide@address.com>
 * @version 1.0
 * @package Enigma
 * @subpackage Core
 */
class Enigma {

	/**
	* The plugboard that connects input and output to the 1st rotor.
    * @var EnigmaPlugboard
    */
	private $plugboard = null;

	/**
	* The rotors used by the Enigma.
    * @var array EnigmaRotor
    */
	private $rotors = null;

	/**
	* The reflector used by the Enigma.
    * @var array EnigmaReflector
    */
	private $reflector = null;

	/**
	* The rotors available for this model of the Enigma.
    * @var array EnigmaRotor
    */
	private $availablerotors = null;

	/**
	* The reflectors available for this model of the Enigma.
    * @var array EnigmaReflector
    */
	private $availablereflectors = null;

    /**
     * Constructor sets up the plugboard and creates the rotors and reflectros available for the given model.
     * The initital rotors and reflectros are mounted.
     * @param integer ID for the model to emulate
     * @param array integer IDs for the rotors for the initial setup
     * @param integer ID for the reflector for the initial setup
     * @uses $ENIGMA_ROTORS
     * @uses $ENIGMA_REFLECTORS
     * @uses EnigmaPlugboard
     * @uses EnigmaRotor
     * @uses EnigmaReflector
     */
	public function __construct($model, $rotors, $reflector) {
		global $ENIGMA_ROTORS, $ENIGMA_REFLECTORS;

		$this->rotors = array();
		$this->availablerotors = array();
		$this->availablereflectors = array();

		$this->plugboard = new EnigmaPlugboard();

		foreach($ENIGMA_ROTORS as $r) if (in_array($model, $r["used"])) $this->availablerotors[$r["key"]] = new EnigmaRotor($r["wiring"], $r["notches"]);
		foreach($ENIGMA_REFLECTORS as $r) if (in_array($model, $r["used"])) $this->availablereflectors[$r["key"]] = new EnigmaReflector($r["wiring"]);

		foreach($rotors as $key=>$value) $this->mountRotor($key, $value);
		$this->mountReflector($reflector);
	}

    /**
     * Advance the rotors.
     * Rotor 1 advances every time, rotor 2 when a notch on rotor 1 is open and when rotor 3 advances, rotor 3 when a notch on rotor 2 is open
     * @return void
     */
	private function advance() {
		if ($this->rotors[1]->isNotchOpen()) {
			$this->rotors[2]->advance();
			$this->rotors[1]->advance();
		}
		if ($this->rotors[0]->isNotchOpen()) $this->rotors[1]->advance();
		$this->rotors[0]->advance();
	}

    /**
     * Encode a single letter.
     * The letter passes the plugboard, the rotors, the reflector, the rotors in the opposite direction and again the plugboard.
     * Every encoding triggers the advancemechanism.
     * @see advance
     * @param string letter to encode
     * @return string encoded letter
     * @uses enigma_l2p
     * @uses enigma_p2l
     */
	public function encodeLetter($letter) {
		$this->advance();
		$letter = enigma_l2p($letter);
		$letter = $this->plugboard->processLetter($letter);
		for ($idx=0; $idx<sizeof($this->rotors); $idx++) $letter = $this->rotors[$idx]->processLetter1stPass($letter);
		$letter = $this->reflector->processLetter($letter);
		for ($idx=(sizeof($this->rotors)-1); $idx>-1; $idx--) $letter = $this->rotors[$idx]->processLetter2ndPass($letter);
		$letter = $this->plugboard->processLetter($letter);
		$letter = enigma_p2l($letter);
		return $letter;
	}

    /**
     * Mount a rotor into the enigma.
     * A rotor may only be used in one position at a time, so if an rotor is already in use nothing is changed.
     * The previously used rotor will be replaced.
     * @param integer ID of the position to set the rotor
     * @param integer ID of the rotor to use
     * @return void
     */
	public function mountRotor($position, $rotor) {
		if($this->availablerotors[$rotor]->inUse) return;
		if($this->rotors[$position]) $this->rotors[$position]->inUse = false;
		$this->rotors[$position] = $this->availablerotors[$rotor];
		$this->rotors[$position]->inUse = true;
	}

    /**
     * Mount a reflector into the enigma.
     * The previously used reflector will be replaced.
     * @param integer ID of the reflector to use
     * @return void
     */
	public function mountReflector($reflector) {
		$this->reflector = $this->availablereflectors[$reflector];
	}

    /**
     * Turn a rotor to a new position.
     * @param integer ID of the rotor to turn
     * @param string letter to turn to
     * @return void
     * @uses enigma_l2p
     */
	public function setPosition($position, $letter) {
		$this->rotors[$position]->setPosition(enigma_l2p($letter));
	}

    /**
     * Get the current position of a rotor.
     * @param integer ID of the rotor
     * @return string current position
     * @uses enigma_p2l
     */
	public function getPosition($position) {
		return enigma_p2l($this->rotors[$position]->getPosition());
	}

    /**
     * Turn the ringstellung of a rotor to a new position.
     * @param integer ID of the rotor
     * @param string letter to turn to
     * @return void
     * @uses enigma_l2p
     */
	public function setRingstellung($position, $letter) {
		$this->rotors[$position]->setRingstellung(enigma_l2p($letter));
	}

    /**
     * Connect 2 letters on the plugboard.
     * The letter are transformed to integer first
     * @param string letter 1 to connect
     * @param string letter 2 to connect
     * @return void
     * @uses enigma_l2p
     */
	public function plugLetters($letter1, $letter2) {
		$this->plugboard->plugLetters(enigma_l2p($letter1), enigma_l2p($letter2));
	}

    /**
     * Disconnects 2 letters on the plugboard.
     * Because letters are connected in pairs, we only need to know one of them.
     * @param string 1 of the 2 letters to disconnect
     * @return void
     * @uses enigma_l2p
     */
	public function unplugLetters($letter) {
		$this->plugboard->unplugLetters(enigma_l2p($letter));
	}


}
?>
Return current item: Enigma