GIT repositories

Index page of all the GIT repositories that are clonable form this server via HTTPS. Übersichtsseite aller GIT-Repositories, die von diesem Server aus über git clone (HTTPS) erreichbar sind.

Services

A bunch of service scripts to convert, analyse and generate data. Ein paar Services zum Konvertieren, Analysieren und Generieren von Daten.

GNU octave web interface

A web interface for GNU Octave, which allows to run scientific calculations from netbooks, tables or smartphones. The interface provides a web form generator for Octave script parameters with pre-validation, automatic script list generation, as well presenting of output text, figures and files in a output HTML page. Ein Webinterface für GNU-Octave, mit dem wissenschaftliche Berechnungen von Netbooks, Tablets oder Smartphones aus durchgeführt werden können. Die Schnittstelle beinhaltet einen Formulargenerator für Octave-Scriptparameter, mit Einheiten und Einfabevalidierung. Textausgabe, Abbildungen und generierte Dateien werden abgefangen und in einer HTML-Seite dem Nutzer als Ergebnis zur Verfügung gestellt.

Human user verification image class

Human user verification image class

To prevent bots form submitting online-forms, it is a commonly used technique to verify "human user" with a code that has to be entered by reading letters and numbers in a noisy image. This class is a simple way to do this:

Um Bots davon abzuhalten, Online-Formulare abzuschicken oder sich automatisch zu registrieren, werden mit den Formularen üblicherweise verrauschte Bilder mitgeschickt, welche einen zufälligen Code aus Zahlen und Buchstaben enthalten. Der Nutzer muss diesen Code entziffern und eingeben. Mit dieser Klasse kann diese Technik auf einfache Weise angewandt werden:

Sample source code

Anwendungsbeispiel

<?php
// Before doing anything else, we include the library
require_once('HumanUserVerification.class.php');
 
 
// This is the entry key we use for the $_SESSION for this sample code
$sessionKey = 'huv-image';
 
if(isset($_GET['img'])) {
    //
    // This section sends the imgage (we use the same script for sending HTML
    // and the binary image.
    // Check referrer and valid session
    if(isset($_SERVER['HTTP_REFERER']) && strpos(strtolower($_SERVER['HTTP_REFERER']),
            strtolower($_SERVER['HTTP_HOST'])) !== false
            && isset($_SESSION[$sessionKey])
            && is_array($_SESSION[$sessionKey])
            && isset($_SESSION[$sessionKey]['text'])
            && strlen(trim($_SESSION[$sessionKey]['text'])) > 0
    ){
        // Retrieve the data saved in the session and set the corresponding
        // instance properties
        $cfg = &$_SESSION[$sessionKey];
        $vi = new HumanUserVerificationImage(trim($cfg['text']));
        if(isset($cfg['width'])) try { $vi->setWidth($cfg['width']); } catch(Exception $e) { ; }
        if(isset($cfg['height'])) try { $vi->setHeight($cfg['height']); } catch(Exception $e) { ; }
        if(isset($cfg['noise'])) try { $vi->setNoise($cfg['noise']); } catch(Exception $e) { ; }
 
        // Finally send the image as binay code to the browser and exit.
        $vi->sendImage();
    }
 
    /*
     *
     * Alternatively, you can use the static function to create an image
     * and save the corresponding SHA1 hash code in a cookie:
     *
     *      HumanUserVerificationImage::sendValidationImageAndExit();
     *
     *  This method is much easier to use, but less configurable.
     *
     */
 
    // exit if the $vi->sendImage() method did not do this yet.
    exit();
}
 
 
////////////////////////////////////////////////////////////////////////////////
// This section is the normal HTML script:
//
 
// Create the instance
$vi = new HumanUserVerificationImage();
 
