[Xfce4-commits] [www/wiki.xfce.org] 02/03: Add captcha and loglog plugins

noreply at xfce.org noreply at xfce.org
Mon Mar 20 22:22:36 CET 2017


This is an automated email from the git hooks/post-receive script.

skunnyk pushed a commit to branch master
in repository www/wiki.xfce.org.

commit 256a3c89ada3ea71d2f97be3ce2cbe6fcf135867
Author: Romain B <skunnyk at alteroot.org>
Date:   Sun Mar 19 19:36:32 2017 +0100

    Add captcha and loglog plugins
    
    	- Captcha to avoid spam by require captcha on sigin/signup
    	- loglog plugin to know how many wiki active users we have
---
 lib/plugins/captcha/.travis.yml                    |   13 +
 lib/plugins/captcha/EasySVG.php                    |  516 +++++++++
 lib/plugins/captcha/_test/helper.test.php          |  149 +++
 lib/plugins/captcha/action.php                     |  224 ++++
 lib/plugins/captcha/conf/default.php               |   15 +
 lib/plugins/captcha/conf/metadata.php              |   15 +
 lib/plugins/captcha/figlet.flf                     | 1097 ++++++++++++++++++++
 lib/plugins/captcha/figlet.php                     |  169 +++
 lib/plugins/captcha/fonts/Rufscript010.ttf         |  Bin 0 -> 23080 bytes
 lib/plugins/captcha/fonts/VeraSe.ttf               |  Bin 0 -> 60280 bytes
 .../fonts/goudy_bookletter_1911-webfont.svg        |  145 +++
 lib/plugins/captcha/fonts/ostrich-sans-black.svg   |  141 +++
 lib/plugins/captcha/helper.php                     |  464 +++++++++
 lib/plugins/captcha/img.php                        |   22 +
 lib/plugins/captcha/lang/ar/lang.php               |   12 +
 lib/plugins/captcha/lang/ar/settings.php           |   23 +
 lib/plugins/captcha/lang/cs/lang.php               |   13 +
 lib/plugins/captcha/lang/cs/settings.php           |   23 +
 lib/plugins/captcha/lang/cy/lang.php               |   12 +
 lib/plugins/captcha/lang/cy/settings.php           |   22 +
 lib/plugins/captcha/lang/da/lang.php               |   12 +
 lib/plugins/captcha/lang/da/settings.php           |   23 +
 lib/plugins/captcha/lang/de-informal/lang.php      |   12 +
 lib/plugins/captcha/lang/de-informal/settings.php  |   23 +
 lib/plugins/captcha/lang/de/lang.php               |   12 +
 lib/plugins/captcha/lang/de/settings.php           |   24 +
 lib/plugins/captcha/lang/en/audio/LICENSE          |    4 +
 lib/plugins/captcha/lang/en/audio/a.wav            |  Bin 0 -> 33134 bytes
 lib/plugins/captcha/lang/en/audio/b.wav            |  Bin 0 -> 32318 bytes
 lib/plugins/captcha/lang/en/audio/c.wav            |  Bin 0 -> 33342 bytes
 lib/plugins/captcha/lang/en/audio/d.wav            |  Bin 0 -> 35886 bytes
 lib/plugins/captcha/lang/en/audio/e.wav            |  Bin 0 -> 30862 bytes
 lib/plugins/captcha/lang/en/audio/f.wav            |  Bin 0 -> 35310 bytes
 lib/plugins/captcha/lang/en/audio/g.wav            |  Bin 0 -> 34478 bytes
 lib/plugins/captcha/lang/en/audio/h.wav            |  Bin 0 -> 33422 bytes
 lib/plugins/captcha/lang/en/audio/i.wav            |  Bin 0 -> 34030 bytes
 lib/plugins/captcha/lang/en/audio/j.wav            |  Bin 0 -> 35438 bytes
 lib/plugins/captcha/lang/en/audio/k.wav            |  Bin 0 -> 34566 bytes
 lib/plugins/captcha/lang/en/audio/l.wav            |  Bin 0 -> 32030 bytes
 lib/plugins/captcha/lang/en/audio/m.wav            |  Bin 0 -> 32550 bytes
 lib/plugins/captcha/lang/en/audio/n.wav            |  Bin 0 -> 37678 bytes
 lib/plugins/captcha/lang/en/audio/o.wav            |  Bin 0 -> 34862 bytes
 lib/plugins/captcha/lang/en/audio/p.wav            |  Bin 0 -> 34862 bytes
 lib/plugins/captcha/lang/en/audio/q.wav            |  Bin 0 -> 32798 bytes
 lib/plugins/captcha/lang/en/audio/r.wav            |  Bin 0 -> 35830 bytes
 lib/plugins/captcha/lang/en/audio/s.wav            |  Bin 0 -> 35374 bytes
 lib/plugins/captcha/lang/en/audio/t.wav            |  Bin 0 -> 33010 bytes
 lib/plugins/captcha/lang/en/audio/u.wav            |  Bin 0 -> 37854 bytes
 lib/plugins/captcha/lang/en/audio/v.wav            |  Bin 0 -> 33166 bytes
 lib/plugins/captcha/lang/en/audio/w.wav            |  Bin 0 -> 34862 bytes
 lib/plugins/captcha/lang/en/audio/x.wav            |  Bin 0 -> 34862 bytes
 lib/plugins/captcha/lang/en/audio/y.wav            |  Bin 0 -> 35070 bytes
 lib/plugins/captcha/lang/en/audio/z.wav            |  Bin 0 -> 34382 bytes
 lib/plugins/captcha/lang/en/lang.php               |   12 +
 lib/plugins/captcha/lang/en/settings.php           |   25 +
 lib/plugins/captcha/lang/eo/lang.php               |   13 +
 lib/plugins/captcha/lang/eo/settings.php           |   22 +
 lib/plugins/captcha/lang/es/lang.php               |   12 +
 lib/plugins/captcha/lang/es/settings.php           |   20 +
 lib/plugins/captcha/lang/fa/lang.php               |   12 +
 lib/plugins/captcha/lang/fa/settings.php           |   23 +
 lib/plugins/captcha/lang/fr/lang.php               |   14 +
 lib/plugins/captcha/lang/fr/settings.php           |   28 +
 lib/plugins/captcha/lang/hu/lang.php               |   12 +
 lib/plugins/captcha/lang/hu/settings.php           |   22 +
 lib/plugins/captcha/lang/is/lang.php               |   12 +
 lib/plugins/captcha/lang/is/settings.php           |   22 +
 lib/plugins/captcha/lang/it/lang.php               |   13 +
 lib/plugins/captcha/lang/it/settings.php           |   23 +
 lib/plugins/captcha/lang/ja/lang.php               |   13 +
 lib/plugins/captcha/lang/ja/settings.php           |   24 +
 lib/plugins/captcha/lang/ko/lang.php               |   14 +
 lib/plugins/captcha/lang/ko/settings.php           |   24 +
 lib/plugins/captcha/lang/nl/lang.php               |   14 +
 lib/plugins/captcha/lang/nl/settings.php           |   25 +
 lib/plugins/captcha/lang/nn/lang.php               |   12 +
 lib/plugins/captcha/lang/nn/settings.php           |   21 +
 lib/plugins/captcha/lang/no/lang.php               |   13 +
 lib/plugins/captcha/lang/no/settings.php           |   23 +
 lib/plugins/captcha/lang/pl/lang.php               |   12 +
 lib/plugins/captcha/lang/pl/settings.php           |   21 +
 lib/plugins/captcha/lang/pt-br/lang.php            |   12 +
 lib/plugins/captcha/lang/pt-br/settings.php        |   23 +
 lib/plugins/captcha/lang/pt/lang.php               |   12 +
 lib/plugins/captcha/lang/pt/settings.php           |   23 +
 lib/plugins/captcha/lang/ru/lang.php               |   13 +
 lib/plugins/captcha/lang/ru/settings.php           |   24 +
 lib/plugins/captcha/lang/sk/lang.php               |   13 +
 lib/plugins/captcha/lang/sk/settings.php           |   22 +
 lib/plugins/captcha/lang/tr/lang.php               |   12 +
 lib/plugins/captcha/lang/tr/settings.php           |   24 +
 lib/plugins/captcha/lang/uk/lang.php               |   12 +
 lib/plugins/captcha/lang/uk/settings.php           |   21 +
 lib/plugins/captcha/lang/zh-tw/lang.php            |   13 +
 lib/plugins/captcha/lang/zh-tw/settings.php        |   24 +
 lib/plugins/captcha/lang/zh/lang.php               |   13 +
 lib/plugins/captcha/lang/zh/settings.php           |   27 +
 lib/plugins/captcha/manager.dat                    |    3 +
 lib/plugins/captcha/plugin.info.txt                |    8 +
 lib/plugins/captcha/script.js                      |   32 +
 lib/plugins/captcha/sound.png                      |  Bin 0 -> 610 bytes
 lib/plugins/captcha/style.css                      |   36 +
 lib/plugins/captcha/wav.php                        |   88 ++
 lib/plugins/loglog/action.php                      |  121 +++
 lib/plugins/loglog/admin.php                       |  182 ++++
 lib/plugins/loglog/admin.svg                       |    1 +
 lib/plugins/loglog/lang/ar/intro.txt               |    3 +
 lib/plugins/loglog/lang/ar/lang.php                |   16 +
 lib/plugins/loglog/lang/cs/intro.txt               |    3 +
 lib/plugins/loglog/lang/cs/lang.php                |   17 +
 lib/plugins/loglog/lang/da/intro.txt               |    3 +
 lib/plugins/loglog/lang/da/lang.php                |   18 +
 lib/plugins/loglog/lang/de/intro.txt               |    3 +
 lib/plugins/loglog/lang/de/lang.php                |   15 +
 lib/plugins/loglog/lang/en/intro.txt               |    3 +
 lib/plugins/loglog/lang/en/lang.php                |   15 +
 lib/plugins/loglog/lang/eo/intro.txt               |    3 +
 lib/plugins/loglog/lang/eo/lang.php                |   16 +
 lib/plugins/loglog/lang/fr/intro.txt               |    3 +
 lib/plugins/loglog/lang/fr/lang.php                |   18 +
 lib/plugins/loglog/lang/hr/intro.txt               |    3 +
 lib/plugins/loglog/lang/hr/lang.php                |   17 +
 lib/plugins/loglog/lang/hu/intro.txt               |    3 +
 lib/plugins/loglog/lang/hu/lang.php                |   18 +
 lib/plugins/loglog/lang/ja/intro.txt               |    4 +
 lib/plugins/loglog/lang/ja/lang.php                |   17 +
 lib/plugins/loglog/lang/ko/intro.txt               |    3 +
 lib/plugins/loglog/lang/ko/lang.php                |   17 +
 lib/plugins/loglog/lang/nl/intro.txt               |    3 +
 lib/plugins/loglog/lang/nl/lang.php                |   18 +
 lib/plugins/loglog/lang/ru/intro.txt               |    3 +
 lib/plugins/loglog/lang/ru/lang.php                |   18 +
 lib/plugins/loglog/lang/zh-tw/lang.php             |   15 +
 lib/plugins/loglog/lang/zh/intro.txt               |    3 +
 lib/plugins/loglog/lang/zh/lang.php                |   16 +
 lib/plugins/loglog/manager.dat                     |    2 +
 lib/plugins/loglog/pix/error.png                   |  Bin 0 -> 543 bytes
 lib/plugins/loglog/pix/off.png                     |  Bin 0 -> 402 bytes
 lib/plugins/loglog/pix/perm.png                    |  Bin 0 -> 447 bytes
 lib/plugins/loglog/pix/temp.png                    |  Bin 0 -> 431 bytes
 lib/plugins/loglog/plugin.info.txt                 |    7 +
 lib/plugins/loglog/style.css                       |   30 +
 142 files changed, 4778 insertions(+)

diff --git a/lib/plugins/captcha/.travis.yml b/lib/plugins/captcha/.travis.yml
new file mode 100644
index 0000000..321f554
--- /dev/null
+++ b/lib/plugins/captcha/.travis.yml
@@ -0,0 +1,13 @@
+language: php
+php:
+  - "7.0"
+  - "5.6"
+  - "5.5"
+  - "5.4"
+  - "5.3"
+env:
+  - DOKUWIKI=master
+  - DOKUWIKI=stable
+before_install: wget https://raw.github.com/splitbrain/dokuwiki-travis/master/travis.sh
+install: sh travis.sh
+script: cd _test && phpunit --stderr --group plugin_captcha
diff --git a/lib/plugins/captcha/EasySVG.php b/lib/plugins/captcha/EasySVG.php
new file mode 100644
index 0000000..82b0b55
--- /dev/null
+++ b/lib/plugins/captcha/EasySVG.php
@@ -0,0 +1,516 @@
+<?php
+/**
+ * EasySVG - Generate SVG from PHP
+ * @author Simon Tarchichi <kartsims at gmail.com>
+ * @version 0.1b
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform
+ * @see http://stackoverflow.com/questions/14684846/flattening-svg-matrix-transforms-in-inkscape
+ * @see http://stackoverflow.com/questions/7742148/how-to-convert-text-to-svg-paths
+ */
+class EasySVG {
+
+    protected $font;
+    protected $svg;
+
+    public function __construct() {
+        // default font data
+        $this->font = new stdClass;
+        $this->font->id = '';
+        $this->font->horizAdvX = 0;
+        $this->font->unitsPerEm = 0;
+        $this->font->ascent = 0;
+        $this->font->descent = 0;
+        $this->font->glyphs = array();
+        $this->font->size = 20;
+        $this->font->color = '';
+        $this->font->lineHeight = 1;
+        $this->font->letterSpacing = 0;
+
+        $this->clearSVG();
+    }
+
+    public function clearSVG() {
+        $this->svg = new SimpleXMLElement('<svg></svg>');
+    }
+
+    /**
+     * Function takes UTF-8 encoded string and returns unicode number for every character.
+     * @param  string $str
+     * @return string
+     */
+    private function _utf8ToUnicode( $str ) {
+        $unicode = array();
+        $values = array();
+        $lookingFor = 1;
+
+        for ($i = 0; $i < strlen( $str ); $i++ ) {
+            $thisValue = ord( $str[ $i ] );
+            if ( $thisValue < 128 ) $unicode[] = $thisValue;
+            else {
+                if ( count( $values ) == 0 ) $lookingFor = ( $thisValue < 224 ) ? 2 : 3;
+                $values[] = $thisValue;
+                if ( count( $values ) == $lookingFor ) {
+                    $number = ( $lookingFor == 3 ) ?
+                        ( ( $values[0] % 16 ) * 4096 ) + ( ( $values[1] % 64 ) * 64 ) + ( $values[2] % 64 ):
+                        ( ( $values[0] % 32 ) * 64 ) + ( $values[1] % 64 );
+
+                    $unicode[] = $number;
+                    $values = array();
+                    $lookingFor = 1;
+                }
+            }
+        }
+
+        return $unicode;
+    }
+
+    /**
+     * Set font params (short-hand method)
+     * @param string $filepath
+     * @param integer $size
+     * @param string $color
+     */
+    public function setFont( $filepath, $size, $color ) {
+        $this->setFontSVG($filepath);
+        $this->setFontSize($size);
+        $this->setFontColor($color);
+    }
+
+    /**
+     * Set font size for display
+     * @param int $size
+     * @return void
+     */
+    public function setFontSize( $size ) {
+        $this->font->size = $size;
+    }
+
+    /**
+     * Set font color
+     * @param string $color
+     * @return void
+     */
+    public function setFontColor( $color ) {
+        $this->font->color = $color;
+    }
+
+    /**
+     * Set the line height from default (1) to custom value
+     * @param  float $value
+     * @return void
+     */
+    public function setLineHeight( $value ) {
+        $this->font->lineHeight = $value;
+    }
+
+    /**
+     * Set the letter spacing from default (0) to custom value
+     * @param  float $value
+     * @return void
+     */
+    public function setLetterSpacing( $value ) {
+        $this->font->letterSpacing = $value;
+    }
+
+    /**
+     * Function takes path to SVG font (local path) and processes its xml
+     * to get path representation of every character and additional
+     * font parameters
+     * @param  string $filepath
+     * @return void
+     */
+    public function setFontSVG( $filepath ) {
+        $this->font->glyphs = array();
+        $z = new XMLReader;
+        $z->open($filepath);
+
+        // move to the first <product /> node
+        while ($z->read()) {
+            $name = $z->name;
+
+            if ($z->nodeType == XMLReader::ELEMENT) {
+                if ($name == 'font') {
+                    $this->font->id = $z->getAttribute('id');
+                    $this->font->horizAdvX = $z->getAttribute('horiz-adv-x');
+                }
+
+                if ($name == 'font-face') {
+                    $this->font->unitsPerEm = $z->getAttribute('units-per-em');
+                    $this->font->ascent = $z->getAttribute('ascent');
+                    $this->font->descent = $z->getAttribute('descent');
+                }
+
+                if ($name == 'glyph') {
+                    $unicode = $z->getAttribute('unicode');
+                    $unicode = $this->_utf8ToUnicode($unicode);
+
+                    if (isset($unicode[0])) {
+                        $unicode = $unicode[0];
+
+                        $this->font->glyphs[$unicode] = new stdClass();
+                        $this->font->glyphs[$unicode]->horizAdvX = $z->getAttribute('horiz-adv-x');
+                        if (empty($this->font->glyphs[$unicode]->horizAdvX)) {
+                            $this->font->glyphs[$unicode]->horizAdvX = $this->font->horizAdvX;
+                        }
+                        $this->font->glyphs[$unicode]->d = $z->getAttribute('d');
+
+                        // save em value for letter spacing (109 is unicode for the letter 'm')
+                        if ($unicode == '109') {
+                            $this->font->em = $this->font->glyphs[$unicode]->horizAdvX;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Add a path to the SVG
+     * @param string $def
+     * @param array $attributes
+     * @return SimpleXMLElement
+     */
+    public function addPath($def, $attributes=array()) {
+        $path = $this->svg->addChild('path');
+        foreach($attributes as $key=>$value){
+            $path->addAttribute($key, $value);
+        }
+        $path->addAttribute('d', $def);
+        return $path;
+    }
+
+    /**
+     * Add a text to the SVG
+     * @param string $def
+     * @param float $x
+     * @param float $y
+     * @param array $attributes
+     * @return SimpleXMLElement
+     */
+    public function addText($text, $x=0, $y=0, $attributes=array()) {
+        $def = $this->textDef($text);
+
+        if($x!=0 || $y!=0){
+            $def = $this->defTranslate($def, $x, $y);
+        }
+
+        if($this->font->color) {
+            $attributes['fill'] = $this->font->color;
+        }
+
+        return $this->addPath($def, $attributes);
+    }
+
+
+    /**
+     * Function takes UTF-8 encoded string and size, returns xml for SVG paths representing this string.
+     * @param string $text UTF-8 encoded text
+     * @return string xml for text converted into SVG paths
+     */
+    public function textDef($text) {
+        $def = array();
+
+        $horizAdvX = 0;
+        $horizAdvY = $this->font->ascent + $this->font->descent;
+        $fontSize = floatval($this->font->size) / $this->font->unitsPerEm;
+        $text = $this->_utf8ToUnicode($text);
+
+        for($i = 0; $i < count($text); $i++) {
+
+            $letter = $text[$i];
+
+            // line break support (10 is unicode for linebreak)
+            if($letter==10){
+                $horizAdvX = 0;
+                $horizAdvY += $this->font->lineHeight * ( $this->font->ascent + $this->font->descent );
+                continue;
+            }
+
+            // extract character definition
+            $d = $this->font->glyphs[$letter]->d;
+
+            // transform typo from original SVG format to straight display
+            $d = $this->defScale($d, $fontSize, -$fontSize);
+            $d = $this->defTranslate($d, $horizAdvX, $horizAdvY*$fontSize*2);
+
+            $def[] = $d;
+
+            // next letter's position
+            $horizAdvX += $this->font->glyphs[$letter]->horizAdvX * $fontSize + $this->font->em * $this->font->letterSpacing * $fontSize;
+        }
+        return implode(' ', $def);
+    }
+
+
+    /**
+     * Function takes UTF-8 encoded string and size, returns width and height of the whole text
+     * @param string $text UTF-8 encoded text
+     * @return array ($width, $height)
+     */
+    public function textDimensions($text) {
+        $def = array();
+
+        $fontSize = floatval($this->font->size) / $this->font->unitsPerEm;
+        $text = $this->_utf8ToUnicode($text);
+
+        $lineWidth = 0;
+        $lineHeight = ( $this->font->ascent + $this->font->descent ) * $fontSize * 2;
+
+        $width = 0;
+        $height = $lineHeight;
+
+        for($i = 0; $i < count($text); $i++) {
+
+            $letter = $text[$i];
+
+            // line break support (10 is unicode for linebreak)
+            if($letter==10){
+                $width = $lineWidth>$width ? $lineWidth : $width;
+                $height += $lineHeight * $this->font->lineHeight;
+                $lineWidth = 0;
+                continue;
+            }
+
+            $lineWidth += $this->font->glyphs[$letter]->horizAdvX * $fontSize + $this->font->em * $this->font->letterSpacing * $fontSize;
+        }
+
+        // only keep the widest line's width
+        $width = $lineWidth>$width ? $lineWidth : $width;
+
+        return array($width, $height);
+    }
+
+
+    /**
+     * Function takes unicode character and returns the UTF-8 equivalent
+     * @param  string $str
+     * @return string
+     */
+    public function unicodeDef( $unicode ) {
+
+        $horizAdvY = $this->font->ascent + $this->font->descent;
+        $fontSize =  floatval($this->font->size) / $this->font->unitsPerEm;
+
+        // extract character definition
+        $d = $this->font->glyphs[hexdec($unicode)]->d;
+
+        // transform typo from original SVG format to straight display
+        $d = $this->defScale($d, $fontSize, -$fontSize);
+        $d = $this->defTranslate($d, 0, $horizAdvY*$fontSize*2);
+
+        return $d;
+    }
+
+    /**
+     * Returns the character width, as set in the font file
+     * @param  string  $str
+     * @param  boolean $is_unicode
+     * @return float
+     */
+    public function characterWidth( $char, $is_unicode = false ) {
+        if ($is_unicode){
+            $letter = hexdec($char);
+        }
+        else {
+            $letter = $this->_utf8ToUnicode($char);
+        }
+
+        if (!isset($this->font->glyphs[$letter]))
+            return NULL;
+
+        $fontSize = floatval($this->font->size) / $this->font->unitsPerEm;
+        return $this->font->glyphs[$letter]->horizAdvX * $fontSize;
+    }
+
+
+    /**
+     * Applies a translate transformation to definition
+     * @param  string  $def definition
+     * @param  float $x
+     * @param  float $y
+     * @return string
+     */
+    public function defTranslate($def, $x=0, $y=0){
+        return $this->defApplyMatrix($def, array(1, 0, 0, 1, $x, $y));
+    }
+
+    /**
+     * Applies a translate transformation to definition
+     * @param  string  $def    Definition
+     * @param  integer $angle  Rotation angle (degrees)
+     * @param  integer $x      X coordinate of rotation center
+     * @param  integer $y      Y coordinate of rotation center
+     * @return string
+     */
+    public function defRotate($def, $angle, $x=0, $y=0){
+        if($x==0 && $y==0){
+            $angle = deg2rad($angle);
+            return $this->defApplyMatrix($def, array(cos($angle), sin($angle), -sin($angle), cos($angle), 0, 0));
+        }
+
+        // rotate by a given point
+        $def = $this->defTranslate($def, $x, $y);
+        $def = $this->defRotate($def, $angle);
+        $def = $this->defTranslate($def, -$x, -$y);
+        return $def;
+    }
+
+    /**
+     * Applies a scale transformation to definition
+     * @param  string  $def definition
+     * @param  integer $x
+     * @param  integer $y
+     * @return string
+     */
+    public function defScale($def, $x=1, $y=1){
+        return $this->defApplyMatrix($def, array($x, 0, 0, $y, 0, 0));
+    }
+
+    /**
+     * Calculates the new definition with the matrix applied
+     * @param  string $def
+     * @param  array  $matrix
+     * @return string
+     */
+    public function defApplyMatrix($def, $matrix){
+
+        // if there are several shapes in this definition, do the operation for each
+        preg_match_all('/M[^zZ]*[zZ]/', $def, $shapes);
+        $shapes = $shapes[0];
+        if(count($shapes)>1){
+            foreach($shapes as &$shape)
+                $shape = $this->defApplyMatrix($shape, $matrix);
+            return implode(' ', $shapes);
+        }
+
+        preg_match_all('/[a-zA-Z]+[^a-zA-Z]*/', $def, $instructions);
+        $instructions = $instructions[0];
+
+        $return = '';
+        foreach($instructions as &$instruction){
+            $i = preg_replace('/[^a-zA-Z]*/', '', $instruction);
+            preg_match_all('/\-?[0-9\.]+/', $instruction, $coords);
+            $coords = $coords[0];
+
+            if(empty($coords)){
+                continue;
+            }
+
+            $new_coords = array();
+            while(count($coords)>0){
+
+                // do the matrix calculation stuff
+                list($a, $b, $c, $d, $e, $f) = $matrix;
+
+                // exception for relative instruction
+                if( preg_match('/[a-z]/', $i) ){
+                    $e = 0;
+                    $f = 0;
+                }
+
+                // convert horizontal lineto (relative)
+                if( $i=='h' ){
+                    $i = 'l';
+                    $x = floatval( array_shift($coords) );
+                    $y = 0;
+
+                    // add new point's coordinates
+                    $current_point = array(
+                        $a*$x + $c*$y + $e,
+                        $b*$x + $d*$y + $f,
+                    );
+                    $new_coords = array_merge($new_coords, $current_point);
+                }
+
+                // convert vertical lineto (relative)
+                elseif( $i=='v' ){
+                    $i = 'l';
+                    $x = 0;
+                    $y = floatval( array_shift($coords) );
+
+                    // add new point's coordinates
+                    $current_point = array(
+                        $a*$x + $c*$y + $e,
+                        $b*$x + $d*$y + $f,
+                    );
+                    $new_coords = array_merge($new_coords, $current_point);
+                }
+
+                // convert quadratic bezier curve (relative)
+                elseif( $i=='q' ){
+                    $x = floatval( array_shift($coords) );
+                    $y = floatval( array_shift($coords) );
+
+                    // add new point's coordinates
+                    $current_point = array(
+                        $a*$x + $c*$y + $e,
+                        $b*$x + $d*$y + $f,
+                    );
+                    $new_coords = array_merge($new_coords, $current_point);
+
+                    // same for 2nd point
+                    $x = floatval( array_shift($coords) );
+                    $y = floatval( array_shift($coords) );
+
+                    // add new point's coordinates
+                    $current_point = array(
+                        $a*$x + $c*$y + $e,
+                        $b*$x + $d*$y + $f,
+                    );
+                    $new_coords = array_merge($new_coords, $current_point);
+                }
+
+                // every other commands
+                // @TODO: handle 'a,c,s' (elliptic arc curve) commands
+                // cf. http://www.w3.org/TR/SVG/paths.html#PathDataCurveCommands
+                else{
+                    $x = floatval( array_shift($coords) );
+                    $y = floatval( array_shift($coords) );
+
+                    // add new point's coordinates
+                    $current_point = array(
+                        $a*$x + $c*$y + $e,
+                        $b*$x + $d*$y + $f,
+                    );
+                    $new_coords = array_merge($new_coords, $current_point);
+                }
+
+
+            }
+
+            $instruction = $i . implode(',', $new_coords);
+
+            // remove useless commas
+            $instruction = preg_replace('/,\-/','-', $instruction);
+        }
+
+        return implode('', $instructions);
+    }
+
+
+
+    /**
+     *
+     * Short-hand methods
+     *
+     */
+
+
+    /**
+     * Return full SVG XML
+     * @return string
+     */
+    public function asXML(){
+        return $this->svg->asXML();
+    }
+
+    /**
+     * Adds an attribute to the SVG
+     * @param string $key
+     * @param string $value
+     */
+    public function addAttribute($key, $value){
+        return $this->svg->addAttribute($key, $value);
+    }
+}
diff --git a/lib/plugins/captcha/_test/helper.test.php b/lib/plugins/captcha/_test/helper.test.php
new file mode 100644
index 0000000..3e79923
--- /dev/null
+++ b/lib/plugins/captcha/_test/helper.test.php
@@ -0,0 +1,149 @@
+<?php
+
+class helper_plugin_captcha_public extends helper_plugin_captcha {
+
+    public function get_field_in() {
+        return $this->field_in;
+    }
+
+    public function get_field_sec() {
+        return $this->field_sec;
+    }
+
+    public function get_field_hp() {
+        return $this->field_hp;
+    }
+
+    public function storeCaptchaCookie($fixed, $rand) {
+        parent::storeCaptchaCookie($fixed, $rand);
+    }
+}
+
+/**
+ * @group plugin_captcha
+ * @group plugins
+ */
+class helper_plugin_captcha_test extends DokuWikiTest {
+
+    protected $pluginsEnabled = array('captcha');
+
+    public function testConfig() {
+        global $conf;
+        $conf['plugin']['captcha']['lettercount'] = 20;
+
+        $helper = new helper_plugin_captcha_public();
+
+        // generateCAPTCHA generates a maximum of 16 chars
+        $code = $helper->_generateCAPTCHA("fixed", 0);
+        $this->assertEquals(16, strlen($code));
+    }
+
+    public function testDecrypt() {
+
+        $helper = new helper_plugin_captcha_public();
+
+        $rand = "12345";
+        $secret = $helper->encrypt($rand);
+        $this->assertNotSame(false, $secret);
+        $this->assertSame($rand, $helper->decrypt($secret));
+
+        $this->assertFalse($helper->decrypt(''));
+        $this->assertFalse($helper->decrypt('X'));
+    }
+
+    public function testCheck() {
+
+        global $INPUT, $ID;
+
+        $helper = new helper_plugin_captcha_public();
+
+        $INPUT->set($helper->get_field_hp(), '');
+        $INPUT->set($helper->get_field_in(), 'X');
+        $INPUT->set($helper->get_field_sec(), '');
+
+        $this->assertFalse($helper->check(false));
+        $INPUT->set($helper->get_field_sec(), 'X');
+        $this->assertFalse($helper->check(false));
+
+        // create the captcha and store the cookie
+        $rand = 0;
+        $code = $helper->_generateCAPTCHA($helper->_fixedIdent(), $rand);
+        $helper->storeCaptchaCookie($helper->_fixedIdent(), $rand);
+
+        // check with missing secrect -> fail
+        $INPUT->set($helper->get_field_in(), $code);
+        $this->assertFalse($helper->check(false));
+
+        // set secret -> success
+        $INPUT->set($helper->get_field_sec(), $helper->encrypt($rand));
+        $this->assertTrue($helper->check(false));
+
+        // try again, cookie is gone -> fail
+        $this->assertFalse($helper->check(true));
+
+        // set the cookie but change the ID -> fail
+        $helper->storeCaptchaCookie($helper->_fixedIdent(), $rand);
+        $ID = 'test:fail';
+        $this->assertFalse($helper->check(false));
+    }
+
+    public function testGenerate() {
+
+        $helper = new helper_plugin_captcha_public();
+
+        $rand = 0;
+        $code = $helper->_generateCAPTCHA($helper->_fixedIdent(), $rand);
+        $newcode = $helper->_generateCAPTCHA($helper->_fixedIdent() . 'X', $rand);
+        $this->assertNotEquals($newcode, $code);
+        $newcode = $helper->_generateCAPTCHA($helper->_fixedIdent(), $rand + 0.1);
+        $this->assertNotEquals($newcode, $code);
+    }
+
+    public function testCleanup() {
+        // we need a complete fresh environment:
+        $this->setUpBeforeClass();
+
+        global $conf;
+        $path = $conf['tmpdir'] . '/captcha/';
+        $today = "$path/" . date('Y-m-d');
+
+        $helper = new helper_plugin_captcha_public();
+
+        // nothing at all
+        $dirs = glob("$path/*");
+        $this->assertEquals(array(), $dirs);
+
+        // store a cookie
+        $helper->storeCaptchaCookie('test', 0);
+
+        // nothing but today's data
+        $dirs = glob("$path/*");
+        $this->assertEquals(array($today), $dirs);
+
+        // add some fake cookies
+        io_saveFile("$path/2017-01-01/foo.cookie", '');
+        io_saveFile("$path/2017-01-02/foo.cookie", '');
+        io_saveFile("$path/2017-01-03/foo.cookie", '');
+        io_saveFile("$path/2017-01-04/foo.cookie", '');
+
+        // all directories there
+        $dirs = glob("$path/*");
+        $this->assertEquals(
+            array(
+                "$path/2017-01-01",
+                "$path/2017-01-02",
+                "$path/2017-01-03",
+                "$path/2017-01-04",
+                $today
+            ),
+            $dirs
+        );
+
+        // clean up
+        $helper->_cleanCaptchaCookies();
+
+        // nothing but today's data
+        $dirs = glob("$path/*");
+        $this->assertEquals(array($today), $dirs);
+    }
+}
diff --git a/lib/plugins/captcha/action.php b/lib/plugins/captcha/action.php
new file mode 100644
index 0000000..907b2c5
--- /dev/null
+++ b/lib/plugins/captcha/action.php
@@ -0,0 +1,224 @@
+<?php
+/**
+ * CAPTCHA antispam plugin
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Andreas Gohr <gohr at cosmocode.de>
+ */
+
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
+
+class action_plugin_captcha extends DokuWiki_Action_Plugin {
+
+    /**
+     * register the eventhandlers
+     */
+    public function register(Doku_Event_Handler $controller) {
+        // check CAPTCHA success
+        $controller->register_hook(
+            'ACTION_ACT_PREPROCESS',
+            'BEFORE',
+            $this,
+            'handle_captcha_input',
+            array()
+        );
+
+        // inject in edit form
+        $controller->register_hook(
+            'HTML_EDITFORM_OUTPUT',
+            'BEFORE',
+            $this,
+            'handle_form_output',
+            array()
+        );
+
+        // inject in user registration
+        $controller->register_hook(
+            'HTML_REGISTERFORM_OUTPUT',
+            'BEFORE',
+            $this,
+            'handle_form_output',
+            array()
+        );
+
+        // inject in password reset
+        $controller->register_hook(
+            'HTML_RESENDPWDFORM_OUTPUT',
+            'BEFORE',
+            $this,
+            'handle_form_output',
+            array()
+        );
+
+        if($this->getConf('loginprotect')) {
+            // inject in login form
+            $controller->register_hook(
+                'HTML_LOGINFORM_OUTPUT',
+                'BEFORE',
+                $this,
+                'handle_form_output',
+                array()
+            );
+            // check on login
+            $controller->register_hook(
+                'AUTH_LOGIN_CHECK',
+                'BEFORE',
+                $this,
+                'handle_login',
+                array()
+            );
+        }
+
+        // clean up captcha cookies
+        $controller->register_hook(
+            'INDEXER_TASKS_RUN',
+            'AFTER',
+            $this,
+            'handle_indexer',
+            array()
+        );
+    }
+
+    /**
+     * Check if the current mode should be handled by CAPTCHA
+     *
+     * Note: checking needs to be done when a form has been submitted, not when the form
+     * is shown for the first time. Except for the editing process this is not determined
+     * by $act alone but needs to inspect other input variables.
+     *
+     * @param string $act cleaned action mode
+     * @return bool
+     */
+    protected function needs_checking($act) {
+        global $INPUT;
+
+        switch($act) {
+            case 'save':
+                return true;
+            case 'register':
+            case 'resendpwd':
+                return $INPUT->bool('save');
+            case 'login':
+                // we do not handle this here, but in handle_login()
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Aborts the given mode
+     *
+     * Aborting depends on the mode. It might unset certain input parameters or simply switch
+     * the mode to something else (giving as return which needs to be passed back to the
+     * ACTION_ACT_PREPROCESS event)
+     *
+     * @param string $act cleaned action mode
+     * @return string the new mode to use
+     */
+    protected function abort_action($act) {
+        global $INPUT;
+
+        switch($act) {
+            case 'save':
+                return 'preview';
+            case 'register':
+            case 'resendpwd':
+                $INPUT->post->set('save', false);
+                return $act;
+            case 'login':
+                // we do not handle this here, but in handle_login()
+            default:
+                return $act;
+        }
+    }
+
+    /**
+     * Handles CAPTCHA check in login
+     *
+     * Logins happen very early in the DokuWiki lifecycle, so we have to intercept them
+     * in their own event.
+     *
+     * @param Doku_Event $event
+     * @param $param
+     */
+    public function handle_login(Doku_Event $event, $param) {
+        global $INPUT;
+        if(!$this->getConf('loginprotect')) return; // no protection wanted
+        if(!$INPUT->bool('u')) return; // this login was not triggered by a form
+
+        // we need to have $ID set for the captcha check
+        global $ID;
+        $ID = getID();
+
+        /** @var helper_plugin_captcha $helper */
+        $helper = plugin_load('helper', 'captcha');
+        if(!$helper->check()) {
+            $event->data['silent'] = true; // we have our own message
+            $event->result = false; // login fail
+            $event->preventDefault();
+            $event->stopPropagation();
+        }
+    }
+
+    /**
+     * Intercept all actions and check for CAPTCHA first.
+     */
+    public function handle_captcha_input(Doku_Event $event, $param) {
+        $act = act_clean($event->data);
+        if(!$this->needs_checking($act)) return;
+
+        // do nothing if logged in user and no CAPTCHA required
+        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) {
+            return;
+        }
+
+        // check captcha
+        /** @var helper_plugin_captcha $helper */
+        $helper = plugin_load('helper', 'captcha');
+        if(!$helper->check()) {
+            $event->data = $this->abort_action($act);
+        }
+    }
+
+    /**
+     * Inject the CAPTCHA in a DokuForm
+     */
+    public function handle_form_output(Doku_Event $event, $param) {
+        // get position of submit button
+        $pos = $event->data->findElementByAttribute('type', 'submit');
+        if(!$pos) return; // no button -> source view mode
+
+        // do nothing if logged in user and no CAPTCHA required
+        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) {
+            return;
+        }
+
+        // get the CAPTCHA
+        /** @var helper_plugin_captcha $helper */
+        $helper = plugin_load('helper', 'captcha');
+        $out = $helper->getHTML();
+
+        // new wiki - insert after the submit button
+        $event->data->insertElement($pos + 1, $out);
+    }
+
+    /**
+     * Clean cookies once per day
+     */
+    public function handle_indexer(Doku_Event $event, $param) {
+        $lastrun = getCacheName('captcha', '.captcha');
+        $last = @filemtime($lastrun);
+        if(time() - $last < 24 * 60 * 60) return;
+
+        /** @var helper_plugin_captcha $helper */
+        $helper = plugin_load('helper', 'captcha');
+        $helper->_cleanCaptchaCookies();
+        touch($lastrun);
+
+        $event->preventDefault();
+        $event->stopPropagation();
+    }
+}
+
diff --git a/lib/plugins/captcha/conf/default.php b/lib/plugins/captcha/conf/default.php
new file mode 100644
index 0000000..426dc17
--- /dev/null
+++ b/lib/plugins/captcha/conf/default.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Options for the CAPTCHA plugin
+ *
+ * @author Andreas Gohr <andi at splitbrain.org>
+ */
+
+$conf['mode']        = 'js';
+$conf['forusers']    = 0;
+$conf['loginprotect']= 0;
+$conf['lettercount'] = 5;
+$conf['width']       = 125;
+$conf['height']      = 30;
+$conf['question']    = 'What\'s the answer to life, the universe and everything?';
+$conf['answer']      = '42';
diff --git a/lib/plugins/captcha/conf/metadata.php b/lib/plugins/captcha/conf/metadata.php
new file mode 100644
index 0000000..099a6a1
--- /dev/null
+++ b/lib/plugins/captcha/conf/metadata.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Options for the CAPTCHA plugin
+ *
+ * @author Andreas Gohr <andi at splitbrain.org>
+ */
+
+$meta['mode']        = array('multichoice', '_choices' => array('js', 'text', 'math', 'question', 'image', 'audio', 'svg', 'svgaudio', 'figlet'));
+$meta['forusers']    = array('onoff');
+$meta['loginprotect']= array('onoff');
+$meta['lettercount'] = array('numeric', '_min' => 3, '_max' => 16);
+$meta['width']       = array('numeric', '_pattern' => '/[0-9]+/');
+$meta['height']      = array('numeric', '_pattern' => '/[0-9]+/');
+$meta['question']    = array('string');
+$meta['answer']      = array('string');
diff --git a/lib/plugins/captcha/figlet.flf b/lib/plugins/captcha/figlet.flf
new file mode 100644
index 0000000..24284b8
--- /dev/null
+++ b/lib/plugins/captcha/figlet.flf
@@ -0,0 +1,1097 @@
+flf2a$ 5 4 14 15 10 0 22415 96
+SmSlant by Glenn Chappell 6/93 - based on Small & Slant
+Includes ISO Latin-1
+figlet release 2.1 -- 12 Aug 1994
+Permission is hereby given to modify this font, as long as the
+modifier's name is placed on a comment line.
+
+Modified by Paul Burton <solution at earthlink.net> 12/96 to include new parameter
+supported by FIGlet and FIGWin.  May also be slightly modified for better use
+of new full-width/kern/smush alternatives, but default output is NOT changed.
+
+    $@
+   $ @
+  $  @
+ $   @
+$    @@
+   __@
+  / /@
+ /_/ @
+(_)  @
+     @@
+ _ _ @
+( | )@
+|/|/ @
+$    @
+     @@
+     ____ @
+  __/ / /_@
+ /_  . __/@
+/_    __/ @
+ /_/_/    @@
+     @
+  _//@
+ (_-<@
+/ __/@
+//   @@
+ _   __@
+(_)_/_/@
+ _/_/_ @
+/_/ (_)@
+       @@
+  ____   @
+ / __/___@
+ > _/_ _/@
+|_____/  @
+         @@
+ _ @
+( )@
+|/ @
+$  @
+   @@
+    __@
+  _/_/@
+ / /  @
+/ /   @
+|_|   @@
+    _ @
+   | |@
+   / /@
+ _/_/ @
+/_/   @@
+    @
+ _/|@
+> _<@
+|/  @
+    @@
+    __ @
+ __/ /_@
+/_  __/@
+ /_/   @
+       @@
+   @
+   @
+ _ @
+( )@
+|/ @@
+     @
+ ____@
+/___/@
+ $   @
+     @@
+   @
+   @
+ _ @
+(_)@
+   @@
+     __@
+   _/_/@
+ _/_/  @
+/_/    @
+       @@
+  ___ @
+ / _ \@
+/ // /@
+\___/ @
+      @@
+  ___@
+ <  /@
+ / / @
+/_/  @
+     @@
+   ___ @
+  |_  |@
+ / __/ @
+/____/ @
+       @@
+   ____@
+  |_  /@
+ _/_ < @
+/____/ @
+       @@
+  ____@
+ / / /@
+/_  _/@
+ /_/  @
+      @@
+   ____@
+  / __/@
+ /__ \ @
+/____/ @
+       @@
+  ____@
+ / __/@
+/ _ \ @
+\___/ @
+      @@
+ ____@
+/_  /@
+ / / @
+/_/  @
+     @@
+  ___ @
+ ( _ )@
+/ _  |@
+\___/ @
+      @@
+  ___ @
+ / _ \@
+ \_, /@
+/___/ @
+      @@
+   _ @
+  (_)@
+ _   @
+(_)  @
+     @@
+   _ @
+  (_)@
+ _   @
+( )  @
+|/   @@
+  __@
+ / /@
+< < @
+ \_\@
+    @@
+      @
+  ____@
+ /___/@
+/___/ @
+      @@
+__  @
+\ \ @
+ > >@
+/_/ @
+    @@
+ ___ @
+/__ \@
+ /__/@
+(_)  @
+     @@
+  _____ @
+ / ___ \@
+/ / _ `/@
+\ \_,_/ @
+ \___/  @@
+   ___ @
+  / _ |@
+ / __ |@
+/_/ |_|@
+       @@
+   ___ @
+  / _ )@
+ / _  |@
+/____/ @
+       @@
+  _____@
+ / ___/@
+/ /__  @
+\___/  @
+       @@
+   ___ @
+  / _ \@
+ / // /@
+/____/ @
+       @@
+   ____@
+  / __/@
+ / _/  @
+/___/  @
+       @@
+   ____@
+  / __/@
+ / _/  @
+/_/    @
+       @@
+  _____@
+ / ___/@
+/ (_ / @
+\___/  @
+       @@
+   __ __@
+  / // /@
+ / _  / @
+/_//_/  @
+        @@
+   ____@
+  /  _/@
+ _/ /  @
+/___/  @
+       @@
+     __@
+ __ / /@
+/ // / @
+\___/  @
+       @@
+   __ __@
+  / //_/@
+ / ,<   @
+/_/|_|  @
+        @@
+   __ @
+  / / @
+ / /__@
+/____/@
+      @@
+   __  ___@
+  /  |/  /@
+ / /|_/ / @
+/_/  /_/  @
+          @@
+   _  __@
+  / |/ /@
+ /    / @
+/_/|_/  @
+        @@
+  ____ @
+ / __ \@
+/ /_/ /@
+\____/ @
+       @@
+   ___ @
+  / _ \@
+ / ___/@
+/_/    @
+       @@
+  ____ @
+ / __ \@
+/ /_/ /@
+\___\_\@
+       @@
+   ___ @
+  / _ \@
+ / , _/@
+/_/|_| @
+       @@
+   ____@
+  / __/@
+ _\ \  @
+/___/  @
+       @@
+ ______@
+/_  __/@
+ / /   @
+/_/    @
+       @@
+  __  __@
+ / / / /@
+/ /_/ / @
+\____/  @
+        @@
+  _   __@
+ | | / /@
+ | |/ / @
+ |___/  @
+        @@
+  _      __@
+ | | /| / /@
+ | |/ |/ / @
+ |__/|__/  @
+           @@
+   _  __@
+  | |/_/@
+ _>  <  @
+/_/|_|  @
+        @@
+ __  __@
+ \ \/ /@
+  \  / @
+  /_/  @
+       @@
+  ____@
+ /_  /@
+  / /_@
+ /___/@
+      @@
+    ___@
+   / _/@
+  / /  @
+ / /   @
+/__/   @@
+__   @
+\ \  @
+ \ \ @
+  \_\@
+     @@
+    ___@
+   /  /@
+   / / @
+ _/ /  @
+/__/   @@
+ //|@
+|/||@
+ $  @
+$   @
+    @@
+     @
+     @
+     @
+ ____@
+/___/@@
+ _ @
+( )@
+ V @
+$  @
+   @@
+      @
+ ___ _@
+/ _ `/@
+\_,_/ @
+      @@
+   __ @
+  / / @
+ / _ \@
+/_.__/@
+      @@
+     @
+ ____@
+/ __/@
+\__/ @
+     @@
+     __@
+ ___/ /@
+/ _  / @
+\_,_/  @
+       @@
+     @
+ ___ @
+/ -_)@
+\__/ @
+     @@
+   ___@
+  / _/@
+ / _/ @
+/_/   @
+      @@
+       @
+  ___ _@
+ / _ `/@
+ \_, / @
+/___/  @@
+   __ @
+  / / @
+ / _ \@
+/_//_/@
+      @@
+   _ @
+  (_)@
+ / / @
+/_/  @
+     @@
+      _ @
+     (_)@
+    / / @
+ __/ /  @
+|___/   @@
+   __  @
+  / /__@
+ /  '_/@
+/_/\_\ @
+       @@
+   __@
+  / /@
+ / / @
+/_/  @
+     @@
+       @
+  __ _ @
+ /  ' \@
+/_/_/_/@
+       @@
+      @
+  ___ @
+ / _ \@
+/_//_/@
+      @@
+     @
+ ___ @
+/ _ \@
+\___/@
+     @@
+       @
+   ___ @
+  / _ \@
+ / .__/@
+/_/    @@
+      @
+ ___ _@
+/ _ `/@
+\_, / @
+ /_/  @@
+      @
+  ____@
+ / __/@
+/_/   @
+      @@
+     @
+  ___@
+ (_-<@
+/___/@
+     @@
+  __ @
+ / /_@
+/ __/@
+\__/ @
+     @@
+      @
+ __ __@
+/ // /@
+\_,_/ @
+      @@
+      @
+ _  __@
+| |/ /@
+|___/ @
+      @@
+        @
+ _    __@
+| |/|/ /@
+|__,__/ @
+        @@
+      @
+ __ __@
+ \ \ /@
+/_\_\ @
+      @@
+       @
+  __ __@
+ / // /@
+ \_, / @
+/___/  @@
+    @
+ ___@
+/_ /@
+/__/@
+    @@
+    __@
+  _/_/@
+_/ /  @
+/ /   @
+\_\   @@
+    __@
+   / /@
+  / / @
+ / /  @
+/_/   @@
+   __  @
+   \ \ @
+   / /_@
+ _/_/  @
+/_/    @@
+ /\//@
+//\/ @
+ $   @
+$    @
+     @@
+   _  _ @
+  (_)(_)@
+ / - |  @
+/_/|_|  @
+        @@
+  _   _ @
+ (_)_(_)@
+/ __ \  @
+\____/  @
+        @@
+  _   _ @
+ (_) (_)@
+/ /_/ / @
+\____/  @
+        @@
+  _  _ @
+ (_)(_)@
+/ _ `/ @
+\_,_/  @
+       @@
+  _  _ @
+ (_)(_)@
+/ _ \  @
+\___/  @
+       @@
+  _  _ @
+ (_)(_)@
+/ // / @
+\_,_/  @
+       @@
+    ____ @
+   / _  )@
+  / /< < @
+ / //__/ @
+/_/      @@
+160  NO-BREAK SPACE
+    $@
+   $ @
+  $  @
+ $   @
+$    @@
+161  INVERTED EXCLAMATION MARK
+   _ @
+  (_)@
+ / / @
+/_/  @
+     @@
+162  CENT SIGN
+     @
+ __//@
+/ __/@
+\ _/ @
+//   @@
+163  POUND SIGN
+     __ @
+  __/__|@
+ /_ _/_ @
+(_,___/ @
+        @@
+164  CURRENCY SIGN
+   /|_/|@
+  | . / @
+ /_  |  @
+|/ |/   @
+        @@
+165  YEN SIGN
+    ____@
+  _| / /@
+ /_  __/@
+/_  __/ @
+ /_/    @@
+166  BROKEN BAR
+    __@
+   / /@
+  /_/ @
+ / /  @
+/_/   @@
+167  SECTION SIGN
+     __ @
+   _/ _)@
+  / | | @
+ | |_/  @
+(__/    @@
+168  DIAERESIS
+ _   _ @
+(_) (_)@
+ $   $ @
+$   $  @
+       @@
+169  COPYRIGHT SIGN
+   ____  @
+  / ___\ @
+ / / _/ |@
+| |__/ / @
+ \____/  @@
+170  FEMININE ORDINAL INDICATOR
+   ___ _@
+  / _ `/@
+ _\_,_/ @
+/____/  @
+        @@
+171  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+  ____@
+ / / /@
+< < < @
+ \_\_\@
+      @@
+172  NOT SIGN
+     @
+ ____@
+/_  /@
+ /_/ @
+     @@
+173  SOFT HYPHEN
+    @
+ ___@
+/__/@
+ $  @
+    @@
+174  REGISTERED SIGN
+   ____  @
+  / __ \ @
+ / / -) |@
+| //\\ / @
+ \____/  @@
+175  MACRON
+ ____@
+/___/@
+ $   @
+$    @
+     @@
+176  DEGREE SIGN
+  __ @
+ /. |@
+|__/ @
+ $   @
+     @@
+177  PLUS-MINUS SIGN
+      __ @
+   __/ /_@
+  /_  __/@
+ __/_/_  @
+/_____/  @@
+178  SUPERSCRIPT TWO
+  __ @
+ |_ )@
+/__| @
+ $   @
+     @@
+179  SUPERSCRIPT THREE
+  ___@
+ |_ /@
+/__) @
+ $   @
+     @@
+180  ACUTE ACCENT
+ __@
+/_/@
+ $ @
+$  @
+   @@
+181  MICRO SIGN
+        @
+   __ __@
+  / // /@
+ / .,_/ @
+/_/     @@
+182  PILCROW SIGN
+  _____@
+ /    /@
+|_ / / @
+/_/_/  @
+       @@
+183  MIDDLE DOT
+   @
+ _ @
+(_)@
+$  @
+   @@
+184  CEDILLA
+   @
+   @
+   @
+ _ @
+/_)@@
+185  SUPERSCRIPT ONE
+  __@
+ < /@
+/_/ @
+$   @
+    @@
+186  MASCULINE ORDINAL INDICATOR
+   ___ @
+  / _ \@
+ _\___/@
+/____/ @
+       @@
+187  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+____  @
+\ \ \ @
+ > > >@
+/_/_/ @
+      @@
+188  VULGAR FRACTION ONE QUARTER
+  __  __   @
+ < /_/_/___@
+/_//_//_' /@
+ /_/   /_/ @
+           @@
+189  VULGAR FRACTION ONE HALF
+  __  __  @
+ < /_/_/_ @
+/_//_/|_ )@
+ /_/ /__| @
+          @@
+190  VULGAR FRACTION THREE QUARTERS
+  ___  __   @
+ |_ /_/_/___@
+/__)/_//_' /@
+  /_/   /_/ @
+            @@
+191  INVERTED QUESTION MARK
+   _ @
+ _(_)@
+/ _/_@
+\___/@
+     @@
+192  LATIN CAPITAL LETTER A WITH GRAVE
+   __ @
+  _\_\@
+ / - |@
+/_/|_|@
+      @@
+193  LATIN CAPITAL LETTER A WITH ACUTE
+    __@
+  _/_/@
+ / - |@
+/_/|_|@
+      @@
+194  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    //|@
+  _|/||@
+ / - | @
+/_/|_| @
+       @@
+195  LATIN CAPITAL LETTER A WITH TILDE
+    /\//@
+  _//\/ @
+ / - |  @
+/_/|_|  @
+        @@
+196  LATIN CAPITAL LETTER A WITH DIAERESIS
+   _  _ @
+  (_)(_)@
+ / - |  @
+/_/|_|  @
+        @@
+197  LATIN CAPITAL LETTER A WITH RING ABOVE
+   (())@
+  / _ |@
+ / __ |@
+/_/ |_|@
+       @@
+198  LATIN CAPITAL LETTER AE
+   _______@
+  / _  __/@
+ / _  _/  @
+/_//___/  @
+          @@
+199  LATIN CAPITAL LETTER C WITH CEDILLA
+  _____@
+ / ___/@
+/ /__  @
+\___/  @
+/_)    @@
+200  LATIN CAPITAL LETTER E WITH GRAVE
+  __ @
+  \_\@
+ / -<@
+/__< @
+     @@
+201  LATIN CAPITAL LETTER E WITH ACUTE
+    __@
+  _/_/@
+ / -< @
+/__<  @
+      @@
+202  LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+   //|@
+  |/||@
+ / -< @
+/__<  @
+      @@
+203  LATIN CAPITAL LETTER E WITH DIAERESIS
+  _  _ @
+ (_)(_)@
+ / -<  @
+/__<   @
+       @@
+204  LATIN CAPITAL LETTER I WITH GRAVE
+   __  @
+  _\_\ @
+ /_ __/@
+/____/ @
+       @@
+205  LATIN CAPITAL LETTER I WITH ACUTE
+     __@
+  __/_/@
+ /_ __/@
+/____/ @
+       @@
+206  LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    //|@
+  _|/||@
+ /_ __/@
+/____/ @
+       @@
+207  LATIN CAPITAL LETTER I WITH DIAERESIS
+   _  _ @
+  (_)(_)@
+ /_ __/ @
+/____/  @
+        @@
+208  LATIN CAPITAL LETTER ETH
+   ____ @
+ _/ __ \@
+/_ _// /@
+/_____/ @
+        @@
+209  LATIN CAPITAL LETTER N WITH TILDE
+     /\//@
+  __//\/ @
+ /  |/ / @
+/_/|__/  @
+         @@
+210  LATIN CAPITAL LETTER O WITH GRAVE
+  __  @
+ _\_\ @
+/ __ \@
+\____/@
+      @@
+211  LATIN CAPITAL LETTER O WITH ACUTE
+    __@
+ __/_/@
+/ __ \@
+\____/@
+      @@
+212  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+   //|@
+ _|/||@
+/ __ \@
+\____/@
+      @@
+213  LATIN CAPITAL LETTER O WITH TILDE
+   /\//@
+ _//\/ @
+/ __ \ @
+\____/ @
+       @@
+214  LATIN CAPITAL LETTER O WITH DIAERESIS
+  _   _ @
+ (_)_(_)@
+/ __ \  @
+\____/  @
+        @@
+215  MULTIPLICATION SIGN
+     @
+ /|/|@
+ > < @
+|/|/ @
+     @@
+216  LATIN CAPITAL LETTER O WITH STROKE
+  _____ @
+ / _// \@
+/ //// /@
+\_//__/ @
+        @@
+217  LATIN CAPITAL LETTER U WITH GRAVE
+   __  @
+ __\_\ @
+/ /_/ /@
+\____/ @
+       @@
+218  LATIN CAPITAL LETTER U WITH ACUTE
+     __@
+ __ /_/@
+/ /_/ /@
+\____/ @
+       @@
+219  LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    //|@
+ __|/||@
+/ /_/ /@
+\____/ @
+       @@
+220  LATIN CAPITAL LETTER U WITH DIAERESIS
+  _   _ @
+ (_) (_)@
+/ /_/ / @
+\____/  @
+        @@
+221  LATIN CAPITAL LETTER Y WITH ACUTE
+   __@
+__/_/@
+\ V /@
+ /_/ @
+     @@
+222  LATIN CAPITAL LETTER THORN
+   __ @
+  / / @
+ / -_)@
+/_/   @
+      @@
+223  LATIN SMALL LETTER SHARP S
+    ____ @
+   / _  )@
+  / /< < @
+ / //__/ @
+/_/      @@
+224  LATIN SMALL LETTER A WITH GRAVE
+  __  @
+ _\_\_@
+/ _ `/@
+\_,_/ @
+      @@
+225  LATIN SMALL LETTER A WITH ACUTE
+    __@
+ __/_/@
+/ _ `/@
+\_,_/ @
+      @@
+226  LATIN SMALL LETTER A WITH CIRCUMFLEX
+   //|@
+ _|/||@
+/ _ `/@
+\_,_/ @
+      @@
+227  LATIN SMALL LETTER A WITH TILDE
+   /\//@
+ _//\/ @
+/ _ `/ @
+\_,_/  @
+       @@
+228  LATIN SMALL LETTER A WITH DIAERESIS
+  _  _ @
+ (_)(_)@
+/ _ `/ @
+\_,_/  @
+       @@
+229  LATIN SMALL LETTER A WITH RING ABOVE
+   __ @
+ _(())@
+/ _ `/@
+\_,_/ @
+      @@
+230  LATIN SMALL LETTER AE
+         @
+ ___ ___ @
+/ _ ` -_)@
+\_,____/ @
+         @@
+231  LATIN SMALL LETTER C WITH CEDILLA
+     @
+ ____@
+/ __/@
+\__/ @
+/_)  @@
+232  LATIN SMALL LETTER E WITH GRAVE
+  __ @
+ _\_\@
+/ -_)@
+\__/ @
+     @@
+233  LATIN SMALL LETTER E WITH ACUTE
+   __@
+ _/_/@
+/ -_)@
+\__/ @
+     @@
+234  LATIN SMALL LETTER E WITH CIRCUMFLEX
+  //|@
+ |/||@
+/ -_)@
+\__/ @
+     @@
+235  LATIN SMALL LETTER E WITH DIAERESIS
+ _  _ @
+(_)(_)@
+/ -_) @
+\__/  @
+      @@
+236  LATIN SMALL LETTER I WITH GRAVE
+  __ @
+  \_\@
+ / / @
+/_/  @
+     @@
+237  LATIN SMALL LETTER I WITH ACUTE
+   __@
+  /_/@
+ / / @
+/_/  @
+     @@
+238  LATIN SMALL LETTER I WITH CIRCUMFLEX
+   //|@
+  |/||@
+ / /  @
+/_/   @
+      @@
+239  LATIN SMALL LETTER I WITH DIAERESIS
+ _   _ @
+(_)_(_)@
+ / /   @
+/_/    @
+       @@
+240  LATIN SMALL LETTER ETH
+   _||_@
+ __ || @
+/ _` | @
+\___/  @
+       @@
+241  LATIN SMALL LETTER N WITH TILDE
+    /\//@
+  _//\/ @
+ / _ \  @
+/_//_/  @
+        @@
+242  LATIN SMALL LETTER O WITH GRAVE
+  __ @
+ _\_\@
+/ _ \@
+\___/@
+     @@
+243  LATIN SMALL LETTER O WITH ACUTE
+   __@
+ _/_/@
+/ _ \@
+\___/@
+     @@
+244  LATIN SMALL LETTER O WITH CIRCUMFLEX
+   //|@
+ _|/||@
+/ _ \ @
+\___/ @
+      @@
+245  LATIN SMALL LETTER O WITH TILDE
+   /\//@
+ _//\/ @
+/ _ \  @
+\___/  @
+       @@
+246  LATIN SMALL LETTER O WITH DIAERESIS
+  _  _ @
+ (_)(_)@
+/ _ \  @
+\___/  @
+       @@
+247  DIVISION SIGN
+   _ @
+ _(_)@
+/___/@
+(_)  @
+     @@
+248  LATIN SMALL LETTER O WITH STROKE
+     @
+ ___ @
+/ //\@
+\//_/@
+     @@
+249  LATIN SMALL LETTER U WITH GRAVE
+   __ @
+ __\_\@
+/ // /@
+\_,_/ @
+      @@
+250  LATIN SMALL LETTER U WITH ACUTE
+    __@
+ __/_/@
+/ // /@
+\_,_/ @
+      @@
+251  LATIN SMALL LETTER U WITH CIRCUMFLEX
+   //|@
+ _|/||@
+/ // /@
+\_,_/ @
+      @@
+252  LATIN SMALL LETTER U WITH DIAERESIS
+  _  _ @
+ (_)(_)@
+/ // / @
+\_,_/  @
+       @@
+253  LATIN SMALL LETTER Y WITH ACUTE
+     __@
+  __/_/@
+ / // /@
+ \_, / @
+/___/  @@
+254  LATIN SMALL LETTER THORN
+    __ @
+   / / @
+  / _ \@
+ / .__/@
+/_/    @@
+255  LATIN SMALL LETTER Y WITH DIAERESIS
+   _  _ @
+  (_)(_)@
+ / // / @
+ \_, /  @
+/___/   @@
diff --git a/lib/plugins/captcha/figlet.php b/lib/plugins/captcha/figlet.php
new file mode 100644
index 0000000..bd7692b
--- /dev/null
+++ b/lib/plugins/captcha/figlet.php
@@ -0,0 +1,169 @@
+<?php
+/*        _         _____  _       _       _
+ *   ___ | |_  ___ |   __||_| ___ | | ___ | |_
+ *  | . ||   || . ||   __|| || . || || -_||  _|
+ *  |  _||_|_||  _||__|   |_||_  ||_||___||_|
+ *  |_|       |_|            |___|
+ *
+ *  Author   :      Lucas Baltes (lucas at thebobo.com)
+ *                  $Author: lhb $
+ *
+ *  Website  :      http://www.thebobo.com/
+ *
+ *  Date     :      $Date: 2003/03/16 10:08:01 $
+ *  Rev      :      $Revision: 1.0 $
+ *
+ *  Copyright:      2003 - Lucas Baltes
+ *  License  :      GPL - http://www.gnu.org/licenses/gpl.html
+ *
+ *  Purpose  :      Figlet font class
+ *
+ *  Comments :      phpFiglet is a php class to somewhat recreate the
+ *                  functionality provided by the original figlet program
+ *                  (http://www.figlet.org/). It does not (yet) support the
+ *                  more advanced features like kerning or smushing. It can
+ *                  use the same (flf2a) fonts as the original figlet program
+ *                  (see their website for more fonts).
+ *
+ *  Usage    :      $phpFiglet = new phpFiglet();
+ *
+ *                  if ($phpFiglet->loadFont("fonts/standard.flf")) {
+ *                      $phpFiglet->display("Hello World");
+ *                  } else {
+ *                      trigger_error("Could not load font file");
+ *                  }
+ *
+ */
+
+
+class phpFiglet
+{
+
+    /*
+     *  Internal variables
+     */
+
+    var $signature;
+    var $hardblank;
+    var $height;
+    var $baseline;
+    var $maxLenght;
+    var $oldLayout;
+    var $commentLines;
+    var $printDirection;
+    var $fullLayout;
+    var $codeTagCount;
+    var $fontFile;
+
+
+    /*
+     *  Contructor
+     */
+
+    function phpFiglet()
+    {
+
+    }
+
+
+    /*
+     *  Load an flf font file. Return true on success, false on error.
+     */
+
+    function loadfont($fontfile)
+    {
+        $this->fontFile = @file($fontfile);
+        if (!$this->fontFile) return false;
+
+        $hp = explode(" ", $this->fontFile[0]); // get header
+
+        $this->signature = substr($hp[0], 0, strlen($hp[0]) -1);
+        $this->hardblank = substr($hp[0], strlen($hp[0]) -1, 1);
+        $this->height = $hp[1];
+        $this->baseline = $hp[2];
+        $this->maxLenght = $hp[3];
+        $this->oldLayout = $hp[4];
+        $this->commentLines = $hp[5] + 1;
+        $this->printDirection = $hp[6];
+        $this->fullLayout = $hp[7];
+        $this->codeTagCount = $hp[8];
+
+        unset($hp);
+
+        if ($this->signature != "flf2a") {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+
+    /*
+     *  Get a character as a string, or an array with one line
+     *  for each font height.
+     */
+
+    function getCharacter($character, $asarray = false)
+    {
+        $asciValue = ord($character);
+        $start = $this->commentLines + ($asciValue - 32) * $this->height;
+        $data = ($asarray) ? array() : "";
+
+        for ($a = 0; $a < $this->height; $a++)
+        {
+            $tmp = $this->fontFile[$start + $a];
+            $tmp = str_replace("@", "", $tmp);
+            //$tmp = trim($tmp);
+            $tmp = str_replace($this->hardblank, " ", $tmp);
+
+            if ($asarray) {
+                $data[] = $tmp;
+            } else {
+                $data .= $tmp;
+            }
+        }
+
+        return $data;
+    }
+
+
+    /*
+     *  Returns a figletized line of characters.
+     */
+
+    function fetch($line)
+    {
+        $ret = "";
+
+        for ($i = 0; $i < (strlen($line)); $i++)
+        {
+            $data[] = $this->getCharacter($line[$i], true);
+        }
+
+        @reset($data);
+
+        for ($i = 0; $i < $this->height; $i++)
+        {
+            while (list($k, $v) = each($data))
+            {
+                $ret .= str_replace("\n", "", $v[$i]);
+            }
+            reset($data);
+            $ret .= "\n";
+        }
+
+        return $ret;
+    }
+
+
+    /*
+     *  Display (print) a figletized line of characters.
+     */
+
+    function display($line)
+    {
+        print $this->fetch($line);
+    }
+
+}
+?>
diff --git a/lib/plugins/captcha/fonts/Rufscript010.ttf b/lib/plugins/captcha/fonts/Rufscript010.ttf
new file mode 100644
index 0000000..887a449
Binary files /dev/null and b/lib/plugins/captcha/fonts/Rufscript010.ttf differ
diff --git a/lib/plugins/captcha/fonts/VeraSe.ttf b/lib/plugins/captcha/fonts/VeraSe.ttf
new file mode 100644
index 0000000..4b4ecc6
Binary files /dev/null and b/lib/plugins/captcha/fonts/VeraSe.ttf differ
diff --git a/lib/plugins/captcha/fonts/goudy_bookletter_1911-webfont.svg b/lib/plugins/captcha/fonts/goudy_bookletter_1911-webfont.svg
new file mode 100644
index 0000000..b60239e
--- /dev/null
+++ b/lib/plugins/captcha/fonts/goudy_bookletter_1911-webfont.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG webfont generated by Font Squirrel.
+Copyright   : This font has been released into the public domain by its author Barry Schwartz This applies worldwideIn some countries this may not be legally possible if soBarry Schwartz grants anyone the right to use this work for any purpose without any conditions unless such conditions are required by law
+</metadata>
+<defs>
+<font id="webfontiT6p4ac4" horiz-adv-x="464" >
+<font-face units-per-em="2048" ascent="1509" descent="-539" />
+<missing-glyph horiz-adv-x="512" />
+<glyph unicode=" "  horiz-adv-x="512" />
+<glyph unicode="&#x09;" horiz-adv-x="512" />
+<glyph unicode="&#xa0;" horiz-adv-x="512" />
+<glyph unicode="!" horiz-adv-x="665" d="M221 1251q0 31 27 47q139 82 149 82q20 0 21 -53v-47q0 -281 -35 -531.5t-57 -316.5q-10 -33 -35 -33q-31 0 -31 62v35q-4 127 -9 251.5t-10 211.5l-10 155l-6 103zM233 72q0 45 32 73.5t75 28.5t73.5 -30.5t30.5 -73.5q0 -41 -29.5 -72t-74.5 -31q-43 0 -75 30t-32 75z " />
+<glyph unicode="&#x22;" horiz-adv-x="796" d="M78 981v2q0 10 121 367q43 115 108 114q35 0 55.5 -22.5t20.5 -55.5q0 -27 -29 -79q-190 -340 -198 -351q-16 -20 -37 -20q-18 0 -29.5 13.5t-11.5 31.5zM416 981v2q0 10 123 367q39 115 108 114q33 0 53.5 -22.5t20.5 -55.5q0 -31 -27 -79l-109 -193q-87 -154 -91 -158 q-16 -20 -37 -20q-18 0 -29.5 13.5t-11.5 31.5z" />
+<glyph unicode="#" horiz-adv-x="1130" d="M111 360q0 20 1 29.5t8 17t23 7.5h179q6 0 6 4q41 281 41 295q0 10 -15 10h-207q-37 0 -36 45q0 47 36 47h222q18 0 18 16q57 410 59 412q10 16 48 17h2q41 0 41 -27q0 -8 -29 -205t-29 -203q0 -10 17 -10h213q16 0 18 14q57 412 61 416q10 14 33 15h6h15q33 0 32 -23 q0 -10 -27.5 -205.5t-27.5 -206t10 -10.5h152q39 0 39 -53q0 -39 -33 -39h-176q-6 0 -10 -12l-23 -163q-16 -118 -16 -122q0 -12 14 -12h207q37 0 37 -45q0 -47 -37 -47h-213q-23 0 -27 -23q-51 -362 -53 -367q-10 -20 [...]
+<glyph unicode="$" horiz-adv-x="987" d="M33 272q0 47 28.5 80t71.5 33q37 0 61.5 -25.5t24.5 -68.5q0 -12 -3 -35t-3 -37q0 -70 53 -101.5t105 -31.5q10 0 10 8v533q0 25 -19 26q-133 29 -205.5 128.5t-72.5 209.5q0 125 80 213t198 99q18 4 19 16v43q0 41 41 41h2q43 0 43 -41v-39v-4q0 -12 12 -12 q127 -14 209 -82t82 -138q0 -39 -23.5 -64.5t-60.5 -25.5q-43 0 -68.5 33t-35 73t-34 78t-67.5 46h-4q-10 0 -10 -10v-357q0 -6 -1 -18.5t-1 -14.5q0 -27 21.5 -37t76.5 -28q190 -82 242 -250q18 -61 18 -125q0 -162 -99 -259t-2 [...]
+<glyph unicode="%" horiz-adv-x="1679" d="M84 709q0 203 90 313.5t221 110.5q106 0 194.5 -87.5t88.5 -277.5q0 -186 -86 -303t-225 -117q-106 0 -194.5 86.5t-88.5 274.5zM207 776q0 -80 24.5 -176t73.5 -139q43 -35 90 -35q125 0 150 174q10 61 10 113q0 133 -50 237.5t-138 104.5q-47 0 -80 -29t-49.5 -75 t-23.5 -89t-7 -86zM385 -213q0 8 8 25q809 1380 815 1386q16 20 47 21q18 0 40 -9.5t22 -27.5q0 -10 -8 -23q-819 -1380 -828 -1388q-18 -23 -45 -23q-18 0 -34.5 11.5t-16.5 27.5zM1001 170q0 203 90.5 313.5t221.5 110 [...]
+<glyph unicode="&#x26;" horiz-adv-x="1695" d="M61 502q0 59 13.5 115.5t34 96.5t39 67.5t36.5 45.5l17 21q4 8 4 14v2q0 6 -21.5 34t-43 77t-21.5 108q0 139 107.5 246t250.5 107q76 0 147.5 -30t71.5 -95q0 -39 -28.5 -65.5t-63.5 -26.5q-41 0 -87 51t-91 51q-74 0 -145.5 -67.5t-71.5 -170.5q0 -59 28.5 -114.5 t51.5 -55.5q4 0 35.5 14.5t84 28t105.5 13.5q76 0 127 -32t51 -83t-54 -84t-134 -33h-2q-49 0 -95.5 12.5t-72 24.5t-29.5 12q-12 0 -24 -20l-2 -4q-55 -98 -56 -213q0 -55 15.5 -110.5t52.5 -114t93 -102.5t147.5  [...]
+<glyph unicode="'" horiz-adv-x="458" d="M78 983v2q0 8 121 365q43 115 108 114q35 0 55.5 -22.5t20.5 -55.5q0 -27 -29 -79q-190 -340 -198 -351q-16 -20 -37 -20q-18 0 -29.5 14.5t-11.5 32.5z" />
+<glyph unicode="(" horiz-adv-x="743" d="M92 537q0 250 120 490.5t335 414.5q39 29 61 28q43 0 43 -38q0 -27 -28 -50q-168 -152 -271.5 -367.5t-103.5 -475.5q0 -246 96 -464t270 -376q33 -33 33 -55q0 -18 -12 -29.5t-31 -11.5q-25 0 -49 20q-211 166 -337 407t-126 507z" />
+<glyph unicode=")" horiz-adv-x="743" d="M92 -350.5q0 18.5 31 49.5q168 152 270.5 367t102.5 475q0 248 -95.5 465t-269.5 376q-33 27 -33 54q0 18 12.5 30.5t31 12.5t48.5 -23q211 -166 336 -406.5t125 -506.5q0 -250 -119.5 -490.5t-334.5 -414.5q-39 -29 -62 -29q-18 0 -30.5 11t-12.5 29.5z" />
+<glyph unicode="*" horiz-adv-x="686" d="M29 999q0 41 47 70t93 46.5t46 31.5q0 12 -27.5 22.5t-62.5 17.5t-62.5 30.5t-27.5 60.5q0 31 24.5 51.5t53.5 20.5q37 0 87 -54.5t72 -54.5q10 0 11 14q0 10 -9.5 55.5t-9.5 73.5q0 92 82 93q80 0 80 -95q0 -35 -12.5 -84t-12.5 -51q0 -4 5 -4q8 0 69.5 50t102.5 50 q31 0 55 -23.5t24 -55.5q0 -29 -29.5 -52.5t-65.5 -35t-65.5 -23.5t-29.5 -23q0 -12 47 -22t93 -34.5t46 -76.5q0 -35 -23.5 -57t-54.5 -22q-43 0 -96 54t-59 54q-14 0 -14 -18q0 -29 9 -79t9 -63q0 -41 -31 -60.5t-55.5 [...]
+<glyph unicode="+" horiz-adv-x="1435" d="M109 518v27q0 45 49 45h501v510q0 41 41 41h29q49 0 49 -54v-497h510q41 0 41 -39v-29q0 -49 -55 -49h-496v-506q0 -45 -45 -45h-28q-45 0 -46 47v504h-503q-47 0 -47 45z" />
+<glyph unicode="," d="M80 92q0 47 38 80t87 33q74 0 127 -68.5t53 -167.5q0 -119 -78 -194.5t-129 -75.5q-39 0 -39 35q0 16 10.5 25.5t35 23.5t42.5 31q53 49 54 96q0 35 -22.5 53.5t-50.5 21.5t-61.5 16t-50.5 38q-16 22 -16 53z" />
+<glyph unicode="-" d="M25 369v28q0 20 7 29.5t31 28.5l282 197q50 34 63 34q33 0 32 -80q0 -29 -37 -57l-173 -123l-103 -75l-40 -26.5t-26 -9.5q-36 1 -36 54z" />
+<glyph unicode="." d="M111 88q0 51 35.5 85t85 34t86 -36t36.5 -85t-34.5 -85t-86.5 -36q-49 0 -85.5 35t-36.5 88z" />
+<glyph unicode="/" horiz-adv-x="890" d="M12 -354q0 8 772 1523q10 18 31 19q63 0 64 -37q0 -8 -351 -672l-127 -253l-99 -197l-74 -148l-53 -106l-35 -70q-15 -31 -21 -45t-11.5 -22.5t-5.5 -9.5t-2 -3q-10 -8 -26 -8q-62 0 -62 29z" />
+<glyph unicode="0" horiz-adv-x="972" d="M25 432q0 195 134 332t322 137q186 0 319.5 -137t133.5 -332q0 -193 -133 -331t-322 -138q-186 0 -320 136t-134 333zM160 440q0 -145 95 -249.5t230 -104.5q129 0 225.5 97.5t96.5 249t-98.5 253.5t-229.5 102t-225 -102.5t-94 -245.5z" />
+<glyph unicode="1" horiz-adv-x="729" d="M53 836q0 33 31 32q6 0 39 -2t89 -3t124 -1q66 0 122 1t89 3t39 2q29 0 28 -45q0 -20 -11 -27.5t-46 -9.5t-96 -6q-29 -2 -29 -32v-623q0 -41 37 -43q111 -4 146.5 -11.5t35.5 -45.5q0 -37 -35 -37l-34 4q-37 2 -98.5 5t-121 3t-118.5 -3l-97 -5l-34 -4q-29 0 -29 43 q0 35 37 39q70 4 104.5 7t42.5 10t8 32v629q0 29 -30 32q-31 2 -70 3t-53 2t-32.5 3.5t-24 7.5t-9.5 14.5t-4 25.5z" />
+<glyph unicode="2" horiz-adv-x="921" d="M51 616q0 111 80 181.5t203 70.5q143 0 250.5 -85t107.5 -214q0 -59 -29.5 -117.5t-58.5 -92t-103.5 -106.5l-103.5 -103q-8 -12 -8 -15q0 -16 23 -16q47 0 149 8q78 6 134.5 39t101.5 131q8 20 24 20q37 0 37 -24q0 -6 -76 -262q-4 -16 -12 -22.5t-19.5 -6.5t-27.5 -2 q-98 -4 -328.5 -15.5t-238.5 -11.5q-55 0 -56 39q0 16 11.5 25.5t56.5 38t94 65.5q147 115 254 252q49 66 49 119q0 94 -87 161.5t-183 67.5q-76 0 -121 -44t-49 -101q0 -53 -31 -53h-2q-41 -1 -41 73z" />
+<glyph unicode="3" horiz-adv-x="737" d="M53 694q0 88 51.5 150.5t139.5 62.5q35 0 84 -14t102 -41t90 -76t37 -108q0 -55 -29.5 -127t-59.5 -121t-30 -51q0 -10 15.5 -15.5t52.5 -16.5t72 -32q117 -68 116 -233q0 -199 -88 -312q-51 -66 -137 -99.5t-176 -33.5q-111 0 -173.5 51.5t-62.5 98.5q0 35 28 58.5 t62.5 23.5t60 -22.5t41 -49.5t54.5 -49.5t94 -22.5q96 0 141.5 78t45.5 186.5t-55.5 171t-194.5 62.5q-29 0 -53.5 -2t-28.5 -2q-35 0 -35 27q0 10 4 14t24.5 20.5t43.5 38.5q131 127 131 250q0 72 -44 135.5t-145 63.5q- [...]
+<glyph unicode="4" horiz-adv-x="915" d="M47 29q0 16 35 65l534 766q14 18 33 19q29 0 29 -37l-2 -668q0 -23 20 -22h33q37 0 60.5 2t25.5 2q41 0 41 -27q0 -8 -8 -61.5t-14 -59.5q-8 -8 -25 -8h-115q-18 0 -18 -14v-342q0 -25 -21 -25h-82q-20 0 -20 25v336q0 20 -16 20h-455q-35 0 -35 29zM223 145 q0 -10 13 -10h296q20 0 21 27v436q0 16 -10 16q-4 0 -13 -8q-307 -455 -307 -461z" />
+<glyph unicode="5" horiz-adv-x="780" d="M78 401q0 8 65 236l64 227q10 27 35 27q12 0 168.5 -49t173 -49t34 18t33 42t19.5 28q8 6 16 6q10 0 21.5 -8.5t11.5 -20.5q0 -6 -94 -223q-8 -23 -27 -23q-14 0 -172 49.5t-162 49.5h-2q-14 0 -24.5 -28t-36.5 -134v-4q-2 -4 -2 -6q0 -12 14 -13h27q147 0 256.5 -110.5 t109.5 -290.5q0 -162 -96 -305q-55 -80 -144.5 -148.5t-132.5 -68.5q-35 0 -34 30q0 14 19.5 29.5t47 30t68.5 52.5t74 89q74 117 73 244q0 141 -82 227t-190 86q-35 0 -70 -10l-35 -10q-26 -1 -26 30z" />
+<glyph unicode="6" horiz-adv-x="989" d="M68 465q0 293 205.5 529.5t512.5 293.5q4 2 15 2q18 0 29.5 -15t11.5 -32q0 -23 -33 -37q-324 -104 -504 -383l-2 -2v-4q0 -6 8 -6l15 2q14 2 40.5 5t51.5 3q203 0 348 -136t145 -339q0 -168 -109.5 -285.5t-279.5 -117.5q-180 0 -317 141t-137 381zM199 444 q0 -180 94 -299.5t225 -119.5q100 0 168 72.5t68 193.5q0 98 -35 198.5t-117 179.5t-192 79q-78 0 -128.5 -49.5t-66.5 -113t-16 -141.5z" />
+<glyph unicode="7" horiz-adv-x="921" d="M72 477q0 2 9 63.5t18.5 168t11.5 215.5q0 39 36 39q23 0 29 -20.5t14 -74.5q4 -25 29 -24h619q45 0 45 -37v-2q0 -10 -119 -365l-137 -430q-59 -193 -80 -268.5t-37 -126.5t-21.5 -55t-21.5 -6q-12 -2 -39 -3h-2h-12q-57 0 -58 29q0 10 228 676q133 367 133 375 q0 39 -62 49q-113 10 -202 10q-170 0 -224 -14q-20 -4 -28 -15.5t-22.5 -54.5t-39.5 -131q-10 -31 -33 -31q-34 0 -34 33z" />
+<glyph unicode="8" horiz-adv-x="915" d="M33 313q0 141 141 254l107 82q16 12 16 18.5t-10 12.5q-96 66 -157.5 157t-61.5 191q0 129 103 234.5t257 105.5q141 0 239.5 -75.5t98.5 -215.5q0 -102 -60.5 -197.5t-156.5 -148.5q-6 -2 -6 -10q0 -2 6 -8q145 -66 233 -168.5t88 -214.5q0 -150 -134 -262.5 t-308 -112.5q-164 0 -279.5 106.5t-115.5 251.5zM184 309q0 -113 79 -185.5t188 -72.5q102 0 175.5 65.5t73.5 162.5q0 98 -81.5 186t-212.5 153q-20 12 -31 13q-35 0 -113 -102.5t-78 -219.5zM209 1053q0 -92 55 -167t111.5 -1 [...]
+<glyph unicode="9" horiz-adv-x="1042" d="M66 465q0 174 124.5 293t296.5 119q197 0 338.5 -151t141.5 -368q0 -240 -180.5 -463t-469.5 -313q-53 -14 -63 -14q-20 0 -29.5 17.5t-9.5 31.5q0 25 35 35q111 35 210 96.5t155.5 118.5t88 97t31.5 46t-6 6l-24 -6q-23 -6 -63 -13t-79 -7q-205 0 -351 142.5t-146 332.5 zM215 512q0 -166 99.5 -304t267.5 -138q92 0 137 37.5t67 107.5q23 74 23 145q0 174 -107.5 299t-248.5 125q-92 0 -165 -68.5t-73 -203.5z" />
+<glyph unicode=":" horiz-adv-x="466" d="M133 88q0 51 36 85t85 34t86 -36t37 -85t-36 -85t-87 -36q-49 0 -85 35t-36 88zM133 723q0 51 36 85t85 34t86 -36t37 -85t-36 -85t-87 -36q-49 0 -85 35t-36 88z" />
+<glyph unicode=";" d="M129 92q0 47 38 80t87 33q74 0 127 -68.5t53 -167.5q0 -119 -79 -194.5t-130 -75.5q-37 0 -37 35q0 16 10.5 25.5t35 23.5t42.5 31q53 51 54 96v2q0 35 -22.5 52.5t-51.5 21.5t-61.5 16t-49.5 37q-16 18 -16 53zM133 723q0 51 36 85t85 34t86 -36t37 -85t-36 -85t-87 -36 q-49 0 -85 35t-36 88z" />
+<glyph unicode="&#x3c;" horiz-adv-x="1376" d="M106 471v39q0 23 37 37q1073 391 1082 391q47 0 47 -78q0 -29 -39 -41l-903 -330l915 -331q27 -10 27 -35t-14.5 -50.5t-45.5 -25.5q-10 0 -1071 387q-35 12 -35 37z" />
+<glyph unicode="=" horiz-adv-x="1435" d="M109 670v28q0 45 47 45h1130q41 0 41 -41v-26q0 -51 -53 -51h-1118q-47 0 -47 45zM111 365v28q0 45 47 45h1130q41 0 41 -41v-28q0 -49 -53 -50h-1120q-45 1 -45 46z" />
+<glyph unicode="&#x3e;" horiz-adv-x="1376" d="M106 122.5q0 24.5 27 35.5l916 331l-904 330q-39 12 -39 41q0 78 48 78q8 0 1081 -391q37 -14 37 -37v-39q0 -25 -35 -37q-1063 -387 -1071 -387q-31 0 -45.5 25.5t-14.5 50z" />
+<glyph unicode="?" horiz-adv-x="778" d="M31 1272q0 92 131 121q80 18 166 18q178 0 270 -95t92 -206q0 -70 -34.5 -131t-85.5 -109l-100 -96q-50 -49 -85 -115.5t-35 -146.5q0 -10 1 -24.5t1 -20.5q0 -37 -17.5 -55.5t-35.5 -18.5q-55 0 -55 113q0 90 43 176t93 143.5t93 137t43 157.5q0 88 -51 150.5t-127 62.5 q-43 0 -75 -23.5t-46 -52t-39.5 -52t-60.5 -23.5q-37 0 -61.5 26.5t-24.5 63.5zM203 88q0 51 36.5 85t86 34t86.5 -36t37 -85t-36 -85t-87 -36q-49 0 -86 35t-37 88z" />
+<glyph unicode="@" horiz-adv-x="2048" d="M180 381v2q0 88 19.5 176t66.5 196.5t150.5 210t249.5 175.5q221 111 444 110q295 0 479.5 -186t184.5 -459q0 -254 -147.5 -438t-332.5 -184q-68 0 -112.5 23.5t-59 52t-23.5 52t-11.5 23.5t-10.5 -8q-125 -156 -268 -156q-80 0 -135.5 55.5t-55.5 143.5 q0 133 141.5 322.5t272.5 269.5q80 49 154 49q23 0 40 -3t19 -3q16 0 32.5 31.5t18.5 33.5q10 8 27 9q47 0 47 -35l-51 -182q-51 -182 -90 -406q-10 -47 -10 -80q0 -53 29.5 -75.5t68.5 -22.5q66 0 142.5 42t123.5 109q104 145 105 [...]
+<glyph unicode="A" horiz-adv-x="1681" d="M18 31q0 20 6.5 31.5t17.5 16.5t28.5 8t40.5 5q49 6 71.5 25.5t44.5 72.5q152 338 314 656l265 503q36 67 52 81q23 16 49 16q55 0 86 -78l295 -680q223 -543 228 -549q27 -41 87 -49t66 -31q4 -16 4 -26q0 -45 -41 -45l-35 4q-33 2 -89 5t-111 3q-66 0 -120 -3t-86 -6 t-38 -3q-41 0 -41 35q0 25 5 36t18.5 17t37 9t60.5 7q41 8 41 39t-49 183.5t-105 279.5q-8 20 -37 20h-481q-33 0 -47 -24q-70 -129 -124 -268.5t-54 -174.5q0 -20 8 -32.5t24.5 -17.5t40.5 -8l56 -7q45 -4 45 -49t-4 [...]
+<glyph unicode="B" horiz-adv-x="1155" d="M35 45q0 27 17.5 33t97.5 14h2q14 2 21 5t13.5 11.5t6.5 24.5v1120q0 27 -14.5 41.5t-32 17.5t-60.5 7q-37 0 -37 51q0 37 37 37q2 0 14.5 -1t34.5 -1h49q63 0 179 9t178 9q221 0 340 -82q125 -90 125 -235q0 -94 -54.5 -178t-140.5 -137q-4 -4 -4 -7q0 -2 6 -6 q121 -25 203 -124t82 -232q0 -135 -78 -238.5t-182 -148.5q-104 -47 -246 -47q-47 0 -140.5 6t-140.5 6q-33 0 -108.5 -2t-124.5 -2h-4q-12 0 -19.5 2t-13.5 13t-6 34zM369 168q0 -23 2 -34t16 -24.5t43 -17.5q61 -8 96 -8q1 [...]
+<glyph unicode="C" horiz-adv-x="1433" d="M39 686q0 152 62.5 291t164.5 240q219 209 522 208h3q109 0 201.5 -26.5t144 -54t55.5 -27.5q16 0 27.5 33.5t31.5 40.5q4 0 12.5 1t10.5 1q23 0 26 -25l15 -104q12 -104 26.5 -213t14.5 -117q0 -35 -41 -35q-20 0 -30.5 3t-15.5 14.5t-7 30t-7 48.5q-12 82 -53 135 q-70 88 -177 144.5t-241 56.5q-221 0 -384.5 -167t-163.5 -439q0 -283 167.5 -476.5t407.5 -193.5q180 0 329.5 110.5t205.5 293.5q8 27 30 26q33 0 33 -22l-51 -334q-8 -33 -45 -33h-2h-58q-31 0 -50 -11t-46 -32q-176  [...]
+<glyph unicode="D" horiz-adv-x="1452" d="M20 57q0 25 15.5 34t49.5 11t87 4q33 2 44 19.5t11 54.5v1037q0 29 -9 44t-29.5 21t-52.5 7t-77 3q-37 0 -36 47q0 43 45 43h372q190 0 330.5 -16t263.5 -74q166 -78 277.5 -231.5t111.5 -358.5q0 -260 -180 -453.5t-414 -236.5q-72 -12 -182 -12h-579q-48 0 -48 57z M410 190q0 -37 16 -54t57 -25q66 -12 131 -13q244 0 424.5 146.5t180.5 402.5q0 152 -63.5 293t-182.5 229q-174 127 -426 127q-88 0 -112.5 -12t-24.5 -51v-1043z" />
+<glyph unicode="E" horiz-adv-x="1183" d="M18 37q0 18 10.5 27.5t45.5 22.5l100 38q29 10 37 26.5t8 53.5v1067q0 23 -9 29t-46 12q-59 2 -97 11t-38 46q0 45 39 45h942q35 0 45 -33l35 -157q25 -111 24 -115q0 -31 -43 -31q-31 0 -57 37q-47 88 -73 130t-40 51.5t-47 9.5h-385q-29 0 -43 -12.5t-17 -27t-3 -38.5 v-309q0 -45 40 -46h314q23 0 37 3.5t27.5 18.5t13.5 46v64q0 45 55 45q57 0 57 -60v-377q0 -59 -57 -59q-55 0 -55 45v111q0 45 -54 45h-282q-31 0 -48.5 -4t-35 -22.5t-17.5 -55.5v-469q0 -70 66 -78q88 -14 190 -1 [...]
+<glyph unicode="F" horiz-adv-x="1107" d="M20 1348q0 61 37 61q6 0 27.5 -2t60.5 -4t84 -2q35 0 154 3t178 3h389h11q55 0 67 -51q47 -213 47 -219q0 -20 -12 -33.5t-29 -13.5q-20 0 -34.5 14t-35.5 52l-59 104q-16 27 -29.5 35t-41.5 8h-377q-37 0 -48.5 -18.5t-11.5 -55.5v-342q0 -31 31 -31h342q20 0 28.5 8 t13.5 36t13 77q8 55 49 55q47 0 48 -43q0 -6 -2 -30.5t-4.5 -66.5t-2.5 -93t2.5 -95.5t4.5 -69t2 -28.5q0 -53 -56 -53q-25 0 -34 14.5t-13 48t-10 93.5q-2 29 -37 28h-334q-45 0 -45 -57v-508q0 -18 2 -27.5t8.5 -21. [...]
+<glyph unicode="G" horiz-adv-x="1415" d="M33 725q0 307 200.5 514t487.5 207q84 0 164 -20.5t127 -44t84 -45t41 -23.5h8q23 0 53.5 39t36.5 41q10 6 25 6q29 0 28 -29v-55q0 -72 3 -145.5t8.5 -119.5t7.5 -79l4 -35q0 -33 -60 -33q-23 0 -31 13.5t-10 36t-19 66.5t-50 91q-78 106 -197 172t-248 66 q-82 0 -159.5 -32t-146 -98.5t-110.5 -186.5t-42 -279q0 -156 35.5 -280t91 -198.5t128 -125t141 -70t138.5 -19.5q117 0 218.5 48.5t119.5 85.5q6 12 6 34v232q0 33 -16.5 46t-59.5 17t-116 10q-57 4 -58 48q0 47 45 47q6 0 34  [...]
+<glyph unicode="H" horiz-adv-x="1560" d="M29 1352q0 10 3 21t14 22.5t30 11.5q6 0 37.5 -1t85 -2t116.5 -1h7q66 0 121 1t86.5 2t37.5 1q14 0 22.5 -6t11.5 -14.5t5 -22.5q0 -4 1 -10t1 -8q0 -20 -12 -27.5t-47 -9.5t-96 -6q-47 -2 -47 -62v-338q0 -29 26 -29h692q35 0 35 37v303q0 74 -43 89q-16 6 -45 8 t-49.5 3t-35.5 11t-15 33q0 49 49 49q6 0 32.5 -1t75 -2t103.5 -1q63 0 127.5 2t103.5 4l37 2q39 0 39 -41q0 -29 -15.5 -41t-46.5 -16l-79 -10q-55 -6 -56 -60v-1075v-10q0 -61 58 -66q39 -4 67.5 -4t44 -11t15.5 -36q0 - [...]
+<glyph unicode="I" horiz-adv-x="661" d="M27 53q0 20 12 28.5t51 10.5t109 6q43 2 43 58v1065q0 6 1 16t1 12q0 20 -11.5 28.5t-41 10.5t-82.5 4q-47 4 -48 43q0 57 45 58l33 -2l91 -6q56 -3 112 -3q57 0 105.5 2t75 4.5t32.5 2.5q35 0 35 -39q0 -23 -5 -35t-19.5 -17.5t-40 -7.5t-64.5 -6q-33 -2 -33 -35v-1106 q0 -47 37 -51q86 -2 124 -8t38 -39q0 -59 -41 -59l-37 4q-37 2 -99.5 5t-124 3t-125 -3t-100.5 -5l-37 -4q-31 0 -34 47q-2 6 -2 18z" />
+<glyph unicode="J" horiz-adv-x="647" d="M-168 -276q0 41 25.5 70.5t66.5 29.5q51 0 102.5 -67.5t94.5 -67.5q70 0 102 125q18 66 19 133v1272q0 35 -17.5 49t-54.5 17t-94 9q-45 4 -45 43q0 55 45 56l35 -2l98 -5.5t121 -3.5h8q63 0 116.5 2t85 4.5t38.5 2.5q35 0 34 -41q0 -31 -12 -43.5t-42 -15.5t-77 -7 q-53 -4 -53 -70v-1099q0 -119 -49 -227.5t-131 -186.5q-18 -18 -52 -45t-94.5 -58.5t-105.5 -31.5q-70 0 -117 50.5t-47 107.5z" />
+<glyph unicode="K" horiz-adv-x="1339" d="M25 1360q0 18 14 33.5t45 15.5q6 0 34.5 -2t80 -4t110.5 -2h2q59 0 110.5 2t80 4t35.5 2q31 0 45 -17.5t14 -35.5q0 -37 -75 -42t-83 -9q-31 -14 -30 -68v-8v-436q0 -35 26 -35q14 0 53 43q365 406 373 420q16 20 17 43q0 29 -21.5 42t-46.5 13t-46.5 10t-21.5 35 q0 43 47 43q6 0 34 -1t76 -2t106 -1h12q53 0 100 1t72.5 2t32.5 1q57 0 57 -43q0 -25 -27.5 -36t-78 -19.5t-76.5 -18.5q-41 -16 -81 -56t-67 -73l-320 -345q-46 -50 -46 -62q0 -14 16 -31l492 -519q66 -71 86 -83q35 -23  [...]
+<glyph unicode="L" horiz-adv-x="1153" d="M23 1337q0 51 38 52q4 0 77 -2.5t157 -4.5h14q66 0 121 1t88 3.5t39 2.5q23 0 29 -13.5t6 -42.5q0 -47 -45 -47q-68 0 -106 -1t-50 -12t-12 -46v-1039q0 -20 3 -32.5t15.5 -22.5t34.5 -10h391h6q76 0 113 55q10 16 45 92t41 82q12 16 31 17q10 0 22.5 -3.5t25.5 -14.5 t13 -29q0 -14 -41 -289q-2 -14 -5 -22.5t-15 -15.5t-35 -7l-121 4q-121 2 -325.5 5t-407.5 3h-109q-33 0 -32 33q0 16 5 24.5t18.5 13.5t35 10t53.5 11q47 12 47 66v6v1075q0 29 -10 38t-35.5 10t-68.5 1q-51 4 -51 49z" />
+<glyph unicode="M" horiz-adv-x="2043" d="M37 33q0 29 16.5 42t50 16t84.5 9q31 4 45.5 19.5t15.5 38t5 51.5q51 608 51 915q0 25 -22 52q-2 2 -26 31.5t-40 44t-53 31.5t-78 17q-41 6 -41 37q0 45 37 45h295q35 0 51 -26l387 -647l240 -381q12 -25 35 -25q18 0 28 23l555 1038q10 18 37 18h297q31 0 31 -45 q0 -20 -11.5 -30.5t-25.5 -14.5t-52 -12t-71 -18q-49 -12 -49 -60q10 -993 10 -995v-14q0 -33 3 -49.5t19.5 -32t49.5 -19.5q45 -4 73.5 -6t43 -13.5t14.5 -39.5q0 -45 -41 -45l-39 4q-37 2 -99.5 5t-125.5 3q-61 0 -124  [...]
+<glyph unicode="N" horiz-adv-x="1636" d="M18 1341q0 53 45 54h252q49 0 82 -39l322 -373l186 -209l265 -288q87 -93 107.5 -113.5t29.5 -20.5q14 0 14 21q4 147 4 219q0 309 -18 610q-2 61 -29 76.5t-104 24.5q-45 6 -46 43q0 18 14.5 33.5t45.5 15.5q4 0 29.5 -1t69.5 -3t97 -2q51 0 95.5 2t69 3t28.5 1 q43 0 43 -47q0 -35 -29 -44q-20 -6 -43 -7q-10 0 -21 1q-5 1 -9 1q-30 0 -56 -24q-29 -28 -28 -95q-8 -369 -9 -555q0 -152 2.5 -282t4.5 -203.5t2 -90.5q0 -96 -41 -96q-25 0 -101 86l-424 483q-449 500 -454 500l-8 -8q-2 [...]
+<glyph unicode="O" horiz-adv-x="1593" d="M37 723q0 311 223 531.5t533 220.5q324 0 543.5 -232.5t219.5 -552.5q0 -317 -215 -528t-520 -211q-150 0 -294 58.5t-253 162.5q-233 225 -237 551zM231 786q0 -184 62.5 -342.5t199 -266t320.5 -107.5q74 0 146.5 18t144.5 63.5t127 111t89 165.5t34 225 q0 164 -54.5 318.5t-171.5 257.5q-156 137 -368.5 137t-370.5 -148.5t-158 -431.5z" />
+<glyph unicode="P" horiz-adv-x="1171" d="M29 37q0 29 9 39t37.5 13t80.5 7q35 4 46 16.5t11 39.5v1095q0 53 -45 53h-74q-14 0 -22.5 2.5t-17.5 14.5t-9 37q0 45 45 45h51q102 0 261 10t227 10q262 0 399 -123q119 -109 119 -266v-2q-2 -109 -60.5 -194.5t-148.5 -133.5q-152 -84 -461 -84h-61q-27 0 -27 -32 v-416q0 -35 13.5 -52.5t52.5 -19.5q94 -2 143 -5t63.5 -12t14.5 -40v-2q0 -49 -39 -49l-41 4q-41 2 -108.5 5t-133.5 3q-68 0 -136 -3t-107 -5l-41 -4q-41 0 -41 49zM393 713q0 -16 12.5 -20.5t63.5 -4.5q225 0 365.5 9 [...]
+<glyph unicode="Q" horiz-adv-x="1540" d="M41 725q0 152 60.5 295t168.5 250q217 213 525 213q133 0 267 -51.5t236 -153.5q109 -106 167.5 -250.5t58.5 -298.5q0 -207 -103.5 -396.5t-269.5 -301.5q-6 -6 -6 -10.5t6 -8.5q80 -55 169 -148t136 -124q82 -55 174 -55q16 0 28.5 1t14.5 1q25 0 25 -21 q0 -25 -60.5 -53.5t-121.5 -28.5q-57 0 -112.5 20.5t-94.5 53.5l-80 71q-41 38 -72 70q-178 178 -223 178l-47 -6q-47 -4 -90 -4q-154 0 -295.5 60.5t-243.5 165.5q-217 221 -217 532zM240 803q0 -182 70.5 -349t209.5 -277.5t314 [...]
+<glyph unicode="R" horiz-adv-x="1425" d="M29 1343q0 39 26 39h72q96 0 243.5 12.5t209.5 12.5q131 0 229 -35t149.5 -91t75 -113.5t23.5 -116.5q0 -133 -82 -223.5t-152 -116.5q-10 -6 -10 -10.5t4 -8.5q147 -174 255 -341t124 -185q57 -66 111 -66q31 0 54 22.5t34 22.5q20 0 20 -22q0 -37 -50 -93.5t-128 -56.5 q-104 0 -217 150l-205 291q-176 246 -188 254q-10 8 -35 8h-150q-29 0 -28 -31v-473v-6q0 -59 53 -66q68 -6 109.5 -9t59 -15.5t17.5 -42.5q0 -45 -41 -45l-39 4q-37 2 -99 5t-125.5 3t-126 -3t-99.5 -5l-37 -4q-37 [...]
+<glyph unicode="S" horiz-adv-x="1007" d="M51 131q0 6 7.5 41t19.5 112.5t20 180.5q4 43 45 43q31 0 39 -19.5t19 -99.5q6 -102 8 -109.5t45 -64.5q100 -135 264 -135q123 0 210 83t87 202q0 139 -119 225q-70 49 -208 84t-179 51q-121 47 -182 136t-61 196q0 141 104 243.5t262 102.5q74 0 133.5 -20.5t91 -41 t39.5 -20.5q12 0 36 41t50 41q33 0 33 -39q0 -4 -2 -25.5t-4 -60.5t-2 -84t2 -82t4 -58.5t2 -25.5q0 -31 -35 -31h-2q-29 0 -42 21.5t-36.5 72t-62.5 95.5q-102 115 -225 114q-86 0 -142.5 -56t-56.5 -136q0 -113 104  [...]
+<glyph unicode="T" horiz-adv-x="1417" d="M25 1094v2q0 8 59 282q6 31 43 31h1194q23 0 30 -11.5t11 -35.5q49 -250 49 -262q0 -18 -11 -31.5t-28 -13.5q-25 0 -47 39q-45 82 -69.5 121.5t-39 49t-47.5 9.5h-301q-45 0 -45 -55v-1074q0 -27 13.5 -36t54.5 -13t119 -10q25 -2 31 -13.5t6 -43.5q0 -41 -35 -41l-41 4 q-39 2 -105.5 5t-132 3t-132 -3t-105.5 -5l-41 -4q-41 0 -41 53q0 25 10 34t44 13t95 8q43 4 56.5 22.5t13.5 53.5v1038q0 63 -55 64h-306q-39 0 -52 -8.5t-25 -32.5q-59 -125 -79 -158t-46 -33q-20 0 -32.5 14.5t- [...]
+<glyph unicode="U" horiz-adv-x="1548" d="M35 1362q0 49 41 49q4 0 68.5 -2t138.5 -4h12q57 0 106.5 2t78 3t34.5 1q39 0 39 -53q0 -35 -32 -42t-95 -11q-66 -8 -66 -72v-641q0 -137 24 -230.5t101 -162.5q123 -113 369 -113q287 0 375 186q39 80 39 228v28q0 20 -1 63.5t-1 63.5v557q0 25 -4.5 42.5t-11.5 28.5 t-18 17.5t-26.5 10.5t-35 6t-42.5 4q-45 4 -45 45q0 45 39 45q6 0 29 -1t63.5 -3t88 -2t88.5 2t63.5 3t28.5 1q37 0 37 -53q0 -25 -14.5 -33t-35 -10t-40 -10.5t-34 -41t-14.5 -92.5q0 -4 -1 -10t-1 -10v-465q0 -16 1 [...]
+<glyph unicode="V" horiz-adv-x="1699" d="M33 1370q0 41 59 41q6 0 36 -1t82 -3t112 -2q57 0 106 2t76.5 3t34.5 1q37 0 36 -39q0 -18 -5 -28.5t-17 -16.5t-34.5 -9t-57.5 -9q-55 -6 -55 -54q0 -16 12 -41q137 -305 294.5 -597.5t180.5 -319.5q8 -8 18 -8q14 0 23 16q238 432 409 893q12 37 13 45q0 47 -45 62 q-16 6 -54 6t-58.5 9t-20.5 40q0 51 45 51q6 0 32.5 -1t73.5 -3t102.5 -2t102.5 2t73.5 3t32.5 1q45 0 46 -55q0 -25 -15.5 -35t-37 -11t-52.5 -12.5t-51 -33.5q-23 -25 -79 -163t-197.5 -445.5t-329.5 -655.5q-25 -41  [...]
+<glyph unicode="W" horiz-adv-x="2052" d="M27 1354q0 57 51 57q4 0 29.5 -1t69.5 -3t97 -2q51 0 94.5 2t69 3t29.5 1q37 0 37 -51q0 -27 -17.5 -36t-39 -7t-47 -2t-38.5 -19q-10 -12 -10 -26.5t6 -26.5q109 -344 320 -907q14 -37 31 -37h6q2 0 7 6t8 12.5t12 27.5l18 41l26 65l35 88l47 120l60 152q4 16 4 25v2 q0 12 -135 403q-20 57 -36 65.5t-108 12.5q-35 0 -35 45q0 47 48 47q6 0 32.5 -1t74.5 -3t104 -2h2q55 0 102 2t73.5 3t32.5 1q35 0 35 -45q0 -14 -4 -22.5t-14 -13.5t-27.5 -7t-42.5 -4q-63 -8 -63 -51q0 -6 4 -27q96 [...]
+<glyph unicode="X" horiz-adv-x="1361" d="M10 27q0 23 4 34t14.5 17t31 9t51.5 9q29 6 48 15.5t36.5 27t36.5 44.5l51 71q301 422 301 428q0 8 -326 528q-43 70 -69.5 83.5t-100.5 19.5q-51 4 -51 53q0 45 41 45q6 0 36.5 -1t84 -3t114.5 -2h6q61 0 113.5 2t81.5 3t35 1q20 0 29.5 -11t9.5 -48q0 -23 -22.5 -31 t-49.5 -7t-49.5 -10.5t-22.5 -39.5q0 -12 25 -62l155 -255q50 -81 60 -96t14 -15t9 4q172 238 217 305t45 106q0 23 -9.5 37.5t-24.5 19.5t-35.5 7t-43.5 2q-53 4 -53 59q0 35 33 35q6 0 36.5 -1t84 -3t114.5 -2q63 0  [...]
+<glyph unicode="Y" horiz-adv-x="1366" d="M23 1366q0 45 51 45q6 0 34.5 -1t80 -3t110.5 -2t109.5 2t79 3t34.5 1q37 0 37 -41q0 -31 -11 -42t-41 -13t-81 -6q-53 -6 -53 -47v-5q0 -14 39 -83l252 -435q16 -29 28 -28q4 0 17 12l228 313q79 111 104.5 155t25.5 73q0 33 -30 44q-23 9 -50 8q-7 0 -14.5 -0.5 t-14.5 -0.5q-26 0 -50 9q-30 11 -29 46q0 41 43 41q6 0 29.5 -1t64.5 -3t88 -2h6q66 2 122 4t60 2q29 0 43.5 -13.5t14.5 -27.5q0 -23 -43 -54.5t-64 -58.5l-297 -383q-158 -209 -185.5 -248.5t-27.5 -82.5v-400q0 -25 14. [...]
+<glyph unicode="Z" horiz-adv-x="1288" d="M33 43q0 18 16 39q397 563 864 1079q29 33 29 45q0 23 -29 23h-661q-51 0 -71.5 -13.5t-33 -55.5t-30.5 -120q-10 -45 -43 -45q-41 0 -41 52q0 8 4 48t8 108.5t4 150.5v76q0 57 43 57q31 0 53 -49q16 -55 113 -56h893q49 0 49 -36q0 -10 -10 -26.5t-51 -71.5l-123 -161 l-297 -372q-223 -270 -328 -455q-10 -14 -10 -31q0 -31 37 -40t168 -17q98 -6 200 -6h43q135 0 202 21.5t102 103.5q14 33 28.5 117t20.5 96q14 20 39 20q16 0 32.5 -14t16.5 -43v-2q0 -39 -4 -71t-10.5 -71.5t-10.5  [...]
+<glyph unicode="[" horiz-adv-x="774" d="M47 541q0 74 59 73q16 0 31 -7t17 -7q8 0 8 14v840q0 70 51 70q10 0 79.5 -37t162.5 -37q59 0 118.5 14.5t94.5 30.5l34 14q10 0 17.5 -11t7.5 -21q0 -29 -71.5 -83.5t-166.5 -56.5q-12 0 -12 -14l2 -1583q0 -14 8.5 -18.5t23.5 -4.5t48 -10t70 -33q39 -25 67.5 -54.5 t28.5 -43.5q0 -27 -25 -27q-4 0 -39.5 18.5t-97 36t-131.5 17.5q-61 0 -114.5 -13.5t-84 -25.5t-36.5 -12q-33 0 -33 45v848q0 14 -8 14q-2 0 -17.5 -10t-32.5 -10q-59 0 -59 84zM256 -317q0 -10 8 -11q2 0 15.5 9.5t41 [...]
+<glyph unicode="\" horiz-adv-x="481" d="M6 1221q0 16 23.5 30.5t40.5 14.5q23 0 30 -31q113 -559 244 -1100t131 -545q0 -18 -25.5 -35.5t-37.5 -17.5q-23 0 -23 23q-383 1653 -383 1661z" />
+<glyph unicode="]" horiz-adv-x="774" d="M47 1477q0 10 7 21t18 11l34 -14q35 -16 94.5 -30.5t118.5 -14.5q92 0 162 37t80 37q51 0 51 -70v-840q0 -14 9 -14q2 0 16 7t31 7q59 0 59 -73q0 -84 -59 -84q-16 0 -31.5 10t-18.5 10q-8 0 -8 -14v-848q0 -45 -32 -45q-6 0 -37 12t-84.5 25.5t-114.5 13.5 q-70 0 -131 -17.5t-97 -36t-40 -18.5q-25 0 -25 27q0 14 28.5 44t67.5 54q37 23 70 33t48.5 10t23.5 4.5t8 18.5l2 1583q0 14 -12 14q-94 2 -166 56.5t-72 83.5zM381 -268q0 -10 8 -13q37 -6 64.5 -17t41 -20.5t15.5 -9.5q8 0 8 1 [...]
+<glyph unicode="^" horiz-adv-x="866" d="M104 991q0 16 15 41l166 283q55 92 72.5 113.5t39.5 31.5q16 6 31 6q14 0 27.5 -5t23.5 -14t19.5 -20.5t16.5 -22.5t15 -22l201 -319q33 -53 33 -73.5t-14.5 -34t-35 -13.5t-40 14.5t-33.5 33.5l-29 38q-121 158 -143.5 185.5t-34.5 27.5q-8 -2 -15 -8t-47 -54l-126 -155 q-18 -20 -31.5 -37.5t-30 -29t-34.5 -11.5q-20 0 -33 13.5t-13 31.5z" />
+<glyph unicode="_" horiz-adv-x="1079" d="M55 -94q0 51 29 51h913q29 0 29 -51v-4q0 -57 -29 -58h-913q-29 0 -29 54v8z" />
+<glyph unicode="`" d="M16 1360q0 33 22.5 54.5t53.5 21.5h2q57 0 113 -86l184 -274q31 -46 31 -64q0 -16 -11.5 -28.5t-27.5 -12.5h-4q-12 0 -27.5 12t-81.5 79l-202 206q-52 51 -52 92z" />
+<glyph unicode="a" horiz-adv-x="866" d="M59 707q0 59 97.5 120.5t218.5 61.5q39 0 79 -8.5t90 -29t85 -69.5t43 -118q4 -49 4 -74v-404q0 -37 14.5 -58.5t27.5 -26.5t27 -5q37 0 57.5 34t33.5 34q18 0 18 -27q0 -47 -43 -104.5t-115 -57.5q-31 0 -60.5 13.5t-45 28t-27.5 28.5l-12 14q-2 0 -2 1t-2 1q-4 0 -7 -3 l-14.5 -15t-33.5 -27q-88 -57 -191 -57q-104 0 -168.5 66.5t-64.5 162.5v2q0 115 86 183q39 31 102 52t117.5 29.5t97.5 12.5l43 4q16 4 16 29v73q0 106 -49 164q-51 55 -119 56q-109 0 -176 -138q-16 -23 -45 -22q- [...]
+<glyph unicode="b" horiz-adv-x="995" d="M8 1343q0 16 27 27q227 90 233 90q29 -4 29 -41q0 -68 -3 -328t-3 -282q0 -12 8 -12q4 0 38 21.5t98.5 42t142.5 20.5q180 0 289.5 -125t109.5 -328q0 -78 -18.5 -150.5t-84 -154.5t-169.5 -121q-106 -41 -230 -41q-53 0 -112.5 19.5t-86.5 19.5q-35 0 -62.5 -21.5 t-39.5 -21.5q-33 0 -33 61q0 121 3 600.5t3 598.5q0 29 -24 45l-91.5 56t-23.5 25zM283 133q0 -37 28 -49q94 -39 189 -39q156 0 252 96.5t96 251.5q0 166 -102.5 272.5t-239.5 106.5q-72 0 -146.5 -33.5t-74.5 -66.5v-525 [...]
+<glyph unicode="c" horiz-adv-x="780" d="M35 403q0 209 120.5 341.5t317.5 132.5q109 0 184.5 -46.5t75.5 -105.5q0 -35 -24.5 -56.5t-57.5 -21.5q-45 0 -114.5 61.5t-133.5 61.5q-94 0 -163.5 -93t-69.5 -222q0 -145 92 -253t232 -108q70 0 122 28t81.5 55.5t45.5 27.5q14 0 24.5 -10.5t10.5 -24.5 q0 -16 -12 -33q-55 -74 -142 -124t-196 -50q-174 0 -283.5 125t-109.5 315z" />
+<glyph unicode="d" horiz-adv-x="1011" d="M35 424q0 180 114.5 311t339.5 131h3q59 0 111 -7t81 -15l29 -8q14 0 14 18v344q0 16 -4 24.5t-16.5 16.5t-36.5 17l-66 26q-39 10 -39 33q0 10 19 22q254 125 264 125q25 0 24 -28q0 -18 -2 -104.5t-3 -236t-1 -323.5q0 -547 6 -602q0 -14 9.5 -19.5t30 -6.5t57.5 -3 q39 0 39 -28q0 -14 -10.5 -21.5t-46.5 -24t-64 -32.5q-39 -20 -72 -44t-47 -35t-23 -11q-16 0 -16 20v68q0 6 -4 6l-18 -12q-18 -12 -45 -27.5t-76 -28t-105 -12.5q-197 0 -321.5 135t-124.5 332zM172 442q0 -174 115. [...]
+<glyph unicode="e" horiz-adv-x="837" d="M45 422q0 209 109.5 335t269.5 126q100 0 195.5 -56.5t156.5 -140.5q16 -20 17 -45v-2q0 -39 -60.5 -66.5t-105.5 -35.5q-317 -106 -377 -128t-60 -34q0 -18 12.5 -58.5t41 -97.5t94 -99t156.5 -42q139 0 243 100q29 29 47 29q33 0 33 -31q0 -16 -14 -33 q-66 -84 -161 -133t-202 -49q-53 0 -105 14.5t-105.5 48t-93.5 85t-65.5 132.5t-25.5 181zM182 477q0 -14 11 -14q4 0 190 72.5t192 74.5q18 8 19 25q0 27 -69.5 81t-145.5 54q-90 0 -143.5 -79t-53.5 -214z" />
+<glyph unicode="f" horiz-adv-x="598" d="M20 774q0 61 43 62q76 0 90.5 2t14.5 18v2q6 250 88 393q59 100 167.5 162t207.5 62q76 0 111.5 -34t35.5 -73q0 -31 -23.5 -55.5t-62.5 -24.5q-29 0 -83 24.5t-87 24.5q-104 0 -157.5 -126t-53.5 -318v-19q0 -20 3 -26t18 -6h200q45 0 46 -41v-2q0 -63 -54 -64h-192 q-18 0 -19 -16v-588v-6q0 -47 41 -49q72 -2 94.5 -7.5t22.5 -35.5q0 -45 -33 -45l-26 4q-27 2 -71 5t-87 3q-45 0 -89 -3t-71 -5l-26 -4q-31 0 -31 51q0 16 8 22.5t29.5 9.5t58.5 9q12 2 19.5 8t9.5 14.5t2 18.5v8q8 102 [...]
+<glyph unicode="g" horiz-adv-x="901" d="M45 567q0 131 95.5 225.5t236.5 94.5q86 0 167 -37t91 -37q61 0 106 66q29 47 60 47q29 0 53.5 -27t24.5 -57q0 -35 -31 -61.5t-73 -43t-44 -18.5q-8 -8 -8 -17q0 -4 5 -20t11 -45t6 -64q0 -143 -98 -243.5t-241 -100.5q-39 0 -75 9.5t-44 9.5q-29 0 -60.5 -36t-31.5 -69 q0 -53 86 -71.5t222 -22.5t193 -20q92 -27 139.5 -90.5t47.5 -137.5q0 -106 -99.5 -193t-326.5 -87q-96 0 -170 18.5t-117 45t-69.5 63.5t-36 67.5t-9.5 63.5q0 29 8.5 56.5t19.5 45t25.5 33.5t24.5 24.5t19 12.5l10 [...]
+<glyph unicode="h" horiz-adv-x="1052" d="M25 1303q0 23 32 38q225 131 236 132h2q31 0 31 -39l-2 -631q0 -14 10 -15q2 0 33.5 19.5t89 38t118.5 18.5q195 0 275 -186q31 -74 42 -169t17 -374q0 -20 4.5 -32.5t15.5 -19.5t21.5 -9t34.5 -4q35 -4 35 -37q0 -45 -27 -45l-26 4q-25 2 -70 5t-90 3q-43 0 -87 -3 t-71 -5l-26 -4q-23 0 -23 28v15q0 29 24.5 35t92.5 12q31 4 36 30.5t5 147.5q0 201 -25.5 290t-73.5 140q-74 74 -165 74q-61 0 -115.5 -34t-63.5 -67q-2 -8 -2 -26q0 -492 4 -506q6 -29 31 -41t52.5 -12t49 -9.5t21.5 - [...]
+<glyph unicode="i" horiz-adv-x="497" d="M31 753.5q0 16.5 19.5 28t35.5 15.5q221 106 225 106h2q29 0 29 -33l-2 -65q-4 -66 -7 -177.5t-3 -221.5v-68q0 -186 6 -222t41 -40q33 -4 53.5 -7t29.5 -11.5t9 -24.5q0 -45 -25 -45l-26 4q-27 2 -72 5t-90 3t-90 -3t-72 -5l-26 -4q-31 0 -31 35q0 33 12 39t88 16 q35 6 45.5 23.5t10.5 50.5v96v193q0 89 1 140.5t1 61.5q0 16 -7.5 24.5t-38 21.5t-94.5 38q-24 10 -24 26.5zM213 1266q0 39 28.5 67.5t69.5 28.5t70 -27.5t29 -66.5q0 -41 -30 -70t-71 -29t-68.5 28t-27.5 69z" />
+<glyph unicode="j" horiz-adv-x="475" d="M-74 -403q0 33 24.5 60.5t65.5 27.5q12 0 32 -3.5t30 -3.5q25 0 47 9.5t46 48.5t24 104q0 10 -1 57.5t-1 131.5v180q0 115 1 213t2 153.5t1 67.5q0 23 -7.5 34t-35 29.5t-80.5 49.5q-18 10 -19 24q0 10 9.5 17.5t64.5 30.5l172 73q8 4 14 4q20 0 21 -33q0 -10 -1 -60 t-2 -138t-1 -193q0 -162 2 -301t4 -218t2 -95q0 -43 -31 -90q-29 -41 -65.5 -85t-110.5 -104.5t-129 -60.5q-33 0 -55.5 19.5t-22.5 50.5zM213 1237q0 41 28.5 68.5t69.5 27.5t70 -27.5t29 -66.5t-30 -67.5t-71 -28.5t-6 [...]
+<glyph unicode="k" horiz-adv-x="929" d="M10 1350q0 20 41 34q195 86 203 86q23 0 22 -34v-967q0 -8 7 -8q8 0 12 8q137 135 170 172t33 69.5t-27 54t-27 32.5v20q0 27 43 27h119q59 0 110.5 2t80 3t34.5 1q31 0 31 -39q0 -25 -10 -32t-47 -11t-62 -10q-43 -12 -93 -48t-82 -68l-122 -124q-14 -14 -14 -18 q0 -6 30 -42l208 -249q35 -43 57.5 -65.5t64.5 -47t87 -30.5q33 -4 32 -35q0 -43 -32 -43l-27 4l-76 5t-94 3t-94 -3l-76 -5l-27 -4q-27 0 -26 35v2q0 27 15 37t32.5 10t33 7t15.5 27q0 29 -96.5 156t-114.5 146q0 4 -8 4t- [...]
+<glyph unicode="l" horiz-adv-x="489" d="M23 1329v2q0 10 32.5 28.5t218.5 113.5q12 8 25 8q29 0 29 -39v-1297q0 -25 5 -38t16 -19t31.5 -9t51.5 -9q35 -6 35 -41q0 -41 -25 -41l-28 4q-27 2 -73 5t-91 3q-43 0 -87 -2t-71 -6l-26 -2q-29 0 -29 37v6q0 27 12 33t72 12q37 4 47 22.5t10 55.5v1042q0 14 -4 22.5 t-15.5 13.5t-27.5 15q-61 35 -84.5 50.5t-23.5 29.5z" />
+<glyph unicode="m" horiz-adv-x="1480" d="M45 33q0 20 16.5 28.5t38 9.5t40 13t20.5 39v508q0 20 -4 29.5t-22.5 24.5t-55.5 42q-18 12 -18.5 24.5t20 27t145.5 91.5q33 18 39 19q18 0 19 -25v-78q0 -12 8 -12q2 0 31.5 22.5t82 45t107.5 22.5q37 0 73 -11t61.5 -27.5t45 -33t29.5 -28.5l12 -12q2 -2 8 -2 q4 0 7.5 1t8.5 5t11 10t23 16l36 23q102 59 199 59q90 0 167 -53t110 -170q23 -78 22 -240v-260q0 -33 8 -45t29.5 -18t60.5 -12q29 -4 29 -37q0 -41 -31 -41q-4 0 -26.5 3t-61.5 6t-84 3t-85 -3t-62.5 -6t-26.5 -3q-33 0 - [...]
+<glyph unicode="n" horiz-adv-x="1021" d="M23 25q0 29 12 35t67 14q35 6 44.5 21.5t9.5 47.5v490q0 35 -10.5 48t-82.5 67q-12 12 -12 20v2q0 10 25.5 25.5t169.5 91.5q12 8 20 8q25 0 25 -31v-80v-6l-2 -6q0 -8 6 -8h2l22 18l55 42t87 43.5t117 19.5h4q41 0 82 -11.5t89 -40t79.5 -91t39.5 -152.5q4 -35 5 -105 v-38q0 -31 -1.5 -111t-1.5 -205v-4q0 -20 5.5 -32.5t17.5 -17.5t30.5 -7t45.5 -6q29 -4 28 -37q0 -41 -30 -41q-6 0 -27.5 3t-60.5 6t-84 3q-41 0 -81 -3t-63 -5l-24 -4q-29 0 -29 41q0 18 9.5 25t33 11.5t64.5 10.5q [...]
+<glyph unicode="o" horiz-adv-x="956" d="M43 418q0 207 131 337t311 130q184 0 306 -131t122 -336q0 -211 -127 -334t-309 -123q-193 0 -313.5 132t-120.5 325zM203 428q0 -162 77.5 -264.5t202.5 -102.5q127 0 209 103.5t82 245.5q0 160 -91 269t-212 109q-100 0 -184 -88t-84 -272z" />
+<glyph unicode="p" horiz-adv-x="1011" d="M27 -426q0 25 23.5 33t94.5 20q45 8 45 58v946v4q0 31 -26 41q-100 43 -118.5 52t-18.5 20v2q0 8 28 25l191 112q33 16 35 16q16 0 16 -22v-121q0 -12 6 -12l27 28q27 29 83 61.5t126 43.5q16 2 47 2q168 0 277.5 -130t109.5 -313q0 -203 -136.5 -328.5t-351.5 -125.5 q-31 0 -62.5 3t-49.5 7l-19 2q-14 0 -14 -23v-280v-6q0 -49 45 -54q92 -4 128 -12t36 -51q0 -31 -25 -31q-4 0 -29.5 2t-68.5 4t-94 2q-66 0 -131.5 -4t-102.5 -8l-39 -4q-32 0 -32 41zM324 152q0 -39 53 -64q66 -33 1 [...]
+<glyph unicode="q" horiz-adv-x="1075" d="M33 436q0 78 29.5 154t91 144.5t172 111.5t254.5 43q76 0 153.5 -13.5t79.5 -13.5q35 0 53.5 25.5t24.5 25.5q23 0 22 -112q0 -8 1 -26.5t1 -29.5v-1030q0 -61 21.5 -77.5t91.5 -24.5q29 -6 29 -29q0 -45 -37 -45l-37 2q-35 2 -76 2q-70 0 -136 -6t-103 -12l-37 -6 q-37 0 -37 37q0 20 12 29t38 14.5t63 11.5q59 12 59 82v352q0 14 -12 14q-4 0 -37 -19.5t-94.5 -38.5t-133.5 -19q-186 0 -321 133t-135 321zM180 477q0 -156 113 -263.5t266 -107.5q55 0 112.5 17.5t78.5 36.5q18 18 18  [...]
+<glyph unicode="r" horiz-adv-x="733" d="M25 23q0 31 25.5 39t66.5 12q37 8 37 49v543q0 27 -20.5 43t-92.5 65q-6 6 -8 14q0 6 27 20l188 91l18 6q25 0 25 -41v-82q0 -10 6 -10q2 0 91 60.5t122 72.5q25 8 59 8q55 0 107.5 -25.5t52.5 -64.5v-2q-2 -23 -22.5 -44t-32.5 -27q-12 -10 -37 -25.5t-47 -15.5 q-25 0 -55.5 25.5t-65.5 25.5q-43 0 -94 -32t-66 -52q-8 -12 -8 -37v-492v-8q0 -57 51 -61q59 -4 93 -7t45.5 -11.5t11.5 -30.5q0 -41 -29 -41l-31 4q-29 2 -78 5t-98 3q-51 0 -101 -3t-79 -5l-29 -4q-32 0 -32 35z" />
+<glyph unicode="s" horiz-adv-x="692" d="M53 256q0 39 7.5 51t30 12t27.5 -18t7 -52t12 -56q18 -39 86 -80t148 -41q70 0 118 37.5t48 99t-49.5 101.5t-103.5 49.5t-93 23.5q-227 66 -228 250q0 96 81 168.5t214 72.5q27 0 50.5 -3t37 -5t15.5 -2q8 0 23.5 10.5t27.5 10.5q25 0 33 -39l22 -122q16 -89 17 -93 q0 -33 -47 -33q-18 0 -28.5 15.5t-19 43t-18.5 41.5q-23 31 -72 55.5t-96 24.5q-53 0 -91 -30.5t-38 -77.5q0 -102 162 -148q70 -12 148.5 -38.5t127.5 -84.5q61 -72 62 -161q0 -106 -84 -191.5t-228 -85.5q-78 0 -159.5 [...]
+<glyph unicode="t" horiz-adv-x="681" d="M41 774q0 12 28.5 37t83 83t101.5 140q23 37 41 37q27 0 27 -33q0 -14 -1.5 -71.5t-1.5 -71.5q0 -41 41 -41h185q4 0 8 -1t8 -1q53 0 53 -39q0 -37 -18 -59q-10 -10 -37 -11h-240q-20 0 -20 -18q-2 -383 -2 -479q0 -152 104 -152q55 0 131 61.5t92.5 61.5t27 -11 t10.5 -26q0 -12 -15 -35q-162 -184 -285 -184q-74 0 -135 59.5t-71 190.5q-2 23 -2 65q0 51 4 244t4 209q0 18 -15 19h-65q-41 -1 -41 26z" />
+<glyph unicode="u" horiz-adv-x="1034" d="M14 815v6q0 27 23 29q205 12 213 12q20 0 20 -24v-420q0 -137 37 -211q29 -55 85.5 -96t131.5 -41q100 0 174 73q35 39 35 62v504q0 20 -6 32.5t-21.5 18.5t-42 11t-65.5 11q-31 6 -31 33q0 31 29 35q66 2 119 4t73.5 3t35.5 1h24q31 0 31 -41v-641q0 -16 17 -24.5 t85 -36.5q16 -6 16 -24.5t-4 -26t-18 -12.5t-33.5 -9t-60.5 -20.5t-88 -42.5q-12 -8 -23 -9q-29 0 -29 41v47q0 8 -6 9l-37 -27q-37 -25 -104.5 -51.5t-142.5 -26.5q-125 0 -210 79t-104 218q-6 61 -6 125q0 37 1 177t1 1 [...]
+<glyph unicode="v" horiz-adv-x="1003" d="M4 823.5q0 26.5 25 26.5q6 0 30.5 -1t68.5 -3t95 -2q53 0 97.5 2t69 3t30.5 1q29 0 29 -41q0 -23 -10.5 -30t-47.5 -8t-57 -5q-41 -4 -41 -37q0 -29 73.5 -208t170.5 -343l2 -2q8 -14 16 -14q10 0 10 10q100 174 148.5 342t48.5 221q0 18 -14.5 26.5t-41 9.5t-65.5 5h-4 q-27 6 -27 35v10q0 29 25 29q4 0 25.5 -1t58.5 -3t80 -2t79.5 2t58 3t26.5 1q31 0 30 -39q0 -37 -50 -40t-62 -21q-4 -8 -13 -41q-70 -252 -168 -480.5t-129 -261.5q-14 -18 -39 -18q-35 0 -67 63q-156 276 -259.5 5 [...]
+<glyph unicode="w" horiz-adv-x="1540" d="M12 815q0 35 37 35q4 0 23.5 -1t54.5 -3t74 -2h6q39 0 71.5 2t52 3t23.5 1q25 0 25 -35q0 -25 -19.5 -35t-44 -8t-44 -4t-19.5 -27q0 -14 12 -39q96 -256 230 -514q8 -16 20 -16q8 0 14.5 7t6.5 9q57 90 120.5 212t65.5 147v2q0 10 -35 85t-43 87q-16 27 -45 37t-51.5 9 t-40 6t-17.5 30q0 47 33 47q6 0 33 -1t75 -3t103 -2t103.5 2t75 3t32.5 1q29 0 29 -31v-12q0 -16 -5 -21.5t-32 -8.5t-82 -7q-47 -4 -47 -43q0 -33 82 -205t174 -319q16 -29 33 -29q18 0 24 19q94 166 146.5 329.5t5 [...]
+<glyph unicode="x" horiz-adv-x="907" d="M18 33q0 23 16.5 31t41 11t37.5 11q4 2 18 23l88 114l65 84l42 54q20 26 26 35.5t12.5 17.5t6.5 9v5q0 6 -9 14q-129 166 -190 238t-71.5 79t-41.5 11q-37 4 -36 45q0 35 26 35q4 0 25.5 -1t59.5 -3t83 -2t84 2t60.5 3t25.5 1q25 0 25 -29v-4q0 -4 1 -10t1 -8 q0 -12 -6.5 -17.5t-22.5 -7.5t-45 -4q-33 -4 -33 -29q0 -8 29 -49l49 -64l34 -44l19 -26q8 -11 11.5 -14t5.5 -4t4 -1q4 0 10 6q143 190 143 200q0 23 -50 26t-50 28q0 51 27 51q4 0 22.5 -1t51 -3t71.5 -2h6q39 0 73 2t53.5 3t [...]
+<glyph unicode="y" horiz-adv-x="958" d="M8 815q0 35 29 35q4 0 24.5 -1t56.5 -3t79 -2t78.5 2t57 3t25.5 1q27 0 27 -33q0 -16 -3 -25.5t-11.5 -13.5t-23.5 -5t-38 -3q-31 -4 -30 -29q0 -20 65.5 -175.5t157.5 -327.5q0 -12 14 -13q8 0 16 15q2 4 5 6q168 401 168 481q0 23 -10.5 33t-33 11t-55.5 3 q-39 4 -39 39q0 37 39 37q4 0 24.5 -1t56.5 -3t79 -2h2q41 0 77 2t55.5 3t23.5 1q25 0 24 -41q0 -23 -11 -28t-69 -11q-14 -2 -19 -4t-15.5 -24.5t-19.5 -52.5t-40 -109l-67 -172q-199 -483 -367 -738q-82 -127 -152 -127q-33 0  [...]
+<glyph unicode="z" horiz-adv-x="739" d="M25 47q0 18 26 62l418 563q12 12 12 26q0 29 -41 29h-243q-14 0 -20.5 -6t-11.5 -26.5t-13 -59.5q-10 -33 -35 -33q-37 0 -37 27l6 26q4 29 9 79t5 104v61q0 31 33 31h12q23 0 27 -38t31 -38h446q45 0 45 -31q0 -4 -12 -28l-406 -550q-59 -81 -59 -89q0 -23 33 -23h297 q6 0 17 -1t14 -1q18 0 26 9.5t13.5 37l15.5 78.5q10 33 35 33q49 0 49 -35l-6 -41q-6 -39 -13.5 -109.5t-7.5 -142.5q0 -39 2 -76v-35q0 -41 -61 -40q-35 0 -35 36v123q0 31 -35 31h-475q-61 0 -61 47z" />
+<glyph unicode="{" horiz-adv-x="514" d="M92 524q0 2 30 18.5t60.5 64.5t30.5 128q0 78 -27.5 229.5t-27.5 235.5q0 145 67.5 210t151.5 65q49 0 49 -11q0 -2 -22.5 -13t-53.5 -43t-47 -77q-14 -43 -14 -94q0 -55 27.5 -183t27.5 -212q0 -86 -23.5 -162t-47 -117t-23.5 -43q0 -4 22.5 -36.5t44 -96t21.5 -141.5 q0 -68 -28.5 -197t-28.5 -192q0 -66 20.5 -119t45 -79t44.5 -42l21 -16q0 -6 -33 -7q-86 0 -157.5 69t-71.5 220q0 82 32.5 220.5t32.5 199.5q0 47 -11 85t-29.5 61.5t-35 39t-30.5 23.5l-15 8q-2 2 -2 4z" />
+<glyph unicode="|" horiz-adv-x="313" d="M102 -379v1823q0 27 50 26h4q55 0 55 -26v-1823q0 -27 -53 -27h-8q-48 0 -48 27z" />
+<glyph unicode="}" horiz-adv-x="514" d="M94 1464q0 10 49 11q84 0 151.5 -64.5t67.5 -210.5q0 -84 -27.5 -235.5t-27.5 -229.5q0 -49 11.5 -87t29 -59.5t32.5 -33.5t30 -18l16 -7q2 -2 2 -4q0 -8 -8 -10q-115 -63 -115 -213q0 -61 33 -199.5t33 -220.5q0 -152 -72 -220.5t-158 -68.5q-33 0 -32 7l20 16 q20 16 45 42t45.5 79t20.5 119q0 63 -29 192t-29 197q0 78 21.5 141.5t44 96t22.5 36.5t-8 21q-86 135 -86 301q0 84 27.5 212t27.5 183q0 63 -21.5 110.5t-47 68t-47 33.5t-21.5 15z" />
+<glyph unicode="~" horiz-adv-x="923" d="M49 395q0 8 45 79t76 101q59 63 135 64q59 0 153.5 -59.5t153.5 -59.5q51 0 95.5 27.5t74 61.5t31.5 34q8 4 12 4q10 0 29.5 -11t19.5 -26q0 -12 -38.5 -66.5t-114.5 -111.5t-154 -57q-74 0 -158.5 60.5t-136.5 60.5q-90 0 -176 -131q-6 -10 -14 -10.5t-20.5 15 t-12.5 25.5z" />
+<glyph unicode="&#xa9;" horiz-adv-x="1581" d="M61 680q0 299 212 515t518 216q303 0 516 -216t213 -515q0 -297 -211 -513t-521 -216q-297 0 -512 212t-215 517zM166 680q0 -262 185.5 -443.5t439 -181.5t439 180.5t185.5 446.5q0 254 -181 438.5t-446 184.5q-260 0 -441 -184.5t-181 -440.5zM309 655 q0 197 142.5 338.5t343.5 141.5q76 0 134 -16.5t88 -34t36 -17.5q4 0 14 23.5t35 23.5q20 0 24 -20q35 -238 35 -273q0 -18 -6 -26.5t-29 -8.5q-20 0 -28 14.5t-8 34t-8.5 49t-26.5 54.5q-102 127 -264 127q-137 0 -242 -105.5 [...]
+<glyph unicode="&#xad;" d="M25 369v28q0 20 7 29.5t31 28.5l282 197q50 34 63 34q33 0 32 -80q0 -29 -37 -57l-173 -123l-103 -75l-40 -26.5t-26 -9.5q-36 1 -36 54z" />
+<glyph unicode="&#xae;" horiz-adv-x="1062" d="M102 1114q0 180 125 306t301 126q180 0 306.5 -126t126.5 -306q0 -176 -127 -302t-306 -126q-176 0 -301 126t-125 302zM174 1114q0 -143 105.5 -247.5t248.5 -104.5q147 0 253 104.5t106 247.5q0 147 -105.5 253t-253.5 106q-143 0 -248.5 -106t-105.5 -253zM291 1356 q0 18 16 18h25q35 0 88 5t76 5q92 0 134 -42t42 -93q0 -49 -30 -82.5t-56 -44.5q59 -68 119 -164q25 -45 53 -45q8 0 16 8.5t17 8.5q12 0 12 -15q0 -12 -20.5 -34.5t-49.5 -22.5q-45 0 -82 55l-135 187q-4 10 -1 [...]
+<glyph unicode="&#xb4;" d="M31 1012q0 14 9 30.5t56 86.5l150 221q55 86 112 86q31 0 53.5 -21.5t22.5 -54.5q0 -39 -49 -92q-266 -272 -285 -287q-14 -10 -30 -10q-18 0 -28.5 12.5t-10.5 28.5z" />
+<glyph unicode="&#x2000;" horiz-adv-x="772" />
+<glyph unicode="&#x2001;" horiz-adv-x="1546" />
+<glyph unicode="&#x2002;" horiz-adv-x="772" />
+<glyph unicode="&#x2003;" horiz-adv-x="1546" />
+<glyph unicode="&#x2004;" horiz-adv-x="514" />
+<glyph unicode="&#x2005;" horiz-adv-x="385" />
+<glyph unicode="&#x2006;" horiz-adv-x="256" />
+<glyph unicode="&#x2007;" horiz-adv-x="256" />
+<glyph unicode="&#x2008;" horiz-adv-x="192" />
+<glyph unicode="&#x2009;" horiz-adv-x="309" />
+<glyph unicode="&#x200a;" horiz-adv-x="83" />
+<glyph unicode="&#x2010;" d="M25 369v28q0 20 7 29.5t31 28.5l282 197q50 34 63 34q33 0 32 -80q0 -29 -37 -57l-173 -123l-103 -75l-40 -26.5t-26 -9.5q-36 1 -36 54z" />
+<glyph unicode="&#x2011;" d="M25 369v28q0 20 7 29.5t31 28.5l282 197q50 34 63 34q33 0 32 -80q0 -29 -37 -57l-173 -123l-103 -75l-40 -26.5t-26 -9.5q-36 1 -36 54z" />
+<glyph unicode="&#x2012;" d="M25 369v28q0 20 7 29.5t31 28.5l282 197q50 34 63 34q33 0 32 -80q0 -29 -37 -57l-173 -123l-103 -75l-40 -26.5t-26 -9.5q-36 1 -36 54z" />
+<glyph unicode="&#x2013;" horiz-adv-x="1079" d="M55 512v8q0 51 29 51h913q29 0 29 -51v-4q0 -57 -29 -57h-913q-29 0 -29 53z" />
+<glyph unicode="&#x2014;" horiz-adv-x="2187" d="M55 512v8q0 51 29 51h2021q29 0 29 -51v-4q0 -33 -6 -45t-23 -12h-2021q-29 0 -29 53z" />
+<glyph unicode="&#x2018;" d="M80 1180q0 109 41 168t74 59q39 -4 38 -41q0 -10 -36.5 -52t-36.5 -85q0 -31 20.5 -54.5t67.5 -23.5q6 0 18.5 1t18.5 1q55 0 78.5 -27.5t23.5 -60.5q0 -43 -36 -79t-95 -36q-66 0 -121 56.5t-55 173.5z" />
+<glyph unicode="&#x2019;" d="M80 1286q0 43 35 79t94 36q66 0 122 -56.5t56 -173.5q0 -109 -42 -167t-75 -58q-16 0 -27.5 11.5t-11.5 27.5q0 10 37 53t37 86q0 29 -20.5 52.5t-67.5 23.5q-6 0 -18.5 -1t-18.5 -1q-55 0 -77.5 27.5t-22.5 60.5z" />
+<glyph unicode="&#x201c;" horiz-adv-x="851" d="M78 1180q0 109 42 168t75 59q39 -4 38 -41q0 -10 -36.5 -52t-36.5 -85q0 -78 88 -78q6 0 18.5 1t18.5 1q55 0 77.5 -27.5t22.5 -60.5q0 -43 -35 -79t-94 -36q-66 0 -122 56.5t-56 173.5zM467 1180q0 109 42 168t75 59q39 -4 39 -41q0 -10 -37 -52t-37 -85q0 -78 88 -78 q6 0 18.5 1t18.5 1q55 0 77.5 -27.5t22.5 -60.5q0 -43 -34.5 -79t-94.5 -36q-66 0 -122 56.5t-56 173.5z" />
+<glyph unicode="&#x201d;" horiz-adv-x="851" d="M78 1286q0 43 36 79t95 36q66 0 121 -56.5t55 -173.5q0 -106 -41 -165.5t-74 -59.5h-2q-14 0 -25.5 12.5t-11.5 26.5q0 10 36 53t36 86q0 76 -88 76q-6 0 -17.5 -1t-17.5 -1q-55 0 -78.5 27.5t-23.5 60.5zM467 1286q0 43 36 79t95 36q66 0 121 -56.5t55 -173.5 q0 -106 -41 -165.5t-74 -59.5h-2q-14 0 -25 12.5t-11 26.5q0 10 35.5 53t35.5 86q0 76 -88 76q-6 0 -17.5 -1t-17.5 -1q-55 0 -78.5 27.5t-23.5 60.5z" />
+<glyph unicode="&#x2022;" horiz-adv-x="585" d="M129 549q0 70 49 117t115 47q70 0 117 -49.5t47 -114.5q0 -70 -49.5 -117t-114.5 -47q-70 0 -117 49t-47 115z" />
+<glyph unicode="&#x2026;" horiz-adv-x="1394" d="M1041 88q0 51 35.5 85t85 34t86 -36t36.5 -85t-34.5 -85t-86.5 -36q-49 0 -85.5 35t-36.5 88zM576 88q0 51 35.5 85t85 34t86 -36t36.5 -85t-34.5 -85t-86.5 -36q-49 0 -85.5 35t-36.5 88zM111 88q0 51 35.5 85t85 34t86 -36t36.5 -85t-34.5 -85t-86.5 -36 q-49 0 -85.5 35t-36.5 88z" />
+<glyph unicode="&#x202f;" horiz-adv-x="309" />
+<glyph unicode="&#x205f;" horiz-adv-x="385" />
+<glyph unicode="&#x20ac;" horiz-adv-x="1460" d="M41 707l51 124h172q41 139 122 244t176 159t183.5 79.5t165.5 25.5q154 0 274 -47t234 -157l-57 -129q-14 23 -45 52t-84 68t-135 65t-174 26q-156 0 -305.5 -92.5t-223.5 -293.5h895l-51 -124h-870q0 -4 -1 -20.5t-1 -29.5q0 -14 1 -30.5t1 -20.5h827l-53 -127h-748 q43 -129 137.5 -220t192.5 -128t195 -37q45 0 90 6t80.5 18.5t68.5 26t60.5 31t49 32.5t39 30.5t28 26.5t16.5 20l8 8l8 -2v-160q-201 -160 -440 -160q-92 0 -184.5 26t-186.5 81t-172 158.5t-121 242.5h-215l51 [...]
+<glyph unicode="&#x2122;" horiz-adv-x="1882" d="M86 1300l29 140q6 16 24 16h582q18 0 22.5 -13t22.5 -130l2 -4q2 -4 2 -6q0 -12 -8 -19.5t-16.5 -7.5t-28.5 20q-20 39 -31.5 58.5t-17.5 23.5t-21 4h-147q-16 0 -17 -22v-520q0 -8 1 -12.5t13.5 -6.5t23.5 -3t48 -3q14 -2 17.5 -8t3.5 -25q0 -25 -21 -24q-4 0 -20.5 2 t-46 3t-64.5 1h-4q-37 0 -67.5 -1t-47 -3t-20.5 -2q-25 0 -25 30q0 14 7.5 20.5t25 7.5t45.5 3q29 4 29 33v504q0 27 -21 26h-151q-20 0 -26.5 -9t-43.5 -81q0 -6 -7 -14t-21 -8q-25 -1 -25 30zM815 784q0 16  [...]
+<glyph unicode="&#xe000;" horiz-adv-x="850" d="M0 850h850v-850h-850v850z" />
+<glyph unicode="&#xfb01;" horiz-adv-x="1095" d="M629 753.5q0 16.5 19.5 28t35.5 15.5q221 106 225 106h2q29 0 29 -33l-2 -65q-4 -66 -7 -177.5t-3 -221.5v-68q0 -186 6 -222t41 -40q33 -4 53.5 -7t29.5 -11.5t9 -24.5q0 -45 -25 -45l-26 4q-27 2 -72 5t-90 3t-90 -3t-72 -5l-26 -4q-31 0 -31 35q0 33 12 39t88 16 q35 6 45.5 23.5t10.5 50.5v96v193q0 89 1 140.5t1 61.5q0 16 -7.5 24.5t-38 21.5t-94.5 38q-24 10 -24 26.5zM811 1266q0 39 28.5 67.5t69.5 28.5t70 -27.5t29 -66.5q0 -41 -30 -70t-71 -29t-68.5 28t-27.5 69zM2 [...]
+<glyph unicode="&#xfb02;" horiz-adv-x="1087" d="M621 1329v2q0 10 32.5 28.5t218.5 113.5q12 8 25 8q29 0 29 -39v-1297q0 -25 5 -38t16 -19t31.5 -9t51.5 -9q35 -6 35 -41q0 -41 -25 -41l-28 4q-27 2 -73 5t-91 3q-43 0 -87 -2t-71 -6l-26 -2q-29 0 -29 37v6q0 27 12 33t72 12q37 4 47 22.5t10 55.5v1042q0 14 -4 22.5 t-15.5 13.5t-27.5 15q-61 35 -84.5 50.5t-23.5 29.5zM20 774q0 61 43 62q76 0 90.5 2t14.5 18v2q6 250 88 393q59 100 167.5 162t207.5 62q76 0 111.5 -34t35.5 -73q0 -31 -23.5 -55.5t-62.5 -24.5q-29 0 -83 [...]
+<glyph unicode="&#xfb03;" horiz-adv-x="1693" d="M1227 753.5q0 16.5 19.5 28t35.5 15.5q221 106 225 106h2q29 0 29 -33l-2 -65q-4 -66 -7 -177.5t-3 -221.5v-68q0 -186 6 -222t41 -40q33 -4 53.5 -7t29.5 -11.5t9 -24.5q0 -45 -25 -45l-26 4q-27 2 -72 5t-90 3t-90 -3t-72 -5l-26 -4q-31 0 -31 35q0 33 12 39t88 16 q35 6 45.5 23.5t10.5 50.5v96v193q0 89 1 140.5t1 61.5q0 16 -7.5 24.5t-38 21.5t-94.5 38q-24 10 -24 26.5zM1409 1266q0 39 28.5 67.5t69.5 28.5t70 -27.5t29 -66.5q0 -41 -30 -70t-71 -29t-68.5 28t-27.5 69z [...]
+<glyph unicode="&#xfb04;" horiz-adv-x="1685" d="M1219 1329v2q0 10 32.5 28.5t218.5 113.5q12 8 25 8q29 0 29 -39v-1297q0 -25 5 -38t16 -19t31.5 -9t51.5 -9q35 -6 35 -41q0 -41 -25 -41l-28 4q-27 2 -73 5t-91 3q-43 0 -87 -2t-71 -6l-26 -2q-29 0 -29 37v6q0 27 12 33t72 12q37 4 47 22.5t10 55.5v1042q0 14 -4 22.5 t-15.5 13.5t-27.5 15q-61 35 -84.5 50.5t-23.5 29.5zM618 774q0 61 43 62q76 0 90.5 2t14.5 18v2q6 250 88 393q59 100 167.5 162t207.5 62q76 0 111.5 -34t35.5 -73q0 -31 -23.5 -55.5t-62.5 -24.5q-29 0 - [...]
+</font>
+</defs></svg> 
\ No newline at end of file
diff --git a/lib/plugins/captcha/fonts/ostrich-sans-black.svg b/lib/plugins/captcha/fonts/ostrich-sans-black.svg
new file mode 100644
index 0000000..5001bbc
--- /dev/null
+++ b/lib/plugins/captcha/fonts/ostrich-sans-black.svg
@@ -0,0 +1,141 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG webfont generated by Font Squirrel.
+Copyright   : Copyright c 2011 by Tyler Finck All rights reserved
+Designer    : Tyler Finck
+Foundry     : Tyler Finck
+Foundry URL : httpwwwsurslycom
+</metadata>
+<defs>
+<font id="OstrichSansBlack" horiz-adv-x="1705" >
+<font-face units-per-em="2048" ascent="1536" descent="-512" />
+<missing-glyph horiz-adv-x="630" />
+<glyph unicode=" "  horiz-adv-x="630" />
+<glyph unicode="&#x09;" horiz-adv-x="630" />
+<glyph unicode="&#xa0;" horiz-adv-x="630" />
+<glyph unicode="!" horiz-adv-x="299" d="M0 4v217h193v-217h-193zM0 334v1179h193v-1179h-193z" />
+<glyph unicode="&#x22;" horiz-adv-x="579" d="M0 1200v309h193v-309h-193zM285 1200v309h192v-309h-192z" />
+<glyph unicode="#" horiz-adv-x="1169" d="M-41 467v195h311l37 192h-284v195h323l90 464h197l-90 -464h157l88 464h197l-88 -464h233v-195h-270l-39 -192h246v-195h-283l-90 -467h-196l90 467h-158l-92 -467h-197l90 467h-272zM467 662h158l39 192h-158z" />
+<glyph unicode="$" horiz-adv-x="729" d="M0 1032q0 78 19.5 142.5t54.5 115.5q55 76 149 109v114h195v-112q53 -16 88 -42t57 -52q78 -100 78 -275v-96h-195v96q0 109 -34 154q-10 10 -30 21.5t-63 11.5t-68.5 -22.5t-38.5 -53.5t-16 -62.5t-3 -48.5q0 -39 10 -65.5t28.5 -47t44 -37t56.5 -30.5q10 -4 19 -9 t18 -12q12 -4 24 -10q27 -12 70 -35.5t82 -63.5t67.5 -100.5t28.5 -148.5q0 -154 -78 -254q-57 -78 -145 -102v-117h-195v115q-53 14 -89 40.5t-56 53.5q-78 96 -78 272v99h193v-99q0 -109 36 -151q8 -10 27.5 -22.5t62.5 [...]
+<glyph unicode="%" horiz-adv-x="1259" d="M0 1022v176q0 55 17.5 101.5t48 80t73.5 52t92 18.5q102 0 168 -70.5t66 -181.5v-176q0 -55 -17.5 -101.5t-48 -80t-73.5 -52t-95 -18.5q-100 0 -165.5 70.5t-65.5 181.5zM193 1022q0 -59 38.5 -59t38.5 59v176q0 59 -38.5 59t-38.5 -59v-176zM199 4l559 1509h207 l-559 -1509h-207zM694 315v177q0 111 65.5 181t168.5 70q49 0 92 -18t73.5 -52t48 -80t17.5 -101v-177q0 -55 -17.5 -101t-48 -80t-73.5 -52.5t-92 -18.5q-102 0 -168 70.5t-66 181.5zM889 315q0 -59 39 -59t39 59v177q0 5 [...]
+<glyph unicode="&#x26;" horiz-adv-x="1036" d="M0 408q0 80 19.5 140t51 106t70.5 82l78 69l15.5 12t13.5 12q-18 31 -38 70t-36 84t-27.5 91t-11.5 93q0 152 43 232q63 115 197 114q145 0 205 -133q23 -49 27.5 -106t4.5 -107q0 -86 -21.5 -166.5t-62.5 -148.5l-18 -29q-8 -12 -16 -22l161 -275q4 35 4 69v62v99h195 v-99q0 -76 -9 -177t-48 -197l174 -279h-230l-65 102q-119 -102 -301 -102q-84 0 -156 32t-123 91q-96 115 -96 281zM193 408q0 -37 10 -75t31.5 -67.5t56.5 -49t84 -19.5q131 0 198 82l-223 385l-6 -7l-63 -56q- [...]
+<glyph unicode="'" horiz-adv-x="323" d="M0 1200v309h193v-309h-193z" />
+<glyph unicode="(" horiz-adv-x="421" d="M0 739q0 362 98 576q41 86 78 123t49 45l105 -162q2 0 4 2l-23 -26q-23 -26 -49 -91t-47.5 -179t-21.5 -288q0 -166 20 -275.5t45 -174t47.5 -92t26.5 -31.5l-105 -164q-12 8 -49 43t-78 121q-51 104 -75.5 248.5t-24.5 324.5z" />
+<glyph unicode=")" horiz-adv-x="438" d="M0 162l23 25q23 26 48 91.5t46.5 178t21.5 288.5q0 166 -19.5 275.5t-44 174.5t-47 92.5t-26.5 31.5l104 164q12 -8 49.5 -43t77.5 -121q100 -209 101 -574q0 -180 -24.5 -324.5t-76.5 -250.5q-39 -86 -75.5 -123t-48.5 -45l-105 162q-2 0 -4 -2z" />
+<glyph unicode="*" horiz-adv-x="753" d="M0 1210l68 181l172 -64v184h192v-184l172 64l68 -181l-170 -63l129 -148l-146 -127l-149 168l-150 -168l-145 127l129 148z" />
+<glyph unicode="+" horiz-adv-x="935" d="M0 662v192h299v299h195v-299h299v-192h-299v-302h-195v302h-299z" />
+<glyph unicode="," horiz-adv-x="323" d="M0 6v211h193v-395z" />
+<glyph unicode="-" horiz-adv-x="770" d="M0 662v192h629v-192h-629z" />
+<glyph unicode="." horiz-adv-x="380" d="M0 0v217h193v-217h-193z" />
+<glyph unicode="/" horiz-adv-x="854" d="M0 0l559 1509h207l-559 -1509h-207z" />
+<glyph unicode="0" horiz-adv-x="770" d="M0 436v641q0 195 72 303q84 129 247.5 129t247.5 -129q74 -109 74 -303v-641q0 -195 -74 -305q-84 -131 -247.5 -131t-247.5 131q-72 112 -72 305zM193 436q0 -92 15 -141t35.5 -71.5t42 -26.5t34 -4t34 4t42 26.5t35.5 71.5t15 141v641q0 90 -15 138.5t-35.5 71 t-42 26.5t-34 4t-34 -4t-42 -26.5t-35.5 -71t-15 -138.5v-641z" />
+<glyph unicode="1" horiz-adv-x="563" d="M0 1165l242 344h186v-1509h-192v1159l-86 -119z" />
+<glyph unicode="2" horiz-adv-x="737" d="M0 0v96q0 94 17.5 171t50 148.5t75.5 141.5l97 150l79 110l53 72q24 33 40 66.5t25 71.5t9 87q0 18 -4 52t-17 68t-38 58.5t-68 24.5q-16 0 -37.5 -3t-42 -22.5t-33.5 -62.5t-13 -121v-98h-193v98q0 184 76 287q29 41 87 77.5t156 36.5q70 0 128.5 -27.5t99.5 -77.5 t65.5 -122t26.5 -158h2v-16h-2q-2 -72 -16.5 -128t-37 -104.5t-50.5 -90.5l-60 -83l-37 -50l-37 -54l-77 -119q-35 -53 -59.5 -101t-40 -92t-23.5 -93h118h224h98v-193h-98h-224h-319z" />
+<glyph unicode="3" horiz-adv-x="737" d="M0 430v96h193v-96q0 -86 13 -130t27 -64q10 -16 29 -29.5t57 -13.5q45 0 71 30.5t38 69.5t15 76t3 51q0 68 -20 113t-48 72.5t-59.5 39.5t-52.5 12h-96h2v193h94q20 0 52 12t60 40t48 73t20 112q0 8 -3 45t-15 78t-37.5 74t-71.5 33q-12 0 -33.5 -4t-42 -26.5t-35.5 -71 t-15 -138.5v-96h-193v96q0 195 72 303q86 129 247.5 129t249.5 -139q72 -113 72 -283q0 -125 -42 -203.5t-87 -119.5l-10 -10q4 -2 5 -4t5 -7q45 -41 87 -119.5t42 -203.5q0 -84 -18.5 -154.5t-53.5 -126.5q-88 -139  [...]
+<glyph unicode="4" horiz-adv-x="778" d="M0 422v192l471 895h176v-1509h-192v422h-455zM221 614h234v451z" />
+<glyph unicode="5" horiz-adv-x="761" d="M0 322v32h193v-32q0 -12 6 -35t21.5 -43.5t39 -35.5t60 -15t61.5 23.5t39 59t20 75.5t6 73v147q0 80 -12 123t-26 62q-10 16 -29 27.5t-59.5 11.5t-59 -13.5t-29.5 -25.5q-39 -51 -38 -152v-65v-2h-193v2v65v905h193h448v-192h-448v-352q57 25 126 24q100 0 160 -40 t88 -81q74 -109 74 -297v-147q0 -168 -72 -281q-43 -70 -107.5 -106.5t-142.5 -36.5q-72 0 -133 28.5t-106 82.5q-39 45 -59.5 100.5t-20.5 110.5z" />
+<glyph unicode="6" horiz-adv-x="753" d="M0 387v197v2v407q0 225 68 355q41 78 105.5 119.5t145.5 41.5q78 0 140.5 -28.5t105.5 -85.5q76 -104 76 -265v-65h-195v65q0 100 -36 148q-10 12 -30 25.5t-61 13.5q-43 0 -67.5 -37t-37.5 -89t-17 -106.5t-4 -91.5v-14q55 29 126 29q162 0 248 -123q74 -109 74 -301 v-152q0 -96 -23.5 -176t-65.5 -137.5t-101.5 -88t-131.5 -30.5q-156 0 -243 119q-76 100 -76 268zM193 387q0 -102 38 -154q10 -12 29 -26t59 -14q37 0 62 24.5t39 61t20 78.5t6 75v152q0 86 -14 133t-33.5 68.5t-42 25 [...]
+<glyph unicode="7" horiz-adv-x="878" d="M0 1317v192h793v-182l-557 -1327h-211l555 1317h-580z" />
+<glyph unicode="8" horiz-adv-x="794" d="M0 426q0 203 78 305q4 6 9 12.5t9 12.5q-6 6 -18 22q-78 102 -78 307q0 203 78 306q86 119 264 118q176 0 264 -118q78 -106 78 -306q0 -201 -78 -307q-12 -16 -18 -22l18 -25q78 -106 78 -305q0 -104 -19.5 -179t-58.5 -128q-90 -119 -264 -119q-176 0 -264 119 q-78 104 -78 307zM193 426q0 -88 14 -135t35.5 -68.5t48 -25.5t51.5 -4t50.5 4t47 25.5t35.5 68.5t14 135q0 86 -12 130t-26 62q-10 14 -33 27.5t-76 13.5t-75.5 -13t-33.5 -28q-14 -18 -27 -62t-13 -130zM193 1085q0 -88 14 [...]
+<glyph unicode="9" horiz-adv-x="753" d="M0 930v151q0 172 72 287q43 70 106.5 105.5t140.5 35.5q160 0 246 -114q76 -104 76 -269v-196v-4v-412q0 -113 -17.5 -202t-50.5 -152q-41 -78 -106.5 -119t-147.5 -41q-78 0 -140 30.5t-105 90.5q-74 104 -74 276v66h193v-66q0 -78 15 -118.5t36.5 -60t42 -22.5t32.5 -3 q41 0 67 33.5t39 82.5t17 104.5t4 100.5v14q-61 -29 -127 -28q-162 0 -245 125q-74 110 -74 305zM193 930q0 -88 14 -136.5t33.5 -70t41 -25.5t37.5 -4q45 0 71 32t38 73t15 78.5t3 50.5v198q0 72 -15 111t-35.5 56. [...]
+<glyph unicode=":" horiz-adv-x="299" d="M0 334v284h193v-284h-193zM0 897v285h193v-285h-193z" />
+<glyph unicode=";" horiz-adv-x="323" d="M0 422v196h193v-391zM0 897v285h193v-285h-193z" />
+<glyph unicode="&#x3c;" />
+<glyph unicode="=" d="M0 436v193h629v-193h-629zM0 887v192h629v-192h-629z" />
+<glyph unicode="&#x3e;" />
+<glyph unicode="?" horiz-adv-x="745" d="M0 995v97q0 186 74 294q86 123 245 123q78 0 142.5 -35.5t107.5 -105.5q66 -104 70 -258h2v-18h-2q-2 -82 -27.5 -151t-59.5 -123t-71 -95l-63 -68l-25 -24q-23 -29 -26.5 -74t-3.5 -123v-102h-195v102q0 45 1 89t8 84t23.5 77t45.5 72q8 8 16 17t19 20l49 51 q29 31 54.5 69.5t42.5 86t19 102.5q0 31 -7 68.5t-21.5 70.5t-38 54.5t-60.5 21.5q-14 0 -35.5 -3t-42 -24.5t-34.5 -67.5t-14 -130v-97h-193zM168 0v217h192v-217h-192z" />
+<glyph unicode="@" horiz-adv-x="1417" d="M-29 805q41 254 207 424q74 76 167 126t198 72q73 15 144 16q25 0 50 -2q96 -7 182.5 -40t158 -89.5t122.5 -133.5q35 -57 57.5 -130t28.5 -155q1 -22 1 -44q0 -55 -7 -109q-10 -75 -37 -138q-25 -66 -78 -119t-125 -90q-70 -35 -138 -46q-30 -5 -58 -5q-35 0 -66 8 q-84 25 -116 96q-29 -4 -55.5 -5t-49.5 -1q-141 0 -211 80q-58 66 -58 178q0 31 5 66q18 147 90 225q82 92 225 92q29 0 60.5 -3t66.5 -13l2 22l193 -32l-17 -97l-4 -25l-10 -65l-14 -87l-17 -95q-8 -47 -14 -87t-10 -62 [...]
+<glyph unicode="A" horiz-adv-x="894" d="M0 0l348 1509h154l352 -1509h-201l-96 422h-262l-96 -422h-199zM340 614h172l-86 371z" />
+<glyph unicode="B" horiz-adv-x="770" d="M0 0v193v1316h291q193 0 282 -114q88 -102 89 -310q0 -205 -89 -311q-4 -6 -16 -18q12 -12 16 -21q88 -106 89 -311q0 -207 -89 -309q-92 -115 -282 -115h-98h-193zM193 852h98q66 0 94.5 15.5t38.5 29.5q43 51 43 188q0 80 -13.5 126t-37 70t-56 30t-69.5 6h-98v-465z M193 193h98q37 0 69.5 6t56 29.5t37 69.5t13.5 126q0 82 -14.5 129t-38 70.5t-55 29.5t-68.5 6h-98v-466z" />
+<glyph unicode="C" horiz-adv-x="794" d="M0 432v647q0 201 86 312q33 41 97.5 79.5t175 38.5t174 -38.5t96.5 -79.5q88 -113 88 -312v-96h-195v96q0 88 -17.5 137.5t-43 71t-54 25.5t-49.5 4q-23 0 -50 -4t-54 -25.5t-44 -71t-17 -137.5v-647q0 -133 47 -192q10 -14 36.5 -30.5t82 -16.5t81 16t37.5 31 q45 61 45 192v96h195v-96q0 -199 -88 -311q-33 -41 -96.5 -81t-174.5 -40q-55 0 -98 11.5t-76.5 28.5t-57.5 38.5t-40 42.5q-86 110 -86 311z" />
+<glyph unicode="D" horiz-adv-x="802" d="M0 0v1509h301q195 0 293 -120q90 -109 90 -316v-635q0 -207 -90 -317q-98 -121 -293 -121h-301zM193 193h108q37 0 71 7t59.5 31.5t41.5 73.5t16 133v635q0 84 -16 133t-41.5 74t-59.5 31t-71 6h-108v-1124z" />
+<glyph unicode="E" horiz-adv-x="761" d="M0 0v1509h625v-192h-432v-465h432v-193h-432v-466h432v-193h-625z" />
+<glyph unicode="F" horiz-adv-x="761" d="M0 0v1509h625v-192h-432v-465h432v-193h-432v-659h-193z" />
+<glyph unicode="G" horiz-adv-x="845" d="M0 430v651q0 203 88 312q92 117 270 116q180 0 273 -116q88 -109 88 -312v-96h-195v96q0 82 -14 129t-37.5 71t-53.5 30t-60.5 6t-60.5 -6t-53.5 -30t-37.5 -71t-14 -129v-651q0 -90 17 -138t44 -69.5t54.5 -25.5t50 -4t51 4t54 25.5t43 69.5t17.5 138v115h-233v194h428 v-309q0 -203 -88 -311q-33 -41 -97.5 -80t-175.5 -39q-109 0 -173 39t-97 80q-88 108 -88 311z" />
+<glyph unicode="H" horiz-adv-x="837" d="M0 0v1509h193v-657h290v657h195v-1509h-195v657h-290v-657h-193z" />
+<glyph unicode="I" horiz-adv-x="413" d="M61 0v1509h193v-1509h-193z" />
+<glyph unicode="J" horiz-adv-x="829" d="M0 401v99h193v-99q0 -78 15 -120.5t37.5 -62t47 -22.5t45.5 -3q51 0 73.5 13t32.5 27q39 49 39 168v1108h193v-1108q0 -188 -82 -290q-29 -37 -90.5 -74t-165.5 -37q-102 0 -163.5 37t-92.5 74q-82 102 -82 290z" />
+<glyph unicode="K" horiz-adv-x="919" d="M0 549l2 4v958h193v-659l428 659h231l-459 -706l445 -803h-222l-344 619l-79 -125v-494h-193v547h-2z" />
+<glyph unicode="L" horiz-adv-x="729" d="M0 2v1509h193v-1316h464v-193h-657z" />
+<glyph unicode="M" horiz-adv-x="1101" d="M0 2v1509h170l305 -1062l303 1062h170v-1509h-192v723l-209 -723h-146l-208 723v-723h-193z" />
+<glyph unicode="N" horiz-adv-x="870" d="M0 2v1509h162l368 -913v913h195v-1509h-164l-368 913v-913h-193z" />
+<glyph unicode="O" horiz-adv-x="829" d="M0 432v649q0 201 86 312q16 20 40 40.5t57.5 38t76.5 28.5t98 11q111 0 175.5 -38.5t97.5 -79.5q86 -111 86 -312v-649q0 -201 -86 -311q-33 -41 -97.5 -80t-175.5 -39q-109 0 -174 39t-98 80q-86 110 -86 311zM193 432q0 -90 17 -138t44 -69.5t54.5 -25.5t49.5 -4 q20 0 49 4t55.5 25.5t44 69.5t17.5 138v649q0 88 -17.5 136.5t-44 70t-55 25.5t-49.5 4q-23 0 -50 -4t-54 -25.5t-44 -70t-17 -136.5v-649z" />
+<glyph unicode="P" horiz-adv-x="786" d="M0 2v1509h313q193 0 293 -112q92 -109 92 -312q0 -207 -92 -313q-98 -115 -293 -115h-120v-657h-193zM193 854h120q80 0 109 18.5t37 28.5q45 47 45 186q0 74 -12.5 119t-36 69.5t-59.5 33t-83 8.5h-120v-463z" />
+<glyph unicode="Q" horiz-adv-x="829" d="M0 438v649q0 137 37 221.5t91 129.5t116.5 59t113.5 14q49 0 111.5 -14t118 -59t92.5 -129t37 -222v-649q0 -172 -66 -280l207 -248h-252l-98 119q-31 -12 -68 -20.5t-82 -8.5q-55 0 -98 11.5t-76.5 29.5t-57.5 40.5t-40 43.5q-86 112 -86 313zM193 438q0 -135 47 -194 q12 -16 37.5 -32.5t80.5 -16.5h15l-146 180h242l43 -53q10 51 10 116v649q0 80 -14 125t-38 69t-52.5 30t-59 6t-60.5 -6t-53.5 -30t-37.5 -69t-14 -125v-649z" />
+<glyph unicode="R" horiz-adv-x="854" d="M0 2v1509h313q195 0 293 -114q90 -104 90 -316q0 -209 -90 -317q-4 -4 -9 -10t-11 -11q55 -53 84.5 -126.5t29.5 -167.5v-447h-194v447q0 199 -193 198h-96h-24v-645h-193zM193 842h24h96q78 0 108 18.5t38 28.5q45 57 45 192q0 76 -12.5 122t-36 71.5t-59.5 34t-83 8.5 h-120v-475z" />
+<glyph unicode="S" horiz-adv-x="813" d="M0 430v96h193v-96q0 -133 47 -190q10 -14 36.5 -29.5t83.5 -15.5q55 0 88 23.5t50.5 57t22.5 73.5t5 71q0 53 -16 90t-43 62.5t-59.5 43t-65.5 31.5l-37 17q-33 14 -83 39.5t-99 72.5q-123 119 -123 303q0 96 25.5 176t73.5 136.5t115 88t146 31.5q111 0 175.5 -38.5 t97.5 -79.5q88 -113 88 -314v-96h-195v96q0 88 -17 137.5t-44 71t-55.5 25.5t-49.5 4q-59 0 -91.5 -28.5t-50 -68.5t-21.5 -80t-4 -61q0 -53 16 -91t43 -65.5t60.5 -47t70.5 -33.5l33 -15q29 -12 79 -35.5t99 -70.5q127  [...]
+<glyph unicode="T" horiz-adv-x="944" d="M0 1317v194h854v-194h-330v-1315h-194v1315h-330z" />
+<glyph unicode="U" horiz-adv-x="829" d="M0 403v1108h193v-1108q0 -78 15 -120.5t37.5 -62t47 -22.5t45 -3t45.5 3t47.5 22.5t37.5 62.5t15 120v1108h193v-1108q0 -188 -82 -288q-31 -41 -92.5 -77t-163.5 -36t-163.5 36t-92.5 77q-82 100 -82 288z" />
+<glyph unicode="V" horiz-adv-x="944" d="M0 1511h199l252 -1013l256 1013h198l-379 -1509h-151z" />
+<glyph unicode="W" horiz-adv-x="1474" d="M0 1509h199l213 -962l213 962h155l211 -962l213 962h199l-334 -1509h-156l-211 965l-213 -965h-155z" />
+<glyph unicode="X" horiz-adv-x="1019" d="M0 0l356 756l-350 753h215l244 -526l250 526h215l-359 -753l355 -756h-213l-248 528l-250 -528h-215z" />
+<glyph unicode="Y" horiz-adv-x="1036" d="M-61 1509h221l305 -553l307 553h221l-432 -778v-731h-192v731z" />
+<glyph unicode="Z" horiz-adv-x="935" d="M0 1317v192h778v-186l-528 -1130h561v-193h-778v188l528 1129h-561z" />
+<glyph unicode="[" />
+<glyph unicode="\" horiz-adv-x="786" d="M0 1509h207l559 -1509h-207z" />
+<glyph unicode="]" />
+<glyph unicode="^" />
+<glyph unicode="_" horiz-adv-x="952" d="M0 0h956v-74h-956v74zM0 -121h956v-74h-956v74z" />
+<glyph unicode="`" horiz-adv-x="323" d="M0 1204v309h193v-309h-193zM72 1276h49v164h-49v-164z" />
+<glyph unicode="a" horiz-adv-x="894" d="M0 0l348 1509h154l352 -1509h-201l-96 422h-262l-96 -422h-199zM340 614h172l-86 371z" />
+<glyph unicode="b" horiz-adv-x="770" d="M0 0v193v1316h291q193 0 282 -114q88 -102 89 -310q0 -205 -89 -311q-4 -6 -16 -18q12 -12 16 -21q88 -106 89 -311q0 -207 -89 -309q-92 -115 -282 -115h-98h-193zM193 852h98q66 0 94.5 15.5t38.5 29.5q43 51 43 188q0 80 -13.5 126t-37 70t-56 30t-69.5 6h-98v-465z M193 193h98q37 0 69.5 6t56 29.5t37 69.5t13.5 126q0 82 -14.5 129t-38 70.5t-55 29.5t-68.5 6h-98v-466z" />
+<glyph unicode="c" horiz-adv-x="794" d="M0 432v647q0 201 86 312q33 41 97.5 79.5t175 38.5t174 -38.5t96.5 -79.5q88 -113 88 -312v-96h-195v96q0 88 -17.5 137.5t-43 71t-54 25.5t-49.5 4q-23 0 -50 -4t-54 -25.5t-44 -71t-17 -137.5v-647q0 -133 47 -192q10 -14 36.5 -30.5t82 -16.5t81 16t37.5 31 q45 61 45 192v96h195v-96q0 -199 -88 -311q-33 -41 -96.5 -81t-174.5 -40q-55 0 -98 11.5t-76.5 28.5t-57.5 38.5t-40 42.5q-86 110 -86 311z" />
+<glyph unicode="d" horiz-adv-x="802" d="M0 0v1509h301q195 0 293 -120q90 -109 90 -316v-635q0 -207 -90 -317q-98 -121 -293 -121h-301zM193 193h108q37 0 71 7t59.5 31.5t41.5 73.5t16 133v635q0 84 -16 133t-41.5 74t-59.5 31t-71 6h-108v-1124z" />
+<glyph unicode="e" horiz-adv-x="761" d="M0 0v1509h625v-192h-432v-465h432v-193h-432v-466h432v-193h-625z" />
+<glyph unicode="f" horiz-adv-x="761" d="M0 0v1509h625v-192h-432v-465h432v-193h-432v-659h-193z" />
+<glyph unicode="g" horiz-adv-x="845" d="M0 430v651q0 203 88 312q92 117 270 116q180 0 273 -116q88 -109 88 -312v-96h-195v96q0 82 -14 129t-37.5 71t-53.5 30t-60.5 6t-60.5 -6t-53.5 -30t-37.5 -71t-14 -129v-651q0 -90 17 -138t44 -69.5t54.5 -25.5t50 -4t51 4t54 25.5t43 69.5t17.5 138v115h-233v194h428 v-309q0 -203 -88 -311q-33 -41 -97.5 -80t-175.5 -39q-109 0 -173 39t-97 80q-88 108 -88 311z" />
+<glyph unicode="h" horiz-adv-x="837" d="M0 0v1509h193v-657h290v657h195v-1509h-195v657h-290v-657h-193z" />
+<glyph unicode="i" horiz-adv-x="413" d="M61 0v1509h193v-1509h-193z" />
+<glyph unicode="j" horiz-adv-x="829" d="M0 401v99h193v-99q0 -78 15 -120.5t37.5 -62t47 -22.5t45.5 -3q51 0 73.5 13t32.5 27q39 49 39 168v1108h193v-1108q0 -188 -82 -290q-29 -37 -90.5 -74t-165.5 -37q-102 0 -163.5 37t-92.5 74q-82 102 -82 290z" />
+<glyph unicode="k" horiz-adv-x="919" d="M0 549l2 4v958h193v-659l428 659h231l-459 -706l445 -803h-222l-344 619l-79 -125v-494h-193v547h-2z" />
+<glyph unicode="l" horiz-adv-x="729" d="M0 2v1509h193v-1316h464v-193h-657z" />
+<glyph unicode="m" horiz-adv-x="1101" d="M0 2v1509h170l305 -1062l303 1062h170v-1509h-192v723l-209 -723h-146l-208 723v-723h-193z" />
+<glyph unicode="n" horiz-adv-x="870" d="M0 2v1509h162l368 -913v913h195v-1509h-164l-368 913v-913h-193z" />
+<glyph unicode="o" horiz-adv-x="829" d="M0 432v649q0 201 86 312q16 20 40 40.5t57.5 38t76.5 28.5t98 11q111 0 175.5 -38.5t97.5 -79.5q86 -111 86 -312v-649q0 -201 -86 -311q-33 -41 -97.5 -80t-175.5 -39q-109 0 -174 39t-98 80q-86 110 -86 311zM193 432q0 -90 17 -138t44 -69.5t54.5 -25.5t49.5 -4 q20 0 49 4t55.5 25.5t44 69.5t17.5 138v649q0 88 -17.5 136.5t-44 70t-55 25.5t-49.5 4q-23 0 -50 -4t-54 -25.5t-44 -70t-17 -136.5v-649z" />
+<glyph unicode="p" horiz-adv-x="786" d="M0 2v1509h313q193 0 293 -112q92 -109 92 -312q0 -207 -92 -313q-98 -115 -293 -115h-120v-657h-193zM193 854h120q80 0 109 18.5t37 28.5q45 47 45 186q0 74 -12.5 119t-36 69.5t-59.5 33t-83 8.5h-120v-463z" />
+<glyph unicode="q" horiz-adv-x="829" d="M0 438v649q0 137 37 221.5t91 129.5t116.5 59t113.5 14q49 0 111.5 -14t118 -59t92.5 -129t37 -222v-649q0 -172 -66 -280l207 -248h-252l-98 119q-31 -12 -68 -20.5t-82 -8.5q-55 0 -98 11.5t-76.5 29.5t-57.5 40.5t-40 43.5q-86 112 -86 313zM193 438q0 -135 47 -194 q12 -16 37.5 -32.5t80.5 -16.5h15l-146 180h242l43 -53q10 51 10 116v649q0 80 -14 125t-38 69t-52.5 30t-59 6t-60.5 -6t-53.5 -30t-37.5 -69t-14 -125v-649z" />
+<glyph unicode="r" horiz-adv-x="854" d="M0 2v1509h313q195 0 293 -114q90 -104 90 -316q0 -209 -90 -317q-4 -4 -9 -10t-11 -11q55 -53 84.5 -126.5t29.5 -167.5v-447h-194v447q0 199 -193 198h-96h-24v-645h-193zM193 842h24h96q78 0 108 18.5t38 28.5q45 57 45 192q0 76 -12.5 122t-36 71.5t-59.5 34t-83 8.5 h-120v-475z" />
+<glyph unicode="s" horiz-adv-x="813" d="M0 430v96h193v-96q0 -133 47 -190q10 -14 36.5 -29.5t83.5 -15.5q55 0 88 23.5t50.5 57t22.5 73.5t5 71q0 53 -16 90t-43 62.5t-59.5 43t-65.5 31.5l-37 17q-33 14 -83 39.5t-99 72.5q-123 119 -123 303q0 96 25.5 176t73.5 136.5t115 88t146 31.5q111 0 175.5 -38.5 t97.5 -79.5q88 -113 88 -314v-96h-195v96q0 88 -17 137.5t-44 71t-55.5 25.5t-49.5 4q-59 0 -91.5 -28.5t-50 -68.5t-21.5 -80t-4 -61q0 -53 16 -91t43 -65.5t60.5 -47t70.5 -33.5l33 -15q29 -12 79 -35.5t99 -70.5q127  [...]
+<glyph unicode="t" horiz-adv-x="944" d="M0 1317v194h854v-194h-330v-1315h-194v1315h-330z" />
+<glyph unicode="u" horiz-adv-x="829" d="M0 403v1108h193v-1108q0 -78 15 -120.5t37.5 -62t47 -22.5t45 -3t45.5 3t47.5 22.5t37.5 62.5t15 120v1108h193v-1108q0 -188 -82 -288q-31 -41 -92.5 -77t-163.5 -36t-163.5 36t-92.5 77q-82 100 -82 288z" />
+<glyph unicode="v" horiz-adv-x="944" d="M0 1511h199l252 -1013l256 1013h198l-379 -1509h-151z" />
+<glyph unicode="w" horiz-adv-x="1474" d="M0 1509h199l213 -962l213 962h155l211 -962l213 962h199l-334 -1509h-156l-211 965l-213 -965h-155z" />
+<glyph unicode="x" horiz-adv-x="1019" d="M0 0l356 756l-350 753h215l244 -526l250 526h215l-359 -753l355 -756h-213l-248 528l-250 -528h-215z" />
+<glyph unicode="y" horiz-adv-x="1036" d="M-61 1509h221l305 -553l307 553h221l-432 -778v-731h-192v731z" />
+<glyph unicode="z" horiz-adv-x="935" d="M0 1317v192h778v-186l-528 -1130h561v-193h-778v188l528 1129h-561z" />
+<glyph unicode="{" />
+<glyph unicode="|" horiz-adv-x="413" d="M61 0v1509h193v-1509h-193z" />
+<glyph unicode="}" />
+<glyph unicode="~" />
+<glyph unicode="&#xa9;" />
+<glyph unicode="&#xad;" horiz-adv-x="770" d="M0 662v192h629v-192h-629z" />
+<glyph unicode="&#xae;" />
+<glyph unicode="&#x2000;" horiz-adv-x="755" />
+<glyph unicode="&#x2001;" horiz-adv-x="1513" />
+<glyph unicode="&#x2002;" horiz-adv-x="755" />
+<glyph unicode="&#x2003;" horiz-adv-x="1513" />
+<glyph unicode="&#x2004;" horiz-adv-x="503" />
+<glyph unicode="&#x2005;" horiz-adv-x="376" />
+<glyph unicode="&#x2006;" horiz-adv-x="251" />
+<glyph unicode="&#x2007;" horiz-adv-x="251" />
+<glyph unicode="&#x2008;" horiz-adv-x="188" />
+<glyph unicode="&#x2009;" horiz-adv-x="301" />
+<glyph unicode="&#x200a;" horiz-adv-x="83" />
+<glyph unicode="&#x2010;" horiz-adv-x="770" d="M0 662v192h629v-192h-629z" />
+<glyph unicode="&#x2011;" horiz-adv-x="770" d="M0 662v192h629v-192h-629z" />
+<glyph unicode="&#x2012;" horiz-adv-x="770" d="M0 662v192h629v-192h-629z" />
+<glyph unicode="&#x2013;" horiz-adv-x="770" d="M0 662v192h629v-192h-629z" />
+<glyph unicode="&#x2014;" horiz-adv-x="770" d="M0 662v192h629v-192h-629z" />
+<glyph unicode="&#x2018;" horiz-adv-x="323" d="M0 1200v309h193v-309h-193z" />
+<glyph unicode="&#x2019;" horiz-adv-x="323" d="M0 1200v309h193v-309h-193z" />
+<glyph unicode="&#x201c;" horiz-adv-x="579" d="M0 1200v309h193v-309h-193zM285 1200v309h192v-309h-192z" />
+<glyph unicode="&#x201d;" horiz-adv-x="579" d="M0 1200v309h193v-309h-193zM285 1200v309h192v-309h-192z" />
+<glyph unicode="&#x2022;" />
+<glyph unicode="&#x2026;" horiz-adv-x="1142" d="M0 0v217h193v-217h-193zM381 0v217h192v-217h-192zM762 0v217h192v-217h-192z" />
+<glyph unicode="&#x202f;" horiz-adv-x="301" />
+<glyph unicode="&#x205f;" horiz-adv-x="376" />
+<glyph unicode="&#xe000;" horiz-adv-x="1510" d="M0 1510h1510v-1510h-1510v1510z" />
+</font>
+</defs></svg> 
\ No newline at end of file
diff --git a/lib/plugins/captcha/helper.php b/lib/plugins/captcha/helper.php
new file mode 100644
index 0000000..0d4f883
--- /dev/null
+++ b/lib/plugins/captcha/helper.php
@@ -0,0 +1,464 @@
+<?php
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Andreas Gohr <andi at splitbrain.org>
+ */
+
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
+
+/**
+ * Class helper_plugin_captcha
+ */
+class helper_plugin_captcha extends DokuWiki_Plugin {
+
+    protected $field_in = 'plugin__captcha';
+    protected $field_sec = 'plugin__captcha_secret';
+    protected $field_hp = 'plugin__captcha_honeypot';
+
+    /**
+     * Constructor. Initializes field names
+     */
+    public function __construct() {
+        $this->field_in  = md5($this->_fixedIdent().$this->field_in);
+        $this->field_sec = md5($this->_fixedIdent().$this->field_sec);
+        $this->field_hp  = md5($this->_fixedIdent().$this->field_hp);
+    }
+
+    /**
+     * Check if the CAPTCHA should be used. Always check this before using the methods below.
+     *
+     * @return bool true when the CAPTCHA should be used
+     */
+    public function isEnabled() {
+        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) return false;
+        return true;
+    }
+
+    /**
+     * Returns the HTML to display the CAPTCHA with the chosen method
+     */
+    public function getHTML() {
+        global $ID;
+
+        $rand = (float) (rand(0, 10000)) / 10000;
+        $this->storeCaptchaCookie($this->_fixedIdent(), $rand);
+
+        if($this->getConf('mode') == 'math') {
+            $code = $this->_generateMATH($this->_fixedIdent(), $rand);
+            $code = $code[0];
+            $text = $this->getLang('fillmath');
+        } elseif($this->getConf('mode') == 'question') {
+            $code = ''; // not used
+            $text = $this->getConf('question');
+        } else {
+            $code = $this->_generateCAPTCHA($this->_fixedIdent(), $rand);
+            $text = $this->getLang('fillcaptcha');
+        }
+        $secret = $this->encrypt($rand);
+
+        $txtlen = $this->getConf('lettercount');
+
+        $out = '';
+        $out .= '<div id="plugin__captcha_wrapper">';
+        $out .= '<input type="hidden" name="'.$this->field_sec.'" value="'.hsc($secret).'" />';
+        $out .= '<label for="plugin__captcha">'.$text.'</label> ';
+
+        switch($this->getConf('mode')) {
+            case 'math':
+            case 'text':
+                $out .= $this->_obfuscateText($code);
+                break;
+            case 'js':
+                $out .= '<span id="plugin__captcha_code">'.$this->_obfuscateText($code).'</span>';
+                break;
+            case 'svg':
+                $out .= '<span class="svg" style="width:'.$this->getConf('width').'px; height:'.$this->getConf('height').'px">';
+                $out .= $this->_svgCAPTCHA($code);
+                $out .= '</span>';
+                break;
+            case 'svgaudio':
+                $out .= '<span class="svg" style="width:'.$this->getConf('width').'px; height:'.$this->getConf('height').'px">';
+                $out .= $this->_svgCAPTCHA($code);
+                $out .= '</span>';
+                $out .= '<a href="'.DOKU_BASE.'lib/plugins/captcha/wav.php?secret='.rawurlencode($secret).'&id='.$ID.'"'.
+                    ' class="JSnocheck" title="'.$this->getLang('soundlink').'">';
+                $out .= '<img src="'.DOKU_BASE.'lib/plugins/captcha/sound.png" width="16" height="16"'.
+                    ' alt="'.$this->getLang('soundlink').'" /></a>';
+                break;
+            case 'image':
+                $out .= '<img src="'.DOKU_BASE.'lib/plugins/captcha/img.php?secret='.rawurlencode($secret).'&id='.$ID.'" '.
+                    ' width="'.$this->getConf('width').'" height="'.$this->getConf('height').'" alt="" /> ';
+                break;
+            case 'audio':
+                $out .= '<img src="'.DOKU_BASE.'lib/plugins/captcha/img.php?secret='.rawurlencode($secret).'&id='.$ID.'" '.
+                    ' width="'.$this->getConf('width').'" height="'.$this->getConf('height').'" alt="" /> ';
+                $out .= '<a href="'.DOKU_BASE.'lib/plugins/captcha/wav.php?secret='.rawurlencode($secret).'&id='.$ID.'"'.
+                    ' class="JSnocheck" title="'.$this->getLang('soundlink').'">';
+                $out .= '<img src="'.DOKU_BASE.'lib/plugins/captcha/sound.png" width="16" height="16"'.
+                    ' alt="'.$this->getLang('soundlink').'" /></a>';
+                break;
+            case 'figlet':
+                require_once(dirname(__FILE__).'/figlet.php');
+                $figlet = new phpFiglet();
+                if($figlet->loadfont(dirname(__FILE__).'/figlet.flf')) {
+                    $out .= '<pre>';
+                    $out .= rtrim($figlet->fetch($code));
+                    $out .= '</pre>';
+                } else {
+                    msg('Failed to load figlet.flf font file. CAPTCHA broken', -1);
+                }
+                break;
+        }
+        $out .= ' <input type="text" size="'.$txtlen.'" name="'.$this->field_in.'" class="edit" /> ';
+
+        // add honeypot field
+        $out .= '<label class="no">'.$this->getLang('honeypot').'<input type="text" name="'.$this->field_hp.'" /></label>';
+        $out .= '</div>';
+        return $out;
+    }
+
+    /**
+     * Checks if the the CAPTCHA was solved correctly
+     *
+     * @param  bool $msg when true, an error will be signalled through the msg() method
+     * @return bool true when the answer was correct, otherwise false
+     */
+    public function check($msg = true) {
+        global $INPUT;
+
+        $field_sec = $INPUT->str($this->field_sec);
+        $field_in  = $INPUT->str($this->field_in);
+        $field_hp  = $INPUT->str($this->field_hp);
+
+        // reconstruct captcha from provided $field_sec
+        $rand = $this->decrypt($field_sec);
+
+        if($this->getConf('mode') == 'math') {
+            $code = $this->_generateMATH($this->_fixedIdent(), $rand);
+            $code = $code[1];
+        } elseif($this->getConf('mode') == 'question') {
+            $code = $this->getConf('answer');
+        } else {
+            $code = $this->_generateCAPTCHA($this->_fixedIdent(), $rand);
+        }
+
+        // compare values
+        if(!$field_sec ||
+            !$field_in ||
+            $rand === false ||
+            utf8_strtolower($field_in) != utf8_strtolower($code) ||
+            trim($field_hp) !== '' ||
+            !$this->retrieveCaptchaCookie($this->_fixedIdent(), $rand)
+        ) {
+            if($msg) msg($this->getLang('testfailed'), -1);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Get the path where a captcha cookie would be stored
+     *
+     * We use a daily temp directory which is easy to clean up
+     *
+     * @param $fixed string the fixed part, any string
+     * @param $rand  float  some random number between 0 and 1
+     * @return string the path to the cookie file
+     */
+    protected function getCaptchaCookiePath($fixed, $rand) {
+        global $conf;
+        $path = $conf['tmpdir'] . '/captcha/' . date('Y-m-d') . '/' . md5($fixed . $rand) . '.cookie';
+        io_makeFileDir($path);
+        return $path;
+    }
+
+    /**
+     * remove all outdated captcha cookies
+     */
+    public function _cleanCaptchaCookies() {
+        global $conf;
+        $path = $conf['tmpdir'] . '/captcha/';
+        $dirs = glob("$path/*", GLOB_ONLYDIR);
+        $today = date('Y-m-d');
+        foreach($dirs as $dir) {
+            if(basename($dir) === $today) continue;
+            if(!preg_match('/\/captcha\//', $dir)) continue; // safety net
+            io_rmdir($dir, true);
+        }
+    }
+
+    /**
+     * Creates a one time captcha cookie
+     *
+     * This is used to prevent replay attacks. It is generated when the captcha form
+     * is shown and checked with the captcha check. Since we can not be sure about the
+     * session state (might be closed or open) we're not using it.
+     *
+     * We're not using the stored values for displaying the captcha image (or audio)
+     * but continue to use our encryption scheme. This way it's still possible to have
+     * multiple captcha checks going on in parallel (eg. with multiple browser tabs)
+     *
+     * @param $fixed string the fixed part, any string
+     * @param $rand  float  some random number between 0 and 1
+     */
+    protected function storeCaptchaCookie($fixed, $rand) {
+        $cache = $this->getCaptchaCookiePath($fixed, $rand);
+        touch($cache);
+    }
+
+    /**
+     * Checks if the captcha cookie exists and deletes it
+     *
+     * @param $fixed string the fixed part, any string
+     * @param $rand  float  some random number between 0 and 1
+     * @return bool true if the cookie existed
+     */
+    protected function retrieveCaptchaCookie($fixed, $rand) {
+        $cache = $this->getCaptchaCookiePath($fixed, $rand);
+        if(file_exists($cache)) {
+            unlink($cache);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Build a semi-secret fixed string identifying the current page and user
+     *
+     * This string is always the same for the current user when editing the same
+     * page revision, but only for one day. Editing a page before midnight and saving
+     * after midnight will result in a failed CAPTCHA once, but makes sure it can
+     * not be reused which is especially important for the registration form where the
+     * $ID usually won't change.
+     *
+     * @return string
+     */
+    public function _fixedIdent() {
+        global $ID;
+        $lm = @filemtime(wikiFN($ID));
+        $td = date('Y-m-d');
+        return auth_browseruid() .
+            auth_cookiesalt() .
+            $ID . $lm . $td;
+    }
+
+    /**
+     * Adds random space characters within the given text
+     *
+     * Keeps subsequent numbers without spaces (for math problem)
+     *
+     * @param $text
+     * @return string
+     */
+    protected function _obfuscateText($text) {
+        $new = '';
+
+        $spaces = array(
+            "\r",
+            "\n",
+            "\r\n",
+            ' ',
+            "\xC2\xA0", // \u00A0    NO-BREAK SPACE
+            "\xE2\x80\x80", // \u2000    EN QUAD
+            "\xE2\x80\x81", // \u2001    EM QUAD
+            "\xE2\x80\x82", // \u2002    EN SPACE
+            //         "\xE2\x80\x83", // \u2003    EM SPACE
+            "\xE2\x80\x84", // \u2004    THREE-PER-EM SPACE
+            "\xE2\x80\x85", // \u2005    FOUR-PER-EM SPACE
+            "\xE2\x80\x86", // \u2006    SIX-PER-EM SPACE
+            "\xE2\x80\x87", // \u2007    FIGURE SPACE
+            "\xE2\x80\x88", // \u2008    PUNCTUATION SPACE
+            "\xE2\x80\x89", // \u2009    THIN SPACE
+            "\xE2\x80\x8A", // \u200A    HAIR SPACE
+            "\xE2\x80\xAF", // \u202F    NARROW NO-BREAK SPACE
+            "\xE2\x81\x9F", // \u205F    MEDIUM MATHEMATICAL SPACE
+
+            "\xE1\xA0\x8E\r\n", // \u180E    MONGOLIAN VOWEL SEPARATOR
+            "\xE2\x80\x8B\r\n", // \u200B    ZERO WIDTH SPACE
+            "\xEF\xBB\xBF\r\n", // \uFEFF    ZERO WIDTH NO-BREAK SPACE
+        );
+
+        $len = strlen($text);
+        for($i = 0; $i < $len - 1; $i++) {
+            $new .= $text{$i};
+
+            if(!is_numeric($text{$i + 1})) {
+                $new .= $spaces[array_rand($spaces)];
+            }
+        }
+        $new .= $text{$len - 1};
+        return $new;
+    }
+
+    /**
+     * Generate some numbers from a known string and random number
+     *
+     * @param $fixed string the fixed part, any string
+     * @param $rand  float  some random number between 0 and 1
+     * @return string
+     */
+    protected function _generateNumbers($fixed, $rand) {
+        $fixed   = hexdec(substr(md5($fixed), 5, 5)); // use part of the md5 to generate an int
+        $rand = $rand * 0xFFFFF; // bitmask from the random number
+        return md5($rand ^ $fixed); // combine both values
+    }
+
+    /**
+     * Generates a random char string
+     *
+     * @param $fixed string the fixed part, any string
+     * @param $rand  float  some random number between 0 and 1
+     * @return string
+     */
+    public function _generateCAPTCHA($fixed, $rand) {
+        $numbers = $this->_generateNumbers($fixed, $rand);
+
+        // now create the letters
+        $code = '';
+        $lettercount = $this->getConf('lettercount') * 2;
+        if($lettercount > strlen($numbers)) $lettercount = strlen($numbers);
+        for($i = 0; $i < $lettercount; $i += 2) {
+            $code .= chr(floor(hexdec($numbers[$i].$numbers[$i + 1]) / 10) + 65);
+        }
+
+        return $code;
+    }
+
+    /**
+     * Create a mathematical task and its result
+     *
+     * @param $fixed string the fixed part, any string
+     * @param $rand  float  some random number between 0 and 1
+     * @return array taks, result
+     */
+    protected function _generateMATH($fixed, $rand) {
+        $numbers = $this->_generateNumbers($fixed, $rand);
+
+        // first letter is the operator (+/-)
+        $op  = (hexdec($numbers[0]) > 8) ? -1 : 1;
+        $num = array(hexdec($numbers[1].$numbers[2]), hexdec($numbers[3]));
+
+        // we only want positive results
+        if(($op < 0) && ($num[0] < $num[1])) rsort($num);
+
+        // prepare result and task text
+        $res  = $num[0] + ($num[1] * $op);
+        $task = $num[0].(($op < 0) ? '-' : '+').$num[1].'=?';
+
+        return array($task, $res);
+    }
+
+    /**
+     * Create a CAPTCHA image
+     *
+     * @param string $text the letters to display
+     */
+    public function _imageCAPTCHA($text) {
+        $w = $this->getConf('width');
+        $h = $this->getConf('height');
+
+        $fonts = glob(dirname(__FILE__).'/fonts/*.ttf');
+
+        // create a white image
+        $img   = imagecreatetruecolor($w, $h);
+        $white = imagecolorallocate($img, 255, 255, 255);
+        imagefill($img, 0, 0, $white);
+
+        // add some lines as background noise
+        for($i = 0; $i < 30; $i++) {
+            $color = imagecolorallocate($img, rand(100, 250), rand(100, 250), rand(100, 250));
+            imageline($img, rand(0, $w), rand(0, $h), rand(0, $w), rand(0, $h), $color);
+        }
+
+        // draw the letters
+        $txtlen = strlen($text);
+        for($i = 0; $i < $txtlen; $i++) {
+            $font  = $fonts[array_rand($fonts)];
+            $color = imagecolorallocate($img, rand(0, 100), rand(0, 100), rand(0, 100));
+            $size  = rand(floor($h / 1.8), floor($h * 0.7));
+            $angle = rand(-35, 35);
+
+            $x       = ($w * 0.05) + $i * floor($w * 0.9 / $txtlen);
+            $cheight = $size + ($size * 0.5);
+            $y       = floor($h / 2 + $cheight / 3.8);
+
+            imagettftext($img, $size, $angle, $x, $y, $color, $font, $text[$i]);
+        }
+
+        header("Content-type: image/png");
+        imagepng($img);
+        imagedestroy($img);
+    }
+
+    /**
+     * Create an SVG of the given text
+     *
+     * @param string $text
+     * @return string
+     */
+    public function _svgCAPTCHA($text) {
+        require_once(__DIR__ . '/EasySVG.php');
+
+        $fonts = glob(__DIR__ . '/fonts/*.svg');
+
+        $x = 0; // where we start to draw
+        $y = 100; // our max height
+
+        $svg = new EasySVG();
+
+        // draw the letters
+        $txtlen = strlen($text);
+        for($i = 0; $i < $txtlen; $i++) {
+            $char = $text[$i];
+            $size = rand($y / 2, $y - $y * 0.1); // 50-90%
+            $svg->setFontSVG($fonts[array_rand($fonts)]);
+
+            $svg->setFontSize($size);
+            $svg->setLetterSpacing(round(rand(1, 4) / 10, 2)); // 0.1 - 0.4
+            $svg->addText($char, $x, rand(0, round($y - $size))); // random up and down
+
+            list($w) = $svg->textDimensions($char);
+            $x += $w;
+        }
+
+        $svg->addAttribute('width', $x . 'px');
+        $svg->addAttribute('height', $y . 'px');
+        $svg->addAttribute('viewbox', "0 0 $x $y");
+        return $svg->asXML();
+    }
+
+    /**
+     * Encrypt the given string with the cookie salt
+     *
+     * @param string $data
+     * @return string
+     */
+    public function encrypt($data) {
+        if(function_exists('auth_encrypt')) {
+            $data = auth_encrypt($data, auth_cookiesalt()); // since binky
+        } else {
+            $data = PMA_blowfish_encrypt($data, auth_cookiesalt()); // deprecated
+        }
+
+        return base64_encode($data);
+    }
+
+    /**
+     * Decrypt the given string with the cookie salt
+     *
+     * @param string $data
+     * @return string
+     */
+    public function decrypt($data) {
+        $data = base64_decode($data);
+        if($data === false || $data === '') return false;
+
+        if(function_exists('auth_decrypt')) {
+            return auth_decrypt($data, auth_cookiesalt()); // since binky
+        } else {
+            return PMA_blowfish_decrypt($data, auth_cookiesalt()); // deprecated
+        }
+    }
+}
diff --git a/lib/plugins/captcha/img.php b/lib/plugins/captcha/img.php
new file mode 100644
index 0000000..e0efcb7
--- /dev/null
+++ b/lib/plugins/captcha/img.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * CAPTCHA antispam plugin - Image generator
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Andreas Gohr <gohr at cosmocode.de>
+ */
+
+if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__).'/../../../');
+define('NOSESSION', true);
+define('DOKU_DISABLE_GZIP_OUTPUT', 1);
+require_once(DOKU_INC.'inc/init.php');
+require_once(DOKU_INC.'inc/auth.php');
+
+$ID = $_REQUEST['id'];
+/** @var helper_plugin_captcha $plugin */
+$plugin = plugin_load('helper', 'captcha');
+$rand   = $plugin->decrypt($_REQUEST['secret']);
+$code   = $plugin->_generateCAPTCHA($plugin->_fixedIdent(), $rand);
+$plugin->_imageCAPTCHA($code);
+
+//Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/lib/plugins/captcha/lang/ar/lang.php b/lib/plugins/captcha/lang/ar/lang.php
new file mode 100644
index 0000000..54984c6
--- /dev/null
+++ b/lib/plugins/captcha/lang/ar/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author alhajr <alhajr300 at gmail.com>
+ */
+$lang['testfailed']            = 'عذراً، لكن لم يكن الرد على كلمة التحقق بشكل صحيح.';
+$lang['fillcaptcha']           = 'الرجاء تعبئة كافة الأحرف في المربع.';
+$lang['fillmath']              = 'الرجاء حل المعادلة التالية.';
+$lang['soundlink']             = 'إذا كنت لا تستطيع قراءة الحروف على الصورة، تحميل ملف الصوت يساعدك على قراءة الأحرف.';
+$lang['honeypot']              = 'الرجاء الحفاظ على هذا الحقل فارغاً:';
diff --git a/lib/plugins/captcha/lang/ar/settings.php b/lib/plugins/captcha/lang/ar/settings.php
new file mode 100644
index 0000000..d5fbea1
--- /dev/null
+++ b/lib/plugins/captcha/lang/ar/settings.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author alhajr <alhajr300 at gmail.com>
+ * @author habiiibo <habiiibo at gmail.com>
+ */
+$lang['mode']                  = 'أي نوع من كلمة التحقق استخدامها؟';
+$lang['mode_o_js']             = 'نص (مملوءة مسبقا مع جافا سكريبت)';
+$lang['mode_o_text']           = 'النص (دليل فقط)';
+$lang['mode_o_math']           = 'مشكلة الرياضيات';
+$lang['mode_o_question']       = 'مسألة ثابتة';
+$lang['mode_o_image']          = 'الصورة (أسوأ إمكانية الوصول)';
+$lang['mode_o_audio']          = 'الصورة + الصوت (أفضل إمكانية الوصول)';
+$lang['mode_o_figlet']         = 'برنامج صنع الكلمات (تعذر الوصول)';
+$lang['forusers']              = 'استخدام كلمة التحقق في تسجيل المستخدمين، أيضا؟';
+$lang['loginprotect']          = 'لا بد من ادخال كود التحقق او كابتشا لمتابعة تسجيل الدخول؟';
+$lang['lettercount']           = 'عدد من الرسائل لاستخدام (3-16). إذا قمت بزيادة كمية، ومن المؤكد أن زيادة العرض في الصورة أدناه كذلك.';
+$lang['width']                 = 'عرض الصورة كلمة التحقق (بالبكسل)';
+$lang['height']                = 'ارتفاع الصورة كلمة التحقق (بالبكسل)';
+$lang['question']              = 'سؤال لوضع مسألة ثابتة';
+$lang['answer']                = 'جواب المسألة الثابتة';
diff --git a/lib/plugins/captcha/lang/cs/lang.php b/lib/plugins/captcha/lang/cs/lang.php
new file mode 100644
index 0000000..e03223f
--- /dev/null
+++ b/lib/plugins/captcha/lang/cs/lang.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Antonin Komenda <gree at grees.net>
+ * @author Jaroslav Lichtblau <jlichtblau at seznam.cz>
+ */
+$lang['testfailed']            = 'Bohužel, ale na CAPTCHA nebylo odpovězeno správně. Jste vůbec člověk?';
+$lang['fillcaptcha']           = 'Vyplňte, prosím, všechna písmena v poli, abyste dokázali, že nejste robot.';
+$lang['fillmath']              = 'Prosíme, vyřešte nasledující rovnici, abyste dokázali, že nejste robot.';
+$lang['soundlink']             = 'Pokud nedokážete přečíst písmena na obrázku, stáhněte si tento .wav soubor, kde je text přečtený.';
+$lang['honeypot']              = 'Ponechte prosím toto pole prázdné:';
diff --git a/lib/plugins/captcha/lang/cs/settings.php b/lib/plugins/captcha/lang/cs/settings.php
new file mode 100644
index 0000000..5167538
--- /dev/null
+++ b/lib/plugins/captcha/lang/cs/settings.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Antonin Komenda <gree at grees.net>
+ * @author Jaroslav Lichtblau <jlichtblau at seznam.cz>
+ */
+$lang['mode']                  = 'Který typ CAPTCHA se má použít?';
+$lang['mode_o_js']             = 'Text (předvyplněný JavaScriptem)';
+$lang['mode_o_text']           = 'Text (pouze manuálně vložený)';
+$lang['mode_o_math']           = 'Matematický problém';
+$lang['mode_o_question']       = 'Vlastní otázka';
+$lang['mode_o_image']          = 'Obrázek (špatná přístupnost)';
+$lang['mode_o_audio']          = 'Obrázek (lepší přístupnost)';
+$lang['mode_o_figlet']         = 'ASCII art figlet (špatná přístupnost) ';
+$lang['forusers']              = 'Používat CAPTCHA i pro registrované uživatele?';
+$lang['loginprotect']          = 'Vyžadovat pro přihlášení CAPTCHA?';
+$lang['lettercount']           = 'Počet použitých písmen (3-16). Pokud navýšíte množství, ujistěte se, že jste navýšili i šířku obrázku níže.';
+$lang['width']                 = 'Šírka CAPTCHA obrázku (v bodech)';
+$lang['height']                = 'Výška CAPTCHA obrázku (v bodech)';
+$lang['question']              = 'Otázka pro režim vlastní otázky';
+$lang['answer']                = 'Odpověď pro režim vlastní otázky';
diff --git a/lib/plugins/captcha/lang/cy/lang.php b/lib/plugins/captcha/lang/cy/lang.php
new file mode 100644
index 0000000..42e3d51
--- /dev/null
+++ b/lib/plugins/captcha/lang/cy/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Alan Davies <ben.brynsadler at gmail.com>
+ */
+$lang['testfailed']            = 'Sori, ond wnaethoch chi ddim ateb y CAPTCHA\'n gywir. Efallai \'dych chi ddim yn ddynol wedi\'r cyfan?';
+$lang['fillcaptcha']           = 'Llenwch pob llythyren i\'r blwch i brofi\'ch bod chi\'n ddynol.';
+$lang['fillmath']              = 'Datryswch yr hafaliad canlynol i brofi\'ch bod chi\'n ddynol.';
+$lang['soundlink']             = 'Os \'dych chi ddim yn gallu darllen llythrennau\'r ddelwedd, lawrlwythwch y ffeil .wav hwn er mwyn cael nhw wedi\'u darllen i chi.';
+$lang['honeypot']              = 'Cadwch y maes hwn yn wag:';
diff --git a/lib/plugins/captcha/lang/cy/settings.php b/lib/plugins/captcha/lang/cy/settings.php
new file mode 100644
index 0000000..2e0a0b7
--- /dev/null
+++ b/lib/plugins/captcha/lang/cy/settings.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Alan Davies <ben.brynsadler at gmail.com>
+ */
+$lang['mode']                  = 'Pa fath CAPTCHA i\'w ddefnyddio?';
+$lang['mode_o_js']             = 'Testun (wedi\'i rhaglenwi gan JavaScript)';
+$lang['mode_o_text']           = 'Testun (gan law yn unig)';
+$lang['mode_o_math']           = 'Problem fathemategol';
+$lang['mode_o_question']       = 'Cwestiwn gosodedig';
+$lang['mode_o_image']          = 'Delwedd (hygyrchedd gwael)';
+$lang['mode_o_audio']          = 'Delwedd+Sain (gwell hygyrchedd)';
+$lang['mode_o_figlet']         = 'Celf Figlet ASCII (hygyrchedd gwael)';
+$lang['forusers']              = 'Defnyddio CAPTCHA ar gyfer defnyddwyr sydd wedi mewngofnodi hefyd?';
+$lang['loginprotect']          = 'Angen CAPTCHA i fewngofnodi?';
+$lang['lettercount']           = 'Bufer y llythrennau i\'w defnyddio (3-16). Os ydych chi\'n cynnyddu\'r nifer, sicrhewch eich bod chi\'n cynyddu lled y ddelwedd isod hefyd.';
+$lang['width']                 = 'Lled y ddelwedd CAPTCHA (picsel)';
+$lang['height']                = 'Uchder y ddelwedd CAPTCHA (picsel)';
+$lang['question']              = 'Cwestiwn ar gyfer modd cwestiwn gosodedig';
+$lang['answer']                = 'Ateb ar gyfer modd cwestiwn gosodedig';
diff --git a/lib/plugins/captcha/lang/da/lang.php b/lib/plugins/captcha/lang/da/lang.php
new file mode 100644
index 0000000..bed7a73
--- /dev/null
+++ b/lib/plugins/captcha/lang/da/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author soer9648 <soer9648 at eucl.dk>
+ */
+$lang['testfailed']            = 'Desværre, CAPTCHA blev ikke besvaret korrekt. Du er muligvis ikke et menneske?';
+$lang['fillcaptcha']           = 'Skriv venligst alle bogstaverne i boksen for at bevise at du er et menneske.';
+$lang['fillmath']              = 'Løs venligst følgende ligning for at bevise at du er et menneske.';
+$lang['soundlink']             = 'Hvis du ikke kan læse bogstaverne på skærmen, kan du downloade denne .wav-fil, for at få dem læst op.';
+$lang['honeypot']              = 'Hold venligst dette felt tomt:';
diff --git a/lib/plugins/captcha/lang/da/settings.php b/lib/plugins/captcha/lang/da/settings.php
new file mode 100644
index 0000000..36f6276
--- /dev/null
+++ b/lib/plugins/captcha/lang/da/settings.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author soer9648 <soer9648 at eucl.dk>
+ * @author Jacob Palm <mail at jacobpalm.dk>
+ */
+$lang['mode']                  = 'Hvilken type CAPTCHA skal benyttes?';
+$lang['mode_o_js']             = 'Tekst (præudfyldt af JavaScript)';
+$lang['mode_o_text']           = 'Tekst (kun manuelt)';
+$lang['mode_o_math']           = 'Matematikproblem';
+$lang['mode_o_question']       = 'Løsning';
+$lang['mode_o_image']          = 'Billede (dårlig tilgængelighed)';
+$lang['mode_o_audio']          = 'Billede+Audio (bedre tilgængelighed)';
+$lang['mode_o_figlet']         = 'Figlet ASCII Art (dårlig tilgængelighed)';
+$lang['forusers']              = 'Benyt også CAPTCHA til brugere der er logget ind?';
+$lang['loginprotect']          = 'Kræv CAPTCHA ved login?';
+$lang['lettercount']           = 'Antal af bogstaver der skal benyttes (3-16). Hvis du øger antallet, skal du også huske at øge bredden af billedet herunder.';
+$lang['width']                 = 'Bredden af CAPTCHA-billedet (pixel)';
+$lang['height']                = 'Højden af CAPTCHA-billedet (pixel)';
+$lang['question']              = 'Spørgsmål til fast-spørgsmål-tilstand';
+$lang['answer']                = 'Svar til fast-spørgsmål-tilstand';
diff --git a/lib/plugins/captcha/lang/de-informal/lang.php b/lib/plugins/captcha/lang/de-informal/lang.php
new file mode 100644
index 0000000..867031e
--- /dev/null
+++ b/lib/plugins/captcha/lang/de-informal/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Thomas Templin <templin at gnuwhv.de>
+ */
+$lang['testfailed']            = 'Das CAPTCHA wurde nicht korrekt beantwortet.';
+$lang['fillcaptcha']           = 'Bitte übertrage die Buchstaben in das Eingabefeld.';
+$lang['fillmath']              = 'Bitte löse folgende Gleichung:';
+$lang['soundlink']             = 'Wenn Du die Buchstaben auf dem Bild nicht lesen kannst, lade diese .wav Datei herunter, um sie vorgelesen zu bekommen.';
+$lang['honeypot']              = 'Dieses Feld bitte leer lassen';
diff --git a/lib/plugins/captcha/lang/de-informal/settings.php b/lib/plugins/captcha/lang/de-informal/settings.php
new file mode 100644
index 0000000..28a2004
--- /dev/null
+++ b/lib/plugins/captcha/lang/de-informal/settings.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Thomas Templin <templin at gnuwhv.de>
+ * @author Dana <dannax3 at gmx.de>
+ */
+$lang['mode']                  = 'Welcher CAPTCHA-Typ soll benutzt werden?';
+$lang['mode_o_js']             = 'Text (automatisch ausgefüllt via JavaScript)';
+$lang['mode_o_text']           = 'Text (manuell auszufüllen)';
+$lang['mode_o_math']           = 'Mathe-Aufgabe';
+$lang['mode_o_question']       = 'Feste Frage';
+$lang['mode_o_image']          = 'Bild (nicht barrierefrei)';
+$lang['mode_o_audio']          = 'Bild+Audio (barrierefrei)';
+$lang['mode_o_figlet']         = 'Figlet ASCII-Kunst (nicht barrierefrei)';
+$lang['forusers']              = 'CAPTCHA auch für  angemeldete Benutzer verwenden?';
+$lang['loginprotect']          = 'Vorraussetzen eines CAPTCHA zum Einloggen?';
+$lang['lettercount']           = 'Anzahl der zu verwendenen Buchstaben (3-16). Wenn Du die Anzahl erhöhst, denke daran auch die Breite des Bildes im nächsten Feld zu erhöhen.';
+$lang['width']                 = 'Breite des CAPTCHA Bildes (in Pixel)';
+$lang['height']                = 'Höhe  des CAPTCHA Bildes (in Pixel)';
+$lang['question']              = 'Frage für den "Feste Frage" Modus.';
+$lang['answer']                = 'Antwort für den "Feste Frage" Modus.';
diff --git a/lib/plugins/captcha/lang/de/lang.php b/lib/plugins/captcha/lang/de/lang.php
new file mode 100644
index 0000000..ac6fa4a
--- /dev/null
+++ b/lib/plugins/captcha/lang/de/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Andreas Gohr <andi at splitbrain.org>
+ */
+$lang['testfailed']            = 'Das CAPTCHA wurde nicht korrekt beantwortet.';
+$lang['fillcaptcha']           = 'Bitte übertragen Sie die Buchstaben in das Eingabefeld.';
+$lang['fillmath']              = 'Bitte lösen Sie folgende Gleichung:';
+$lang['soundlink']             = 'Wenn Sie die Buchstaben auf dem Bild nicht lesen können, laden Sie diese .wav Datei herunter, um sie vorgelesen zu bekommen.';
+$lang['honeypot']              = 'Dieses Feld bitte leer lassen';
diff --git a/lib/plugins/captcha/lang/de/settings.php b/lib/plugins/captcha/lang/de/settings.php
new file mode 100644
index 0000000..549a53d
--- /dev/null
+++ b/lib/plugins/captcha/lang/de/settings.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Andreas Gohr <andi at splitbrain.org>
+ * @author Thomas Templin <templin at gnuwhv.de>
+ * @author Leo Rudin <leo.rudin at gmx.ch>
+ */
+$lang['mode']                  = 'Welcher CAPTCHA-Typ soll benutzt werden?';
+$lang['mode_o_js']             = 'Text (automatisch ausgefüllt via JavaScript)';
+$lang['mode_o_text']           = 'Text (manuell auszufüllen)';
+$lang['mode_o_math']           = 'Mathe-Aufgabe';
+$lang['mode_o_question']       = 'Feste Frage';
+$lang['mode_o_image']          = 'Bild (nicht barrierefrei)';
+$lang['mode_o_audio']          = 'Bild+Audio (barrierefrei)';
+$lang['mode_o_figlet']         = 'Figlet ASCII-Kunst (nicht barrierefrei)';
+$lang['forusers']              = 'Soll das CAPTCHA auch für eingeloggte Benutzer gebraucht werden?';
+$lang['loginprotect']          = 'Benötigt es ein CAPTCHA um sich einzuloggen?';
+$lang['lettercount']           = 'Anzahl der zu verwendenen Buchstaben (3-16). Wenn Sie die Anzahl erhöhen, denken Sie daran auch die Breite des Bildes im nächsten Feld zu erhöhen.';
+$lang['width']                 = 'Weite des CAPTCHA Bildes (pixel)';
+$lang['height']                = 'Höhe des CAPTCHA Bildes (pixel)';
+$lang['question']              = 'Frage für den "Feste Frage" Modus.';
+$lang['answer']                = 'Antwort für den "Feste Frage" Modus.';
diff --git a/lib/plugins/captcha/lang/en/audio/LICENSE b/lib/plugins/captcha/lang/en/audio/LICENSE
new file mode 100644
index 0000000..e97f8cc
--- /dev/null
+++ b/lib/plugins/captcha/lang/en/audio/LICENSE
@@ -0,0 +1,4 @@
+This work is licensed under the Creative Commons Sampling Plus 1.0 License. To
+view a copy of this license, visit
+http://creativecommons.org/licenses/sampling+/1.0/ or send a letter to Creative
+Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.
diff --git a/lib/plugins/captcha/lang/en/audio/a.wav b/lib/plugins/captcha/lang/en/audio/a.wav
new file mode 100644
index 0000000..e7505ca
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/a.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/b.wav b/lib/plugins/captcha/lang/en/audio/b.wav
new file mode 100644
index 0000000..eb9fffa
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/b.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/c.wav b/lib/plugins/captcha/lang/en/audio/c.wav
new file mode 100644
index 0000000..117fc93
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/c.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/d.wav b/lib/plugins/captcha/lang/en/audio/d.wav
new file mode 100644
index 0000000..9a1ea52
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/d.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/e.wav b/lib/plugins/captcha/lang/en/audio/e.wav
new file mode 100644
index 0000000..0770161
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/e.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/f.wav b/lib/plugins/captcha/lang/en/audio/f.wav
new file mode 100644
index 0000000..dc4ff2b
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/f.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/g.wav b/lib/plugins/captcha/lang/en/audio/g.wav
new file mode 100644
index 0000000..df4d6d4
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/g.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/h.wav b/lib/plugins/captcha/lang/en/audio/h.wav
new file mode 100644
index 0000000..50365bb
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/h.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/i.wav b/lib/plugins/captcha/lang/en/audio/i.wav
new file mode 100644
index 0000000..bb1875a
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/i.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/j.wav b/lib/plugins/captcha/lang/en/audio/j.wav
new file mode 100644
index 0000000..56a9535
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/j.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/k.wav b/lib/plugins/captcha/lang/en/audio/k.wav
new file mode 100644
index 0000000..28e0fd9
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/k.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/l.wav b/lib/plugins/captcha/lang/en/audio/l.wav
new file mode 100644
index 0000000..a56a314
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/l.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/m.wav b/lib/plugins/captcha/lang/en/audio/m.wav
new file mode 100644
index 0000000..d081c81
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/m.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/n.wav b/lib/plugins/captcha/lang/en/audio/n.wav
new file mode 100644
index 0000000..bd4304d
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/n.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/o.wav b/lib/plugins/captcha/lang/en/audio/o.wav
new file mode 100644
index 0000000..02ffa9b
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/o.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/p.wav b/lib/plugins/captcha/lang/en/audio/p.wav
new file mode 100644
index 0000000..1863235
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/p.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/q.wav b/lib/plugins/captcha/lang/en/audio/q.wav
new file mode 100644
index 0000000..24fc9c0
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/q.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/r.wav b/lib/plugins/captcha/lang/en/audio/r.wav
new file mode 100644
index 0000000..8f55782
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/r.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/s.wav b/lib/plugins/captcha/lang/en/audio/s.wav
new file mode 100644
index 0000000..c92e5ba
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/s.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/t.wav b/lib/plugins/captcha/lang/en/audio/t.wav
new file mode 100644
index 0000000..4fc1955
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/t.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/u.wav b/lib/plugins/captcha/lang/en/audio/u.wav
new file mode 100644
index 0000000..cc142fd
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/u.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/v.wav b/lib/plugins/captcha/lang/en/audio/v.wav
new file mode 100644
index 0000000..246553d
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/v.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/w.wav b/lib/plugins/captcha/lang/en/audio/w.wav
new file mode 100644
index 0000000..b0d7659
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/w.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/x.wav b/lib/plugins/captcha/lang/en/audio/x.wav
new file mode 100644
index 0000000..726fedc
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/x.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/y.wav b/lib/plugins/captcha/lang/en/audio/y.wav
new file mode 100644
index 0000000..4edf31f
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/y.wav differ
diff --git a/lib/plugins/captcha/lang/en/audio/z.wav b/lib/plugins/captcha/lang/en/audio/z.wav
new file mode 100644
index 0000000..f329629
Binary files /dev/null and b/lib/plugins/captcha/lang/en/audio/z.wav differ
diff --git a/lib/plugins/captcha/lang/en/lang.php b/lib/plugins/captcha/lang/en/lang.php
new file mode 100644
index 0000000..7163928
--- /dev/null
+++ b/lib/plugins/captcha/lang/en/lang.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * English language file
+ *
+ * @author Andreas Gohr <andi at splitbrain.org>
+ */
+
+$lang['testfailed']  = "Sorry, but the CAPTCHA wasn't answered correctly. Maybe you're not human at all?";
+$lang['fillcaptcha'] = "Please fill all the letters into the box to prove you're human.";
+$lang['fillmath']    = "Please solve the following equation to prove you're human.";
+$lang['soundlink']   = "If you can't read the letters on the image, download this .wav file to get them read to you.";
+$lang['honeypot']    = "Please keep this field empty: ";
diff --git a/lib/plugins/captcha/lang/en/settings.php b/lib/plugins/captcha/lang/en/settings.php
new file mode 100644
index 0000000..c3c33aa
--- /dev/null
+++ b/lib/plugins/captcha/lang/en/settings.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * English language file
+ *
+ * @author Andreas Gohr <andi at splitbrain.org>
+ */
+
+$lang['mode']          = "Which type of CAPTCHA to use?";
+$lang['mode_o_js']     = "Text (prefilled with JavaScript)";
+$lang['mode_o_text']   = "Text (manual only)";
+$lang['mode_o_math']   = "Math Problem";
+$lang['mode_o_question'] = "Fixed Question";
+$lang['mode_o_image']  = "Image (bad accessibility)";
+$lang['mode_o_audio']  = "Image+Audio (better accessibility)";
+$lang['mode_o_svg']  = "SVG (bad accessibility, readable)";
+$lang['mode_o_svgaudio']  = "SVG+Audio (better accessibility, readable)";
+$lang['mode_o_figlet'] = "Figlet ASCII Art (bad accessibility)";
+
+$lang['forusers']   = "Use CAPTCHA for logged in users, too?";
+$lang['loginprotect'] = "Require a CAPTCHA to login?";
+$lang['lettercount']= "Number of letters to use (3-16). If you increase the amount, be sure to increase the width of the image below as well.";
+$lang['width']      = "Width of the CAPTCHA image (pixel)";
+$lang['height']     = "Height of the CAPTCHA image (pixel)";
+$lang['question']   = "Question for fixed question mode";
+$lang['answer']     = "Answer for fixed question mode";
diff --git a/lib/plugins/captcha/lang/eo/lang.php b/lib/plugins/captcha/lang/eo/lang.php
new file mode 100644
index 0000000..01ed128
--- /dev/null
+++ b/lib/plugins/captcha/lang/eo/lang.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Tradukis Ljosxa Kuznecov <ka2pink at gmail.com>
+ * @author Robert Bogenschneider <bogi at uea.org>
+ */
+$lang['testfailed']            = 'Pardonon, sed CAPTCHA ne respondis korekte. Eble vi tute ne estas homo, ĉu?';
+$lang['fillcaptcha']           = 'Bonvolu tajpi ĉiujn literojn en la kampeton, por pruvi ke vi estas homo.';
+$lang['fillmath']              = 'Bonvolu solvi sekvan ekvacion por pruvi, ke vi estas homa.';
+$lang['soundlink']             = 'Se vi ne povas legi la literojn en la bildo, ŝarĝu tiun .wav-dosieron por aŭdi ilin.';
+$lang['honeypot']              = 'Bonvolu lasi tiun kampon malplena:';
diff --git a/lib/plugins/captcha/lang/eo/settings.php b/lib/plugins/captcha/lang/eo/settings.php
new file mode 100644
index 0000000..c197757
--- /dev/null
+++ b/lib/plugins/captcha/lang/eo/settings.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Tradukis Ljosxa Kuznecov <ka2pink at gmail.com>
+ * @author Robert Bogenschneider <bogi at uea.org>
+ */
+$lang['mode']                  = 'Kiun varianton de CAPTCHA uzi?';
+$lang['mode_o_js']             = 'Teksto (prilaborita per Java-skripto)';
+$lang['mode_o_text']           = 'Teksto (nur permane)';
+$lang['mode_o_math']           = 'Matematika problemo';
+$lang['mode_o_question']       = 'Fiksa demando';
+$lang['mode_o_image']          = 'Bildo (malbona alirebleco)';
+$lang['mode_o_audio']          = 'Bildo+Sono (pli bona alirebleco)';
+$lang['mode_o_figlet']         = 'Figlet ASCII - arto (malbona alirebleco)';
+$lang['forusers']              = 'Uzi CAPTCHA-n ankaŭ por ensalutintaj uzantoj?';
+$lang['lettercount']           = 'Kvanto da uzendaj literoj (3-16). Se vi pligrandigas la kvanton, certigu ke vi same pligrandigas la larĝecon de la suba bildo.';
+$lang['width']                 = 'Larĝeco de CAPTCHA-bildo (pikseloj)';
+$lang['height']                = 'Alteco de CAPTCHA-bildo (pikseloj)';
+$lang['question']              = 'Demando por fiks-demanda funkciado';
+$lang['answer']                = 'Respondo por fiks-demanda funkciado';
diff --git a/lib/plugins/captcha/lang/es/lang.php b/lib/plugins/captcha/lang/es/lang.php
new file mode 100644
index 0000000..91f5396
--- /dev/null
+++ b/lib/plugins/captcha/lang/es/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Antonio Castilla <antoniocastilla at trazoide.com>
+ */
+$lang['testfailed']            = 'Lo sentimos, pero el CAPTCHA no fue respondido correctamente. Tal vez no eres una persona.';
+$lang['fillcaptcha']           = 'Por favor, complete todas las letras de la caja para demostrar que eres una persona.';
+$lang['fillmath']              = 'Por favor, resuelve la siguiente ecuación para demostrar que eres una persona.';
+$lang['soundlink']             = 'Si no puede leer toda las letras de la imagen, descargue el archivo wav que lo leerá por ti.';
+$lang['honeypot']              = 'Por favor, mantenga este campo vacío: ';
diff --git a/lib/plugins/captcha/lang/es/settings.php b/lib/plugins/captcha/lang/es/settings.php
new file mode 100644
index 0000000..8e02dd3
--- /dev/null
+++ b/lib/plugins/captcha/lang/es/settings.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Antonio Castilla <antoniocastilla at trazoide.com>
+ */
+$lang['mode']                  = '¿Qué tipo de CAPTCHA usará?';
+$lang['mode_o_js']             = 'Texto (rellenados con JavaScript)';
+$lang['mode_o_text']           = 'Texto (manual)';
+$lang['mode_o_math']           = 'Problemas de matemáticas';
+$lang['mode_o_question']       = 'Pregunta fija';
+$lang['mode_o_image']          = 'Imagen (peor accesibilidad)';
+$lang['mode_o_audio']          = 'Imagen + Audio (peor accesibilidad)';
+$lang['forusers']              = '¿Utilizar CAPTCHA para los usuarios registrados también?';
+$lang['lettercount']           = 'Número de letras para usar (3-16). Si aumenta la cantidad, asegúrese de incrementar el ancho de la imagen de abajo también.';
+$lang['width']                 = 'Ancho de la imagen CAPTCHA (pixel)';
+$lang['height']                = 'Altura de la imagen CAPTCHA (pixel)';
+$lang['question']              = 'Pregunta para el modo de pregunta fija';
+$lang['answer']                = 'Responda al modo de pregunta fija';
diff --git a/lib/plugins/captcha/lang/fa/lang.php b/lib/plugins/captcha/lang/fa/lang.php
new file mode 100644
index 0000000..53f1fec
--- /dev/null
+++ b/lib/plugins/captcha/lang/fa/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Hossein Bayesteh <hosbai at gmail.com>
+ */
+$lang['testfailed']            = 'متاسفم، شما به درستی مقدار کپچا را جواب نداده اید. لطفا با دقت بیشتری آن را پر نمایید.';
+$lang['fillcaptcha']           = 'لطفا تمام حروف تصویر کپچا را وارد نمایید. می خواهیم مطمئن شویم شما ربات نیستید.';
+$lang['fillmath']              = 'لطفا معادله را حل کرده و پاسخ را وارد نمایید. می خواهیم مطمئن شویم شما ربات نیستید.';
+$lang['soundlink']             = 'اگر تصویر نامفهوم است. این فایل صوتی را دانلود کرده تا آن را برای شما بخواند.';
+$lang['honeypot']              = 'لطفا این بخش را خالی بگذارید: ';
diff --git a/lib/plugins/captcha/lang/fa/settings.php b/lib/plugins/captcha/lang/fa/settings.php
new file mode 100644
index 0000000..bfc5c8e
--- /dev/null
+++ b/lib/plugins/captcha/lang/fa/settings.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Hossein Bayesteh <hosbai at gmail.com>
+ * @author Sam01 <m.sajad079 at gmail.com>
+ */
+$lang['mode']                  = 'از کدام نوع کپچا می خواهید استفاده کنید؟';
+$lang['mode_o_js']             = 'متن (با جاوااسکریپت تنظیم می شود)';
+$lang['mode_o_text']           = 'متن (فقط دستی)';
+$lang['mode_o_math']           = 'سوال ریاضی';
+$lang['mode_o_question']       = 'سوال ثابت';
+$lang['mode_o_image']          = 'عکس (دسترسی بد)';
+$lang['mode_o_audio']          = 'عکس+صوت (دسترسی بهتر)';
+$lang['mode_o_figlet']         = 'Figlet ASCII Art (دسترسی بد)';
+$lang['forusers']              = ' آیا برای کاربران وارد شده به سایت نیز از کپچا استفاده شود؟';
+$lang['loginprotect']          = 'برای ورود به سایت کپچا نیاز باشد؟';
+$lang['lettercount']           = 'تعداد حروف مورد استفاده (3 تا 16 حرف). اگر شما مقدار را اضافه می کنید، مطمئن شوید که عرض تصویر را متناظرا افزایش دهید.';
+$lang['width']                 = 'عرض تصویر کپچا (پیکسل)';
+$lang['height']                = 'ارتفاع تصویر کپچا (پیکسل)';
+$lang['question']              = 'سوال برای حالت «سوال ثابت« ';
+$lang['answer']                = 'پاسخ سوال برای حالت «سوال ثابت»';
diff --git a/lib/plugins/captcha/lang/fr/lang.php b/lib/plugins/captcha/lang/fr/lang.php
new file mode 100644
index 0000000..fa57aed
--- /dev/null
+++ b/lib/plugins/captcha/lang/fr/lang.php
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Emmanuel Dupin <seedfloyd at gmail.com>
+ * @author bruno <bruno at ninesys.fr>
+ * @author Fabrice Dejaigher <fabrice at chtiland.com>
+ */
+$lang['testfailed']            = 'Désolé, vous n\'avez pas répondu correctement au test anti-spam. Peut-être n\'êtes vous pas humain ?';
+$lang['fillcaptcha']           = 'Merci de recopier le code ci-contre pour prouver que vous êtes humain :';
+$lang['fillmath']              = 'S\'il vous plaît résolvez l\'équation suivante pour prouver que vous êtes humain.';
+$lang['soundlink']             = 'Si vous ne pouvez pas lire le code, téléchargez ce fichier .wav pour l\'écouter.';
+$lang['honeypot']              = 'Merci de laisser ce champ vide : ';
diff --git a/lib/plugins/captcha/lang/fr/settings.php b/lib/plugins/captcha/lang/fr/settings.php
new file mode 100644
index 0000000..50236dc
--- /dev/null
+++ b/lib/plugins/captcha/lang/fr/settings.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Emmanuel Dupin <seedfloyd at gmail.com>
+ * @author bruno <bruno at ninesys.fr>
+ * @author Fabrice Dejaigher <fabrice at chtiland.com>
+ * @author Pietroni <pietroni at informatique.univ-paris-diderot.fr>
+ * @author Schplurtz le Déboulonné <Schplurtz at laposte.net>
+ */
+$lang['mode']                  = 'Quel type de CAPTCHA utiliser ?';
+$lang['mode_o_js']             = 'Texte (prérempli avec JavaScript)';
+$lang['mode_o_text']           = 'Texte (remplissage manuel)';
+$lang['mode_o_math']           = 'Problème mathématique';
+$lang['mode_o_question']       = 'Question fixe';
+$lang['mode_o_image']          = 'Image (mauvaise accessibilité)';
+$lang['mode_o_audio']          = 'Image + Audio (meilleure accessibilité)';
+$lang['mode_o_svg']            = 'SVG (lisible, mauvaise accessibilité)';
+$lang['mode_o_svgaudio']       = 'SVG + Audio (lisible, meilleure accessibilité)';
+$lang['mode_o_figlet']         = 'ASCII Art (mauvaise accessibilité)';
+$lang['forusers']              = 'Utiliser également le CAPTCHA pour les utilisateurs connectés ?';
+$lang['loginprotect']          = 'Exiger un CAPTCHA pour se connecter?';
+$lang['lettercount']           = 'Nombre de lettres à utiliser (3 à 16). Pensez à augmenter la taille de l\'image ci-dessous en adéquation avec le nombre de lettres afin que celles-ci soient correctement affichées.';
+$lang['width']                 = 'Largeur de l\'image du CAPTCHA (en pixels)';
+$lang['height']                = 'Hauteur de l\'image du CAPTCHA (en pixels)';
+$lang['question']              = 'Question pour le mode \'question fixe\'';
+$lang['answer']                = 'Réponse pour le mode \'question fixe\'';
diff --git a/lib/plugins/captcha/lang/hu/lang.php b/lib/plugins/captcha/lang/hu/lang.php
new file mode 100644
index 0000000..49bd062
--- /dev/null
+++ b/lib/plugins/captcha/lang/hu/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Serenity87HUN <anikototh87 at gmail.com>
+ */
+$lang['testfailed']            = 'Rosszul válaszoltál a CAPTCHA-ra. Lehet, hogy nem is ember vagy?';
+$lang['fillcaptcha']           = 'Kérlek írd be az összes betűt a dobozba, hogy bebizonyítsd, ember vagy.';
+$lang['fillmath']              = 'Kérlek oldd meg az alábbi egyenletet, hogy bebizonyítsd, ember vagy.';
+$lang['soundlink']             = 'Ha nem látod a képen szereplő szöveget, töltsd le ezt a .wav fájlt, amiben felolvassák.';
+$lang['honeypot']              = 'Ezt a mezőt kérlek hagyd üresen:';
diff --git a/lib/plugins/captcha/lang/hu/settings.php b/lib/plugins/captcha/lang/hu/settings.php
new file mode 100644
index 0000000..348363c
--- /dev/null
+++ b/lib/plugins/captcha/lang/hu/settings.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Serenity87HUN <anikototh87 at gmail.com>
+ * @author Marina Vladi <deldadam at gmail.com>
+ */
+$lang['mode']                  = 'Milyen CAPTCHA-t használjunk?';
+$lang['mode_o_js']             = 'Szöveg (JavaScript által kitöltve)';
+$lang['mode_o_text']           = 'Szöveg (kézzel kitöltendő)';
+$lang['mode_o_math']           = 'Matematikai feladat';
+$lang['mode_o_question']       = 'Biztonsági kérdés';
+$lang['mode_o_image']          = 'Kép (nehezen érthető)';
+$lang['mode_o_audio']          = 'Kép+hang (jobban érthető)';
+$lang['mode_o_figlet']         = 'FIGlet-betűrajz (nehezen érthető)';
+$lang['forusers']              = 'Bejelentkezett felhasználóknál is használjunk CAPTCHA-t?';
+$lang['lettercount']           = 'Felhasználandó betűk száma (3-16). Ha növeled a karakterek számát, ne felejtsd el a kép szélességét is megváltoztatni.';
+$lang['width']                 = 'CAPTCHA-hoz felhasznált kép szélessége (pixel)';
+$lang['height']                = 'CAPTCHA-hoz felhasznált kép magassága (pixel)';
+$lang['question']              = 'Biztonsági kérdés mód kérdése';
+$lang['answer']                = 'Válasz a biztonsági kérdésre';
diff --git a/lib/plugins/captcha/lang/is/lang.php b/lib/plugins/captcha/lang/is/lang.php
new file mode 100644
index 0000000..652978c
--- /dev/null
+++ b/lib/plugins/captcha/lang/is/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Þór Sigurðsson <thor at orku.net>
+ */
+$lang['testfailed']            = 'Því miður, en staðfestingarkóðanum var ekki rétt svarað. Kannski ertu ekki mennsk(ur) þrátt fyrir allt?';
+$lang['fillcaptcha']           = 'Vinsamlegast ritaðu alla stafina inn í reitinn til að sanna að þú sért manneskja.';
+$lang['fillmath']              = 'Vinsamlegast leystu eftirfarandi jöfnu til að sanna að þú sért manneskja.';
+$lang['soundlink']             = 'Ef þú getur ekki lesið stafina á myndinni, sæktu þá þessa .wav skrá til að fá stafina lesna fyrir þig.';
+$lang['honeypot']              = 'Vinsamlegast skildu þennan reit eftir auðan:';
diff --git a/lib/plugins/captcha/lang/is/settings.php b/lib/plugins/captcha/lang/is/settings.php
new file mode 100644
index 0000000..2867f30
--- /dev/null
+++ b/lib/plugins/captcha/lang/is/settings.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Þór Sigurðsson <thor at orku.net>
+ */
+$lang['mode']                  = 'Hverslags stafestingarkóða á að nota?';
+$lang['mode_o_js']             = 'Texta (fylltan fyrirfram með JavaScript)';
+$lang['mode_o_text']           = 'Texta (aðeins handvirkt)';
+$lang['mode_o_math']           = 'Stærðfræðiþraut';
+$lang['mode_o_question']       = 'Fyrirfram ákveðin spurning';
+$lang['mode_o_image']          = 'Mynd (slæmt aðgengi fatlaðra)';
+$lang['mode_o_audio']          = 'Mynd og hljóð (betra aðgengi fatlaðra)';
+$lang['mode_o_figlet']         = 'Figlet ASCII mynd (slæmt aðgengi fatlaðra)';
+$lang['forusers']              = 'Á að nota staðfestingarkóða fyrir innskráða notendur líka?';
+$lang['loginprotect']          = 'Þarf að nota staðfestingarkóða til að skrá inn?';
+$lang['lettercount']           = 'Fjöldi stafa sem á að nota (3-16). Ef þú eykur fjöldann, vertu þá viss um að auka breidd myndarinnar að neðan einnig.';
+$lang['width']                 = 'Breidd staðfestingarmyndarinnar í punktum';
+$lang['height']                = 'Hæð staðfestingarmyndarinnar í punktum';
+$lang['question']              = 'Spurning fyrir fyrir ákveðnu staðfestingarspurninguna';
+$lang['answer']                = 'Svar fyrir fyrirfram ákveðnu staðfestingarspurninguna';
diff --git a/lib/plugins/captcha/lang/it/lang.php b/lib/plugins/captcha/lang/it/lang.php
new file mode 100644
index 0000000..444023c
--- /dev/null
+++ b/lib/plugins/captcha/lang/it/lang.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Willy
+ * @author Torpedo <dgtorpedo at gmail.com>
+ */
+$lang['testfailed']            = 'Spiacente, ma non hai risposto correttamente a CAPTCHA. Potresti non essere del tutto umano.';
+$lang['fillcaptcha']           = 'Per favore inserisci le lettere nel box accanto per provare che sei una persona reale.';
+$lang['fillmath']              = 'Per favore risolvi la seguente equazione per dimostrare che sei un essere umano.';
+$lang['soundlink']             = 'Se non riesci a leggere le lettere nell\'immagine, scarica questo file .wav ed eseguilo, leggerà le lettere per te.';
+$lang['honeypot']              = 'Per favore lascia questo campo vuoto:';
diff --git a/lib/plugins/captcha/lang/it/settings.php b/lib/plugins/captcha/lang/it/settings.php
new file mode 100644
index 0000000..b45b957
--- /dev/null
+++ b/lib/plugins/captcha/lang/it/settings.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author by Willy
+ * @author Torpedo <dgtorpedo at gmail.com>
+ */
+$lang['mode']                  = 'Che tipo di CAPTCHA vuoi usare?';
+$lang['mode_o_js']             = 'Testo (precompilato con JavaScript)';
+$lang['mode_o_text']           = 'Testo (Solo Manuale)';
+$lang['mode_o_math']           = 'Problema di matematica';
+$lang['mode_o_question']       = 'Domanda Immutabile';
+$lang['mode_o_image']          = 'Immagine (Non molto Accessibile)';
+$lang['mode_o_audio']          = 'Immagine + Audio (Migliore Accessibilità)';
+$lang['mode_o_figlet']         = 'Immagine ASCII FIGlet (Non molto Accessibile)';
+$lang['forusers']              = 'Vuoi usare CAPTCHA anche per gli utenti loggati?';
+$lang['loginprotect']          = 'Richiedere un CAPTCHA per l\'accesso?';
+$lang['lettercount']           = 'Numero di lettere da usare (3-16). Se aumenti il numero, accertati di aumentare anche la larghezza dell\'immagine qui sotto.';
+$lang['width']                 = 'Larghezza dell\'immagine di CAPTCHA (pixel)';
+$lang['height']                = 'Altezza dell\'immagine di CAPTCHA (pixel)';
+$lang['question']              = 'Domanda per la modalità Domanda Immutabile';
+$lang['answer']                = 'Risposta per la modalità Domanda Immutabile';
diff --git a/lib/plugins/captcha/lang/ja/lang.php b/lib/plugins/captcha/lang/ja/lang.php
new file mode 100644
index 0000000..7e7fd25
--- /dev/null
+++ b/lib/plugins/captcha/lang/ja/lang.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author OHTSU Yoshifumi <dev at decomo.info>
+ * @author Hideaki SAWADA <chuno at live.jp>
+ */
+$lang['testfailed']            = '申し訳ありませんが、CAPTCHAに対して適切に応答していません。おそらくですが人ではありませんね?';
+$lang['fillcaptcha']           = '人間の証明として、ボックス内の全ての文字を入力してください。';
+$lang['fillmath']              = '人間の証明として、以下の数式の答えを入力して下さい。';
+$lang['soundlink']             = '画像の文字が読めなければ、文字を読んだ.wavファイルをダウンロードして下さい。';
+$lang['honeypot']              = 'この項目は空のままにして下さい:';
diff --git a/lib/plugins/captcha/lang/ja/settings.php b/lib/plugins/captcha/lang/ja/settings.php
new file mode 100644
index 0000000..1fb5372
--- /dev/null
+++ b/lib/plugins/captcha/lang/ja/settings.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author OHTSU Yoshifumi <dev at decomo.info>
+ * @author Hideaki SAWADA <chuno at live.jp>
+ * @author Ikuo Obataya <i.obataya at gmail.com>
+ */
+$lang['mode']                  = '認証の方式';
+$lang['mode_o_js']             = '文字 (JavaScriptによる自動入力)';
+$lang['mode_o_text']           = '文字 (手動入力)';
+$lang['mode_o_math']           = '計算式';
+$lang['mode_o_question']       = '固定質問';
+$lang['mode_o_image']          = '画像 (低アクセシビリティ)';
+$lang['mode_o_audio']          = '画像+音声 (中アクセシビリティ)';
+$lang['mode_o_figlet']         = 'Figlet [アルファベットAA] (低アクセシビリティ)';
+$lang['forusers']              = 'ログインユーザーに対してもCAPTCHA認証を行う';
+$lang['loginprotect']          = 'ログインにCAPTCHAを要求しますか?';
+$lang['lettercount']           = '使用する文字数(3~16)。文字数を増やす場合は下の画像の幅も同様に増やして下さい。';
+$lang['width']                 = 'CAPTCHA画像の幅 (ピクセル)';
+$lang['height']                = 'CAPTCHA画像の高さ(ピクセル)';
+$lang['question']              = '固定質問方式の質問';
+$lang['answer']                = '固定質問方式の回答';
diff --git a/lib/plugins/captcha/lang/ko/lang.php b/lib/plugins/captcha/lang/ko/lang.php
new file mode 100644
index 0000000..fb254a0
--- /dev/null
+++ b/lib/plugins/captcha/lang/ko/lang.php
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Andreas Gohr <andi at splitbrain.org>
+ * @author Myeongjin <aranet100 at gmail.com>
+ * @author chobkwon <chobkwon at gmail.com>
+ */
+$lang['testfailed']            = '죄송하지만 CAPTCHA(캡차)가 올바르지 않습니다. 아마도 인간이 아니죠?';
+$lang['fillcaptcha']           = '인간임을 증명하기 위해 상자에 있는 모든 글자를 채워주세요.';
+$lang['fillmath']              = '인간임을 증명하기 위해 다음 방정식을 푸세요.';
+$lang['soundlink']             = '그림에 있는 글자를 읽을 수 없다면, 당신에게 들려줄 이 .wav 파일을 다운로드하세요.';
+$lang['honeypot']              = '이 필드는 비어 있도록 유지하세요:';
diff --git a/lib/plugins/captcha/lang/ko/settings.php b/lib/plugins/captcha/lang/ko/settings.php
new file mode 100644
index 0000000..49865a8
--- /dev/null
+++ b/lib/plugins/captcha/lang/ko/settings.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Andreas Gohr <andi at splitbrain.org>
+ * @author Myeongjin <aranet100 at gmail.com>
+ * @author chobkwon <chobkwon at gmail.com>
+ */
+$lang['mode']                  = '어떤 CAPTCHA(캡차) 종류를 사용하겠습니까?';
+$lang['mode_o_js']             = '글자 (자바스크립트로 미리 채워짐)';
+$lang['mode_o_text']           = '글자 (설명문서만)';
+$lang['mode_o_math']           = '수학 문제';
+$lang['mode_o_question']       = '고정된 질문';
+$lang['mode_o_image']          = '그림 (접근성이 낮음)';
+$lang['mode_o_audio']          = '그림+소리 (접근성이 더 나음)';
+$lang['mode_o_figlet']         = 'Figlet ASCII 아트 (접근성이 낮음)';
+$lang['forusers']              = '로그인한 사용자도 CAPTCHA(캡차)를 사용하겠습니까?';
+$lang['loginprotect']          = '로그인하려면 CAPTCHA(캡차)가 필요합니까?';
+$lang['lettercount']           = '사용할 글자 수. (3-16) 양을 증가하면, 아래 그림의 너비도 증가해야 합니다.';
+$lang['width']                 = 'CAPTCHA(캡차) 그림의 너비 (픽셀)';
+$lang['height']                = 'CAPTCHA(캡차) 그림의 높이 (픽셀)';
+$lang['question']              = '고정된 질문 모드에 대한 질문';
+$lang['answer']                = '고정된 질문 모드에 대한 답변';
diff --git a/lib/plugins/captcha/lang/nl/lang.php b/lib/plugins/captcha/lang/nl/lang.php
new file mode 100644
index 0000000..bf07a56
--- /dev/null
+++ b/lib/plugins/captcha/lang/nl/lang.php
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Ruben Schouten <mail at ruben.cc>
+ * @author Mark C. Prins <mprins at users.sf.net>
+ * @author Mark Prins <mprins at users.sf.net>
+ */
+$lang['testfailed']            = 'Sorry, maar de CAPTCHA is onjuist beantwoord. Misschien ben je toch geen mens?';
+$lang['fillcaptcha']           = 'Tik de letters in het onderstaande vakje over om aan te tonen dat je een mens bent.';
+$lang['fillmath']              = 'Geef antwoord op de rekensom om aan te tonen dat je een mens bent.';
+$lang['soundlink']             = 'Als je de letters in de afbeelding niet kunt lezen kun je dit .wav bestand downloaden om ze te laten voorlezen.';
+$lang['honeypot']              = 'Dit veld leeg laten';
diff --git a/lib/plugins/captcha/lang/nl/settings.php b/lib/plugins/captcha/lang/nl/settings.php
new file mode 100644
index 0000000..0050236
--- /dev/null
+++ b/lib/plugins/captcha/lang/nl/settings.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Ruben Schouten <mail at ruben.cc>
+ * @author Mark C. Prins <mprins at users.sf.net>
+ * @author Mark Prins <mprins at users.sf.net>
+ * @author Johan Wijnker <johan at wijnker.eu>
+ */
+$lang['mode']                  = 'Welk type CAPTCHA wil je gebruiken?';
+$lang['mode_o_js']             = 'Tekst (automatisch ingevuld via JavaScript)';
+$lang['mode_o_text']           = 'Tekst (handmatig overtikken)';
+$lang['mode_o_math']           = 'Wiskunde opgave (eenvoudige rekensom)';
+$lang['mode_o_question']       = 'Vaste vraag';
+$lang['mode_o_image']          = 'Afbeelding (slechte toegankelijkhied)';
+$lang['mode_o_audio']          = 'Afbeelding+Audio (betere toegankelijkheid)';
+$lang['mode_o_figlet']         = 'Figlet ASCII Art (slechte toegankelijkheid)';
+$lang['forusers']              = 'Ook CAPTCHA voor ingelogde gebruikers gebruiken?';
+$lang['loginprotect']          = 'Vereis een CAPTCHA om in te loggen?';
+$lang['lettercount']           = 'Aantal te gebruiken letters (3-16). Let er op ook de breedte van de afbeelding hieronder te vergroten als het aantal wordt verhoogd';
+$lang['width']                 = 'Breedte van de CAPTCHA afbeelding (pixels)';
+$lang['height']                = 'Hoogte van de CAPTCHA afbeelding (pixels)';
+$lang['question']              = 'Vraag voor de vaste vraag modus';
+$lang['answer']                = 'Antwoord voor de vaste vraag modus';
diff --git a/lib/plugins/captcha/lang/nn/lang.php b/lib/plugins/captcha/lang/nn/lang.php
new file mode 100644
index 0000000..dc20a1a
--- /dev/null
+++ b/lib/plugins/captcha/lang/nn/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Pål Julius Skogholt <pal.julius at skogholt.org>
+ */
+$lang['testfailed']            = 'Lei for det, men CAPTHCA-svaret ditt var ikkje korrekt. Er du kanskje ikkje eit menneske likevel?';
+$lang['fillcaptcha']           = 'Gjer vel og fyll inn alle bokstavane i boksen for å bevise at du er eit menenske.';
+$lang['fillmath']              = 'Gjer vel og løys denne likninga for å bevise at du er menneske';
+$lang['soundlink']             = 'Dersom du ikkje kan lese bokstavane i bildet, last ned .wav-fila for å få dei opplest';
+$lang['honeypot']              = 'Hald dette feltet tomt';
diff --git a/lib/plugins/captcha/lang/nn/settings.php b/lib/plugins/captcha/lang/nn/settings.php
new file mode 100644
index 0000000..5bf2d60
--- /dev/null
+++ b/lib/plugins/captcha/lang/nn/settings.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Pål Julius Skogholt <pal.julius at skogholt.org>
+ */
+$lang['mode']                  = 'Kva type CAPTCA skal du bruke?';
+$lang['mode_o_js']             = 'Tekst (forfylt med JavaScript)';
+$lang['mode_o_text']           = 'Tekst (berre manuell)';
+$lang['mode_o_math']           = 'Matteproblem';
+$lang['mode_o_question']       = 'Fast spørsmål';
+$lang['mode_o_image']          = 'Bilde (vanskeleg tilgjenge)';
+$lang['mode_o_audio']          = 'Bilde og lys (betre tilgjenge)';
+$lang['mode_o_figlet']         = 'Figlet ASCII-kunst (vanskeleg tilgjenge)';
+$lang['forusers']              = 'Bruk CAPTCHA for innlogga brukarar';
+$lang['lettercount']           = 'Kor mange bokstavar skal brukast (3-16). Dersom du aukar mengda, må du og utvide storleiken på feltet.';
+$lang['width']                 = 'Breidda på CAPTCHA-bildet (pikslar)';
+$lang['height']                = 'Høgda på CAPTCHA-bildet (i pikslar)';
+$lang['question']              = 'Fast spørsmål';
+$lang['answer']                = 'Svar på fast spørsmål';
diff --git a/lib/plugins/captcha/lang/no/lang.php b/lib/plugins/captcha/lang/no/lang.php
new file mode 100644
index 0000000..0ef1790
--- /dev/null
+++ b/lib/plugins/captcha/lang/no/lang.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Pål Julius Skogholt <pal.julius at skogholt.org>
+ * @author Arne Hanssen <arne.hanssen at getmail.no>
+ */
+$lang['testfailed']            = 'Dessverre, du svarte ikke rett på CAPTCHAen. Kanskje du ikke er et menneske likevel?';
+$lang['fillcaptcha']           = 'Vennligst fyll inn alle bokstavene i feltet for å bevise at du er et menneske.';
+$lang['fillmath']              = 'Vennligst løys denne ligninga for å bevise at du er et menneske.';
+$lang['soundlink']             = 'Dersom du ikke kan lese bokstavene på bildet, last ned denne .wav-fila for å få de opplest.';
+$lang['honeypot']              = 'Vennligst hold dette feltet tomt.';
diff --git a/lib/plugins/captcha/lang/no/settings.php b/lib/plugins/captcha/lang/no/settings.php
new file mode 100644
index 0000000..677e6ce
--- /dev/null
+++ b/lib/plugins/captcha/lang/no/settings.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Pål Julius Skogholt <pal.julius at skogholt.org>
+ * @author Daniel Raknes <rada at jbv.no>
+ */
+$lang['mode']                  = 'Hvilken type CAPTCHA vil du bruke?';
+$lang['mode_o_js']             = 'Tekst (forfylt med JavaScript)';
+$lang['mode_o_text']           = 'Tekst (bare manuelt)';
+$lang['mode_o_math']           = 'Matteproblem';
+$lang['mode_o_question']       = 'Fast spørsmål';
+$lang['mode_o_image']          = 'Bilde (vanskelig tilgjengelig)';
+$lang['mode_o_audio']          = 'Bilde og lyd (bedre tilgjengelighet)';
+$lang['mode_o_figlet']         = 'Figlet ASCII-kunst (vanskelig tilgjengelig)';
+$lang['forusers']              = 'Bruke CAPTCHA for innlogga brukere?';
+$lang['loginprotect']          = 'Kreve CAPTCHA ved innlogging?';
+$lang['lettercount']           = 'Antall bokstaver (3-16). Om du øker antallet må du også øke bredden av bildet under.';
+$lang['width']                 = 'Bredde på CAPTCHA-bildet (i piksler)';
+$lang['height']                = 'Høyde på CAPTCHA-bildet (i piksler)';
+$lang['question']              = 'Fast spørsmål';
+$lang['answer']                = 'Svar på fast spørsmål';
diff --git a/lib/plugins/captcha/lang/pl/lang.php b/lib/plugins/captcha/lang/pl/lang.php
new file mode 100644
index 0000000..cb23f92
--- /dev/null
+++ b/lib/plugins/captcha/lang/pl/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Paweł Jan Czochański <czochanski at gmail.com>
+ */
+$lang['testfailed']            = 'Wybacz, ale CAPTCHA nie została uzupełniona poprawnie. Może wcale nie jesteś człowiekiem?';
+$lang['fillcaptcha']           = 'Proszę wprowadzić wszystkie znaki w pole, by udowodnić, że jesteś człowiekiem.';
+$lang['fillmath']              = 'Proszę rozwiązać poniższe równanie, by udowodnić, że jesteś człowiekiem.';
+$lang['soundlink']             = 'Jeżeli nie jesteś w stanie przeczytać znaków widocznych na obrazie pobierz plik .wav, w którym zawarta jest ich głosowa reprezentacja.';
+$lang['honeypot']              = 'Proszę pozostawić to pole puste.';
diff --git a/lib/plugins/captcha/lang/pl/settings.php b/lib/plugins/captcha/lang/pl/settings.php
new file mode 100644
index 0000000..33605ed
--- /dev/null
+++ b/lib/plugins/captcha/lang/pl/settings.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Paweł Jan Czochański <czochanski at gmail.com>
+ * @author Mati <mackosa at wp.pl>
+ */
+$lang['mode']                  = 'Jaki typ CAPTCHA zastosować?';
+$lang['mode_o_text']           = 'Tekst (tylko ręcznie)';
+$lang['mode_o_math']           = 'Problem matematyczny';
+$lang['mode_o_question']       = 'Stałe pytanie';
+$lang['mode_o_image']          = 'Obraz (słaba dostępność)';
+$lang['mode_o_audio']          = 'Obraz+Dźwięk (lepsza dostępność)';
+$lang['mode_o_figlet']         = 'Sztuka figletowych ASCII (słaba dostępność)';
+$lang['forusers']              = 'Stosować CAPTCHA również dla zalogowanych użytkowników?';
+$lang['lettercount']           = 'Wykorzystywane liczby i litery (3-16). Pamiętaj by wraz ze wzrostem ich ilości zwiększać również szerokość obrazu poniżej.';
+$lang['width']                 = 'Szerokość obrazu CAPTCHA (w pikselach)';
+$lang['height']                = 'Wysokość obrazu CAPTCHA (w pikselach)';
+$lang['question']              = 'Pytanie stosowane w trybie stałego pytania';
+$lang['answer']                = 'Odpowiedź na stałe pytanie';
diff --git a/lib/plugins/captcha/lang/pt-br/lang.php b/lib/plugins/captcha/lang/pt-br/lang.php
new file mode 100644
index 0000000..7a37dd1
--- /dev/null
+++ b/lib/plugins/captcha/lang/pt-br/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Juliano Marconi Lanigra <juliano.marconi at gmail.com>
+ */
+$lang['testfailed']            = 'Desculpe, mas o CAPTCHA não foi preenchido corretamente. Talvez você não seja humano?';
+$lang['fillcaptcha']           = 'Por favor preencha todas as letras dentro da caixa para provar que você é humano.';
+$lang['fillmath']              = 'Por favor resolva a seguinte equação para provar que você é humano.';
+$lang['soundlink']             = 'Se você não pode ler as letras na imagem, faça o download desse .wav para que elas sejam lidas para você.';
+$lang['honeypot']              = 'Por favor deixe esse campo em branco:';
diff --git a/lib/plugins/captcha/lang/pt-br/settings.php b/lib/plugins/captcha/lang/pt-br/settings.php
new file mode 100644
index 0000000..01d3e84
--- /dev/null
+++ b/lib/plugins/captcha/lang/pt-br/settings.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Juliano Marconi Lanigra <juliano.marconi at gmail.com>
+ * @author Oze Projetos <oze at oze.net.br>
+ */
+$lang['mode']                  = 'Qual tipo de CAPTCHA usar?';
+$lang['mode_o_js']             = 'Texto (pré-preenchido com JavaScript)';
+$lang['mode_o_text']           = 'Texto (somente manual)';
+$lang['mode_o_math']           = 'Problema de Matemática';
+$lang['mode_o_question']       = 'Questão Resolvida';
+$lang['mode_o_image']          = 'Imagem (acessibilidade ruim)';
+$lang['mode_o_audio']          = 'Imagem+Áudio (acessibilidade melhor)';
+$lang['mode_o_figlet']         = 'Figlet ASCII Art (acessibilidade ruim)';
+$lang['forusers']              = 'Também usar CAPTCHA para usuários logados?';
+$lang['loginprotect']          = 'Exigir um CAPTCHA para entrar?';
+$lang['lettercount']           = 'Número de letras para usar (3-16). Se você aumentar a quantidade, lembre de também aumentar a largura da imagem abaixo.';
+$lang['width']                 = 'Largura da imagem do CAPTCHA (pixel)';
+$lang['height']                = 'Altura da imagem do CAPTCHA (pixel)';
+$lang['question']              = 'Pergunta para o modo de pergunta fixa';
+$lang['answer']                = 'Resposta para o modo de pergunta fixa';
diff --git a/lib/plugins/captcha/lang/pt/lang.php b/lib/plugins/captcha/lang/pt/lang.php
new file mode 100644
index 0000000..3ee95d5
--- /dev/null
+++ b/lib/plugins/captcha/lang/pt/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author André Neves <drakferion at gmail.com>
+ */
+$lang['testfailed']            = 'Infelizmente o CAPTCHA não foi respondido corretamente. Talvez você afinal não seja humano?';
+$lang['fillcaptcha']           = 'Por favor preencha todas as letras na caixa para provar que é humano.';
+$lang['fillmath']              = 'Por favor resolva a seguinte equação para provar que é humano.';
+$lang['soundlink']             = 'Se não pode ler as letras na imagem, descarregue este ficheiro .wav para as ouvir.';
+$lang['honeypot']              = 'Por favor mantenha este campo vazio:';
diff --git a/lib/plugins/captcha/lang/pt/settings.php b/lib/plugins/captcha/lang/pt/settings.php
new file mode 100644
index 0000000..4682f81
--- /dev/null
+++ b/lib/plugins/captcha/lang/pt/settings.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author André Neves <drakferion at gmail.com>
+ * @author ANeves <drakferion at gmail.com>
+ */
+$lang['mode']                  = 'Que tipo de CAPTCHA usar?';
+$lang['mode_o_js']             = 'Texto (pré-preenchido com JavaScript)';
+$lang['mode_o_text']           = 'Texto (somente manual)';
+$lang['mode_o_math']           = 'Problema Matemático';
+$lang['mode_o_question']       = 'Pergunta Fixa';
+$lang['mode_o_image']          = 'Imagem (má acessibilidade)';
+$lang['mode_o_audio']          = 'Imagem+Áudio (melhor acessibilidade)';
+$lang['mode_o_figlet']         = 'Arte em ASCII Figlet (má acessibilidade)';
+$lang['forusers']              = 'Também usar CAPTCHA para utilizadores autenticados?';
+$lang['loginprotect']          = 'Exigir um CAPTCHA para se autenticar.';
+$lang['lettercount']           = 'Número de letras a usar (3-16). Se aumentar a quantidade, assegure-se de aumentar também a largura da imagem, abaixo.';
+$lang['width']                 = 'Largura da imagem CAPTCHA (pixel)';
+$lang['height']                = 'Altura da imagem CAPTCHA (pixel)';
+$lang['question']              = 'Pergunta para o modo de pergunta fixa';
+$lang['answer']                = 'Resposta para o modo de pergunta fixa';
diff --git a/lib/plugins/captcha/lang/ru/lang.php b/lib/plugins/captcha/lang/ru/lang.php
new file mode 100644
index 0000000..4810ec3
--- /dev/null
+++ b/lib/plugins/captcha/lang/ru/lang.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Aleksandr Selivanov <alexgearbox at gmail.com>
+ * @author Ilya Rozhkov <impeck at ya.ru>
+ */
+$lang['testfailed']            = 'Извините, код подтверждения введён неверно.';
+$lang['fillcaptcha']           = 'Пожалуйста, введите код подтверждения, чтобы доказать, что вы не робот:';
+$lang['fillmath']              = 'Ответьте пожалуйста на вопрос, чтобы доказать, что вы человек.';
+$lang['soundlink']             = 'Если вы не можете прочитать символы на изображении, загрузите и воспроизведите wav-файл.';
+$lang['honeypot']              = 'Пожалуйста, оставьте это поле пустым:';
diff --git a/lib/plugins/captcha/lang/ru/settings.php b/lib/plugins/captcha/lang/ru/settings.php
new file mode 100644
index 0000000..dc01396
--- /dev/null
+++ b/lib/plugins/captcha/lang/ru/settings.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Aleksandr Selivanov <alexgearbox at gmail.com>
+ * @author Ilya Rozhkov <impeck at ya.ru>
+ * @author Shpak Andrey <ashpak at ashpak.ru>
+ */
+$lang['mode']                  = 'Какой тип CAPTCHA использовать?';
+$lang['mode_o_js']             = 'Текст (заполнение JavaScript)';
+$lang['mode_o_text']           = 'Текст (ручной ввод)';
+$lang['mode_o_math']           = 'Математическая задача';
+$lang['mode_o_question']       = 'Конкретный вопрос';
+$lang['mode_o_image']          = 'Изображение (хорошая защита)';
+$lang['mode_o_audio']          = 'Изображение и звук (плохая защита)';
+$lang['mode_o_figlet']         = 'Figlet ASCII Art (хорошая защита)';
+$lang['forusers']              = 'Использоваться CAPTCHA для зарегистрированных пользователей?';
+$lang['loginprotect']          = 'Требовать ввод CAPTCHA для входа?';
+$lang['lettercount']           = 'Количество букв (3-16). Если вы увеличиваете количество букв, не забудьте увеличить ширину изображения ниже.';
+$lang['width']                 = 'Ширина изображения CAPTCHA (пиксель)';
+$lang['height']                = 'Высота изображения CAPTCHA (пиксель)';
+$lang['question']              = 'Вопрос для режима конкретного вопроса';
+$lang['answer']                = 'Ответ для режима конкретного вопроса ';
diff --git a/lib/plugins/captcha/lang/sk/lang.php b/lib/plugins/captcha/lang/sk/lang.php
new file mode 100644
index 0000000..f04ab4c
--- /dev/null
+++ b/lib/plugins/captcha/lang/sk/lang.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Jozef Riha <jose1711 at gmail.com>
+ * @author Martin Michalek <michalek.dev at gmail.com>
+ */
+$lang['testfailed']            = 'Ľutujem, ale na CAPTCHA nebolo odpovedané správne. Je možné, že by ste vôbec neboli človekom?';
+$lang['fillcaptcha']           = 'Vyplňte prosím všetky písmená v poli, aby ste dokázali, že nie ste skript.';
+$lang['fillmath']              = 'Prosím vyriešte nasledujúcu rovnicu, aby sme vás odlíšili od automatických web nástrojov.';
+$lang['soundlink']             = 'Ak nedokážete prečítať písmená na obrázku, stiahnite si tento .wav súbor a text vám prečítame.';
+$lang['honeypot']              = 'Prosím nechajte toto pole prázdne:';
diff --git a/lib/plugins/captcha/lang/sk/settings.php b/lib/plugins/captcha/lang/sk/settings.php
new file mode 100644
index 0000000..2f6c582
--- /dev/null
+++ b/lib/plugins/captcha/lang/sk/settings.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Jozef Riha <jose1711 at gmail.com>
+ * @author Martin Michalek <michalek.dev at gmail.com>
+ */
+$lang['mode']                  = 'Ktorý typ CAPTCHA sa má použiť?';
+$lang['mode_o_js']             = 'Text (predvyplnený JavaScriptom)';
+$lang['mode_o_text']           = 'Text (iba manuálne vložený)';
+$lang['mode_o_math']           = 'Matematický problém';
+$lang['mode_o_question']       = 'Pevne zadaná otázka';
+$lang['mode_o_image']          = 'Obrázok (pre ľudí s postihom)';
+$lang['mode_o_audio']          = 'Obrázok a zvuk (pre ľudí s menším postihom)';
+$lang['mode_o_figlet']         = 'ASCII obrázok (pre ľudí s postihom)';
+$lang['forusers']              = 'Používať CAPTCHA aj pre registrovaných užívateľov?';
+$lang['lettercount']           = 'Počet písmen (3-16). Ak zvýšite počet, zväčšite tiež šírku obrázka uvedeného nižšie.';
+$lang['width']                 = 'Šírka CAPTCHA obrázku (v bodoch)';
+$lang['height']                = 'Výška CAPTCHA obrázku (v bodoch)';
+$lang['question']              = 'Otázka pre typ pevne zadanej otázky';
+$lang['answer']                = 'Odpoveď pre typ pevne zadanej otázky';
diff --git a/lib/plugins/captcha/lang/tr/lang.php b/lib/plugins/captcha/lang/tr/lang.php
new file mode 100644
index 0000000..5132d09
--- /dev/null
+++ b/lib/plugins/captcha/lang/tr/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Ozan Hacibekiroglu <ozan_haci at yahoo.com>
+ */
+$lang['testfailed']            = 'Üzgünüz, CAPTCHA doğru cevaplanmadı. Belki bir insan değilsiniz (bot\'sunuz)?';
+$lang['fillcaptcha']           = 'İnsan olduğunuzu kanıtlamak için lütfen bütün harfleri kutuya giriniz.';
+$lang['fillmath']              = 'Lütfen şu eşitliği çözünüz ki insan olduğunuzu ispatlayınız.';
+$lang['soundlink']             = 'Eğer resimdeki harfleri okuyamıyorsanız, bu .wav dosyasını size okuması için indiriniz.';
+$lang['honeypot']              = 'Lütfen bu alanı boş bırakınız: ';
diff --git a/lib/plugins/captcha/lang/tr/settings.php b/lib/plugins/captcha/lang/tr/settings.php
new file mode 100644
index 0000000..3ab73a2
--- /dev/null
+++ b/lib/plugins/captcha/lang/tr/settings.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Ehliman <ehlimansen at gmail.com>
+ * @author Ozan Hacibekiroglu <ozan_haci at yahoo.com>
+ * @author İlker R. Kapaç <irifat at gmail.com>
+ */
+$lang['mode']                  = 'Ne çeşit CAPTCHA kullanılacak?';
+$lang['mode_o_js']             = 'Metin (JavaScript ile önceden doldurulur)';
+$lang['mode_o_text']           = 'Metin (sadece manuel)';
+$lang['mode_o_math']           = 'Matematik Problemi';
+$lang['mode_o_question']       = 'Sabit Soru';
+$lang['mode_o_image']          = 'Resim (Kötü erişebilirlik)';
+$lang['mode_o_audio']          = 'Resim+Ses (iyi erişebilirlik)';
+$lang['mode_o_figlet']         = 'Figlet ASCII Art (kötü erişebilirlik)';
+$lang['forusers']              = 'CAPTCHA giriş yapmış kullanıcılar için de kullanılsın mı?';
+$lang['loginprotect']          = 'Oturum açılışında CAPTCHA sorulsun mu?';
+$lang['lettercount']           = 'Kullanılacak harf sayısı (3-16). Karakter sayısını artırırsanız, resim genişliğinin de arttığından emin olunuz.';
+$lang['width']                 = 'CAPTCHA resminin genişliği (piksel)';
+$lang['height']                = 'CAPTCHA resminin yüksekliği (piksel)';
+$lang['question']              = 'Sabit soru modu için soru';
+$lang['answer']                = 'Sabit soru modu için cevap';
diff --git a/lib/plugins/captcha/lang/uk/lang.php b/lib/plugins/captcha/lang/uk/lang.php
new file mode 100644
index 0000000..898a138
--- /dev/null
+++ b/lib/plugins/captcha/lang/uk/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Oleksandr Baranyuk <boffin at drivehq.com>
+ */
+$lang['testfailed']            = 'Вибачте, ви дали неправильну CAPTCHA-відповідь. Може ви взагалі не людина?';
+$lang['fillcaptcha']           = 'Будь ласка неберіть всі символи аби підтвердити, що ви людина.';
+$lang['fillmath']              = 'Розв\'жіть, будь ласка це рівняння аби підтвердити, що ви людина.';
+$lang['soundlink']             = 'Якщо ви не можете прочитати літери на картинці, завантажте цей .wav файл і прослухайте.';
+$lang['honeypot']              = 'Залиште це поле порожнім:';
diff --git a/lib/plugins/captcha/lang/uk/settings.php b/lib/plugins/captcha/lang/uk/settings.php
new file mode 100644
index 0000000..949c615
--- /dev/null
+++ b/lib/plugins/captcha/lang/uk/settings.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Oleksandr Baranyuk <boffin at drivehq.com>
+ */
+$lang['mode']                  = 'Який тип CAPTCHA використати?';
+$lang['mode_o_js']             = 'Текст (заповнений JavaScript)';
+$lang['mode_o_text']           = 'Текст (лише вручну)';
+$lang['mode_o_math']           = 'Математична задача';
+$lang['mode_o_question']       = 'Фіксоване питання';
+$lang['mode_o_image']          = 'Зображення (погана впізнаваність)';
+$lang['mode_o_audio']          = 'Зображення+аудіо (краща впізнаваність)';
+$lang['mode_o_figlet']         = 'Картинка з ASCII-символів (погана впізнаваність)';
+$lang['forusers']              = 'Використовувати CAPTCHA для авторизованих користувачів?';
+$lang['lettercount']           = 'Кількість символів (3-16). Якщо ви збільшуєте кількість, розширте також картинку нижче.';
+$lang['width']                 = 'Ширина CAPTCHA-зображення (пікселів)';
+$lang['height']                = 'Висота CAPTCHA-зображення (пікселів)';
+$lang['question']              = 'Питання для режиму фіксованого питання';
+$lang['answer']                = 'Відповідь для режиму фіксованого питання';
diff --git a/lib/plugins/captcha/lang/zh-tw/lang.php b/lib/plugins/captcha/lang/zh-tw/lang.php
new file mode 100644
index 0000000..4f6355f
--- /dev/null
+++ b/lib/plugins/captcha/lang/zh-tw/lang.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Danny Lin <danny0838 at pchome.com.tw>
+ * @author lioujheyu <lioujheyu at gmail.com>
+ */
+$lang['testfailed']            = '很抱歉,您沒有輸入正確的 CAPTCHA 驗證碼。';
+$lang['fillcaptcha']           = '請將字母填入方框。';
+$lang['fillmath']              = '請解開下列方程式以證明你是人類';
+$lang['soundlink']             = '如果您無法閱讀圖片中的字母,請下載收聽這個 WAV 檔。';
+$lang['honeypot']              = '請保持這個欄位空白';
diff --git a/lib/plugins/captcha/lang/zh-tw/settings.php b/lib/plugins/captcha/lang/zh-tw/settings.php
new file mode 100644
index 0000000..e494563
--- /dev/null
+++ b/lib/plugins/captcha/lang/zh-tw/settings.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Danny Lin <danny0838 at pchome.com.tw>
+ * @author lioujheyu <lioujheyu at gmail.com>
+ * @author CHENG <wucy0612 at gmail.com>
+ */
+$lang['mode']                  = '使用哪種 CAPTCHA 類型?';
+$lang['mode_o_js']             = '文字 (預先用 Javascript 填入)';
+$lang['mode_o_text']           = '文字 (手動填入)';
+$lang['mode_o_math']           = '數學問題';
+$lang['mode_o_question']       = '固定問題';
+$lang['mode_o_image']          = '圖片 (易用性差)';
+$lang['mode_o_audio']          = '圖片+聲音 (易用性較佳)';
+$lang['mode_o_figlet']         = 'Figlet ASCII 藝術字 (易用性差)';
+$lang['forusers']              = '已登入使用者也要 CAPTCHA 驗證嗎?';
+$lang['loginprotect']          = '登入前需要 CAPTCHA 驗證嗎?';
+$lang['lettercount']           = '多少字母會被使用(3-16)。如果你增加使用個數,請確保同時加寬圖片長度';
+$lang['width']                 = 'CAPTCHA 圖片寬度 (像素)';
+$lang['height']                = 'CAPTCHA 圖片高度 (像素)';
+$lang['question']              = '固定問題模式的問題';
+$lang['answer']                = '固定問題模式的答案';
diff --git a/lib/plugins/captcha/lang/zh/lang.php b/lib/plugins/captcha/lang/zh/lang.php
new file mode 100644
index 0000000..1846cd2
--- /dev/null
+++ b/lib/plugins/captcha/lang/zh/lang.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Andreas Gohr <andi at splitbrain.org>
+ * @author lainme <lainme993 at gmail.com>
+ */
+$lang['testfailed']            = '抱歉,您输入的验证码不正确。';
+$lang['fillcaptcha']           = '请在输入框中填入验证码以证明您不是机器人。';
+$lang['fillmath']              = '请填入算式的结果以证明您不是机器人。';
+$lang['soundlink']             = '如果您无法阅读图片中的字母,请下载此 .wav 文件。';
+$lang['honeypot']              = '请将此区域留空:';
diff --git a/lib/plugins/captcha/lang/zh/settings.php b/lib/plugins/captcha/lang/zh/settings.php
new file mode 100644
index 0000000..28f3dc7
--- /dev/null
+++ b/lib/plugins/captcha/lang/zh/settings.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Andreas Gohr <andi at splitbrain.org>
+ * @author lainme <lainme993 at gmail.com>
+ * @author 橙子狼 <2949384951 at qq.com>
+ * @author kuma <kuma000 at qq.com>
+ */
+$lang['mode']                  = '使用什么类型的验证码?';
+$lang['mode_o_js']             = '文本 (预先由 JavaScript 填写)';
+$lang['mode_o_text']           = '文本 (手动输入)';
+$lang['mode_o_math']           = '算术题';
+$lang['mode_o_question']       = '固定问题';
+$lang['mode_o_image']          = '图片 (无障碍性差)';
+$lang['mode_o_audio']          = '图片+音频 (更好的无障碍性)';
+$lang['mode_o_svg']            = 'SVG(不好的无障碍环境,易读的)';
+$lang['mode_o_svgaudio']       = 'SVG +音频(更好的无障碍环境,易读的)';
+$lang['mode_o_figlet']         = 'Figlet ASCII 艺术 (无障碍性差)';
+$lang['forusers']              = '对已登入的用户也适用吗?';
+$lang['loginprotect']          = '请输入验证码';
+$lang['lettercount']           = '使用字母的数目 (3-16)。如果您增加数目,请确保同时增加图片的宽度。';
+$lang['width']                 = '验证码图片宽度 (像素)';
+$lang['height']                = '验证码图片高度 (像素)';
+$lang['question']              = '固定问题模式的问题';
+$lang['answer']                = '固定问题模式的答案';
diff --git a/lib/plugins/captcha/manager.dat b/lib/plugins/captcha/manager.dat
new file mode 100644
index 0000000..68d7c9a
--- /dev/null
+++ b/lib/plugins/captcha/manager.dat
@@ -0,0 +1,3 @@
+downloadurl=https://github.com/splitbrain/dokuwiki-plugin-captcha/zipball/master
+installed=Sun, 14 Feb 2016 12:17:57 +0100
+updated=Sun, 05 Mar 2017 13:23:20 +0100
diff --git a/lib/plugins/captcha/plugin.info.txt b/lib/plugins/captcha/plugin.info.txt
new file mode 100644
index 0000000..1b37630
--- /dev/null
+++ b/lib/plugins/captcha/plugin.info.txt
@@ -0,0 +1,8 @@
+base   captcha
+author Andreas Gohr
+email  andi at splitbrain.org
+date   2017-02-02
+name   CAPTCHA Plugin
+desc   Use a CAPTCHA challenge to protect DokuWiki against automated spam
+url    http://www.dokuwiki.org/plugin:captcha
+
diff --git a/lib/plugins/captcha/script.js b/lib/plugins/captcha/script.js
new file mode 100644
index 0000000..3cb402c
--- /dev/null
+++ b/lib/plugins/captcha/script.js
@@ -0,0 +1,32 @@
+
+jQuery(function () {
+    var $wrap = jQuery('#plugin__captcha_wrapper');
+    if(!$wrap.length) return;
+
+    /**
+     * Autofill and hide the whole CAPTCHA stuff in the simple JS mode
+     */
+    var $code = jQuery('#plugin__captcha_code');
+    if ($code.length) {
+        var $box = $wrap.find('input[type=text]');
+        $box.first().val($code.text().replace(/([^A-Z])+/g, ''));
+        $wrap.hide();
+    }
+
+    /**
+     * Add a HTML5 player for the audio version of the CAPTCHA
+     */
+    var $audiolink = $wrap.find('a');
+    if($audiolink.length) {
+        var audio = document.createElement('audio');
+        if(audio) {
+            audio.src = $audiolink.attr('href');
+            $wrap.append(audio);
+            $audiolink.click(function (e) {
+                audio.play();
+                e.preventDefault();
+                e.stopPropagation();
+            });
+        }
+    }
+});
diff --git a/lib/plugins/captcha/sound.png b/lib/plugins/captcha/sound.png
new file mode 100644
index 0000000..6056d23
Binary files /dev/null and b/lib/plugins/captcha/sound.png differ
diff --git a/lib/plugins/captcha/style.css b/lib/plugins/captcha/style.css
new file mode 100644
index 0000000..e29676b
--- /dev/null
+++ b/lib/plugins/captcha/style.css
@@ -0,0 +1,36 @@
+.dokuwiki #plugin__captcha_wrapper img {
+    margin: 1px;
+    vertical-align: bottom;
+    border: 1px solid __border__;
+}
+
+.dokuwiki #plugin__captcha_wrapper pre {
+    font-size: 70%;
+    font-family: monospace;
+    font-weight: bold;
+    border: none;
+    background-color: __background__;
+    color: __text__;
+    padding: 0;
+}
+
+.dokuwiki #plugin__captcha_wrapper .svg {
+    display: inline-block;
+    background-color: __background__;
+    vertical-align: bottom;
+}
+
+.dokuwiki #plugin__captcha_wrapper svg {
+    width: 100%;
+    height: 100%;
+}
+.dokuwiki #plugin__captcha_wrapper svg path {
+    fill: __text__;
+}
+.dokuwiki #plugin__captcha_wrapper .no {
+    display: none;
+}
+
+.dokuwiki #plugin__captcha_wrapper {
+clear: left;
+}
diff --git a/lib/plugins/captcha/wav.php b/lib/plugins/captcha/wav.php
new file mode 100644
index 0000000..7cc98cf
--- /dev/null
+++ b/lib/plugins/captcha/wav.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * CAPTCHA antispam plugin - sound generator
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Andreas Gohr <gohr at cosmocode.de>
+ */
+
+if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__).'/../../../');
+define('NOSESSION', true);
+define('DOKU_DISABLE_GZIP_OUTPUT', 1);
+require_once(DOKU_INC.'inc/init.php');
+require_once(DOKU_INC.'inc/auth.php');
+
+$ID = $_REQUEST['id'];
+/** @var $plugin helper_plugin_captcha */
+$plugin = plugin_load('helper', 'captcha');
+
+if($plugin->getConf('mode') != 'audio' && $plugin->getConf('mode') != 'svgaudio') {
+    http_status(404);
+    exit;
+}
+
+$rand = $plugin->decrypt($_REQUEST['secret']);
+$code = strtolower($plugin->_generateCAPTCHA($plugin->_fixedIdent(), $rand));
+
+// prepare an array of wavfiles
+$lc   = dirname(__FILE__).'/lang/'.$conf['lang'].'/audio/';
+$en   = dirname(__FILE__).'/lang/en/audio/';
+$wavs = array();
+$lettercount = $plugin->getConf('lettercount');
+if($lettercount > strlen($code)) $lettercount = strlen($code);
+for($i = 0; $i < $lettercount; $i++) {
+    $file = $lc.$code{$i}.'.wav';
+    if(!@file_exists($file)) $file = $en.$code{$i}.'.wav';
+    $wavs[] = $file;
+}
+
+header('Content-type: audio/x-wav');
+header('Content-Disposition: attachment;filename=captcha.wav');
+
+echo joinwavs($wavs);
+
+/**
+ * Join multiple wav files
+ *
+ * All wave files need to have the same format and need to be uncompressed.
+ * The headers of the last file will be used (with recalculated datasize
+ * of course)
+ *
+ * @link http://ccrma.stanford.edu/CCRMA/Courses/422/projects/WaveFormat/
+ * @link http://www.thescripts.com/forum/thread3770.html
+ */
+function joinwavs($wavs) {
+    $fields = join(
+        '/', array(
+                  'H8ChunkID', 'VChunkSize', 'H8Format',
+                  'H8Subchunk1ID', 'VSubchunk1Size',
+                  'vAudioFormat', 'vNumChannels', 'VSampleRate',
+                  'VByteRate', 'vBlockAlign', 'vBitsPerSample'
+             )
+    );
+
+    $data = '';
+    foreach($wavs as $wav) {
+        $fp     = fopen($wav, 'rb');
+        $header = fread($fp, 36);
+        $info   = unpack($fields, $header);
+
+        // read optional extra stuff
+        if($info['Subchunk1Size'] > 16) {
+            $header .= fread($fp, ($info['Subchunk1Size'] - 16));
+        }
+
+        // read SubChunk2ID
+        $header .= fread($fp, 4);
+
+        // read Subchunk2Size
+        $size = unpack('vsize', fread($fp, 4));
+        $size = $size['size'];
+
+        // read data
+        $data .= fread($fp, $size);
+    }
+
+    return $header.pack('V', strlen($data)).$data;
+}
+
diff --git a/lib/plugins/loglog/action.php b/lib/plugins/loglog/action.php
new file mode 100644
index 0000000..b32c262
--- /dev/null
+++ b/lib/plugins/loglog/action.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Login/Logout logging plugin
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Andreas Gohr <gohr at cosmocode.de>
+ */
+
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
+
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
+require_once(DOKU_PLUGIN . 'action.php');
+
+class action_plugin_loglog extends DokuWiki_Action_Plugin {
+
+    var $islogin = false;
+
+    /**
+     * register the eventhandlers
+     */
+    function register(Doku_Event_Handler $controller) {
+        $controller->register_hook(
+            'ACTION_ACT_PREPROCESS',
+            'BEFORE',
+            $this,
+            'handle_before',
+            array()
+        );
+
+        // allow other plugins to emit logging events
+        $controller->register_hook(
+            'PLUGIN_LOGLOG_LOG',
+            'BEFORE',
+            $this,
+            'handle_custom',
+            array()
+        );
+
+        // autologout plugin
+        $controller->register_hook(
+            'ACTION_AUTH_AUTOLOGOUT',
+            'BEFORE',
+            $this,
+            'handle_autologout',
+            array()
+        );
+    }
+
+    /**
+     * Log an action
+     *
+     * @param $msg
+     * @param null|string $user
+     */
+    protected function _log($msg, $user = null) {
+        global $conf;
+        global $INPUT;
+
+        if(is_null($user)) $user = $INPUT->server->str('REMOTE_USER');
+        if(!$user) $user = $_REQUEST['u'];
+        if(!$user) return;
+
+        $t   = time();
+        $log = $t . "\t" . strftime($conf['dformat'], $t) . "\t" . $_SERVER['REMOTE_ADDR'] . "\t" . $user . "\t" . $msg;
+        io_saveFile($conf['cachedir'] . '/loglog.log', "$log\n", true);
+    }
+
+    /**
+     * Handle custom logging events
+     *
+     * @param Doku_Event $event
+     * @param mixed $param data passed to the event handler
+     */
+    public function handle_custom(Doku_Event $event, $param) {
+        if(isset($event->data['message'])) {
+            $log = $event->data['message'];
+        } else {
+            return;
+        }
+        if(isset($event->data['user'])) {
+            $user = $event->data['user'];
+        } else {
+            $user = null;
+        }
+
+        $this->_log($log, $user);
+    }
+
+    /**
+     * Handle autologoffs by the autologout plugin
+     *
+     * @param Doku_Event $event
+     * @param mixed $param data passed to the event handler
+     */
+    public function handle_autologout(Doku_Event $event, $param) {
+        $this->_log('has been automatically logged off');
+    }
+
+    /**
+     * catch standard logins/logouts
+     *
+     * @param Doku_Event $event
+     * @param mixed $param data passed to the event handler
+     */
+    public function handle_before(Doku_Event $event, $param) {
+        $act = act_clean($event->data);
+        if($act == 'logout') {
+            $this->_log('logged off');
+        } elseif(!empty($_SERVER['REMOTE_USER']) && $act == 'login') {
+            if(isset($_REQUEST['r'])) {
+                $this->_log('logged in permanently');
+            } else {
+                $this->_log('logged in temporarily');
+            }
+        } elseif($_REQUEST['u'] && $_REQUEST['http_credentials'] && empty($_SERVER['REMOTE_USER'])) {
+            $this->_log('failed login attempt');
+        }
+    }
+}
+
diff --git a/lib/plugins/loglog/admin.php b/lib/plugins/loglog/admin.php
new file mode 100644
index 0000000..d8f8a28
--- /dev/null
+++ b/lib/plugins/loglog/admin.php
@@ -0,0 +1,182 @@
+<?php
+
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
+
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
+require_once(DOKU_PLUGIN.'admin.php');
+
+
+class admin_plugin_loglog extends DokuWiki_Admin_Plugin {
+
+    /**
+     * Access for managers allowed
+     */
+    function forAdminOnly(){
+        return false;
+    }
+
+    /**
+     * return sort order for position in admin menu
+     */
+    function getMenuSort() {
+        return 141;
+    }
+
+    /**
+     * handle user request
+     */
+    function handle() {
+    }
+
+    /**
+     * output appropriate html
+     */
+    function html() {
+        global $ID, $conf, $lang;
+        $go  = isset($_REQUEST['time']) ? intval($_REQUEST['time']) : 0;
+        if(!$go) $go = time()+60*60; //one hour in the future to trick pagination
+        $min = $go-(7*24*60*60);
+        $max = $go;
+
+        echo $this->locale_xhtml('intro');
+
+        echo '<p>'.$this->getLang('range').' '.strftime($conf['dformat'],$min).
+             ' - '.strftime($conf['dformat'],$max).'</p>';
+
+
+        echo '<table class="inline loglog">';
+        echo '<tr>';
+        echo '<th>'.$this->getLang('date').'</th>';
+        echo '<th>'.$this->getLang('ip').'</th>';
+        echo '<th>'.$lang['user'].'</th>';
+        echo '<th>'.$this->getLang('action').'</th>';
+        echo '</tr>';
+
+        $lines = $this->_readlines($min,$max);
+        $lines = array_reverse($lines);
+
+        foreach($lines as $line){
+            if (empty($line)) continue; // Filter empty lines
+            list($dt,$junk,$ip,$user,$msg) = explode("\t",$line,5);
+            if($dt < $min) continue;
+            if($dt > $max) continue;
+            if(!$user)     continue;
+
+            if($msg == 'logged off'){
+                $msg = $this->getLang('off');
+                $class = 'off';
+            }elseif($msg == 'logged in permanently'){
+                $msg = $this->getLang('in');
+                $class = 'perm';
+            }elseif($msg == 'logged in temporarily'){
+                $msg = $this->getLang('tin');
+                $class = 'temp';
+            }elseif($msg == 'failed login attempt'){
+                $msg = $this->getLang('fail');
+                $class = 'fail';
+            }elseif($msg == 'has been automatically logged off') {
+                $msg = $this->getLang('autologoff');
+                $class = 'off';
+            }else{
+                $msg = hsc($msg);
+                if(strpos($msg, 'logged off') !== false) {
+                    $class = 'off';
+                } elseif(strpos($msg, 'logged in permanently') !== false) {
+                    $class = 'perm';
+                } elseif(strpos($msg, 'logged in') !== false) {
+                    $class = 'temp';
+                } elseif(strpos($msg, 'failed') !== false) {
+                    $class = 'fail';
+                } else {
+                    $class = 'unknown';
+                }
+            }
+
+            echo '<tr>';
+            echo '<td>'.strftime($conf['dformat'],$dt).'</td>';
+            echo '<td>'.hsc($ip).'</td>';
+            echo '<td>'.hsc($user).'</td>';
+            echo '<td><span class="loglog_'.$class.'">'.$msg.'</span></td>';
+            echo '</tr>';
+        }
+
+        echo '</table>';
+
+        echo '<div class="pagenav">';
+        if($max < time()-(7*24*60*60)){
+        echo '<div class="pagenav-prev">';
+        echo html_btn('newer',$ID,"p",array('do'=>'admin','page'=>'loglog','time'=>$max+(7*24*60*60)));
+        echo '</div>';
+        }
+
+        echo '<div class="pagenav-next">';
+        echo html_btn('older',$ID,"n",array('do'=>'admin','page'=>'loglog','time'=>$min));
+        echo '</div>';
+        echo '</div>';
+
+    }
+
+    /**
+     * Read loglines backward
+     *
+     * @param int $min - start time (in seconds)
+     */
+    function _readlines($min,$max){
+        global $conf;
+        $file = $conf['cachedir'].'/loglog.log';
+
+
+        $data  = array();
+        $lines = array();
+        $chunk_size = 8192;
+
+        if (!@file_exists($file)) return $data;
+        $fp = fopen($file, 'rb');
+        if ($fp===false) return $data;
+
+        //seek to end
+        fseek($fp, 0, SEEK_END);
+        $pos = ftell($fp);
+        $chunk = '';
+
+        while($pos){
+
+            // how much to read? Set pointer
+            if($pos > $chunk_size){
+                $pos -= $chunk_size;
+                $read = $chunk_size;
+            }else{
+                $read = $pos;
+                $pos  = 0;
+            }
+            fseek($fp,$pos);
+
+            $tmp = fread($fp,$read);
+            if($tmp === false) break;
+            $chunk = $tmp.$chunk;
+
+            // now split the chunk
+            $cparts = explode("\n",$chunk);
+
+            // keep the first part in chunk (may be incomplete)
+            if($pos) $chunk = array_shift($cparts);
+
+            // no more parts available, read on
+            if(!count($cparts)) continue;
+
+            // get date of first line:
+            list($cdate) = explode("\t",$cparts[0]);
+
+            if($cdate > $max) continue; // haven't reached wanted area, yet
+
+            // put the new lines on the stack
+            $lines = array_merge($cparts,$lines);
+
+            if($cdate < $min) break; // we have enough
+        }
+        fclose($fp);
+
+        return $lines;
+    }
+}
diff --git a/lib/plugins/loglog/admin.svg b/lib/plugins/loglog/admin.svg
new file mode 100644
index 0000000..3688147
--- /dev/null
+++ b/lib/plugins/loglog/admin.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M16 9c2.33 0 7 1.17 7 3.5V15h-6v-2.5c0-1.5-.81-2.61-1.96-3.45L16 9M8 9c2.33 0 7 1.17 7 3.5V15H1v-2.5C1 10.17 5.67 9 8 9m0-2a3 3 0 0 1-3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3 3 3 0 0 1-3 3m8 0a3 3 0 0 1-3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3 3 3 0 0 1-3 3m-7 9.75V19h6v-2.25L18.25 20 15 23.25V21H9v2.25L5.75 20 9 16.75z"/></svg>
\ No newline at end of file
diff --git a/lib/plugins/loglog/lang/ar/intro.txt b/lib/plugins/loglog/lang/ar/intro.txt
new file mode 100644
index 0000000..b2d2d8f
--- /dev/null
+++ b/lib/plugins/loglog/lang/ar/intro.txt
@@ -0,0 +1,3 @@
+======سجل الدخول و الهروج الاسبوعي للمستخدم======
+
+هذا التقرير يعرض كل تسجيلات الدخول و الخروج للمستخدم خلال الـ 7 ايام الماضيه.تستطيع استخدام زر التحديد في اسفل الصحفه لعرض الاسابيع الماضيه.
\ No newline at end of file
diff --git a/lib/plugins/loglog/lang/ar/lang.php b/lib/plugins/loglog/lang/ar/lang.php
new file mode 100644
index 0000000..15fe6fc
--- /dev/null
+++ b/lib/plugins/loglog/lang/ar/lang.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Ali Almlfy <Almlfy at hotmail.com>
+ */
+$lang['menu']                  = 'سجل الدخول و الخروج الاسبوعي للمستخدم ';
+$lang['date']                  = 'التاريخ';
+$lang['ip']                    = 'عنوان الايبي';
+$lang['action']                = 'نفذ';
+$lang['range']                 = 'اظهر سجل التاريخ';
+$lang['off']                   = 'سجل خروج';
+$lang['in']                    = 'سجل دخول متواصل ';
+$lang['tin']                   = 'سجل دخول موقته';
+$lang['fail']                  = 'محاولت دخول فاشلة';
diff --git a/lib/plugins/loglog/lang/cs/intro.txt b/lib/plugins/loglog/lang/cs/intro.txt
new file mode 100644
index 0000000..0938e13
--- /dev/null
+++ b/lib/plugins/loglog/lang/cs/intro.txt
@@ -0,0 +1,3 @@
+====== Týdenní uživatelská přihlášení/odhlášení ======
+
+Tato obrazovka zobrazuje všechna přihlášení a odhlášení uživatelů z posledních 7 dnů. Pro zobrazení starších týdnů lze použít navigační tlačítka na konci této stránky.
diff --git a/lib/plugins/loglog/lang/cs/lang.php b/lib/plugins/loglog/lang/cs/lang.php
new file mode 100644
index 0000000..21ee07b
--- /dev/null
+++ b/lib/plugins/loglog/lang/cs/lang.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Jaroslav Lichtblau <jlichtblau at seznam.cz>
+ */
+$lang['menu']                  = 'Týdenní uživatelská přihlášení/odhlášení';
+$lang['date']                  = 'Datum';
+$lang['ip']                    = 'IP adresa';
+$lang['action']                = 'Akce';
+$lang['range']                 = 'Zobrazené časové období:';
+$lang['off']                   = 'odhlášení';
+$lang['autologoff']            = 'automaticky odhlášen(a)';
+$lang['in']                    = 'trvalé přihlášení';
+$lang['tin']                   = 'dočasné přihlášení';
+$lang['fail']                  = 'chybné přihlášení';
diff --git a/lib/plugins/loglog/lang/da/intro.txt b/lib/plugins/loglog/lang/da/intro.txt
new file mode 100644
index 0000000..299b805
--- /dev/null
+++ b/lib/plugins/loglog/lang/da/intro.txt
@@ -0,0 +1,3 @@
+====== Ugentlige Brugerlogin/log ud ======
+
+Denne skærm viser alle brugernes login og log ud fra de sidste 7 dage. Du kan benytte navigationsknapperne i bunden af skærmen til at vise tidligere uger.
\ No newline at end of file
diff --git a/lib/plugins/loglog/lang/da/lang.php b/lib/plugins/loglog/lang/da/lang.php
new file mode 100644
index 0000000..83a4ec0
--- /dev/null
+++ b/lib/plugins/loglog/lang/da/lang.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Søren Birk <soer9648 at eucl.dk>
+ * @author Jacob Palm <mail at jacobpalm.dk>
+ */
+$lang['menu']                  = 'Ugentlige Brugerlogin/log ud';
+$lang['date']                  = 'Dato';
+$lang['ip']                    = 'IP-Adresse';
+$lang['action']                = 'Handling';
+$lang['range']                 = 'Vist datorækkevidde';
+$lang['off']                   = 'logget ud';
+$lang['autologoff']            = 'er blevet logget ud automatisk';
+$lang['in']                    = 'permanent logget ind';
+$lang['tin']                   = 'midlertidigt logget ind';
+$lang['fail']                  = 'fejlet login-forsøg';
diff --git a/lib/plugins/loglog/lang/de/intro.txt b/lib/plugins/loglog/lang/de/intro.txt
new file mode 100644
index 0000000..672c92d
--- /dev/null
+++ b/lib/plugins/loglog/lang/de/intro.txt
@@ -0,0 +1,3 @@
+====== Wöchentliche Benutzer An- und Abmeldungen ======
+
+Diese Übersicht zeigt alle An- und Abmeldungen von Benutzern dieses Wikis innerhalb der letzten 7 Tage. Mit den Navigations-Schaltflächen am unteren Bilschirm können sie die Aktivitäten vergangener Wochen einsehen.
diff --git a/lib/plugins/loglog/lang/de/lang.php b/lib/plugins/loglog/lang/de/lang.php
new file mode 100644
index 0000000..3962162
--- /dev/null
+++ b/lib/plugins/loglog/lang/de/lang.php
@@ -0,0 +1,15 @@
+<?php
+
+$lang['menu'] = 'Wöchentliche Benutzeran- und abmeldungen';
+
+$lang['date']   = 'Datum';
+$lang['ip']     = 'IP Adresse';
+$lang['action'] = 'Aktion';
+$lang['range']  = 'Angezeigter Zeitraum:';
+
+$lang['off'] = 'abgemeldet';
+$lang['autologoff'] = 'wurde automatisch abgemeldet';
+$lang['in']  = 'dauerhaft angemeldet';
+$lang['tin'] = 'temporär angemeldet';
+$lang['fail'] = 'gescheiterter Anmeldeversuch';
+
diff --git a/lib/plugins/loglog/lang/en/intro.txt b/lib/plugins/loglog/lang/en/intro.txt
new file mode 100644
index 0000000..c427815
--- /dev/null
+++ b/lib/plugins/loglog/lang/en/intro.txt
@@ -0,0 +1,3 @@
+====== Weekly User Logins/Logouts ======
+
+This screen displays the all user logins and logouts during the last 7 days. You can use the navigation buttons at the bottom of the screen to display earlier weeks.
diff --git a/lib/plugins/loglog/lang/en/lang.php b/lib/plugins/loglog/lang/en/lang.php
new file mode 100644
index 0000000..ab21b9b
--- /dev/null
+++ b/lib/plugins/loglog/lang/en/lang.php
@@ -0,0 +1,15 @@
+<?php
+
+$lang['menu'] = 'Weekly User Logins/Logouts';
+
+$lang['date']   = 'Date';
+$lang['ip']     = 'IP Address';
+$lang['action'] = 'Action';
+$lang['range']  = 'Displayed date range:';
+
+$lang['off'] = 'logged off';
+$lang['autologoff'] = 'has been logged out automatically';
+$lang['in']  = 'logged in permanently';
+$lang['tin'] = 'logged in temporarily';
+$lang['fail'] = 'failed login attempt';
+
diff --git a/lib/plugins/loglog/lang/eo/intro.txt b/lib/plugins/loglog/lang/eo/intro.txt
new file mode 100644
index 0000000..0382fcb
--- /dev/null
+++ b/lib/plugins/loglog/lang/eo/intro.txt
@@ -0,0 +1,3 @@
+====== Semajnaj en/elsalutoj de uzantoj ======
+
+Tiu paĝo montras ĉiujn en- kaj elsalutojn de uzantoj dum la pasintaj 7 tagoj. Vi povas uzi la navigadajn butonojn sube por montri pli fruajn semajnojn.
\ No newline at end of file
diff --git a/lib/plugins/loglog/lang/eo/lang.php b/lib/plugins/loglog/lang/eo/lang.php
new file mode 100644
index 0000000..2936772
--- /dev/null
+++ b/lib/plugins/loglog/lang/eo/lang.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Robert Bogenschneider <bogi at uea.org>
+ */
+$lang['menu']                  = 'Semajnaj en/elsalutoj de uzantoj';
+$lang['date']                  = 'Dato';
+$lang['ip']                    = 'IP-adreso';
+$lang['action']                = 'Agado';
+$lang['range']                 = 'Montrata dato-periodo:';
+$lang['off']                   = 'elsalutinta';
+$lang['in']                    = 'ensalutinta konstante';
+$lang['tin']                   = 'ensalutinta portempe';
+$lang['fail']                  = 'malsukcesa provo ensaluti';
diff --git a/lib/plugins/loglog/lang/fr/intro.txt b/lib/plugins/loglog/lang/fr/intro.txt
new file mode 100644
index 0000000..f6322fe
--- /dev/null
+++ b/lib/plugins/loglog/lang/fr/intro.txt
@@ -0,0 +1,3 @@
+====== Journal hebdomadaire des Connexions/Déconnexions Utilisateurs ======
+
+Cette page affiche les connexions et déconnexions de tous les utilisateurs au cours de 7 derniers jours. Vous pouvez utiliser les boutons de navigation au bas de la page pour afficher les semaines précédentes.
diff --git a/lib/plugins/loglog/lang/fr/lang.php b/lib/plugins/loglog/lang/fr/lang.php
new file mode 100644
index 0000000..fdced2b
--- /dev/null
+++ b/lib/plugins/loglog/lang/fr/lang.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author NicolasFriedli <nicolas at theologique.ch>
+ * @author Nicolas Friedli <nicolas at theologique.ch>
+ */
+$lang['menu']                  = 'Journal hebdomadaire des Connexions/Déconnexions Utilisateurs';
+$lang['date']                  = 'Date';
+$lang['ip']                    = 'Adresse IP';
+$lang['action']                = 'Action';
+$lang['range']                 = 'Période affichée :';
+$lang['off']                   = 'déconnecté';
+$lang['autologoff']            = 'a été connecté automatiquement';
+$lang['in']                    = 'connecté de façon permanente';
+$lang['tin']                   = 'connecté temporairement';
+$lang['fail']                  = 'connextion ratée';
diff --git a/lib/plugins/loglog/lang/hr/intro.txt b/lib/plugins/loglog/lang/hr/intro.txt
new file mode 100644
index 0000000..51d81b8
--- /dev/null
+++ b/lib/plugins/loglog/lang/hr/intro.txt
@@ -0,0 +1,3 @@
+====== Tjedne prijave/odjave korisnika ======
+
+Ovdje su prikazane sve prijave i odjave korisnika u zadnjih 7 dana. Možete koristiti tipke za navigaciju na dnu stranice da prikažete prethodne tjedne.
diff --git a/lib/plugins/loglog/lang/hr/lang.php b/lib/plugins/loglog/lang/hr/lang.php
new file mode 100644
index 0000000..55193c3
--- /dev/null
+++ b/lib/plugins/loglog/lang/hr/lang.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Davor Turkalj <turki.bsc at gmail.com>
+ */
+$lang['menu']                  = 'Tjedne prijave/odjave korisnika';
+$lang['date']                  = 'Datum';
+$lang['ip']                    = 'IP adresa';
+$lang['action']                = 'Aktivnost';
+$lang['range']                 = 'Prikazani opseg datuma:';
+$lang['off']                   = 'odjavljen';
+$lang['autologoff']            = 'bio je odjavljen od strane sustava';
+$lang['in']                    = 'prijavljen trajno';
+$lang['tin']                   = 'prijavljen trenutno';
+$lang['fail']                  = 'neuspio pokušaj prijave';
diff --git a/lib/plugins/loglog/lang/hu/intro.txt b/lib/plugins/loglog/lang/hu/intro.txt
new file mode 100644
index 0000000..6021cad
--- /dev/null
+++ b/lib/plugins/loglog/lang/hu/intro.txt
@@ -0,0 +1,3 @@
+====== Heti felhasználói be-/kijelentkezések ======
+
+A képernyőn az elmúlt 7 napban történt összes felhasználói be- és kijelentkezést láthatjuk. A képernyő alján található navigációs gombokkal a korábbi heteket is megtekinthetjük.
\ No newline at end of file
diff --git a/lib/plugins/loglog/lang/hu/lang.php b/lib/plugins/loglog/lang/hu/lang.php
new file mode 100644
index 0000000..28db50d
--- /dev/null
+++ b/lib/plugins/loglog/lang/hu/lang.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author DelDadam <deldadam at gmail.com>
+ * @author DelD <deldadam at gmail.com>
+ */
+$lang['menu']                  = 'Heti felhasználói be-/kijelentkezések';
+$lang['date']                  = 'Dátum';
+$lang['ip']                    = 'IP-cím';
+$lang['action']                = 'Művelet';
+$lang['range']                 = 'Kijelzett dátumtartomány:';
+$lang['off']                   = 'kijelentkezés';
+$lang['autologoff']            = 'automatikusan kijelentkezett.';
+$lang['in']                    = 'bejelentkezés (tartós)';
+$lang['tin']                   = 'bejelentkezés (ideiglenes)';
+$lang['fail']                  = 'sikertelen bejelentkezési kísérlet';
diff --git a/lib/plugins/loglog/lang/ja/intro.txt b/lib/plugins/loglog/lang/ja/intro.txt
new file mode 100644
index 0000000..c3e5534
--- /dev/null
+++ b/lib/plugins/loglog/lang/ja/intro.txt
@@ -0,0 +1,4 @@
+====== 週間ユーザーログイン/ログアウト ======
+ 
+この画面は、直近7日間の全ユーザーのログイン・ログアウトを表示します。
+画面下部の移動ボタンを使用して、前の週を表示できます。
\ No newline at end of file
diff --git a/lib/plugins/loglog/lang/ja/lang.php b/lib/plugins/loglog/lang/ja/lang.php
new file mode 100644
index 0000000..2b99b33
--- /dev/null
+++ b/lib/plugins/loglog/lang/ja/lang.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Hideaki SAWADA <chuno at live.jp>
+ */
+$lang['menu']                  = '週間ユーザーログイン/ログアウト';
+$lang['date']                  = '日付';
+$lang['ip']                    = 'IPアドレス';
+$lang['action']                = '動作';
+$lang['range']                 = '表示中の日付範囲:';
+$lang['off']                   = 'ログアウト';
+$lang['autologoff']            = '自動的なログアウト';
+$lang['in']                    = '恒久的なログイン';
+$lang['tin']                   = '一時的なログイン';
+$lang['fail']                  = 'ログイン失敗';
diff --git a/lib/plugins/loglog/lang/ko/intro.txt b/lib/plugins/loglog/lang/ko/intro.txt
new file mode 100644
index 0000000..ff6a516
--- /dev/null
+++ b/lib/plugins/loglog/lang/ko/intro.txt
@@ -0,0 +1,3 @@
+====== 주간 사용자 로그인/로그아웃 ======
+
+이 화면은 지난 7일 동안 모든 사용자의 로그인과 로그아웃을 표시합니다. 이전 주를 표시하려면 하면의 아래에 있는 둘러보기 버튼을 사용할 수 있습니다.
\ No newline at end of file
diff --git a/lib/plugins/loglog/lang/ko/lang.php b/lib/plugins/loglog/lang/ko/lang.php
new file mode 100644
index 0000000..d975d17
--- /dev/null
+++ b/lib/plugins/loglog/lang/ko/lang.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Myeongjin <aranet100 at gmail.com>
+ */
+$lang['menu']                  = '주간 사용자 로그인/로그아웃';
+$lang['date']                  = '날짜';
+$lang['ip']                    = 'IP 주소';
+$lang['action']                = '동작';
+$lang['range']                 = '표시할 날짜 범위:';
+$lang['off']                   = '로그아웃됨';
+$lang['autologoff']            = '사용자가 자동으로 로그아웃되었습니다';
+$lang['in']                    = '영구적으로 로그인됨';
+$lang['tin']                   = '일시적으로 로그인됨';
+$lang['fail']                  = '실패한 로그인 시도';
diff --git a/lib/plugins/loglog/lang/nl/intro.txt b/lib/plugins/loglog/lang/nl/intro.txt
new file mode 100644
index 0000000..e47307e
--- /dev/null
+++ b/lib/plugins/loglog/lang/nl/intro.txt
@@ -0,0 +1,3 @@
+====== Weekoverzicht gebruikers Logins/Logouts ======
+
+Dit scherm geeft alle gebruikers logins en logouts weer van de laatste 7 dagen. Onderaan het scherm kan je vorige weken selecteren om op het scherm te tonen.
\ No newline at end of file
diff --git a/lib/plugins/loglog/lang/nl/lang.php b/lib/plugins/loglog/lang/nl/lang.php
new file mode 100644
index 0000000..c925ab3
--- /dev/null
+++ b/lib/plugins/loglog/lang/nl/lang.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Hugo Smet <hugo.smet at scarlet.be>
+ * @author hugo smet <hugo.smet at scarlet.be>
+ */
+$lang['menu']                  = 'Wekelijks gebruikers Logins/Logouts overzicht';
+$lang['date']                  = 'Datum';
+$lang['ip']                    = 'IP adres';
+$lang['action']                = 'Actie';
+$lang['range']                 = 'Datumvork van de getoonde info';
+$lang['off']                   = 'afgelogd';
+$lang['autologoff']            = 'is automatisch afgemeld';
+$lang['in']                    = 'permanent ingelogd';
+$lang['tin']                   = 'tijdelijk ingelogd';
+$lang['fail']                  = 'mislukte login';
diff --git a/lib/plugins/loglog/lang/ru/intro.txt b/lib/plugins/loglog/lang/ru/intro.txt
new file mode 100644
index 0000000..1c8a5be
--- /dev/null
+++ b/lib/plugins/loglog/lang/ru/intro.txt
@@ -0,0 +1,3 @@
+====== Журнал авторизации пользователей ======
+
+Данная страница отображает все входы и выходы зарегистрированных пользователей за последние семь дней. Вы можете использовать кнопки навигации в нижней части экрана для отображения записей за предыдущие недели.
diff --git a/lib/plugins/loglog/lang/ru/lang.php b/lib/plugins/loglog/lang/ru/lang.php
new file mode 100644
index 0000000..f6f7419
--- /dev/null
+++ b/lib/plugins/loglog/lang/ru/lang.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author Aleksandr Selivanov <alexgearbox at yandex.ru>
+ * @author Takumo <9206984 at mail.ru>
+ */
+$lang['menu']                  = 'Журнал авторизации пользователей';
+$lang['date']                  = 'Дата';
+$lang['ip']                    = 'IP-адрес';
+$lang['action']                = 'Действие';
+$lang['range']                 = 'Отображаемый период:';
+$lang['off']                   = 'Выход';
+$lang['autologoff']            = 'был автоматически отключен от системы';
+$lang['in']                    = 'Постоянный вход в систему';
+$lang['tin']                   = 'Временный вход в систему';
+$lang['fail']                  = 'Неудачная попытка входа';
diff --git a/lib/plugins/loglog/lang/zh-tw/lang.php b/lib/plugins/loglog/lang/zh-tw/lang.php
new file mode 100644
index 0000000..7a6d8b3
--- /dev/null
+++ b/lib/plugins/loglog/lang/zh-tw/lang.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author HL <tohelong at gmail.com>
+ */
+$lang['date']                  = '日期';
+$lang['ip']                    = 'IP';
+$lang['action']                = '動作';
+$lang['range']                 = '日期範圍';
+$lang['off']                   = '登出';
+$lang['in']                    = '記住登錄';
+$lang['tin']                   = '登錄';
+$lang['fail']                  = '登錄失敗';
diff --git a/lib/plugins/loglog/lang/zh/intro.txt b/lib/plugins/loglog/lang/zh/intro.txt
new file mode 100644
index 0000000..2a809d2
--- /dev/null
+++ b/lib/plugins/loglog/lang/zh/intro.txt
@@ -0,0 +1,3 @@
+======每周用户登录/注销======
+
+该屏幕显示在过去7天的所有的登录和注销用户。可以使用导航按钮在屏幕的底部显示更多。
\ No newline at end of file
diff --git a/lib/plugins/loglog/lang/zh/lang.php b/lib/plugins/loglog/lang/zh/lang.php
new file mode 100644
index 0000000..0d0af2d
--- /dev/null
+++ b/lib/plugins/loglog/lang/zh/lang.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * 
+ * @author HL <tohelong at gmail.com>
+ */
+$lang['menu']                  = '本周登录/注销的用户';
+$lang['date']                  = '日期';
+$lang['ip']                    = 'IP';
+$lang['action']                = '动作';
+$lang['range']                 = '日期范围';
+$lang['off']                   = '登出';
+$lang['in']                    = '记住我';
+$lang['tin']                   = '登录';
+$lang['fail']                  = '登录失败';
diff --git a/lib/plugins/loglog/manager.dat b/lib/plugins/loglog/manager.dat
new file mode 100644
index 0000000..5a90ae5
--- /dev/null
+++ b/lib/plugins/loglog/manager.dat
@@ -0,0 +1,2 @@
+downloadurl=https://github.com/splitbrain/dokuwiki-plugin-loglog/zipball/master
+installed=Sun, 05 Mar 2017 13:11:17 +0100
diff --git a/lib/plugins/loglog/pix/error.png b/lib/plugins/loglog/pix/error.png
new file mode 100644
index 0000000..dbfda22
Binary files /dev/null and b/lib/plugins/loglog/pix/error.png differ
diff --git a/lib/plugins/loglog/pix/off.png b/lib/plugins/loglog/pix/off.png
new file mode 100644
index 0000000..7417dff
Binary files /dev/null and b/lib/plugins/loglog/pix/off.png differ
diff --git a/lib/plugins/loglog/pix/perm.png b/lib/plugins/loglog/pix/perm.png
new file mode 100644
index 0000000..6ba821f
Binary files /dev/null and b/lib/plugins/loglog/pix/perm.png differ
diff --git a/lib/plugins/loglog/pix/temp.png b/lib/plugins/loglog/pix/temp.png
new file mode 100644
index 0000000..4d3a079
Binary files /dev/null and b/lib/plugins/loglog/pix/temp.png differ
diff --git a/lib/plugins/loglog/plugin.info.txt b/lib/plugins/loglog/plugin.info.txt
new file mode 100644
index 0000000..e015e14
--- /dev/null
+++ b/lib/plugins/loglog/plugin.info.txt
@@ -0,0 +1,7 @@
+base    loglog
+author  Andreas Gohr
+email   dokuwiki at cosmocode.de
+date    2016-02-03
+name    Login/Logout logging plugin
+desc    Log logins and logouts of users to a file
+url     http://www.dokuwiki.org/plugin:loglog
diff --git a/lib/plugins/loglog/style.css b/lib/plugins/loglog/style.css
new file mode 100644
index 0000000..b1fec80
--- /dev/null
+++ b/lib/plugins/loglog/style.css
@@ -0,0 +1,30 @@
+table.loglog {
+    width: 100%;
+    table-layout: fixed;
+    word-wrap: break-word;
+}
+
+table.loglog span {
+    padding-left: 20px;
+}
+
+
+table.loglog span.loglog_off {
+    background: transparent url(pix/off.png) left center no-repeat;
+}
+
+table.loglog span.loglog_perm {
+    background: transparent url(pix/perm.png) left center no-repeat;
+}
+
+table.loglog span.loglog_temp {
+    background: transparent url(pix/temp.png) left center no-repeat;
+}
+
+table.loglog span.loglog_fail {
+    background: transparent url(pix/error.png) left center no-repeat;
+}
+
+
+
+

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list