diff --git a/_test/tests/inc/input.test.php b/_test/tests/inc/input.test.php
index cec0b80f6fa417cbe6e3918479a1d62c0251994a..4a8fb8d7117665e21fa6e53909c33831c4439dc5 100644
--- a/_test/tests/inc/input.test.php
+++ b/_test/tests/inc/input.test.php
@@ -14,8 +14,58 @@ class input_test extends DokuWikiTest {
         'empty'  => '',
         'emptya' => array(),
         'do'     => array('save' => 'Speichern'),
+
     );
 
+    /**
+     * custom filter function
+     *
+     * @param $string
+     * @return mixed
+     */
+    public function myfilter($string) {
+        $string = str_replace('foo', 'bar', $string);
+        $string = str_replace('baz', '', $string);
+        return $string;
+    }
+
+    public function test_filter() {
+        $_GET     = array(
+            'foo'    => 'foo',
+            'zstring'=> "foo\0bar",
+            'znull'  => "\0",
+            'zint'   => '42'."\0".'42',
+            'zintbaz'=> "baz42",
+        );
+        $_POST    = $_GET;
+        $_REQUEST = $_GET;
+        $INPUT    = new Input();
+
+        $filter = array($this,'myfilter');
+
+        $this->assertNotSame('foobar', $INPUT->str('zstring'));
+        $this->assertSame('foobar', $INPUT->filter()->str('zstring'));
+        $this->assertSame('bar', $INPUT->filter($filter)->str('foo'));
+        $this->assertSame('bar', $INPUT->filter()->str('znull', 'bar', true));
+        $this->assertNotSame('foobar', $INPUT->str('zstring')); // make sure original input is unmodified
+
+        $this->assertNotSame('foobar', $INPUT->get->str('zstring'));
+        $this->assertSame('foobar', $INPUT->get->filter()->str('zstring'));
+        $this->assertSame('bar', $INPUT->get->filter($filter)->str('foo'));
+        $this->assertSame('bar', $INPUT->get->filter()->str('znull', 'bar', true));
+        $this->assertNotSame('foobar', $INPUT->get->str('zstring')); // make sure original input is unmodified
+
+        $this->assertNotSame(4242, $INPUT->int('zint'));
+        $this->assertSame(4242, $INPUT->filter()->int('zint'));
+        $this->assertSame(42, $INPUT->filter($filter)->int('zintbaz'));
+        $this->assertSame(42, $INPUT->filter()->str('znull', 42, true));
+
+        $this->assertSame(true, $INPUT->bool('znull'));
+        $this->assertSame(false, $INPUT->filter()->bool('znull'));
+
+        $this->assertSame('foobar', $INPUT->filter()->valid('zstring', array('foobar', 'bang')));
+    }
+
     public function test_str() {
         $_REQUEST      = $this->data;
         $_POST         = $this->data;
diff --git a/inc/Input.class.php b/inc/Input.class.php
index e7eef1c29cc0cae4c8ad540346cc4193678f8060..94da2a10efdc25af5a8d45f8e3c2309b5c1a287f 100644
--- a/inc/Input.class.php
+++ b/inc/Input.class.php
@@ -20,6 +20,11 @@ class Input {
 
     protected $access;
 
+    /**
+     * @var Callable
+     */
+    protected $filter;
+
     /**
      * Intilizes the Input class and it subcomponents
      */
@@ -30,6 +35,32 @@ class Input {
         $this->server = new ServerInput();
     }
 
+    /**
+     * Apply the set filter to the given value
+     *
+     * @param string $data
+     * @return string
+     */
+    protected function applyfilter($data){
+        if(!$this->filter) return $data;
+        return call_user_func($this->filter, $data);
+    }
+
+    /**
+     * Return a filtered copy of the input object
+     *
+     * Expects a callable that accepts one string parameter and returns a filtered string
+     *
+     * @param Callable|string $filter
+     * @return Input
+     */
+    public function filter($filter='stripctl'){
+        $this->filter = $filter;
+        $clone = clone $this;
+        $this->filter = '';
+        return $clone;
+    }
+
     /**
      * Check if a parameter was set
      *
@@ -77,8 +108,9 @@ class Input {
      */
     public function param($name, $default = null, $nonempty = false) {
         if(!isset($this->access[$name])) return $default;
-        if($nonempty && empty($this->access[$name])) return $default;
-        return $this->access[$name];
+        $value = $this->applyfilter($this->access[$name]);
+        if($nonempty && empty($value)) return $default;
+        return $value;
     }
 
     /**
@@ -121,10 +153,11 @@ class Input {
     public function int($name, $default = 0, $nonempty = false) {
         if(!isset($this->access[$name])) return $default;
         if(is_array($this->access[$name])) return $default;
-        if($this->access[$name] === '') return $default;
-        if($nonempty && empty($this->access[$name])) return $default;
+        $value = $this->applyfilter($this->access[$name]);
+        if($value === '') return $default;
+        if($nonempty && empty($value)) return $default;
 
-        return (int) $this->access[$name];
+        return (int) $value;
     }
 
     /**
@@ -138,9 +171,10 @@ class Input {
     public function str($name, $default = '', $nonempty = false) {
         if(!isset($this->access[$name])) return $default;
         if(is_array($this->access[$name])) return $default;
-        if($nonempty && empty($this->access[$name])) return $default;
+        $value = $this->applyfilter($this->access[$name]);
+        if($nonempty && empty($value)) return $default;
 
-        return (string) $this->access[$name];
+        return (string) $value;
     }
 
     /**
@@ -158,7 +192,8 @@ class Input {
     public function valid($name, $valids, $default = null) {
         if(!isset($this->access[$name])) return $default;
         if(is_array($this->access[$name])) return $default; // we don't allow arrays
-        $found = array_search($this->access[$name], $valids);
+        $value = $this->applyfilter($this->access[$name]);
+        $found = array_search($value, $valids);
         if($found !== false) return $valids[$found]; // return the valid value for type safety
         return $default;
     }
@@ -176,10 +211,11 @@ class Input {
     public function bool($name, $default = false, $nonempty = false) {
         if(!isset($this->access[$name])) return $default;
         if(is_array($this->access[$name])) return $default;
-        if($this->access[$name] === '') return $default;
-        if($nonempty && empty($this->access[$name])) return $default;
+        $value = $this->applyfilter($this->access[$name]);
+        if($value === '') return $default;
+        if($nonempty && empty($value)) return $default;
 
-        return (bool) $this->access[$name];
+        return (bool) $value;
     }
 
     /**