// Check if the user has entered the code
if(isset($_GET['input'])) {
 
    try {
        // Verify the code saved in the session with the entered code.
        $vi->setText($_SESSION[$sessionKey]['text']);
        if($vi->verifyInput($_GET['input'])) {
            $inputCorrect = "Input is correct";
        } else {
            $inputCorrect = "Input is not correct";
        }
    } catch(Exception $e) {
        $inputCorrect = "Exception:" . $e->getMessage();
    }
 
    /*
     * Alternatively:
     *
     *  if(HumanUserVerificationImage::verifyValidationImage($_GET['input'])) {
     *      $inputCorrect = "Input is correct";
     *  } else {
     *      $inputCorrect = "Input is not correct";
     *  }
     *
     * Use this static function to verify images sent using the function
     * HumanUserVerificationImage::sendValidationImageAndExit();
     */
}
 
// Set a new random code with 8 characters from the character list
$vi->setRandomText(8, 'ABCDEFGHIJ0123456789klmnopqr?-');
 
// Write the session for the image lookup
$_SESSION[$sessionKey] = array('text' => $vi->getText());
 
// And print it all ...
$text = $vi->getText();
 
print <<<HERE
    <html><body>
    <style>
        body { font-family: monospace; }
        table { border-collapse:collapse; border: solid 1px black; padding: 2px; }
        td { border: solid 1px black; padding: 5px; }
    </style>
        <table>
            <tr><td>Original text</td><td>$text</td></tr>
            <tr><td>Image</td><td><img src="{$_SERVER['PHP_SELF']}?img" /></td></tr>
            <tr><td>Enter here</td><td>
            <form method="GET" action="{$_SERVER['PHP_SELF']}">
                <input type="text" name="input" value="" />
                <input type="submit" name="validate" value="validate">
            </form>
            </td></tr>
            <tr><td>Last value was ok:</td><td>$inputCorrect</td></tr>
        </table>
    </body></html>
HERE;
?>

Output

The output will be a simple table, which contains the plain text code, the image (showing the same code), a form where you can enter the code and a row, which shows if the entered code was correct.

Ausgabe

Die Ausgabe wird eine simple Tabelle sein, welche den zufällig generierten Code als Text und Bild enthält. Außerdem ist ein kleines Formular dabei, in dem der Code eingegeben werden kann. Im Feld darunter wird angezeigt, ob die Eingabe richtig war.

Class source code

Klassen-Quelltext

<?php
 
/**
 * Creates a verification image for human user verification.
 * @gpackage de.atwillys.sw.php.misc
 * @author Stefan Wilhelm
 * @copyright Stefan Wilhelm, 2007
 * @license GPL
 * @version 1.0
 */
 
namespace sw;
 
class HumanUserVerificationImage {
 
  /**
   * Class configuration
   * @var array
   */
  private static $config = array(
  );
 
  /**
   * The width of the image, 0=auto
   * @var int
   */
  private $width = 0;
 
  /**
   * The height of the image
   * @var int
   */
  private $height = 15;
 
  /**
   * The text of the image.
   * @var string
   */
  private $text = '';
 
  /**
   * Noise factor
   * @var double
   */
  private $noise = 0.1;
 
 
    public static function log($what) {
        // add logging code here
    }
 
  /**
   * Sends a verification image to the browser (including a SHA1 hash cookie).
   * The function ::verifyValidationImage() can be used to validate the user
   * input generated in this function.
   * @return void
   * @param bool $saveInSession=false
   * @param int $textLength
   */
  public static function sendValidationImageAndExit($saveInSession=true, $textLength=8) {
 
    OutputBuffer::purge();
    if (isset($_SERVER['HTTP_REFERER']) && strpos(strtolower($_SERVER['HTTP_REFERER']), strtolower($_SERVER['HTTP_HOST'])) !== false) {
      try {
        $vi = new self();
        if (isset($_SESSION[$k]['width']))
          $vi->setWidth($_SESSION[$k]['width']);
        if (isset($_SESSION[$k]['height']))
          $vi->setHeight($_SESSION[$k]['height']);
        if (isset($_SESSION[$k]['noise']))
          $vi->setNoise($_SESSION[$k]['noise']);
        $vi->setRandomText($textLength);
        setcookie("hvimage", sha1(strtoupper($vi->getText())), time() + 30);
        $key = strtolower(__CLASS__);
        if ($saveInSession) {
          $_SESSION[$key] = $vi->getText();
        } else if (isset($_SESSION[$key])) {
          unset($_SESSION[$key]);
        }
        $vi->sendImage();
      } catch (\Exception $e) {
        // Send error image?
      }
    }
    exit();
  }
 
  /**
   * Hard-validates the text of a validation image that the user has entered.
   * There is no tolerance according to O<-->0 etc. The function uses cookies.
   * @param string $input
   * @return book
   */
  public static function verifyValidationImage($input) {
    $key = strtolower(__CLASS__);
    if (isset($_SESSION[$key])) {
      $vi = new self();
      $vi->setText($_SESSION[$key]);
      unset($_SESSION[$key]);
      return $vi->verifyInput($input);
      self::log("Session saved vcode is: $text");
    } else if (!isset($_COOKIE['hvimage']) || empty($_COOKIE['hvimage'])) {
      self::log("No cookie set (hvimage)");
      setcookie("hvimage", '', time());
      return false;
    } else if ($_COOKIE['hvimage'] == sha1(strtoupper(trim($input)))) {
      self::log("Cookie validation OK (hvimage)");
      return true;
    } else {
      self::log("No alternative session key saved ($key)");
    }
    return false;
  }
 
  /**
   * Constructor
   * @param string $text
   */
  public function __construct($text='') {
    if (!empty($text))
      $this->setText(trim($text));
  }
 
  /**
   * Returns the image width
   * @return int
   */
  public function getWidth() {
    return $this->width;
  }
 
  /**
   * Sets the image width
   * @param int $width
   */
  public function setWidth($width) {
    if (!is_numeric($width)) {
      throw new Exception("Invalid image width: '$width'");
    } else {
      $width = intval($width);
      if ($width < 10 || $width > 500)
        $width = 0;
      $this->width = $width;
    }
  }
 
  /**
   * Returns the image height
   * @return int
   */
  public function getHeight() {
    return $this->height;
  }
 
  /**
   * Sets the image height
   * @param int $height
   */
  public function setHeight($height) {
    if (!is_numeric($height)) {
      throw new Exception("Invalid image height: '$height'");
    } else if (intval($height) < 20) {
      throw new Exception("Invalid image height: '$height' (min width is 20)");
    } else {
      $this->height = intval($height);
    }
  }
 
  /**
   * Returns the image text
   * @return string
   */
  public function getText() {
    if (empty($this->text)) {
      $this->setRandomText();
    }
    return $this->text;
  }
 
  /**
   * Sets the text to display
   * @param string $text
   */
  public function setText($text) {
    if (!is_scalar($text)) {
      throw new Exception("Invalid image text (must be a scalar value)");
    } else if (empty($text) || strlen(trim($text)) == 0) {
      $this->text = '';
    } else {
      $this->text = strval($text);
    }
  }
 
  /**
   * Returns the noise factor
   * @return double
   */
  public function getNoise() {
    return $this->noise;
  }
 
  /**
   * Sets the noise factor
   * @param double $noise
   */
  public function setNoise($noise) {
    if (!is_numeric($noise)) {
      throw new Exception('Invalid image noise (not numeric)');
    } else if ($noise > 1 || $noise < 0) {
      throw new Exception('Invalid image noise (must be between 0 and 1)');
    } else {
      $this->noise = $noise;
    }
  }
 
  /**
   * Sets a random text
   * @param int $size
   * @param string charset
   */
  public function setRandomText($size=8, $charset='abcdefghkmnpqrtwxyzABCDEFGHIJKLMNPRTUVWXYZ2346789') {
    $charset = preg_replace('/[\s]/', '', $charset);
    if (!is_numeric($size)) {
      throw new Exception("'Invalid random text size ('$size')'");
    } else if (empty($charset)) {
      throw new Exception('Invalid character set for random text (empty string)');
    } else {
      $l = strlen($charset) - 1;
      $o = '';
      while (strlen($o) < $size) {
        $o .= substr($charset, rand(0, $l), 1);
      }
      $this->text = $o;
      return $o;
    }
  }
 
  /**
   * Generates the png image, returns the local file path
   * @return string
   */
  public function generateImage() {
    $yPositionRange = 2;
    $fontSize = $this->getHeight() - (2 * $yPositionRange);
    $charWidth = imagefontwidth($fontSize) + 3;
    $charHeight = imagefontheight($fontSize);
    $textWidth = $charWidth * strlen($this->getText());
    if ($this->getWidth() == 0)
      $this->width = $textWidth + (2 * $yPositionRange);
    $this->width = 10 * ceil($this->width / 10);
    $noisePixels = $this->getWidth() * $this->getHeight() * $this->getNoise();
    $x0 = ceil(($this->getWidth() - $textWidth) / 2);
    $y0 = ceil(($this->getHeight() - $charHeight) / 2);
 
    $img = imagecreatetruecolor($this->getWidth(), $this->getHeight());
    imagefill($img, 0, 0, 0xffffff);
 
    // Noise
    $w = $this->getWidth() - 1;
    $h = $this->getHeight() - 1;
    for ($i = 0; $i < $noisePixels; $i++) {
      $c = 0x000000;
      imagesetpixel($img, rand(0, $w), rand(0, $h), $c);
    }
 
    $text = $this->getText();
    for ($i = 0; $i < strlen($text); $i++) {
      $ch = substr($text, $i, 1);
      imagestring($img, $fontSize, $x0 + $i * $charWidth, $y0, $ch, 0x000000);
    }
 
    for ($i = floor($noisePixels); $i < $noisePixels; $i++) {
      $c = 0xffffff;
      imagesetpixel($img, rand(0, $w), rand(0, $h), $c);
    }
 
    $file = FileSystem::getTempFileName();
    imagepng($img, $file);
    imagedestroy($img);
    return $file;
  }
 
  /**
   * Sends an image as PNG, flushes the output buffer.
   */
  public function sendImage() {
    $file = $this->generateImage();
    if (!empty($file)) {
      header('Content-type: image/png');
      header('Content-Length: ' . filesize($file));
      header('Cache-Control: max-age:0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
      header('Pragma: no-cache');
      header('Connection:Close');
            while(ob_get_level()) ob_get_clean();
      print file_get_contents($file);
            @unlink($file);
    }
  }
 
  /**
   * Checks the input against the $text instance variable. One spelling
   * error is accepted for characters like O<-->0 and S<-->5.
   * @param string $input
   * @return bool
   */
  public function verifyInput($input) {
    $input = strtoupper(trim($input, " \n\r\t"));
    $text = strtoupper(trim($this->getText(), " \n\r\t"));
    if (empty($input)) {
      self::log('Verification failed: No input');
      return false;
    } else if (strlen($input) != strlen($text)) {
      self::log('Verification failed: Text lengths differ');
      return false;
    } else if ($input == $text) {
      self::log('Verification OK: Texts are equal');
      return true;
    } else if (levenshtein($input, $text) > 1) {
      self::log('Verification failed: More than one character difference');
      return false;
    } else {
      $t1 = $text;
      $t2 = $input;
      $t1 = str_replace(array('0', 'Q', '5'), array('O', 'O', 'S'), $t1);
      $t2 = str_replace(array('0', 'Q', '5'), array('O', 'O', 'S'), $t2);
      if ($t1 == $t2) {
        self::log('Verification OK, after compensation of optical redundant characters');
        return true;
      } else {
        self::log('Verification failed: Even after correction of optical redundant characters');
        return false;
      }
    }
    return false;
  }
 
}