Переглянути джерело

Renamed classes for full PSR-2 compliance, some cleanup

El RIDO 10 роки тому
батько
коміт
b45bef8388
52 змінених файлів з 1941 додано та 1503 видалено
  1. 7 1
      .gitattributes
  2. 1 0
      CHANGELOG.md
  3. 1 0
      CREDITS.md
  4. 4 4
      cfg/conf.ini.sample
  5. 3 3
      index.php
  6. 10 9
      lib/Configuration.php
  7. 1 1
      lib/Data/AbstractData.php
  8. 10 10
      lib/Data/Database.php
  9. 33 28
      lib/Data/Filesystem.php
  10. 10 10
      lib/Filter.php
  11. 3 3
      lib/I18n.php
  12. 14 12
      lib/Model.php
  13. 4 4
      lib/Model/AbstractModel.php
  14. 12 12
      lib/Model/Comment.php
  15. 12 12
      lib/Model/Paste.php
  16. 3 3
      lib/Persistence/AbstractPersistence.php
  17. 8 6
      lib/Persistence/PurgeLimiter.php
  18. 8 6
      lib/Persistence/ServerSalt.php
  19. 8 6
      lib/Persistence/TrafficLimiter.php
  20. 30 29
      lib/PrivateBin.php
  21. 6 6
      lib/Request.php
  22. 2 2
      lib/Sjcl.php
  23. 2 3
      lib/View.php
  24. 6 4
      lib/Vizhash16x16.php
  25. 174 98
      tpl/bootstrap-compact.php
  26. 169 95
      tpl/bootstrap-dark-page.php
  27. 169 95
      tpl/bootstrap-dark.php
  28. 169 95
      tpl/bootstrap-page.php
  29. 169 95
      tpl/bootstrap.php
  30. 141 78
      tpl/page.php
  31. 8 8
      tst/Bootstrap.php
  32. 21 21
      tst/ConfigurationTest.php
  33. 21 15
      tst/ConfigurationTestGenerator.php
  34. 61 58
      tst/Data/DatabaseTest.php
  35. 31 31
      tst/Data/FilesystemTest.php
  36. 81 0
      tst/FilterTest.php
  37. 26 26
      tst/I18nTest.php
  38. 74 59
      tst/JsonApiTest.php
  39. 65 65
      tst/ModelTest.php
  40. 41 0
      tst/Persistence/PurgeLimiterTest.php
  41. 24 21
      tst/Persistence/ServerSaltTest.php
  42. 12 12
      tst/Persistence/TrafficLimiterTest.php
  43. 223 214
      tst/PrivateBinTest.php
  44. 13 19
      tst/PrivateBinWithDbTest.php
  45. 14 14
      tst/RequestTest.php
  46. 21 20
      tst/SjclTest.php
  47. 6 6
      tst/ViewTest.php
  48. 7 10
      tst/Vizhash16x16Test.php
  49. 0 81
      tst/filter.php
  50. 3 3
      tst/phpunit.xml
  51. 0 41
      tst/purgelimiter.php
  52. 0 49
      tst/test.ini

+ 7 - 1
.gitattributes

@@ -1,5 +1,11 @@
 doc/ export-ignore
 tst/ export-ignore
+.codeclimate.yml export-ignore
+.csslintrc export-ignore
+.editorconfig export-ignore
+.eslintignore export-ignore
+.eslintrc export-ignore
 .gitattributes export-ignore
+.github export-ignore
 .gitignore export-ignore
-img/bee*.png export-ignore
+.travis.yml export-ignore

+ 1 - 0
CHANGELOG.md

@@ -13,6 +13,7 @@
     * CHANGED: Upgrading SJCL library to 1.0.4
     * CHANGED: Switched to GCM instead CCM mode for AES encryption for newly created pastes
     * CHANGED: Switched to a SHA256 HMAC of the IP in traffic limiter instead of storing it in plain text on the server
+    * CHANGED: Refactored PHP code to conform to PSR-4 and PSR-2 standards.
     * FIXED: Content-type negociation for HTML in certain uncommon browser configurations
     * FIXED: JavaScript error displayed before page is loaded or during attachment load
     * FIXED: Don't strip space characters at beginning or end of optional password

+ 1 - 0
CREDITS.md

@@ -12,6 +12,7 @@ Simon Rupf - current developer and maintainer
 * azlux - Tab character input support
 * Adam Fisher - Favicons
 * rugk - various stuff, icons
+* Sobak - PSR-4 and PSR-2 refactoring
 
 Translations:
 * Hexalyse - French

+ 4 - 4
cfg/conf.ini.sample

@@ -120,14 +120,14 @@ dir = PATH "data"
 
 [model]
 ; name of data model class to load and directory for storage
-; the default model "privatebin_data" stores everything in the filesystem
-class = privatebin_data
+; the default model "Filesystem" stores everything in the filesystem
+class = Filesystem
 [model_options]
 dir = PATH "data"
 
 ;[model]
 ; example of DB configuration for MySQL
-;class = privatebin_db
+;class = Database
 ;[model_options]
 ;dsn = "mysql:host=localhost;dbname=privatebin;charset=UTF8"
 ;tbl = "privatebin_"	; table prefix
@@ -137,7 +137,7 @@ dir = PATH "data"
 
 ;[model]
 ; example of DB configuration for SQLite
-;class = privatebin_db
+;class = Database
 ;[model_options]
 ;dsn = "sqlite:" PATH "data/db.sq3"
 ;usr = null

+ 3 - 3
index.php

@@ -13,6 +13,6 @@
 // change this, if your php files and data is outside of your webservers document root
 define('PATH', '');
 
-define('PUBLIC_PATH', dirname(__FILE__));
-require __DIR__ . '/vendor/autoload.php';
-new PrivateBin\privatebin;
+define('PUBLIC_PATH', __DIR__);
+require PATH . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
+new PrivateBin\PrivateBin;

+ 10 - 9
lib/configuration.php → lib/Configuration.php

@@ -12,15 +12,16 @@
 
 namespace PrivateBin;
 
+use PrivateBin\I18n;
 use Exception;
 use PDO;
 
 /**
- * configuration
+ * Configuration
  *
  * parses configuration file, ensures default values present
  */
-class configuration
+class Configuration
 {
     /**
      * parsed configuration
@@ -82,7 +83,7 @@ class configuration
             'dir' => 'data',
         ),
         'model' => array(
-            'class' => 'PrivateBin\data\data',
+            'class' => 'Filesystem',
         ),
         'model_options' => array(
             'dir' => 'data',
@@ -102,7 +103,7 @@ class configuration
             $config = parse_ini_file($configFile, true);
             foreach (array('main', 'model', 'model_options') as $section) {
                 if (!array_key_exists($section, $config)) {
-                    throw new Exception(i18n::_('PrivateBin requires configuration section [%s] to be present in configuration file.', $section), 2);
+                    throw new Exception(I18n::_('PrivateBin requires configuration section [%s] to be present in configuration file.', $section), 2);
                 }
             }
         }
@@ -120,11 +121,11 @@ class configuration
             elseif (
                 $section == 'model_options' && in_array(
                     $this->_configuration['model']['class'],
-                    array('privatebin_db', 'zerobin_db')
+                    array('Database', 'privatebin_db', 'zerobin_db')
                 )
             ) {
                 $values = array(
-                    'dsn' => 'sqlite:' . PATH . 'data/db.sq3',
+                    'dsn' => 'sqlite:' . PATH . 'data' . DIRECTORY_SEPARATOR . 'db.sq3',
                     'tbl' => null,
                     'usr' => null,
                     'pwd' => null,
@@ -181,7 +182,7 @@ class configuration
 
         $this->_configuration['model']['class'] = str_replace(
             array('privatebin_data', 'privatebin_db'),
-            array('PrivateBin\\data\\data', 'PrivateBin\\data\\db'),
+            array('Filesystem', 'Database'),
             $this->_configuration['model']['class']
         );
 
@@ -223,7 +224,7 @@ class configuration
     {
         $options = $this->getSection($section);
         if (!array_key_exists($key, $options)) {
-            throw new Exception(i18n::_('Invalid data.') . " $section / $key", 4);
+            throw new Exception(I18n::_('Invalid data.') . " $section / $key", 4);
         }
         return $this->_configuration[$section][$key];
     }
@@ -238,7 +239,7 @@ class configuration
     public function getSection($section)
     {
         if (!array_key_exists($section, $this->_configuration)) {
-            throw new Exception(i18n::_('PrivateBin requires configuration section [%s] to be present in configuration file.', $section), 3);
+            throw new Exception(I18n::_('PrivateBin requires configuration section [%s] to be present in configuration file.', $section), 3);
         }
         return $this->_configuration[$section];
     }

+ 1 - 1
lib/data/AbstractData.php → lib/Data/AbstractData.php

@@ -10,7 +10,7 @@
  * @version   0.22
  */
 
-namespace PrivateBin\data;
+namespace PrivateBin\Data;
 
 /**
  * privatebin_abstract

+ 10 - 10
lib/data/db.php → lib/Data/Database.php

@@ -10,20 +10,20 @@
  * @version   0.22
  */
 
-namespace PrivateBin\data;
+namespace PrivateBin\Data;
 
+use PrivateBin\PrivateBin;
 use Exception;
 use PDO;
 use PDOException;
-use PrivateBin\privatebin;
 use stdClass;
 
 /**
- * privatebin_db
+ * Database
  *
- * Model for DB access, implemented as a singleton.
+ * Model for database access, implemented as a singleton.
  */
-class db extends AbstractData
+class Database extends AbstractData
 {
     /**
      * cache for select queries
@@ -66,12 +66,12 @@ class db extends AbstractData
      * @static
      * @param  array $options
      * @throws Exception
-     * @return privatebin_db
+     * @return Database
      */
     public static function getInstance($options = null)
     {
         // if needed initialize the singleton
-        if (!(self::$_instance instanceof privatebin_db)) {
+        if (!(self::$_instance instanceof Database)) {
             self::$_instance = new self;
         }
 
@@ -122,7 +122,7 @@ class db extends AbstractData
                 }
 
                 // create config table if necessary
-                $db_version = privatebin::VERSION;
+                $db_version = PrivateBin::VERSION;
                 if (!in_array(self::_sanitizeIdentifier('config'), $tables)) {
                     self::_createConfigTable();
                     // if we only needed to create the config table, the DB is older then 0.22
@@ -134,7 +134,7 @@ class db extends AbstractData
                 }
 
                 // update database structure if necessary
-                if (version_compare($db_version, privatebin::VERSION, '<')) {
+                if (version_compare($db_version, PrivateBin::VERSION, '<')) {
                     self::_upgradeDatabase($db_version);
                 }
             } else {
@@ -628,7 +628,7 @@ class db extends AbstractData
         self::_exec(
             'INSERT INTO ' . self::_sanitizeIdentifier('config') .
             ' VALUES(?,?)',
-            array('VERSION', privatebin::VERSION)
+            array('VERSION', PrivateBin::VERSION)
         );
     }
 

+ 33 - 28
lib/data/data.php → lib/Data/Filesystem.php

@@ -10,14 +10,16 @@
  * @version   0.22
  */
 
-namespace PrivateBin\data;
+namespace PrivateBin\Data;
+
+use PrivateBin\Model\Paste;
 
 /**
- * privatebin_data
+ * Filesystem
  *
- * Model for data access, implemented as a singleton.
+ * Model for filesystem data access, implemented as a singleton.
  */
-class data extends AbstractData
+class Filesystem extends AbstractData
 {
     /**
      * directory where data is stored
@@ -34,7 +36,7 @@ class data extends AbstractData
      * @access public
      * @static
      * @param  array $options
-     * @return privatebin_data
+     * @return Filesystem
      */
     public static function getInstance($options = null)
     {
@@ -46,7 +48,7 @@ class data extends AbstractData
             self::$_dir = $options['dir'] . DIRECTORY_SEPARATOR;
         }
         // if needed initialize the singleton
-        if (!(self::$_instance instanceof privatebin_data)) {
+        if (!(self::$_instance instanceof Filesystem)) {
             self::$_instance = new self;
             self::_init();
         }
@@ -68,9 +70,9 @@ class data extends AbstractData
             return false;
         }
         if (!is_dir($storagedir)) {
-            mkdir($storagedir, 0705, true);
+            mkdir($storagedir, 0700, true);
         }
-        return (bool) @file_put_contents($storagedir . $pasteid, json_encode($paste));
+        return (bool) file_put_contents($storagedir . $pasteid, json_encode($paste));
     }
 
     /**
@@ -108,23 +110,26 @@ class data extends AbstractData
      */
     public function delete($pasteid)
     {
-        // Delete the paste itself.
-        @unlink(self::_dataid2path($pasteid) . $pasteid);
+        $pastedir = self::_dataid2path($pasteid);
+        if (is_dir($pastedir)) {
+            // Delete the paste itself.
+            if (is_file($pastedir . $pasteid)) {
+                unlink($pastedir . $pasteid);
+            }
 
-        // Delete discussion if it exists.
-        $discdir = self::_dataid2discussionpath($pasteid);
-        if (is_dir($discdir)) {
-            // Delete all files in discussion directory
-            $dir = dir($discdir);
-            while (false !== ($filename = $dir->read())) {
-                if (is_file($discdir . $filename)) {
-                    @unlink($discdir . $filename);
+            // Delete discussion if it exists.
+            $discdir = self::_dataid2discussionpath($pasteid);
+            if (is_dir($discdir)) {
+                // Delete all files in discussion directory
+                $dir = dir($discdir);
+                while (false !== ($filename = $dir->read())) {
+                    if (is_file($discdir . $filename)) {
+                        unlink($discdir . $filename);
+                    }
                 }
+                $dir->close();
+                rmdir($discdir);
             }
-            $dir->close();
-
-            // Delete the discussion directory.
-            @rmdir($discdir);
         }
     }
 
@@ -158,9 +163,9 @@ class data extends AbstractData
             return false;
         }
         if (!is_dir($storagedir)) {
-            mkdir($storagedir, 0705, true);
+            mkdir($storagedir, 0700, true);
         }
-        return (bool) @file_put_contents($storagedir . $filename, json_encode($comment));
+        return (bool) file_put_contents($storagedir . $filename, json_encode($comment));
     }
 
     /**
@@ -231,7 +236,7 @@ class data extends AbstractData
         $pastes = array();
         $firstLevel = array_filter(
             scandir(self::$_dir),
-            array('self', '_isFirstLevelDir')
+            'self::_isFirstLevelDir'
         );
         if (count($firstLevel) > 0) {
             // try at most 10 times the $batchsize pastes before giving up
@@ -239,7 +244,7 @@ class data extends AbstractData
                 $firstKey = array_rand($firstLevel);
                 $secondLevel = array_filter(
                     scandir(self::$_dir . $firstLevel[$firstKey]),
-                    array('self', '_isSecondLevelDir')
+                    'self::_isSecondLevelDir'
                 );
 
                 // skip this folder in the next checks if it is empty
@@ -256,7 +261,7 @@ class data extends AbstractData
                 }
                 $thirdLevel = array_filter(
                     scandir($path),
-                    array('PrivateBin\\model\\paste', 'isValidId')
+                    'PrivateBin\\Model\\Paste::isValidId'
                 );
                 if (count($thirdLevel) == 0) {
                     continue;
@@ -295,7 +300,7 @@ class data extends AbstractData
     {
         // Create storage directory if it does not exist.
         if (!is_dir(self::$_dir)) {
-            mkdir(self::$_dir, 0705);
+            mkdir(self::$_dir, 0700);
         }
         // Create .htaccess file if it does not exist.
         if (!is_file(self::$_dir . '.htaccess')) {

+ 10 - 10
lib/filter.php → lib/Filter.php

@@ -12,15 +12,15 @@
 
 namespace PrivateBin;
 
+use PrivateBin\I18n;
 use Exception;
-use PrivateBin\i18n;
 
 /**
- * filter
+ * Filter
  *
  * Provides data filtering functions.
  */
-class filter
+class Filter
 {
     /**
      * strips slashes deeply
@@ -30,10 +30,10 @@ class filter
      * @param  mixed $value
      * @return mixed
      */
-    public static function stripslashes_deep($value)
+    public static function stripslashesDeep($value)
     {
         return is_array($value) ?
-            array_map('PrivateBin\\filter::stripslashes_deep', $value) :
+            array_map('self::stripslashesDeep', $value) :
             stripslashes($value);
     }
 
@@ -48,7 +48,7 @@ class filter
      * @throws Exception
      * @return string
      */
-    public static function time_humanreadable($time)
+    public static function formatHumanReadableTime($time)
     {
         if (preg_match('/^(\d+) *(\w+)$/', $time, $matches) !== 1) {
             throw new Exception("Error parsing time format '$time'", 30);
@@ -63,7 +63,7 @@ class filter
             default:
                 $unit = rtrim($matches[2], 's');
         }
-        return i18n::_(array('%d ' . $unit, '%d ' . $unit . 's'), (int) $matches[1]);
+        return I18n::_(array('%d ' . $unit, '%d ' . $unit . 's'), (int) $matches[1]);
     }
 
     /**
@@ -74,7 +74,7 @@ class filter
      * @param  int $size
      * @return string
      */
-    public static function size_humanreadable($size)
+    public static function formatHumanReadableSize($size)
     {
         $iec = array('B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB');
         $i = 0;
@@ -82,7 +82,7 @@ class filter
             $size = $size / 1024;
             $i++;
         }
-        return number_format($size, ($i ? 2 : 0), '.', ' ') . ' ' . i18n::_($iec[$i]);
+        return number_format($size, ($i ? 2 : 0), '.', ' ') . ' ' . I18n::_($iec[$i]);
     }
 
     /**
@@ -95,7 +95,7 @@ class filter
      * @param  string $b
      * @return bool
      */
-    public static function slow_equals($a, $b)
+    public static function slowEquals($a, $b)
     {
         $diff = strlen($a) ^ strlen($b);
         for ($i = 0; $i < strlen($a) && $i < strlen($b); $i++) {

+ 3 - 3
lib/i18n.php → lib/I18n.php

@@ -13,11 +13,11 @@
 namespace PrivateBin;
 
 /**
- * i18n
+ * I18n
  *
  * provides internationalization tools like translation, browser language detection, etc.
  */
-class i18n
+class I18n
 {
     /**
      * language
@@ -84,7 +84,7 @@ class i18n
      */
     public static function _($messageId)
     {
-        return call_user_func_array(array('self', 'translate'), func_get_args());
+        return forward_static_call_array('self::translate', func_get_args());
     }
 
     /**

+ 14 - 12
lib/model.php → lib/Model.php

@@ -12,26 +12,28 @@
 
 namespace PrivateBin;
 
-use PrivateBin\model\paste;
+use PrivateBin\Data;
+use PrivateBin\Model\Paste;
+use PrivateBin\Persistence\PurgeLimiter;
 
 /**
- * model
+ * Model
  *
  * Factory of PrivateBin instance models.
  */
-class model
+class Model
 {
     /**
      * Configuration.
      *
-     * @var configuration
+     * @var Configuration
      */
     private $_conf;
 
     /**
      * Data storage.
      *
-     * @var privatebin_abstract
+     * @var AbstractData
      */
     private $_store = null;
 
@@ -41,7 +43,7 @@ class model
      * @param configuration $conf
      * @return void
      */
-    public function __construct(configuration $conf)
+    public function __construct(Configuration $conf)
     {
         $this->_conf = $conf;
     }
@@ -50,11 +52,11 @@ class model
      * Get a paste, optionally a specific instance.
      *
      * @param string $pasteId
-     * @return model_paste
+     * @return Paste
      */
     public function getPaste($pasteId = null)
     {
-        $paste = new paste($this->_conf, $this->_getStore());
+        $paste = new Paste($this->_conf, $this->_getStore());
         if ($pasteId !== null) {
             $paste->setId($pasteId);
         }
@@ -68,8 +70,8 @@ class model
      */
     public function purge()
     {
-        purgelimiter::setConfiguration($this->_conf);
-        if (purgelimiter::canPurge()) {
+        PurgeLimiter::setConfiguration($this->_conf);
+        if (PurgeLimiter::canPurge()) {
             $this->_getStore()->purge($this->_conf->getKey('batchsize', 'purge'));
         }
     }
@@ -77,13 +79,13 @@ class model
     /**
      * Gets, and creates if neccessary, a store object
      *
-     * @return privatebin_abstract
+     * @return AbstractData
      */
     private function _getStore()
     {
         if ($this->_store === null) {
             $this->_store = forward_static_call(
-                array($this->_conf->getKey('class', 'model'), 'getInstance'),
+                'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model') . '::getInstance',
                 $this->_conf->getSection('model_options')
             );
         }

+ 4 - 4
lib/model/AbstractModel.php → lib/Model/AbstractModel.php

@@ -12,14 +12,14 @@
 
 namespace PrivateBin\Model;
 
+use PrivateBin\Configuration;
+use PrivateBin\Data\AbstractData;
+use PrivateBin\Sjcl;
 use Exception;
-use PrivateBin\configuration;
-use PrivateBin\data\AbstractData;
-use PrivateBin\sjcl;
 use stdClass;
 
 /**
- * model_abstract
+ * AbstractModel
  *
  * Abstract model for PrivateBin objects.
  */

+ 12 - 12
lib/model/comment.php → lib/Model/Comment.php

@@ -12,23 +12,23 @@
 
 namespace PrivateBin\model;
 
+use PrivateBin\Sjcl;
+use PrivateBin\Persistence\TrafficLimiter;
+use PrivateBin\Vizhash16x16;
 use Exception;
-use PrivateBin\sjcl;
-use PrivateBin\trafficlimiter;
-use PrivateBin\vizhash16x16;
 
 /**
- * model_comment
+ * Comment
  *
  * Model of a PrivateBin comment.
  */
-class comment extends AbstractModel
+class Comment extends AbstractModel
 {
     /**
      * Instance's parent.
      *
      * @access private
-     * @var model_paste
+     * @var Paste
      */
     private $_paste;
 
@@ -126,11 +126,11 @@ class comment extends AbstractModel
      * Set paste.
      *
      * @access public
-     * @param model_paste $paste
+     * @param Paste $paste
      * @throws Exception
      * @return void
      */
-    public function setPaste(paste $paste)
+    public function setPaste(Paste $paste)
     {
         $this->_paste = $paste;
         $this->_data->meta->pasteid = $paste->getId();
@@ -140,7 +140,7 @@ class comment extends AbstractModel
      * Get paste.
      *
      * @access public
-     * @return model_paste
+     * @return Paste
      */
     public function getPaste()
     {
@@ -187,7 +187,7 @@ class comment extends AbstractModel
      */
     public function setNickname($nickname)
     {
-        if (!sjcl::isValid($nickname)) {
+        if (!Sjcl::isValid($nickname)) {
             throw new Exception('Invalid data.', 66);
         }
         $this->_data->meta->nickname = $nickname;
@@ -197,8 +197,8 @@ class comment extends AbstractModel
             // If a nickname is provided, we generate a Vizhash.
             // (We assume that if the user did not enter a nickname, he/she wants
             // to be anonymous and we will not generate the vizhash.)
-            $vh = new vizhash16x16();
-            $pngdata = $vh->generate(trafficlimiter::getIp());
+            $vh = new Vizhash16x16();
+            $pngdata = $vh->generate(TrafficLimiter::getIp());
             if ($pngdata != '') {
                 $this->_data->meta->vizhash = 'data:image/png;base64,' . base64_encode($pngdata);
             }

+ 12 - 12
lib/model/paste.php → lib/Model/Paste.php

@@ -10,19 +10,19 @@
  * @version   0.22
  */
 
-namespace PrivateBin\model;
+namespace PrivateBin\Model;
 
+use PrivateBin\PrivateBin;
+use PrivateBin\Persistence\ServerSalt;
+use PrivateBin\Sjcl;
 use Exception;
-use PrivateBin\privatebin;
-use PrivateBin\serversalt;
-use PrivateBin\sjcl;
 
 /**
- * model_paste
+ * Paste
  *
  * Model of a PrivateBin paste.
  */
-class paste extends AbstractModel
+class Paste extends AbstractModel
 {
     /**
      * Get paste data.
@@ -35,14 +35,14 @@ class paste extends AbstractModel
     {
         $this->_data = $this->_store->read($this->getId());
         if ($this->_data === false) {
-            throw new Exception(privatebin::GENERIC_ERROR, 64);
+            throw new Exception(PrivateBin::GENERIC_ERROR, 64);
         }
 
         // check if paste has expired and delete it if neccessary.
         if (property_exists($this->_data->meta, 'expire_date')) {
             if ($this->_data->meta->expire_date < time()) {
                 $this->delete();
-                throw new Exception(privatebin::GENERIC_ERROR, 63);
+                throw new Exception(PrivateBin::GENERIC_ERROR, 63);
             }
             // We kindly provide the remaining time before expiration (in seconds)
             $this->_data->meta->remaining_time = $this->_data->meta->expire_date - time();
@@ -127,14 +127,14 @@ class paste extends AbstractModel
      * @param string $parentId
      * @param string $commentId
      * @throws Exception
-     * @return model_comment
+     * @return Comment
      */
     public function getComment($parentId, $commentId = null)
     {
         if (!$this->exists()) {
             throw new Exception('Invalid data.', 62);
         }
-        $comment = new comment($this->_conf, $this->_store);
+        $comment = new Comment($this->_conf, $this->_store);
         $comment->setPaste($this);
         $comment->setParentId($parentId);
         if ($commentId !== null) {
@@ -186,7 +186,7 @@ class paste extends AbstractModel
      */
     public function setAttachment($attachment)
     {
-        if (!$this->_conf->getKey('fileupload') || !sjcl::isValid($attachment)) {
+        if (!$this->_conf->getKey('fileupload') || !Sjcl::isValid($attachment)) {
             throw new Exception('Invalid attachment.', 71);
         }
         $this->_data->meta->attachment = $attachment;
@@ -202,7 +202,7 @@ class paste extends AbstractModel
      */
     public function setAttachmentName($attachmentname)
     {
-        if (!$this->_conf->getKey('fileupload') || !sjcl::isValid($attachmentname)) {
+        if (!$this->_conf->getKey('fileupload') || !Sjcl::isValid($attachmentname)) {
             throw new Exception('Invalid attachment.', 72);
         }
         $this->_data->meta->attachmentname = $attachmentname;

+ 3 - 3
lib/persistence.php → lib/Persistence/AbstractPersistence.php

@@ -10,16 +10,16 @@
  * @version   0.22
  */
 
-namespace PrivateBin;
+namespace PrivateBin\Persistence;
 
 use Exception;
 
 /**
- * persistence
+ * AbstractPersistence
  *
  * persists data in PHP files
  */
-abstract class persistence
+abstract class AbstractPersistence
 {
     /**
      * path in which to persist something

+ 8 - 6
lib/purgelimiter.php → lib/Persistence/PurgeLimiter.php

@@ -10,14 +10,16 @@
  * @version   0.22
  */
 
-namespace PrivateBin;
+namespace PrivateBin\Persistence;
+
+use PrivateBin\Configuration;
 
 /**
- * purgelimiter
+ * PurgeLimiter
  *
- * Handles purge limiting, so purging is not triggered to often.
+ * Handles purge limiting, so purging is not triggered too frequently.
  */
-class purgelimiter extends persistence
+class PurgeLimiter extends AbstractPersistence
 {
     /**
      * time limit in seconds, defaults to 300s
@@ -46,10 +48,10 @@ class purgelimiter extends persistence
      *
      * @access public
      * @static
-     * @param configuration $conf
+     * @param Configuration $conf
      * @return void
      */
-    public static function setConfiguration(configuration $conf)
+    public static function setConfiguration(Configuration $conf)
     {
         self::setLimit($conf->getKey('limit', 'purge'));
         self::setPath($conf->getKey('dir', 'purge'));

+ 8 - 6
lib/serversalt.php → lib/Persistence/ServerSalt.php

@@ -10,12 +10,12 @@
  * @version   0.22
  */
 
-namespace PrivateBin;
+namespace PrivateBin\Persistence;
 
 use Exception;
 
 /**
- * serversalt
+ * ServerSalt
  *
  * This is a random string which is unique to each PrivateBin installation.
  * It is automatically created if not present.
@@ -24,7 +24,7 @@ use Exception;
  * - to generate unique VizHash in discussions (which are not reproductible across PrivateBin servers)
  * - to generate unique deletion token (which are not re-usable across PrivateBin servers)
  */
-class serversalt extends persistence
+class ServerSalt extends AbstractPersistence
 {
     /**
      * generated salt
@@ -73,8 +73,10 @@ class serversalt extends persistence
 
         $file = 'salt.php';
         if (self::_exists($file)) {
-            $items = explode('|', @file_get_contents(self::getPath($file)));
-            if (!is_array($items) || count($items) != 3) {
+            if (is_readable(self::getPath($file))) {
+                $items = explode('|', file_get_contents(self::getPath($file)));
+            }
+            if (!isset($items) || !is_array($items) || count($items) != 3) {
                 throw new Exception('unable to read file ' . self::getPath($file), 20);
             }
             self::$_salt = $items[1];
@@ -82,7 +84,7 @@ class serversalt extends persistence
             self::$_salt = self::generate();
             self::_store(
                 $file,
-                '<?php /* |'. self::$_salt . '| */ ?>'
+                '<?php /* |' . self::$_salt . '| */ ?>'
             );
         }
         return self::$_salt;

+ 8 - 6
lib/trafficlimiter.php → lib/Persistence/TrafficLimiter.php

@@ -10,14 +10,16 @@
  * @version   0.22
  */
 
-namespace PrivateBin;
+namespace PrivateBin\Persistence;
+
+use PrivateBin\Configuration;
 
 /**
- * trafficlimiter
+ * TrafficLimiter
  *
  * Handles traffic limiting, so no user does more than one call per 10 seconds.
  */
-class trafficlimiter extends persistence
+class TrafficLimiter extends AbstractPersistence
 {
     /**
      * time limit in seconds, defaults to 10s
@@ -55,10 +57,10 @@ class trafficlimiter extends persistence
      *
      * @access public
      * @static
-     * @param configuration $conf
+     * @param Configuration $conf
      * @return void
      */
-    public static function setConfiguration(configuration $conf)
+    public static function setConfiguration(Configuration $conf)
     {
         self::setLimit($conf->getKey('limit', 'traffic'));
         self::setPath($conf->getKey('dir', 'traffic'));
@@ -99,7 +101,7 @@ class trafficlimiter extends persistence
             return true;
         }
 
-        $ip = hash_hmac('sha256', self::getIp(), serversalt::get());
+        $ip = hash_hmac('sha256', self::getIp(), ServerSalt::get());
 
         $file = 'traffic_limiter.php';
         if (!self::_exists($file)) {

+ 30 - 29
lib/privatebin.php → lib/PrivateBin.php

@@ -12,14 +12,15 @@
 
 namespace PrivateBin;
 
+use PrivateBin\Persistence\TrafficLimiter;
 use Exception;
 
 /**
- * privatebin
+ * PrivateBin
  *
  * Controller, puts it all together.
  */
-class privatebin
+class PrivateBin
 {
     /**
      * version
@@ -39,7 +40,7 @@ class privatebin
      * configuration
      *
      * @access private
-     * @var    configuration
+     * @var    Configuration
      */
     private $_conf;
 
@@ -105,7 +106,7 @@ class privatebin
      * @access private
      * @var    string
      */
-    private $_urlbase;
+    private $_urlBase;
 
     /**
      * constructor
@@ -118,10 +119,10 @@ class privatebin
     public function __construct()
     {
         if (version_compare(PHP_VERSION, '5.3.0') < 0) {
-            throw new Exception(i18n::_('PrivateBin requires php 5.3.0 or above to work. Sorry.'), 1);
+            throw new Exception(I18n::_('PrivateBin requires php 5.3.0 or above to work. Sorry.'), 1);
         }
 
-        // load config from ini file
+        // load config from ini file, initialize required classes
         $this->_init();
 
         switch ($this->_request->getOperation()) {
@@ -144,7 +145,7 @@ class privatebin
 
         // output JSON or HTML
         if ($this->_request->isJsonApiCall()) {
-            header('Content-type: ' . request::MIME_JSON);
+            header('Content-type: ' . Request::MIME_JSON);
             header('Access-Control-Allow-Origin: *');
             header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
             header('Access-Control-Allow-Headers: X-Requested-With, Content-Type');
@@ -173,15 +174,15 @@ class privatebin
             }
         }
 
-        $this->_conf = new configuration;
-        $this->_model = new model($this->_conf);
-        $this->_request = new request;
-        $this->_urlbase = array_key_exists('REQUEST_URI', $_SERVER) ?
+        $this->_conf = new Configuration;
+        $this->_model = new Model($this->_conf);
+        $this->_request = new Request;
+        $this->_urlBase = array_key_exists('REQUEST_URI', $_SERVER) ?
             htmlspecialchars($_SERVER['REQUEST_URI']) : '/';
 
         // set default language
         $lang = $this->_conf->getKey('languagedefault');
-        i18n::setLanguageFallback($lang);
+        I18n::setLanguageFallback($lang);
         // force default language, if language selection is disabled and a default is set
         if (!$this->_conf->getKey('languageselection') && strlen($lang) == 2) {
             $_COOKIE['lang'] = $lang;
@@ -212,10 +213,10 @@ class privatebin
     private function _create()
     {
         // Ensure last paste from visitors IP address was more than configured amount of seconds ago.
-        trafficlimiter::setConfiguration($this->_conf);
-        if (!trafficlimiter::canPass()) {
+        TrafficLimiter::setConfiguration($this->_conf);
+        if (!TrafficLimiter::canPass()) {
             return $this->_return_message(
-            1, i18n::_(
+            1, I18n::_(
                 'Please wait %d seconds between each post.',
                 $this->_conf->getKey('limit', 'traffic')
             )
@@ -233,9 +234,9 @@ class privatebin
         ) {
             return $this->_return_message(
             1,
-            i18n::_(
+            I18n::_(
                 'Paste is limited to %s of encrypted data.',
-                filter::size_humanreadable($sizelimit)
+                Filter::formatHumanReadableSize($sizelimit)
             )
         );
         }
@@ -336,7 +337,7 @@ class privatebin
                     }
                 } else {
                     // Make sure the token is valid.
-                    if (filter::slow_equals($deletetoken, $paste->getDeleteToken())) {
+                    if (Filter::slowEquals($deletetoken, $paste->getDeleteToken())) {
                         // Paste exists and deletion token is valid: Delete the paste.
                         $paste->delete();
                         $this->_status = 'Paste was properly deleted.';
@@ -405,23 +406,23 @@ class privatebin
         // label all the expiration options
         $expire = array();
         foreach ($this->_conf->getSection('expire_options') as $time => $seconds) {
-            $expire[$time] = ($seconds == 0) ? i18n::_(ucfirst($time)): filter::time_humanreadable($time);
+            $expire[$time] = ($seconds == 0) ? I18n::_(ucfirst($time)): Filter::formatHumanReadableTime($time);
         }
 
         // translate all the formatter options
-        $formatters = array_map(array('PrivateBin\\i18n', 'translate'), $this->_conf->getSection('formatter_options'));
+        $formatters = array_map('PrivateBin\\I18n::_', $this->_conf->getSection('formatter_options'));
 
         // set language cookie if that functionality was enabled
         $languageselection = '';
         if ($this->_conf->getKey('languageselection')) {
-            $languageselection = i18n::getLanguage();
+            $languageselection = I18n::getLanguage();
             setcookie('lang', $languageselection);
         }
 
-        $page = new view;
+        $page = new View;
         $page->assign('CIPHERDATA', $this->_data);
-        $page->assign('ERROR', i18n::_($this->_error));
-        $page->assign('STATUS', i18n::_($this->_status));
+        $page->assign('ERROR', I18n::_($this->_error));
+        $page->assign('STATUS', I18n::_($this->_status));
         $page->assign('VERSION', self::VERSION);
         $page->assign('DISCUSSION', $this->_conf->getKey('discussion'));
         $page->assign('OPENDISCUSSION', $this->_conf->getKey('opendiscussion'));
@@ -430,13 +431,13 @@ class privatebin
         $page->assign('SYNTAXHIGHLIGHTINGTHEME', $this->_conf->getKey('syntaxhighlightingtheme'));
         $page->assign('FORMATTER', $formatters);
         $page->assign('FORMATTERDEFAULT', $this->_conf->getKey('defaultformatter'));
-        $page->assign('NOTICE', i18n::_($this->_conf->getKey('notice')));
+        $page->assign('NOTICE', I18n::_($this->_conf->getKey('notice')));
         $page->assign('BURNAFTERREADINGSELECTED', $this->_conf->getKey('burnafterreadingselected'));
         $page->assign('PASSWORD', $this->_conf->getKey('password'));
         $page->assign('FILEUPLOAD', $this->_conf->getKey('fileupload'));
         $page->assign('BASE64JSVERSION', $this->_conf->getKey('zerobincompatibility') ? '1.7' : '2.1.9');
         $page->assign('LANGUAGESELECTION', $languageselection);
-        $page->assign('LANGUAGES', i18n::getLanguageLabels(i18n::getAvailableLanguages()));
+        $page->assign('LANGUAGES', I18n::getLanguageLabels(I18n::getAvailableLanguages()));
         $page->assign('EXPIRE', $expire);
         $page->assign('EXPIREDEFAULT', $this->_conf->getKey('default', 'expire'));
         $page->assign('EXPIRECLONE', !$this->_doesExpire || ($this->_doesExpire && $this->_conf->getKey('clone', 'expire')));
@@ -464,7 +465,7 @@ class privatebin
         if (is_readable($file)) {
             $content = str_replace(
                 '?jsonld=',
-                $this->_urlbase . '?jsonld=',
+                $this->_urlBase . '?jsonld=',
                 file_get_contents($file)
             );
         }
@@ -488,10 +489,10 @@ class privatebin
     {
         $result = array('status' => $status);
         if ($status) {
-            $result['message'] = i18n::_($message);
+            $result['message'] = I18n::_($message);
         } else {
             $result['id'] = $message;
-            $result['url'] = $this->_urlbase . '?' . $message;
+            $result['url'] = $this->_urlBase . '?' . $message;
         }
         $result += $other;
         $this->_json = json_encode($result);

+ 6 - 6
lib/request.php → lib/Request.php

@@ -13,11 +13,11 @@
 namespace PrivateBin;
 
 /**
- * request
+ * Request
  *
  * parses request parameters and provides helper functions for routing
 */
-class request
+class Request
 {
     /**
      * MIME type for JSON
@@ -81,10 +81,10 @@ class request
     public function __construct()
     {
         // in case stupid admin has left magic_quotes enabled in php.ini (for PHP < 5.4)
-        if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
-            $_POST   = array_map('filter::stripslashes_deep', $_POST);
-            $_GET    = array_map('filter::stripslashes_deep', $_GET);
-            $_COOKIE = array_map('filter::stripslashes_deep', $_COOKIE);
+        if (version_compare(PHP_VERSION, '5.4.0') < 0 && get_magic_quotes_gpc()) {
+            $_POST   = array_map('PrivateBin\\Filter::stripslashesDeep', $_POST);
+            $_GET    = array_map('PrivateBin\\Filter::stripslashesDeep', $_GET);
+            $_COOKIE = array_map('PrivateBin\\Filter::stripslashesDeep', $_COOKIE);
         }
 
         // decide if we are in JSON API or HTML context

+ 2 - 2
lib/sjcl.php → lib/Sjcl.php

@@ -13,11 +13,11 @@
 namespace PrivateBin;
 
 /**
- * sjcl
+ * Sjcl
  *
  * Provides SJCL validation function.
  */
-class sjcl
+class Sjcl
 {
     /**
      * SJCL validator

+ 2 - 3
lib/view.php → lib/View.php

@@ -11,15 +11,14 @@
  */
 
 namespace PrivateBin;
-
 use Exception;
 
 /**
- * view
+ * View
  *
  * Displays the templates
  */
-class view
+class View
 {
     /**
      * variables available in the template

+ 6 - 4
lib/vizhash16x16.php → lib/Vizhash16x16.php

@@ -13,18 +13,20 @@
 
 namespace PrivateBin;
 
+use PrivateBin\Persistence\ServerSalt;
+
 /**
- * vizhash16x16
+ * Vizhash16x16
  *
  * Example:
- * $vz = new vizhash16x16();
+ * $vz = new Vizhash16x16();
  * $data = $vz->generate('hello');
  * header('Content-type: image/png');
  * echo $data;
  * exit;
  */
 
-class vizhash16x16
+class Vizhash16x16
 {
     /**
      * hash values
@@ -76,7 +78,7 @@ class vizhash16x16
     {
         $this->width  = 16;
         $this->height = 16;
-        $this->salt   = serversalt::get();
+        $this->salt   = ServerSalt::get();
     }
 
     /**

+ 174 - 98
tpl/bootstrap-compact.php

@@ -1,32 +1,46 @@
-<!DOCTYPE html>
+<?php
+use PrivateBin\I18n;
+?><!DOCTYPE html>
 <html lang="en">
 	<head>
 		<meta charset="utf-8" />
 		<meta http-equiv="X-UA-Compatible" content="IE=edge">
 		<meta name="viewport" content="width=device-width, initial-scale=1">
 		<meta name="robots" content="noindex" />
-		<title><?php echo PrivateBin\i18n::_('PrivateBin'); ?></title>
+		<title><?php echo I18n::_('PrivateBin'); ?></title>
 		<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-3.3.5.css" />
 		<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.3.5.css" />
-		<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" /><?php
-if ($SYNTAXHIGHLIGHTING): ?>
-		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" /><?php
-    if (strlen($SYNTAXHIGHLIGHTINGTHEME)): ?>
-		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" /><?php
+		<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+if ($SYNTAXHIGHLIGHTING):
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+    if (strlen($SYNTAXHIGHLIGHTINGTHEME)):
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
     endif;
-endif; ?>
+endif;
+?>
 		<script type="text/javascript" src="js/jquery-1.11.3.js"></script>
 		<script type="text/javascript" src="js/sjcl-1.0.4.js"></script>
 		<script type="text/javascript" src="js/base64-<?php echo rawurlencode($BASE64JSVERSION); ?>.js"></script>
 		<script type="text/javascript" src="js/rawdeflate-0.5.js"></script>
 		<script type="text/javascript" src="js/rawinflate-0.3.js"></script>
-		<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script><?php
-if ($SYNTAXHIGHLIGHTING): ?>
-		<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>"></script><?php
+		<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script>
+<?php
+if ($SYNTAXHIGHLIGHTING):
+?>
+		<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>"></script>
+<?php
+endif;
+if ($MARKDOWN):
+?>
+		<script type="text/javascript" src="js/showdown-1.4.1.js"></script>
+<?php
 endif;
-if ($MARKDOWN): ?>
-		<script type="text/javascript" src="js/showdown-1.4.1.js"></script><?php
-endif; ?>
+?>
 		<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>"></script>
 		<!--[if lt IE 10]>
 		<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
@@ -45,102 +59,138 @@ endif; ?>
 			<div class="container">
 				<div class="navbar-header">
 					<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
-						<span class="sr-only"><?php echo PrivateBin\i18n::_('Toggle navigation'); ?></span>
+						<span class="sr-only"><?php echo I18n::_('Toggle navigation'); ?></span>
 						<span class="icon-bar"></span>
 						<span class="icon-bar"></span>
 						<span class="icon-bar"></span>
 					</button>
 					<a class="reloadlink navbar-brand" href="/">
-						<img alt="<?php echo PrivateBin\i18n::_('PrivateBin'); ?>" src="img/icon.svg" width="20" />
+						<img alt="<?php echo I18n::_('PrivateBin'); ?>" src="img/icon.svg" width="20" />
 					</a>
 				</div>
 				<div id="navbar" class="navbar-collapse collapse">
 					<ul class="nav navbar-nav">
 						<li>
 							<button id="sendbutton" type="button" class="hidden btn btn-default navbar-btn">
-								<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Send'); ?>
-							</button><?php
-if ($EXPIRECLONE): ?>
+								<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'); ?>
+							</button>
+<?php
+if ($EXPIRECLONE):
+?>
 							<button id="clonebutton" type="button" class="hidden btn btn-default navbar-btn">
-								<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Clone'); ?>
-							</button><?php
-endif; ?>
+								<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo I18n::_('Clone'); ?>
+							</button>
+<?php
+endif;
+?>
 							<button id="rawtextbutton" type="button" class="hidden btn btn-default navbar-btn">
-								<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Raw text'); ?>
+								<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'); ?>
 							</button>
 						</li>
 						<li class="dropdown">
-							<select id="pasteExpiration" name="pasteExpiration" class="hidden"><?php
-foreach ($EXPIRE as $key => $value): ?>
+							<select id="pasteExpiration" name="pasteExpiration" class="hidden">
+<?php
+foreach ($EXPIRE as $key => $value):
+?>
 								<option value="<?php echo $key; ?>"<?php
-    if ($key == $EXPIREDEFAULT): ?> selected="selected"<?php
-    endif; ?>><?php echo $value; ?></option><?php
-endforeach; ?>
+    if ($key == $EXPIREDEFAULT):
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
 							</select>
-							<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
-							<ul class="dropdown-menu"><?php
-foreach ($EXPIRE as $key => $value): ?>
+							<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
+							<ul class="dropdown-menu">
+<?php
+foreach ($EXPIRE as $key => $value):
+?>
 								<li>
 									<a href="#" onclick="$('#pasteExpiration').val('<?php echo $key; ?>');$('#pasteExpirationDisplay').text('<?php echo $value; ?>');return false;">
 										<?php echo $value; ?>
 									</a>
-								</li><?php
-endforeach; ?>
+								</li>
+<?php
+endforeach;
+?>
 							</ul>
 						</li>
 						<li id="formatter" class="dropdown">
-							<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Options'); ?> <span class="caret"></span></a>
+							<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Options'); ?> <span class="caret"></span></a>
 							<ul class="dropdown-menu">
 								<li id="burnafterreadingoption" class="checkbox hidden">
 									<label>
 										<input type="checkbox" id="burnafterreading" name="burnafterreading" <?php
-if ($BURNAFTERREADINGSELECTED): ?> checked="checked"<?php
-endif; ?> />
-										<?php echo PrivateBin\i18n::_('Burn after reading'); ?>
+if ($BURNAFTERREADINGSELECTED):
+?> checked="checked"<?php
+endif;
+?> />
+										<?php echo I18n::_('Burn after reading'); ?>
 									</label>
-								</li><?php
-if ($DISCUSSION): ?>
+								</li>
+<?php
+if ($DISCUSSION):
+?>
 								<li id="opendisc" class="checkbox hidden">
 									<label>
 										<input type="checkbox" id="opendiscussion" name="opendiscussion" <?php
-    if ($OPENDISCUSSION): ?> checked="checked"<?php
-    endif; ?> />
-										<?php echo PrivateBin\i18n::_('Open discussion'); ?>
+    if ($OPENDISCUSSION):
+?> checked="checked"<?php
+    endif;
+?> />
+										<?php echo I18n::_('Open discussion'); ?>
 									</label>
-								</li><?php
-endif; ?>
+								</li>
+<?php
+endif;
+?>
 								<li role="separator" class="divider"></li>
 								<li>
 									<div>
-										<?php echo PrivateBin\i18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span>
+										<?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span>
 									</div>
-								</li><?php
-foreach ($FORMATTER as $key => $value): ?>
+								</li>
+<?php
+foreach ($FORMATTER as $key => $value):
+?>
 								<li>
 									<a href="#" onclick="$('#pasteFormatter').val('<?php echo $key; ?>');$('#pasteFormatterDisplay').text('<?php echo $value; ?>');return false;">
 										<?php echo $value; ?>
 									</a>
-								</li><?php
-endforeach; ?>
+								</li>
+<?php
+endforeach;
+?>
 							</ul>
-							<select id="pasteFormatter" name="pasteFormatter" class="hidden"><?php
-foreach ($FORMATTER as $key => $value): ?>
+							<select id="pasteFormatter" name="pasteFormatter" class="hidden">
+<?php
+foreach ($FORMATTER as $key => $value):
+?>
 								<option value="<?php echo $key; ?>"<?php
-    if ($key == $FORMATTERDEFAULT): ?> selected="selected"<?php
-    endif; ?>><?php echo $value; ?></option><?php
-endforeach; ?>
+    if ($key == $FORMATTERDEFAULT):
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
 							</select>
-						</li><?php
-if ($PASSWORD): ?>
+						</li>
+<?php
+if ($PASSWORD):
+?>
 						<li>
 							<div id="password" class="navbar-form hidden">
-								<input type="password" id="passwordinput" placeholder="<?php echo PrivateBin\i18n::_('Password (recommended)'); ?>" class="form-control" size="19"/>
+								<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control" size="19"/>
 							</div>
-						</li><?php
+						</li>
+<?php
 endif;
-if ($FILEUPLOAD): ?>
+if ($FILEUPLOAD):
+?>
 						<li id="attach" class="hidden dropdown">
-							<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Attach a file'); ?> <span class="caret"></span></a>
+							<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Attach a file'); ?> <span class="caret"></span></a>
 							<ul class="dropdown-menu">
 								<li id="filewrap">
 									<div>
@@ -149,62 +199,84 @@ if ($FILEUPLOAD): ?>
 								</li>
 								<li>
 									<a id="fileremovebutton"  href="#">
-										<?php echo PrivateBin\i18n::_('Remove attachment'); ?>
+										<?php echo I18n::_('Remove attachment'); ?>
 									</a>
 								</li>
 							</ul>
-						</li><?php
-endif; ?>
+						</li>
+<?php
+endif;
+?>
 					</ul>
-					<ul class="nav navbar-nav pull-right"><?php
-if (strlen($LANGUAGESELECTION)): ?>
+					<ul class="nav navbar-nav pull-right">
+<?php
+if (strlen($LANGUAGESELECTION)):
+?>
 						<li id="language" class="dropdown">
 							<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> <?php echo $LANGUAGES[$LANGUAGESELECTION][0]; ?> <span class="caret"></span></a>
-							<ul class="dropdown-menu"><?php
-    foreach ($LANGUAGES as $key => $value): ?>
+							<ul class="dropdown-menu">
+<?php
+    foreach ($LANGUAGES as $key => $value):
+?>
 								<li>
 									<a href="#" class="reloadlink" onclick="document.cookie='lang={$key}';">
 										<?php echo $value[0]; ?> (<?php echo $value[1]; ?>)
 									</a>
-								</li><?php
-    endforeach; ?>
+								</li>
+<?php
+    endforeach;
+?>
 							</ul>
-						</li><?php
-endif; ?>
+						</li>
+<?php
+endif;
+?>
 						<li>
 							<button id="newbutton" type="button" class="reloadlink hidden btn btn-default navbar-btn">
-								<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('New'); ?>
+								<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'); ?>
 							</button>
 						</li>
 					</ul>
 				</div>
 			</div>
 		</nav>
-		<header class="container"><?php
-if (strlen($NOTICE)): ?>
+		<header class="container">
+<?php
+if (strlen($NOTICE)):
+?>
 			<div role="alert" class="alert alert-info">
 				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <?php echo htmlspecialchars($NOTICE); ?>
-			</div><?php
-endif; ?>
+			</div>
+<?php
+endif;
+?>
 			<div id="remainingtime" role="alert" class="hidden alert alert-info">
 				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
-			</div><?php
-if ($FILEUPLOAD): ?>
+			</div>
+<?php
+if ($FILEUPLOAD):
+?>
 			<div id="attachment" role="alert" class="hidden alert alert-info">
-				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo PrivateBin\i18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo PrivateBin\i18n::_('Cloned file attached.'); ?></span>
-			</div><?php
+				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo I18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
+			</div>
+<?php
 endif;
-if (strlen($STATUS)): ?>
+if (strlen($STATUS)):
+?>
 			<div id="status" role="alert" class="alert alert-success">
 				<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <?php echo htmlspecialchars($STATUS); ?>
-			</div><?php
-endif; ?>
+			</div>
+<?php
+endif;
+?>
 			<div id="errormessage" role="alert" class="<?php
-if (!strlen($ERROR)): ?>hidden <?php
-endif; ?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
-			<noscript><div id="noscript" role="alert" class="nonworking alert alert-warning"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
-			<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('PrivateBin requires a modern browser to work.'); ?></div>
-			<div id="ienotice" role="alert" class="hidden alert alert-warning"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'); ?>
+if (!strlen($ERROR)):
+?>hidden <?php
+endif;
+?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
+			<noscript><div id="noscript" role="alert" class="nonworking alert alert-warning"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo I18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
+			<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo I18n::_('PrivateBin requires a modern browser to work.'); ?></div>
+			<div id="ienotice" role="alert" class="hidden alert alert-warning"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> <?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'); ?>
 				<a href="https://www.mozilla.org/firefox/">Firefox</a>,
 				<a href="https://www.opera.com/">Opera</a>,
 				<a href="https://www.google.com/chrome">Chrome</a>,
@@ -213,17 +285,21 @@ endif; ?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden
 			<div id="pasteresult" role="alert" class="hidden alert alert-success">
 				<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
 				<div id="deletelink"></div>
-				<div id="pastelink"><?php
-if (strlen($URLSHORTENER)): ?>
+				<div id="pastelink">
+<?php
+if (strlen($URLSHORTENER)):
+?>
 					<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-primary">
-						<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Shorten URL'); ?>
-					</button><?php
-endif; ?>
+						<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'); ?>
+					</button>
+<?php
+endif;
+?>
 				</div>
 			</div>
 			<ul id="preview" class="nav nav-tabs hidden">
-				<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo PrivateBin\i18n::_('Editor'); ?></a></li>
-				<li role="presentation"><a id="messagepreview" href="#"><?php echo PrivateBin\i18n::_('Preview'); ?></a></li>
+				<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li>
+				<li role="presentation"><a id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li>
 			</ul>
 		</header>
 		<section class="container">
@@ -238,16 +314,16 @@ endif; ?>
 		</section>
 		<section class="container">
 			<div id="discussion" class="hidden">
-				<h4><?php echo PrivateBin\i18n::_('Discussion'); ?></h4>
+				<h4><?php echo I18n::_('Discussion'); ?></h4>
 				<div id="comments"></div>
 			</div>
 		</section>
 		<footer class="container">
 			<div class="row">
-				<h4 class="col-md-5 col-xs-8"><?php echo PrivateBin\i18n::_('PrivateBin'); ?> <small>- <?php echo PrivateBin\i18n::_('Because ignorance is bliss'); ?></small></h4>
+				<h4 class="col-md-5 col-xs-8"><?php echo I18n::_('PrivateBin'); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
 				<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
 				<p id="aboutbox" class="col-md-6 col-xs-12">
-					<?php echo PrivateBin\i18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/PrivateBin/PrivateBin/wiki">project page</a>.'); ?>
+					<?php echo I18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/PrivateBin/PrivateBin/wiki">project page</a>.'); ?>
 				</p>
 			</div>
 		</footer>

+ 169 - 95
tpl/bootstrap-dark-page.php

@@ -1,32 +1,46 @@
-<!DOCTYPE html>
+<?php
+use PrivateBin\I18n;
+?><!DOCTYPE html>
 <html lang="en">
 	<head>
 		<meta charset="utf-8" />
 		<meta http-equiv="X-UA-Compatible" content="IE=edge">
 		<meta name="viewport" content="width=device-width, initial-scale=1">
 		<meta name="robots" content="noindex" />
-		<title><?php echo PrivateBin\i18n::_('PrivateBin'); ?></title>
+		<title><?php echo I18n::_('PrivateBin'); ?></title>
 		<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.3.5.css" />
 		<link type="text/css" rel="stylesheet" href="css/bootstrap/darkstrap-0.9.3.css" />
-		<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" /><?php
-if ($SYNTAXHIGHLIGHTING): ?>
-		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" /><?php
-    if (strlen($SYNTAXHIGHLIGHTINGTHEME)): ?>
-		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" /><?php
+		<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+if ($SYNTAXHIGHLIGHTING):
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+    if (strlen($SYNTAXHIGHLIGHTINGTHEME)):
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
     endif;
-endif; ?>
+endif;
+?>
 		<script type="text/javascript" src="js/jquery-1.11.3.js"></script>
 		<script type="text/javascript" src="js/sjcl-1.0.4.js"></script>
 		<script type="text/javascript" src="js/base64-<?php echo rawurlencode($BASE64JSVERSION); ?>.js"></script>
 		<script type="text/javascript" src="js/rawdeflate-0.5.js"></script>
 		<script type="text/javascript" src="js/rawinflate-0.3.js"></script>
-		<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script><?php
-if ($SYNTAXHIGHLIGHTING): ?>
-		<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>"></script><?php
+		<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script>
+<?php
+if ($SYNTAXHIGHLIGHTING):
+?>
+		<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>"></script>
+<?php
+endif;
+if ($MARKDOWN):
+?>
+		<script type="text/javascript" src="js/showdown-1.4.1.js"></script>
+<?php
 endif;
-if ($MARKDOWN): ?>
-		<script type="text/javascript" src="js/showdown-1.4.1.js"></script><?php
-endif; ?>
+?>
 		<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>"></script>
 		<!--[if lt IE 10]>
 		<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
@@ -44,81 +58,105 @@ endif; ?>
 		<nav class="navbar navbar-inverse navbar-static-top">
 			<div class="navbar-header">
 				<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
-					<span class="sr-only"><?php echo PrivateBin\i18n::_('Toggle navigation'); ?></span>
+					<span class="sr-only"><?php echo I18n::_('Toggle navigation'); ?></span>
 					<span class="icon-bar"></span>
 					<span class="icon-bar"></span>
 					<span class="icon-bar"></span>
 				</button>
 				<a class="reloadlink navbar-brand" href="/">
-					<img alt="<?php echo PrivateBin\i18n::_('PrivateBin'); ?>" src="img/icon.svg" width="20" />
+					<img alt="<?php echo I18n::_('PrivateBin'); ?>" src="img/icon.svg" width="20" />
 				</a>
 			</div>
 			<div id="navbar" class="navbar-collapse collapse">
 				<ul class="nav navbar-nav">
 					<li>
 						<button id="sendbutton" type="button" class="hidden btn btn-warning navbar-btn">
-							<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Send'); ?>
-						</button><?php
-if ($EXPIRECLONE): ?>
+							<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'); ?>
+						</button>
+<?php
+if ($EXPIRECLONE):
+?>
 						<button id="clonebutton" type="button" class="hidden btn btn-warning navbar-btn">
-							<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Clone'); ?>
-						</button><?php
-endif; ?>
+							<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo I18n::_('Clone'); ?>
+						</button>
+<?php
+endif;
+?>
 						<button id="rawtextbutton" type="button" class="hidden btn btn-warning navbar-btn">
-							<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Raw text'); ?>
+							<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'); ?>
 						</button>
 					</li>
 					<li class="dropdown">
-						<select id="pasteExpiration" name="pasteExpiration" class="hidden"><?php
-foreach ($EXPIRE as $key => $value): ?>
+						<select id="pasteExpiration" name="pasteExpiration" class="hidden">
+<?php
+foreach ($EXPIRE as $key => $value):
+?>
 							<option value="<?php echo $key; ?>"<?php
-    if ($key == $EXPIREDEFAULT): ?> selected="selected"<?php
-    endif; ?>><?php echo $value; ?></option><?php
-endforeach; ?>
+    if ($key == $EXPIREDEFAULT):
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
 						</select>
-						<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
-						<ul class="dropdown-menu"><?php
-foreach ($EXPIRE as $key => $value): ?>
+						<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
+						<ul class="dropdown-menu">
+<?php
+foreach ($EXPIRE as $key => $value):
+?>
 							<li>
 								<a href="#" onclick="$('#pasteExpiration').val('<?php echo $key; ?>');$('#pasteExpirationDisplay').text('<?php echo $value; ?>');return false;">
 									<?php echo $value; ?>
 								</a>
-							</li><?php
-endforeach; ?>
+							</li>
+<?php
+endforeach;
+?>
 						</ul>
 					</li>
 					<li>
 						<div id="burnafterreadingoption" class="navbar-text checkbox hidden">
 							<label>
 								<input type="checkbox" id="burnafterreading" name="burnafterreading" <?php
-if ($BURNAFTERREADINGSELECTED): ?> checked="checked"<?php
-endif; ?> />
-								<?php echo PrivateBin\i18n::_('Burn after reading'); ?>
+if ($BURNAFTERREADINGSELECTED):
+?> checked="checked"<?php
+endif;
+?> />
+								<?php echo I18n::_('Burn after reading'); ?>
 							</label>
 						</div>
-					</li><?php
-if ($DISCUSSION): ?>
+					</li>
+<?php
+if ($DISCUSSION):
+?>
 					<li>
 						<div id="opendisc" class="navbar-text checkbox hidden">
 							<label>
 								<input type="checkbox" id="opendiscussion" name="opendiscussion" <?php
-    if ($OPENDISCUSSION): ?> checked="checked"<?php
-    endif; ?> />
-								<?php echo PrivateBin\i18n::_('Open discussion'); ?>
+    if ($OPENDISCUSSION):
+?> checked="checked"<?php
+    endif;
+?> />
+								<?php echo I18n::_('Open discussion'); ?>
 						 	</label>
 						</div>
-					</li><?php
+					</li>
+<?php
 endif;
-if ($PASSWORD): ?>
+if ($PASSWORD):
+?>
 					<li>
 						<div id="password" class="navbar-form hidden">
-							<input type="password" id="passwordinput" placeholder="<?php echo PrivateBin\i18n::_('Password (recommended)'); ?>" class="form-control" size="19" />
+							<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control" size="19" />
 						</div>
-					</li><?php
+					</li>
+<?php
 endif;
-if ($FILEUPLOAD): ?>
+if ($FILEUPLOAD):
+?>
 					<li id="attach" class="hidden dropdown">
-						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Attach a file'); ?> <span class="caret"></span></a>
+						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Attach a file'); ?> <span class="caret"></span></a>
 						<ul class="dropdown-menu">
 							<li id="filewrap">
 								<div>
@@ -127,80 +165,112 @@ if ($FILEUPLOAD): ?>
 							</li>
 							<li>
 								<a id="fileremovebutton"  href="#">
-									<?php echo PrivateBin\i18n::_('Remove attachment'); ?>
+									<?php echo I18n::_('Remove attachment'); ?>
 								</a>
 							</li>
 						</ul>
-					</li><?php
-endif; ?>
+					</li>
+<?php
+endif;
+?>
 					<li class="dropdown">
-						<select id="pasteFormatter" name="pasteFormatter" class="hidden"><?php
-foreach ($FORMATTER as $key => $value): ?>
+						<select id="pasteFormatter" name="pasteFormatter" class="hidden">
+<?php
+foreach ($FORMATTER as $key => $value):
+?>
 							<option value="<?php echo $key; ?>"<?php
-    if ($key == $FORMATTERDEFAULT): ?> selected="selected"<?php
-    endif; ?>><?php echo $value; ?></option><?php
-endforeach; ?>
+    if ($key == $FORMATTERDEFAULT):
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
 						</select>
-						<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
-						<ul class="dropdown-menu"><?php
-foreach ($FORMATTER as $key => $value): ?>
+						<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
+						<ul class="dropdown-menu">
+<?php
+foreach ($FORMATTER as $key => $value):
+?>
 							<li>
 								<a href="#" onclick="$('#pasteFormatter').val('<?php echo $key; ?>');$('#pasteFormatterDisplay').text('<?php echo $value; ?>');return false;">
 									<?php echo $value; ?>
 								</a>
-							</li><?php
-endforeach; ?>
+							</li>
+<?php
+endforeach;
+?>
 						</ul>
 					</li>
 				</ul>
-				<ul class="nav navbar-nav pull-right"><?php
-if (strlen($LANGUAGESELECTION)): ?>
+				<ul class="nav navbar-nav pull-right">
+<?php
+if (strlen($LANGUAGESELECTION)):
+?>
 					<li id="language" class="dropdown">
 						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> <?php echo $LANGUAGES[$LANGUAGESELECTION][0]; ?> <span class="caret"></span></a>
-						<ul class="dropdown-menu"><?php
-    foreach ($LANGUAGES as $key => $value): ?>
+						<ul class="dropdown-menu">
+<?php
+    foreach ($LANGUAGES as $key => $value):
+?>
 							<li>
 								<a href="#" class="reloadlink" onclick="document.cookie='lang=<?php echo $key; ?>';">
 									<?php echo $value[0]; ?> (<?php echo $value[1]; ?>)
 								</a>
-							</li><?php
-    endforeach; ?>
+							</li>
+<?php
+    endforeach;
+?>
 						</ul>
-					</li><?php
-endif; ?>
+					</li>
+<?php
+endif;
+?>
 					<li>
 						<button id="newbutton" type="button" class="reloadlink hidden btn btn-warning navbar-btn">
-							<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('New'); ?>
+							<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'); ?>
 						</button>
 					</li>
 				</ul>
 			</div>
 		</nav>
-		<header class="container"><?php
-if (strlen($NOTICE)): ?>
+		<header class="container">
+<?php
+if (strlen($NOTICE)):
+?>
 			<div role="alert" class="alert alert-info">
 				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <?php echo htmlspecialchars($NOTICE); ?>
-			</div><?php
-endif; ?>
+			</div>
+<?php
+endif;
+?>
 			<div id="remainingtime" role="alert" class="hidden alert alert-info">
 				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
-			</div><?php
-if ($FILEUPLOAD): ?>
+			</div>
+<?php
+if ($FILEUPLOAD):
+?>
 			<div id="attachment" role="alert" class="hidden alert alert-info">
-				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo PrivateBin\i18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo PrivateBin\i18n::_('Cloned file attached.'); ?></span>
-			</div><?php
+				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo I18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
+			</div>
+<?php
 endif;
-if (strlen($STATUS)): ?>
+if (strlen($STATUS)):
+?>
 			<div id="status" role="alert" class="alert alert-success">
 				<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <?php echo htmlspecialchars($STATUS); ?>
-			</div><?php
-endif; ?>
+			</div>
+<?php
+endif;
+?>
 			<div id="errormessage" role="alert" class="<?php
-if (!strlen($ERROR)): ?>hidden <?php
-endif; ?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
-			<noscript><div id="noscript" role="alert" class="nonworking alert alert-error"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
-			<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('PrivateBin requires a modern browser to work.'); ?></div>
-			<div id="ienotice" role="alert" class="hidden alert alert-error"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'); ?>
+if (!strlen($ERROR)):
+?>hidden <?php
+endif;
+?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
+			<noscript><div id="noscript" role="alert" class="nonworking alert alert-error"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo I18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
+			<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo I18n::_('PrivateBin requires a modern browser to work.'); ?></div>
+			<div id="ienotice" role="alert" class="hidden alert alert-error"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> <?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'); ?>
 				<a href="https://www.mozilla.org/firefox/">Firefox</a>,
 				<a href="https://www.opera.com/">Opera</a>,
 				<a href="https://www.google.com/chrome">Chrome</a>,
@@ -209,17 +279,21 @@ endif; ?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden
 			<div id="pasteresult" role="alert" class="hidden alert alert-success">
 				<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
 				<div id="deletelink"></div>
-				<div id="pastelink"><?php
-if (strlen($URLSHORTENER)): ?>
+				<div id="pastelink">
+<?php
+if (strlen($URLSHORTENER)):
+?>
 					<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-warning">
-						<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Shorten URL'); ?>
-					</button><?php
-endif; ?>
+						<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'); ?>
+					</button>
+<?php
+endif;
+?>
 				</div>
 			</div>
 			<ul id="preview" class="nav nav-tabs hidden">
-				<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo PrivateBin\i18n::_('Editor'); ?></a></li>
-				<li role="presentation"><a id="messagepreview" href="#"><?php echo PrivateBin\i18n::_('Preview'); ?></a></li>
+				<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li>
+				<li role="presentation"><a id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li>
 			</ul>
 		</header>
 		<section class="container">
@@ -234,16 +308,16 @@ endif; ?>
 		</section>
 		<section class="container">
 			<div id="discussion" class="hidden">
-				<h4><?php echo PrivateBin\i18n::_('Discussion'); ?></h4>
+				<h4><?php echo I18n::_('Discussion'); ?></h4>
 				<div id="comments"></div>
 			</div>
 		</section>
 		<footer class="container">
 			<div class="row">
-				<h4 class="col-md-5 col-xs-8"><?php echo PrivateBin\i18n::_('PrivateBin'); ?> <small>- <?php echo PrivateBin\i18n::_('Because ignorance is bliss'); ?></small></h4>
+				<h4 class="col-md-5 col-xs-8"><?php echo I18n::_('PrivateBin'); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
 				<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
 				<p id="aboutbox" class="col-md-6 col-xs-12">
-					<?php echo PrivateBin\i18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/PrivateBin/PrivateBin/wiki">project page</a>.'); ?>
+					<?php echo I18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/PrivateBin/PrivateBin/wiki">project page</a>.'); ?>
 				</p>
 			</div>
 		</footer>

+ 169 - 95
tpl/bootstrap-dark.php

@@ -1,32 +1,46 @@
-<!DOCTYPE html>
+<?php
+use PrivateBin\I18n;
+?><!DOCTYPE html>
 <html lang="en">
 	<head>
 		<meta charset="utf-8" />
 		<meta http-equiv="X-UA-Compatible" content="IE=edge">
 		<meta name="viewport" content="width=device-width, initial-scale=1">
 		<meta name="robots" content="noindex" />
-		<title><?php echo PrivateBin\i18n::_('PrivateBin'); ?></title>
+		<title><?php echo I18n::_('PrivateBin'); ?></title>
 		<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.3.5.css" />
 		<link type="text/css" rel="stylesheet" href="css/bootstrap/darkstrap-0.9.3.css" />
-		<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" /><?php
-if ($SYNTAXHIGHLIGHTING): ?>
-		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" /><?php
-    if (strlen($SYNTAXHIGHLIGHTINGTHEME)): ?>
-		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" /><?php
+		<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+if ($SYNTAXHIGHLIGHTING):
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+     if (strlen($SYNTAXHIGHLIGHTINGTHEME)):
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
     endif;
-endif; ?>
+endif;
+?>
 		<script type="text/javascript" src="js/jquery-1.11.3.js"></script>
 		<script type="text/javascript" src="js/sjcl-1.0.4.js"></script>
 		<script type="text/javascript" src="js/base64-<?php echo rawurlencode($BASE64JSVERSION); ?>.js"></script>
 		<script type="text/javascript" src="js/rawdeflate-0.5.js"></script>
 		<script type="text/javascript" src="js/rawinflate-0.3.js"></script>
-		<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script><?php
-if ($SYNTAXHIGHLIGHTING): ?>
-		<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>"></script><?php
+		<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script>
+<?php
+if ($SYNTAXHIGHLIGHTING):
+?>
+		<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>"></script>
+<?php
+endif;
+if ($MARKDOWN):
+?>
+		<script type="text/javascript" src="js/showdown-1.4.1.js"></script>
+<?php
 endif;
-if ($MARKDOWN): ?>
-		<script type="text/javascript" src="js/showdown-1.4.1.js"></script><?php
-endif; ?>
+?>
 		<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>"></script>
 		<!--[if lt IE 10]>
 		<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
@@ -44,81 +58,105 @@ endif; ?>
 		<nav class="navbar navbar-inverse navbar-static-top">
 			<div class="navbar-header">
 				<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
-					<span class="sr-only"><?php echo PrivateBin\i18n::_('Toggle navigation'); ?></span>
+					<span class="sr-only"><?php echo I18n::_('Toggle navigation'); ?></span>
 					<span class="icon-bar"></span>
 					<span class="icon-bar"></span>
 					<span class="icon-bar"></span>
 				</button>
 				<a class="reloadlink navbar-brand" href="/">
-					<img alt="<?php echo PrivateBin\i18n::_('PrivateBin'); ?>" src="img/icon.svg" width="20" />
+					<img alt="<?php echo I18n::_('PrivateBin'); ?>" src="img/icon.svg" width="20" />
 				</a>
 			</div>
 			<div id="navbar" class="navbar-collapse collapse">
 				<ul class="nav navbar-nav">
 					<li>
 						<button id="newbutton" type="button" class="reloadlink hidden btn btn-warning navbar-btn">
-							<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('New'); ?>
-						</button><?php
-if ($EXPIRECLONE): ?>
+							<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'); ?>
+						</button>
+<?php
+if ($EXPIRECLONE):
+?>
 						<button id="clonebutton" type="button" class="hidden btn btn-warning navbar-btn">
-							<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Clone'); ?>
-						</button><?php
-endif; ?>
+							<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo I18n::_('Clone'); ?>
+						</button>
+<?php
+endif;
+?>
 						<button id="rawtextbutton" type="button" class="hidden btn btn-warning navbar-btn">
-							<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Raw text'); ?>
+							<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'); ?>
 						</button>
 					</li>
 					<li class="dropdown">
-						<select id="pasteExpiration" name="pasteExpiration" class="hidden"><?php
-foreach ($EXPIRE as $key => $value): ?>
+						<select id="pasteExpiration" name="pasteExpiration" class="hidden">
+<?php
+foreach ($EXPIRE as $key => $value):
+?>
 							<option value="<?php echo $key; ?>"<?php
-    if ($key == $EXPIREDEFAULT): ?> selected="selected"<?php
-    endif; ?>><?php echo $value; ?></option><?php
-endforeach; ?>
+    if ($key == $EXPIREDEFAULT):
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
 						</select>
-						<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
-						<ul class="dropdown-menu"><?php
-foreach ($EXPIRE as $key => $value): ?>
+						<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
+						<ul class="dropdown-menu">
+<?php
+foreach ($EXPIRE as $key => $value):
+?>
 							<li>
 								<a href="#" onclick="$('#pasteExpiration').val('<?php echo $key; ?>');$('#pasteExpirationDisplay').text('<?php echo $value; ?>');return false;">
 									<?php echo $value; ?>
 								</a>
-							</li><?php
-endforeach; ?>
+							</li>
+<?php
+endforeach;
+?>
 						</ul>
 					</li>
 					<li>
 						<div id="burnafterreadingoption" class="navbar-text checkbox hidden">
 							<label>
 								<input type="checkbox" id="burnafterreading" name="burnafterreading" <?php
-if ($BURNAFTERREADINGSELECTED): ?> checked="checked"<?php
-endif; ?> />
-								<?php echo PrivateBin\i18n::_('Burn after reading'); ?>
+if ($BURNAFTERREADINGSELECTED):
+?> checked="checked"<?php
+endif;
+?> />
+								<?php echo I18n::_('Burn after reading'); ?>
 							</label>
 						</div>
-					</li><?php
-if ($DISCUSSION): ?>
+					</li>
+<?php
+if ($DISCUSSION):
+?>
 					<li>
 						<div id="opendisc" class="navbar-text checkbox hidden">
 							<label>
 								<input type="checkbox" id="opendiscussion" name="opendiscussion" <?php
-    if ($OPENDISCUSSION): ?> checked="checked"<?php
-    endif; ?> />
-								<?php echo PrivateBin\i18n::_('Open discussion'); ?>
+    if ($OPENDISCUSSION):
+?> checked="checked"<?php
+    endif;
+?> />
+								<?php echo I18n::_('Open discussion'); ?>
 						 	</label>
 						</div>
-					</li><?php
+					</li>
+<?php
 endif;
-if ($PASSWORD): ?>
+if ($PASSWORD):
+?>
 					<li>
 						<div id="password" class="navbar-form hidden">
-							<input type="password" id="passwordinput" placeholder="<?php echo PrivateBin\i18n::_('Password (recommended)'); ?>" class="form-control" size="19" />
+							<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control" size="19" />
 						</div>
-					</li><?php
+					</li>
+<?php
 endif;
-if ($FILEUPLOAD): ?>
+if ($FILEUPLOAD):
+?>
 					<li id="attach" class="hidden dropdown">
-						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Attach a file'); ?> <span class="caret"></span></a>
+						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Attach a file'); ?> <span class="caret"></span></a>
 						<ul class="dropdown-menu">
 							<li id="filewrap">
 								<div>
@@ -127,80 +165,112 @@ if ($FILEUPLOAD): ?>
 							</li>
 							<li>
 								<a id="fileremovebutton"  href="#">
-									<?php echo PrivateBin\i18n::_('Remove attachment'); ?>
+									<?php echo I18n::_('Remove attachment'); ?>
 								</a>
 							</li>
 						</ul>
-					</li><?php
-endif; ?>
+					</li>
+<?php
+endif;
+?>
 					<li class="dropdown">
-						<select id="pasteFormatter" name="pasteFormatter" class="hidden"><?php
-foreach ($FORMATTER as $key => $value): ?>
+						<select id="pasteFormatter" name="pasteFormatter" class="hidden">
+<?php
+foreach ($FORMATTER as $key => $value):
+?>
 							<option value="<?php echo $key; ?>"<?php
-    if ($key == $FORMATTERDEFAULT): ?> selected="selected"<?php
-    endif; ?>><?php echo $value; ?></option><?php
-endforeach; ?>
+    if ($key == $FORMATTERDEFAULT):
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
 						</select>
-						<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
-						<ul class="dropdown-menu"><?php
-foreach ($FORMATTER as $key => $value): ?>
+						<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
+						<ul class="dropdown-menu">
+<?php
+foreach ($FORMATTER as $key => $value):
+?>
 							<li>
 								<a href="#" onclick="$('#pasteFormatter').val('<?php echo $key; ?>');$('#pasteFormatterDisplay').text('<?php echo $value; ?>');return false;">
 									<?php echo $value; ?>
 								</a>
-							</li><?php
-endforeach; ?>
+							</li>
+<?php
+endforeach;
+?>
 						</ul>
 					</li>
 				</ul>
-				<ul class="nav navbar-nav pull-right"><?php
-if (strlen($LANGUAGESELECTION)): ?>
+				<ul class="nav navbar-nav pull-right">
+<?php
+if (strlen($LANGUAGESELECTION)):
+?>
 					<li id="language" class="dropdown">
 						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> <?php echo $LANGUAGES[$LANGUAGESELECTION][0]; ?> <span class="caret"></span></a>
-						<ul class="dropdown-menu"><?php
-    foreach ($LANGUAGES as $key => $value): ?>
+						<ul class="dropdown-menu">
+<?php
+    foreach ($LANGUAGES as $key => $value):
+?>
 							<li>
 								<a href="#" class="reloadlink" onclick="document.cookie='lang=<?php echo $key; ?>';">
 									<?php echo $value[0]; ?> (<?php echo $value[1]; ?>)
 								</a>
-							</li><?php
-    endforeach; ?>
+							</li>
+<?php
+    endforeach;
+?>
 						</ul>
-					</li><?php
-endif; ?>
+					</li>
+<?php
+endif;
+?>
 					<li>
 						<button id="sendbutton" type="button" class="hidden btn btn-warning navbar-btn">
-							<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Send'); ?>
+							<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'); ?>
 						</button>
 					</li>
 				</ul>
 			</div>
 		</nav>
-		<header class="container"><?php
-if (strlen($NOTICE)): ?>
+		<header class="container">
+<?php
+if (strlen($NOTICE)):
+?>
 			<div role="alert" class="alert alert-info">
 				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <?php echo htmlspecialchars($NOTICE); ?>
-			</div><?php
-endif; ?>
+			</div>
+<?php
+endif;
+?>
 			<div id="remainingtime" role="alert" class="hidden alert alert-info">
 				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
-			</div><?php
-if ($FILEUPLOAD): ?>
+			</div>
+<?php
+if ($FILEUPLOAD):
+?>
 			<div id="attachment" role="alert" class="hidden alert alert-info">
-				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo PrivateBin\i18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo PrivateBin\i18n::_('Cloned file attached.'); ?></span>
-			</div><?php
+				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo I18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
+			</div>
+<?php
 endif;
-if (strlen($STATUS)): ?>
+if (strlen($STATUS)):
+?>
 			<div id="status" role="alert" class="alert alert-success">
 				<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <?php echo htmlspecialchars($STATUS); ?>
-			</div><?php
-endif; ?>
+			</div>
+<?php
+endif;
+?>
 			<div id="errormessage" role="alert" class="<?php
-if (!strlen($ERROR)): ?>hidden <?php
-endif; ?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
-			<noscript><div id="noscript" role="alert" class="nonworking alert alert-error"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
-			<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('PrivateBin requires a modern browser to work.'); ?></div>
-			<div id="ienotice" role="alert" class="hidden alert alert-error"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'); ?>
+if (!strlen($ERROR)):
+?>hidden <?php
+endif;
+?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
+			<noscript><div id="noscript" role="alert" class="nonworking alert alert-error"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo I18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
+			<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo I18n::_('PrivateBin requires a modern browser to work.'); ?></div>
+			<div id="ienotice" role="alert" class="hidden alert alert-error"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> <?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'); ?>
 				<a href="https://www.mozilla.org/firefox/">Firefox</a>,
 				<a href="https://www.opera.com/">Opera</a>,
 				<a href="https://www.google.com/chrome">Chrome</a>,
@@ -209,17 +279,21 @@ endif; ?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden
 			<div id="pasteresult" role="alert" class="hidden alert alert-success">
 				<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
 				<div id="deletelink"></div>
-				<div id="pastelink"><?php
-if (strlen($URLSHORTENER)): ?>
+				<div id="pastelink">
+<?php
+if (strlen($URLSHORTENER)):
+?>
 					<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-warning">
-						<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Shorten URL'); ?>
-					</button><?php
-endif; ?>
+						<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'); ?>
+					</button>
+<?php
+endif;
+?>
 				</div>
 			</div>
 			<ul id="preview" class="nav nav-tabs hidden">
-				<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo PrivateBin\i18n::_('Editor'); ?></a></li>
-				<li role="presentation"><a id="messagepreview" href="#"><?php echo PrivateBin\i18n::_('Preview'); ?></a></li>
+				<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li>
+				<li role="presentation"><a id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li>
 			</ul>
 		</header>
 		<section class="container">
@@ -234,16 +308,16 @@ endif; ?>
 		</section>
 		<section class="container">
 			<div id="discussion" class="hidden">
-				<h4><?php echo PrivateBin\i18n::_('Discussion'); ?></h4>
+				<h4><?php echo I18n::_('Discussion'); ?></h4>
 				<div id="comments"></div>
 			</div>
 		</section>
 		<footer class="container">
 			<div class="row">
-				<h4 class="col-md-5 col-xs-8"><?php echo PrivateBin\i18n::_('PrivateBin'); ?> <small>- <?php echo PrivateBin\i18n::_('Because ignorance is bliss'); ?></small></h4>
+				<h4 class="col-md-5 col-xs-8"><?php echo I18n::_('PrivateBin'); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
 				<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
 				<p id="aboutbox" class="col-md-6 col-xs-12">
-					<?php echo PrivateBin\i18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/PrivateBin/PrivateBin/wiki">project page</a>.'); ?>
+					<?php echo I18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/PrivateBin/PrivateBin/wiki">project page</a>.'); ?>
 				</p>
 			</div>
 		</footer>

+ 169 - 95
tpl/bootstrap-page.php

@@ -1,32 +1,46 @@
-<!DOCTYPE html>
+<?php
+use PrivateBin\I18n;
+?><!DOCTYPE html>
 <html lang="en">
 	<head>
 		<meta charset="utf-8" />
 		<meta http-equiv="X-UA-Compatible" content="IE=edge">
 		<meta name="viewport" content="width=device-width, initial-scale=1">
 		<meta name="robots" content="noindex" />
-		<title><?php echo PrivateBin\i18n::_('PrivateBin'); ?></title>
+		<title><?php echo I18n::_('PrivateBin'); ?></title>
 		<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-3.3.5.css" />
 		<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.3.5.css" />
-		<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" /><?php
-if ($SYNTAXHIGHLIGHTING): ?>
-		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" /><?php
-    if (strlen($SYNTAXHIGHLIGHTINGTHEME)): ?>
-		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" /><?php
+		<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+if ($SYNTAXHIGHLIGHTING):
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+    if (strlen($SYNTAXHIGHLIGHTINGTHEME)):
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
     endif;
-endif; ?>
+endif;
+?>
 		<script type="text/javascript" src="js/jquery-1.11.3.js"></script>
 		<script type="text/javascript" src="js/sjcl-1.0.4.js"></script>
 		<script type="text/javascript" src="js/base64-<?php echo rawurlencode($BASE64JSVERSION); ?>.js"></script>
 		<script type="text/javascript" src="js/rawdeflate-0.5.js"></script>
 		<script type="text/javascript" src="js/rawinflate-0.3.js"></script>
-		<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script><?php
-if ($SYNTAXHIGHLIGHTING): ?>
-		<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>"></script><?php
+		<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script>
+<?php
+if ($SYNTAXHIGHLIGHTING):
+?>
+		<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>"></script>
+<?php
+endif;
+if ($MARKDOWN):
+?>
+		<script type="text/javascript" src="js/showdown-1.4.1.js"></script>
+<?php
 endif;
-if ($MARKDOWN): ?>
-		<script type="text/javascript" src="js/showdown-1.4.1.js"></script><?php
-endif; ?>
+?>
 		<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>"></script>
 		<!--[if lt IE 10]>
 		<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
@@ -44,81 +58,105 @@ endif; ?>
 		<nav class="navbar navbar-default navbar-static-top">
 			<div class="navbar-header">
 				<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
-					<span class="sr-only"><?php echo PrivateBin\i18n::_('Toggle navigation'); ?></span>
+					<span class="sr-only"><?php echo I18n::_('Toggle navigation'); ?></span>
 					<span class="icon-bar"></span>
 					<span class="icon-bar"></span>
 					<span class="icon-bar"></span>
 				</button>
 				<a class="reloadlink navbar-brand" href="/">
-					<img alt="<?php echo PrivateBin\i18n::_('PrivateBin'); ?>" src="img/icon.svg" width="20" />
+					<img alt="<?php echo I18n::_('PrivateBin'); ?>" src="img/icon.svg" width="20" />
 				</a>
 			</div>
 			<div id="navbar" class="navbar-collapse collapse">
 				<ul class="nav navbar-nav">
 					<li>
 						<button id="sendbutton" type="button" class="hidden btn btn-primary navbar-btn">
-							<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Send'); ?>
-						</button><?php
-if ($EXPIRECLONE): ?>
+							<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'); ?>
+						</button>
+<?php
+if ($EXPIRECLONE):
+?>
 						<button id="clonebutton" type="button" class="hidden btn btn-default navbar-btn">
-							<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Clone'); ?>
-						</button><?php
-endif; ?>
+							<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo I18n::_('Clone'); ?>
+						</button>
+<?php
+endif;
+?>
 						<button id="rawtextbutton" type="button" class="hidden btn btn-default navbar-btn">
-							<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Raw text'); ?>
+							<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'); ?>
 						</button>
 					</li>
 					<li class="dropdown">
-						<select id="pasteExpiration" name="pasteExpiration" class="hidden"><?php
-foreach ($EXPIRE as $key => $value): ?>
+						<select id="pasteExpiration" name="pasteExpiration" class="hidden">
+<?php
+foreach ($EXPIRE as $key => $value):
+?>
 							<option value="<?php echo $key; ?>"<?php
-    if ($key == $EXPIREDEFAULT): ?> selected="selected"<?php
-    endif; ?>><?php echo $value; ?></option><?php
-endforeach; ?>
+    if ($key == $EXPIREDEFAULT):
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
 						</select>
-						<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
-						<ul class="dropdown-menu"><?php
-foreach ($EXPIRE as $key => $value): ?>
+						<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
+						<ul class="dropdown-menu">
+<?php
+foreach ($EXPIRE as $key => $value):
+?>
 							<li>
 								<a href="#" onclick="$('#pasteExpiration').val('<?php echo $key; ?>');$('#pasteExpirationDisplay').text('<?php echo $value; ?>');return false;">
 									<?php echo $value; ?>
 								</a>
-							</li><?php
-endforeach; ?>
+							</li>
+<?php
+endforeach;
+?>
 						</ul>
 					</li>
 					<li>
 						<div id="burnafterreadingoption" class="navbar-text checkbox hidden">
 							<label>
 								<input type="checkbox" id="burnafterreading" name="burnafterreading" <?php
-if ($BURNAFTERREADINGSELECTED): ?> checked="checked"<?php
-endif; ?> />
-								<?php echo PrivateBin\i18n::_('Burn after reading'); ?>
+if ($BURNAFTERREADINGSELECTED):
+?> checked="checked"<?php
+endif;
+?> />
+								<?php echo I18n::_('Burn after reading'); ?>
 							</label>
 						</div>
-					</li><?php
-if ($DISCUSSION): ?>
+					</li>
+<?php
+if ($DISCUSSION):
+?>
 					<li>
 						<div id="opendisc" class="navbar-text checkbox hidden">
 							<label>
 								<input type="checkbox" id="opendiscussion" name="opendiscussion" <?php
-    if ($OPENDISCUSSION): ?> checked="checked"<?php
-    endif; ?> />
-								<?php echo PrivateBin\i18n::_('Open discussion'); ?>
+    if ($OPENDISCUSSION):
+?> checked="checked"<?php
+    endif;
+?> />
+								<?php echo I18n::_('Open discussion'); ?>
 						 	</label>
 						</div>
-					</li><?php
+					</li>
+<?php
 endif;
-if ($PASSWORD): ?>
+if ($PASSWORD):
+?>
 					<li>
 						<div id="password" class="navbar-form hidden">
-							<input type="password" id="passwordinput" placeholder="<?php echo PrivateBin\i18n::_('Password (recommended)'); ?>" class="form-control" size="19" />
+							<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control" size="19" />
 						</div>
-					</li><?php
+					</li>
+<?php
 endif;
-if ($FILEUPLOAD): ?>
+if ($FILEUPLOAD):
+?>
 					<li id="attach" class="hidden dropdown">
-						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Attach a file'); ?> <span class="caret"></span></a>
+						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Attach a file'); ?> <span class="caret"></span></a>
 						<ul class="dropdown-menu">
 							<li id="filewrap">
 								<div>
@@ -127,80 +165,112 @@ if ($FILEUPLOAD): ?>
 							</li>
 							<li>
 								<a id="fileremovebutton"  href="#">
-									<?php echo PrivateBin\i18n::_('Remove attachment'); ?>
+									<?php echo I18n::_('Remove attachment'); ?>
 								</a>
 							</li>
 						</ul>
-					</li><?php
-endif; ?>
+					</li>
+<?php
+endif;
+?>
 					<li class="dropdown">
-						<select id="pasteFormatter" name="pasteFormatter" class="hidden"><?php
-foreach ($FORMATTER as $key => $value): ?>
+						<select id="pasteFormatter" name="pasteFormatter" class="hidden">
+<?php
+foreach ($FORMATTER as $key => $value):
+?>
 							<option value="<?php echo $key; ?>"<?php
-    if ($key == $FORMATTERDEFAULT): ?> selected="selected"<?php
-    endif; ?>><?php echo $value; ?></option><?php
-endforeach; ?>
+    if ($key == $FORMATTERDEFAULT):
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
 						</select>
-						<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
-						<ul class="dropdown-menu"><?php
-foreach ($FORMATTER as $key => $value): ?>
+						<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
+						<ul class="dropdown-menu">
+<?php
+foreach ($FORMATTER as $key => $value):
+?>
 							<li>
 								<a href="#" onclick="$('#pasteFormatter').val('<?php echo $key; ?>');$('#pasteFormatterDisplay').text('<?php echo $value; ?>');return false;">
 									<?php echo $value; ?>
 								</a>
-							</li><?php
-endforeach; ?>
+							</li>
+<?php
+endforeach;
+?>
 						</ul>
 					</li>
 				</ul>
-				<ul class="nav navbar-nav pull-right"><?php
-if (strlen($LANGUAGESELECTION)): ?>
+				<ul class="nav navbar-nav pull-right">
+<?php
+if (strlen($LANGUAGESELECTION)):
+?>
 					<li id="language" class="dropdown">
 						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> <?php echo $LANGUAGES[$LANGUAGESELECTION][0]; ?> <span class="caret"></span></a>
-						<ul class="dropdown-menu"><?php
-    foreach ($LANGUAGES as $key => $value): ?>
+						<ul class="dropdown-menu">
+<?php
+    foreach ($LANGUAGES as $key => $value):
+?>
 							<li>
 								<a href="#" class="reloadlink" onclick="document.cookie='lang=<?php echo $key; ?>';">
 									<?php echo $value[0]; ?> (<?php echo $value[1]; ?>)
 								</a>
-							</li><?php
-    endforeach; ?>
+							</li>
+<?php
+    endforeach;
+?>
 						</ul>
-					</li><?php
-endif; ?>
+					</li>
+<?php
+endif;
+?>
 					<li>
 						<button id="newbutton" type="button" class="reloadlink hidden btn btn-default navbar-btn">
-							<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('New'); ?>
+							<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'); ?>
 						</button>
 					</li>
 				</ul>
 			</div>
 		</nav>
-		<header class="container"><?php
-if (strlen($NOTICE)): ?>
+		<header class="container">
+<?php
+if (strlen($NOTICE)):
+?>
 			<div role="alert" class="alert alert-info">
 				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <?php echo htmlspecialchars($NOTICE); ?>
-			</div><?php
-endif; ?>
+			</div>
+<?php
+endif;
+?>
 			<div id="remainingtime" role="alert" class="hidden alert alert-info">
 				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
-			</div><?php
-if ($FILEUPLOAD): ?>
+			</div>
+<?php
+if ($FILEUPLOAD):
+?>
 			<div id="attachment" role="alert" class="hidden alert alert-info">
-				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo PrivateBin\i18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo PrivateBin\i18n::_('Cloned file attached.'); ?></span>
-			</div><?php
+				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo I18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
+			</div>
+<?php
 endif;
-if (strlen($STATUS)): ?>
+if (strlen($STATUS)):
+?>
 			<div id="status" role="alert" class="alert alert-success">
 				<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <?php echo htmlspecialchars($STATUS); ?>
-			</div><?php
-endif; ?>
+			</div>
+<?php
+endif;
+?>
 			<div id="errormessage" role="alert" class="<?php
-if (!strlen($ERROR)): ?>hidden <?php
-endif; ?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
-			<noscript><div id="noscript" role="alert" class="nonworking alert alert-warning"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
-			<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('PrivateBin requires a modern browser to work.'); ?></div>
-			<div id="ienotice" role="alert" class="hidden alert alert-warning"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'); ?>
+if (!strlen($ERROR)):
+?>hidden <?php
+endif;
+?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
+			<noscript><div id="noscript" role="alert" class="nonworking alert alert-warning"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo I18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
+			<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo I18n::_('PrivateBin requires a modern browser to work.'); ?></div>
+			<div id="ienotice" role="alert" class="hidden alert alert-warning"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> <?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'); ?>
 				<a href="https://www.mozilla.org/firefox/">Firefox</a>,
 				<a href="https://www.opera.com/">Opera</a>,
 				<a href="https://www.google.com/chrome">Chrome</a>,
@@ -209,17 +279,21 @@ endif; ?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden
 			<div id="pasteresult" role="alert" class="hidden alert alert-success">
 				<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
 				<div id="deletelink"></div>
-				<div id="pastelink"><?php
-if (strlen($URLSHORTENER)): ?>
+				<div id="pastelink">
+<?php
+if (strlen($URLSHORTENER)):
+?>
 					<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-primary">
-						<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Shorten URL'); ?>
-					</button><?php
-endif; ?>
+						<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'); ?>
+					</button>
+<?php
+endif;
+?>
 				</div>
 			</div>
 			<ul id="preview" class="nav nav-tabs hidden">
-				<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo PrivateBin\i18n::_('Editor'); ?></a></li>
-				<li role="presentation"><a id="messagepreview" href="#"><?php echo PrivateBin\i18n::_('Preview'); ?></a></li>
+				<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li>
+				<li role="presentation"><a id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li>
 			</ul>
 		</header>
 		<section class="container">
@@ -234,16 +308,16 @@ endif; ?>
 		</section>
 		<section class="container">
 			<div id="discussion" class="hidden">
-				<h4><?php echo PrivateBin\i18n::_('Discussion'); ?></h4>
+				<h4><?php echo I18n::_('Discussion'); ?></h4>
 				<div id="comments"></div>
 			</div>
 		</section>
 		<footer class="container">
 			<div class="row">
-				<h4 class="col-md-5 col-xs-8"><?php echo PrivateBin\i18n::_('PrivateBin'); ?> <small>- <?php echo PrivateBin\i18n::_('Because ignorance is bliss'); ?></small></h4>
+				<h4 class="col-md-5 col-xs-8"><?php echo I18n::_('PrivateBin'); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
 				<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
 				<p id="aboutbox" class="col-md-6 col-xs-12">
-					<?php echo PrivateBin\i18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/PrivateBin/PrivateBin/wiki">project page</a>.'); ?>
+					<?php echo I18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/PrivateBin/PrivateBin/wiki">project page</a>.'); ?>
 				</p>
 			</div>
 		</footer>

+ 169 - 95
tpl/bootstrap.php

@@ -1,32 +1,46 @@
-<!DOCTYPE html>
+<?php
+use PrivateBin\I18n;
+?><!DOCTYPE html>
 <html lang="en">
 	<head>
 		<meta charset="utf-8" />
 		<meta http-equiv="X-UA-Compatible" content="IE=edge">
 		<meta name="viewport" content="width=device-width, initial-scale=1">
 		<meta name="robots" content="noindex" />
-		<title><?php echo PrivateBin\i18n::_('PrivateBin'); ?></title>
+		<title><?php echo I18n::_('PrivateBin'); ?></title>
 		<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-3.3.5.css" />
 		<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.3.5.css" />
-		<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" /><?php
-if ($SYNTAXHIGHLIGHTING): ?>
-		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" /><?php
-    if (strlen($SYNTAXHIGHLIGHTINGTHEME)): ?>
-		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" /><?php
+		<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+if ($SYNTAXHIGHLIGHTING):
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+    if (strlen($SYNTAXHIGHLIGHTINGTHEME)):
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
     endif;
-endif; ?>
+endif;
+?>
 		<script type="text/javascript" src="js/jquery-1.11.3.js"></script>
 		<script type="text/javascript" src="js/sjcl-1.0.4.js"></script>
 		<script type="text/javascript" src="js/base64-<?php echo rawurlencode($BASE64JSVERSION); ?>.js"></script>
 		<script type="text/javascript" src="js/rawdeflate-0.5.js"></script>
 		<script type="text/javascript" src="js/rawinflate-0.3.js"></script>
-		<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script><?php
-if ($SYNTAXHIGHLIGHTING): ?>
-		<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>"></script><?php
+		<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script>
+<?php
+if ($SYNTAXHIGHLIGHTING):
+?>
+		<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>"></script>
+<?php
+endif;
+if ($MARKDOWN):
+?>
+		<script type="text/javascript" src="js/showdown-1.4.1.js"></script>
+<?php
 endif;
-if ($MARKDOWN): ?>
-		<script type="text/javascript" src="js/showdown-1.4.1.js"></script><?php
-endif; ?>
+?>
 		<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>"></script>
 		<!--[if lt IE 10]>
 		<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
@@ -44,81 +58,105 @@ endif; ?>
 		<nav class="navbar navbar-default navbar-static-top">
 			<div class="navbar-header">
 				<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
-					<span class="sr-only"><?php echo PrivateBin\i18n::_('Toggle navigation'); ?></span>
+					<span class="sr-only"><?php echo I18n::_('Toggle navigation'); ?></span>
 					<span class="icon-bar"></span>
 					<span class="icon-bar"></span>
 					<span class="icon-bar"></span>
 				</button>
 				<a class="reloadlink navbar-brand" href="/">
-					<img alt="<?php echo PrivateBin\i18n::_('PrivateBin'); ?>" src="img/icon.svg" width="20" />
+					<img alt="<?php echo I18n::_('PrivateBin'); ?>" src="img/icon.svg" width="20" />
 				</a>
 			</div>
 			<div id="navbar" class="navbar-collapse collapse">
 				<ul class="nav navbar-nav">
 					<li>
 						<button id="newbutton" type="button" class="reloadlink hidden btn btn-default navbar-btn">
-							<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('New'); ?>
-						</button><?php
-if ($EXPIRECLONE): ?>
+							<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'); ?>
+						</button>
+<?php
+if ($EXPIRECLONE):
+?>
 						<button id="clonebutton" type="button" class="hidden btn btn-default navbar-btn">
-							<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Clone'); ?>
-						</button><?php
-endif; ?>
+							<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> <?php echo I18n::_('Clone'); ?>
+						</button>
+<?php
+endif;
+?>
 						<button id="rawtextbutton" type="button" class="hidden btn btn-default navbar-btn">
-							<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Raw text'); ?>
+							<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'); ?>
 						</button>
 					</li>
 					<li class="dropdown">
-						<select id="pasteExpiration" name="pasteExpiration" class="hidden"><?php
-foreach ($EXPIRE as $key => $value): ?>
+						<select id="pasteExpiration" name="pasteExpiration" class="hidden">
+<?php
+foreach ($EXPIRE as $key => $value):
+?>
 							<option value="<?php echo $key; ?>"<?php
-    if ($key == $EXPIREDEFAULT): ?> selected="selected"<?php
-    endif; ?>><?php echo $value; ?></option><?php
-endforeach; ?>
+    if ($key == $EXPIREDEFAULT):
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
 						</select>
-						<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
-						<ul class="dropdown-menu"><?php
-foreach ($EXPIRE as $key => $value): ?>
+						<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
+						<ul class="dropdown-menu">
+<?php
+foreach ($EXPIRE as $key => $value):
+?>
 							<li>
 								<a href="#" onclick="$('#pasteExpiration').val('<?php echo $key; ?>');$('#pasteExpirationDisplay').text('<?php echo $value; ?>');return false;">
 									<?php echo $value; ?>
 								</a>
-							</li><?php
-endforeach; ?>
+							</li>
+<?php
+endforeach;
+?>
 						</ul>
 					</li>
 					<li>
 						<div id="burnafterreadingoption" class="navbar-text checkbox hidden">
 							<label>
 								<input type="checkbox" id="burnafterreading" name="burnafterreading" <?php
-if ($BURNAFTERREADINGSELECTED): ?> checked="checked"<?php
-endif; ?> />
-								<?php echo PrivateBin\i18n::_('Burn after reading'); ?>
+if ($BURNAFTERREADINGSELECTED):
+?> checked="checked"<?php
+endif;
+?> />
+								<?php echo I18n::_('Burn after reading'); ?>
 							</label>
 						</div>
-					</li><?php
-if ($DISCUSSION): ?>
+					</li>
+<?php
+if ($DISCUSSION):
+?>
 					<li>
 						<div id="opendisc" class="navbar-text checkbox hidden">
 							<label>
 								<input type="checkbox" id="opendiscussion" name="opendiscussion" <?php
-    if ($OPENDISCUSSION): ?> checked="checked"<?php
-    endif; ?> />
-								<?php echo PrivateBin\i18n::_('Open discussion'); ?>
+    if ($OPENDISCUSSION):
+?> checked="checked"<?php
+    endif;
+?> />
+								<?php echo I18n::_('Open discussion'); ?>
 						 	</label>
 						</div>
-					</li><?php
+					</li>
+<?php
 endif;
-if ($PASSWORD): ?>
+if ($PASSWORD):
+?>
 					<li>
 						<div id="password" class="navbar-form hidden">
-							<input type="password" id="passwordinput" placeholder="<?php echo PrivateBin\i18n::_('Password (recommended)'); ?>" class="form-control" size="19" />
+							<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control" size="19" />
 						</div>
-					</li><?php
+					</li>
+<?php
 endif;
-if ($FILEUPLOAD): ?>
+if ($FILEUPLOAD):
+?>
 					<li id="attach" class="hidden dropdown">
-						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Attach a file'); ?> <span class="caret"></span></a>
+						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Attach a file'); ?> <span class="caret"></span></a>
 						<ul class="dropdown-menu">
 							<li id="filewrap">
 								<div>
@@ -127,80 +165,112 @@ if ($FILEUPLOAD): ?>
 							</li>
 							<li>
 								<a id="fileremovebutton"  href="#">
-									<?php echo PrivateBin\i18n::_('Remove attachment'); ?>
+									<?php echo I18n::_('Remove attachment'); ?>
 								</a>
 							</li>
 						</ul>
-					</li><?php
-endif; ?>
+					</li>
+<?php
+endif;
+?>
 					<li class="dropdown">
-						<select id="pasteFormatter" name="pasteFormatter" class="hidden"><?php
-foreach ($FORMATTER as $key => $value): ?>
+						<select id="pasteFormatter" name="pasteFormatter" class="hidden">
+<?php
+foreach ($FORMATTER as $key => $value):
+?>
 							<option value="<?php echo $key; ?>"<?php
-    if ($key == $FORMATTERDEFAULT): ?> selected="selected"<?php
-    endif; ?>><?php echo $value; ?></option><?php
-endforeach; ?>
+    if ($key == $FORMATTERDEFAULT):
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
 						</select>
-						<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo PrivateBin\i18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
-						<ul class="dropdown-menu"><?php
-foreach ($FORMATTER as $key => $value): ?>
+						<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
+						<ul class="dropdown-menu">
+<?php
+foreach ($FORMATTER as $key => $value):
+?>
 							<li>
 								<a href="#" onclick="$('#pasteFormatter').val('<?php echo $key; ?>');$('#pasteFormatterDisplay').text('<?php echo $value; ?>');return false;">
 									<?php echo $value; ?>
 								</a>
-							</li><?php
-endforeach; ?>
+							</li>
+<?php
+endforeach;
+?>
 						</ul>
 					</li>
 				</ul>
-				<ul class="nav navbar-nav pull-right"><?php
-if (strlen($LANGUAGESELECTION)): ?>
+				<ul class="nav navbar-nav pull-right">
+<?php
+if (strlen($LANGUAGESELECTION)):
+?>
 					<li id="language" class="dropdown">
 						<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> <?php echo $LANGUAGES[$LANGUAGESELECTION][0]; ?> <span class="caret"></span></a>
-						<ul class="dropdown-menu"><?php
-    foreach ($LANGUAGES as $key => $value): ?>
+						<ul class="dropdown-menu">
+<?php
+    foreach ($LANGUAGES as $key => $value):
+?>
 							<li>
 								<a href="#" class="reloadlink" onclick="document.cookie='lang=<?php echo $key; ?>';">
 									<?php echo $value[0]; ?> (<?php echo $value[1]; ?>)
 								</a>
-							</li><?php
-    endforeach; ?>
+							</li>
+<?php
+    endforeach;
+?>
 						</ul>
-					</li><?php
-endif; ?>
+					</li>
+<?php
+endif;
+?>
 					<li>
 						<button id="sendbutton" type="button" class="hidden btn btn-primary navbar-btn">
-							<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Send'); ?>
+							<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'); ?>
 						</button>
 					</li>
 				</ul>
 			</div>
 		</nav>
-		<header class="container"><?php
-if (strlen($NOTICE)): ?>
+		<header class="container">
+<?php
+if (strlen($NOTICE)):
+?>
 			<div role="alert" class="alert alert-info">
 				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <?php echo htmlspecialchars($NOTICE); ?>
-			</div><?php
-endif; ?>
+			</div>
+<?php
+endif;
+?>
 			<div id="remainingtime" role="alert" class="hidden alert alert-info">
 				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
-			</div><?php
-if ($FILEUPLOAD): ?>
+			</div>
+<?php
+if ($FILEUPLOAD):
+?>
 			<div id="attachment" role="alert" class="hidden alert alert-info">
-				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo PrivateBin\i18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo PrivateBin\i18n::_('Cloned file attached.'); ?></span>
-			</div><?php
+				<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo I18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
+			</div>
+<?php
 endif;
-if (strlen($STATUS)): ?>
+if (strlen($STATUS)):
+?>
 			<div id="status" role="alert" class="alert alert-success">
 				<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <?php echo htmlspecialchars($STATUS); ?>
-			</div><?php
-endif; ?>
+			</div>
+<?php
+endif;
+?>
 			<div id="errormessage" role="alert" class="<?php
-if (!strlen($ERROR)): ?>hidden <?php
-endif; ?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
-			<noscript><div id="noscript" role="alert" class="nonworking alert alert-warning"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
-			<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('PrivateBin requires a modern browser to work.'); ?></div>
-			<div id="ienotice" role="alert" class="hidden alert alert-warning"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'); ?>
+if (!strlen($ERROR)):
+?>hidden <?php
+endif;
+?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
+			<noscript><div id="noscript" role="alert" class="nonworking alert alert-warning"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo I18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
+			<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo I18n::_('PrivateBin requires a modern browser to work.'); ?></div>
+			<div id="ienotice" role="alert" class="hidden alert alert-warning"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> <?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'); ?>
 				<a href="https://www.mozilla.org/firefox/">Firefox</a>,
 				<a href="https://www.opera.com/">Opera</a>,
 				<a href="https://www.google.com/chrome">Chrome</a>,
@@ -209,17 +279,21 @@ endif; ?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden
 			<div id="pasteresult" role="alert" class="hidden alert alert-success">
 				<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
 				<div id="deletelink"></div>
-				<div id="pastelink"><?php
-if (strlen($URLSHORTENER)): ?>
+				<div id="pastelink">
+<?php
+if (strlen($URLSHORTENER)):
+?>
 					<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-primary">
-						<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo PrivateBin\i18n::_('Shorten URL'); ?>
-					</button><?php
-endif; ?>
+						<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'); ?>
+					</button>
+<?php
+endif;
+?>
 				</div>
 			</div>
 			<ul id="preview" class="nav nav-tabs hidden">
-				<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo PrivateBin\i18n::_('Editor'); ?></a></li>
-				<li role="presentation"><a id="messagepreview" href="#"><?php echo PrivateBin\i18n::_('Preview'); ?></a></li>
+				<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li>
+				<li role="presentation"><a id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li>
 			</ul>
 		</header>
 		<section class="container">
@@ -234,16 +308,16 @@ endif; ?>
 		</section>
 		<section class="container">
 			<div id="discussion" class="hidden">
-				<h4><?php echo PrivateBin\i18n::_('Discussion'); ?></h4>
+				<h4><?php echo I18n::_('Discussion'); ?></h4>
 				<div id="comments"></div>
 			</div>
 		</section>
 		<footer class="container">
 			<div class="row">
-				<h4 class="col-md-5 col-xs-8"><?php echo PrivateBin\i18n::_('PrivateBin'); ?> <small>- <?php echo PrivateBin\i18n::_('Because ignorance is bliss'); ?></small></h4>
+				<h4 class="col-md-5 col-xs-8"><?php echo I18n::_('PrivateBin'); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
 				<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
 				<p id="aboutbox" class="col-md-6 col-xs-12">
-					<?php echo PrivateBin\i18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/PrivateBin/PrivateBin/wiki">project page</a>.'); ?>
+					<?php echo I18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/PrivateBin/PrivateBin/wiki">project page</a>.'); ?>
 				</p>
 			</div>
 		</footer>

+ 141 - 78
tpl/page.php

@@ -1,27 +1,41 @@
-<!DOCTYPE html>
+<?php
+use PrivateBin\I18n;
+?><!DOCTYPE html>
 <html lang="en">
 	<head>
 		<meta charset="utf-8" />
 		<meta name="robots" content="noindex" />
-		<title><?php echo PrivateBin\i18n::_('PrivateBin'); ?></title>
-		<link type="text/css" rel="stylesheet" href="css/privatebin.css?<?php echo rawurlencode($VERSION); ?>" /><?php
-if ($SYNTAXHIGHLIGHTING): ?>
-		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" /><?php
-    if (strlen($SYNTAXHIGHLIGHTINGTHEME)): ?>
-		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" /><?php
+		<title><?php echo I18n::_('PrivateBin'); ?></title>
+		<link type="text/css" rel="stylesheet" href="css/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+if ($SYNTAXHIGHLIGHTING):
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
+    if (strlen($SYNTAXHIGHLIGHTINGTHEME)):
+?>
+		<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
+<?php
     endif;
-endif; ?>
+endif;
+?>
 		<script type="text/javascript" src="js/jquery-1.11.3.js"></script>
 		<script type="text/javascript" src="js/sjcl-1.0.4.js"></script>
 		<script type="text/javascript" src="js/base64-<?php echo rawurlencode($BASE64JSVERSION); ?>.js"></script>
 		<script type="text/javascript" src="js/rawdeflate-0.5.js"></script>
-		<script type="text/javascript" src="js/rawinflate-0.3.js"></script><?php
-if ($SYNTAXHIGHLIGHTING): ?>
-		<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>"></script><?php
+		<script type="text/javascript" src="js/rawinflate-0.3.js"></script>
+<?php
+if ($SYNTAXHIGHLIGHTING):
+?>
+		<script type="text/javascript" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>"></script>
+<?php
+endif;
+if ($MARKDOWN):
+?>
+		<script type="text/javascript" src="js/showdown-1.4.1.js"></script>
+<?php
 endif;
-if ($MARKDOWN): ?>
-		<script type="text/javascript" src="js/showdown-1.4.1.js"></script><?php
-endif; ?>
+?>
 		<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>"></script>
 		<!--[if lt IE 10]>
 		<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
@@ -38,17 +52,20 @@ endif; ?>
 	<body>
 		<header>
 			<div id="aboutbox">
-				<?php echo PrivateBin\i18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/PrivateBin/PrivateBin/wiki">project page</a>.'); ?><br /><?php
-if (strlen($NOTICE)): ?>
+				<?php echo I18n::_('PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/PrivateBin/PrivateBin/wiki">project page</a>.'); ?><br />
+<?php
+if (strlen($NOTICE)):
+?>
 				<span class="blink">▶</span> <?php echo htmlspecialchars($NOTICE);
-endif; ?>
+endif;
+?>
 			</div>
-			<h1 class="title reloadlink"><?php echo PrivateBin\i18n::_('PrivateBin'); ?></h1><br />
-			<h2 class="title"><?php echo PrivateBin\i18n::_('Because ignorance is bliss'); ?></h2><br />
+			<h1 class="title reloadlink"><?php echo I18n::_('PrivateBin'); ?></h1><br />
+			<h2 class="title"><?php echo I18n::_('Because ignorance is bliss'); ?></h2><br />
 			<h3 class="title"><?php echo $VERSION; ?></h3>
-			<noscript><div id="noscript" class="nonworking"><?php echo PrivateBin\i18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
-			<div id="oldienotice" class="nonworking"><?php echo PrivateBin\i18n::_('PrivateBin requires a modern browser to work.'); ?></div>
-			<div id="ienotice"><?php echo PrivateBin\i18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'); ?>
+			<noscript><div id="noscript" class="nonworking"><?php echo I18n::_('Javascript is required for PrivateBin to work.<br />Sorry for the inconvenience.'); ?></div></noscript>
+			<div id="oldienotice" class="nonworking"><?php echo I18n::_('PrivateBin requires a modern browser to work.'); ?></div>
+			<div id="ienotice"><?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'); ?>
 				<a href="https://www.mozilla.org/firefox/">Firefox</a>,
 				<a href="https://www.opera.com/">Opera</a>,
 				<a href="https://www.google.com/chrome">Chrome</a>,
@@ -60,83 +77,129 @@ endif; ?>
 				<div id="status"><?php echo htmlspecialchars($STATUS); ?></div>
 				<div id="errormessage" class="hidden"><?php echo htmlspecialchars($ERROR); ?></div>
 				<div id="toolbar">
-					<button id="newbutton" class="reloadlink hidden"><img src="img/icon_new.png" width="11" height="15" alt="" /><?php echo PrivateBin\i18n::_('New'); ?></button>
-					<button id="sendbutton" class="hidden"><img src="img/icon_send.png" width="18" height="15" alt="" /><?php echo PrivateBin\i18n::_('Send'); ?></button><?php
-if ($EXPIRECLONE): ?>
-					<button id="clonebutton" class="hidden"><img src="img/icon_clone.png" width="15" height="17" alt="" /><?php echo PrivateBin\i18n::_('Clone'); ?></button><?php
-endif; ?>
-					<button id="rawtextbutton" class="hidden"><img src="img/icon_raw.png" width="15" height="15" alt="" /><?php echo PrivateBin\i18n::_('Raw text'); ?></button>
-					<div id="expiration" class="hidden button"><?php echo PrivateBin\i18n::_('Expires'); ?>:
-						<select id="pasteExpiration" name="pasteExpiration"><?php
-foreach ($EXPIRE as $key => $value): ?>
+					<button id="newbutton" class="reloadlink hidden"><img src="img/icon_new.png" width="11" height="15" alt="" /><?php echo I18n::_('New'); ?></button>
+					<button id="sendbutton" class="hidden"><img src="img/icon_send.png" width="18" height="15" alt="" /><?php echo I18n::_('Send'); ?></button>
+<?php
+if ($EXPIRECLONE):
+?>
+					<button id="clonebutton" class="hidden"><img src="img/icon_clone.png" width="15" height="17" alt="" /><?php echo I18n::_('Clone'); ?></button>
+<?php
+endif;
+?>
+					<button id="rawtextbutton" class="hidden"><img src="img/icon_raw.png" width="15" height="15" alt="" /><?php echo I18n::_('Raw text'); ?></button>
+					<div id="expiration" class="hidden button"><?php echo I18n::_('Expires'); ?>:
+						<select id="pasteExpiration" name="pasteExpiration">
+<?php
+foreach ($EXPIRE as $key => $value):
+?>
 							<option value="<?php echo $key; ?>"<?php
-    if ($key == $EXPIREDEFAULT): ?> selected="selected"<?php
-    endif; ?>><?php echo $value; ?></option><?php
-endforeach; ?>
+    if ($key == $EXPIREDEFAULT):
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
 						</select>
 					</div>
 					<div id="remainingtime" class="hidden"></div>
 					<div id="burnafterreadingoption" class="button hidden">
 						<input type="checkbox" id="burnafterreading" name="burnafterreading" <?php
-if ($BURNAFTERREADINGSELECTED): ?> checked="checked"<?php
-endif; ?> />
-						<label for="burnafterreading"><?php echo PrivateBin\i18n::_('Burn after reading'); ?></label>
-					</div><?php
-if ($DISCUSSION): ?>
+if ($BURNAFTERREADINGSELECTED):
+?> checked="checked"<?php
+endif;
+?> />
+						<label for="burnafterreading"><?php echo I18n::_('Burn after reading'); ?></label>
+					</div>
+<?php
+if ($DISCUSSION):
+?>
 					<div id="opendisc" class="button hidden">
 						<input type="checkbox" id="opendiscussion" name="opendiscussion" <?php
-    if ($OPENDISCUSSION): ?> checked="checked"<?php
-    endif; ?> />
+    if ($OPENDISCUSSION):
+?> checked="checked"<?php
+    endif;
+?> />
 						<label for="opendiscussion" <?php
-    if (!$OPENDISCUSSION): ?> style="color: #BBBBBB;"<?php
-    endif; ?>><?php echo PrivateBin\i18n::_('Open discussion'); ?></label>
-					</div><?php
+    if (!$OPENDISCUSSION):
+?> style="color: #BBBBBB;"<?php
+    endif;
+?>><?php echo I18n::_('Open discussion'); ?></label>
+					</div>
+<?php
 endif;
-if ($PASSWORD): ?>
+if ($PASSWORD):
+?>
 					<div id="password" class="hidden">
-						<input type="password" id="passwordinput" placeholder="<?php echo PrivateBin\i18n::_('Password (recommended)'); ?>" size="32" />
-					</div><?php
-endif; ?>
-					<div id="formatter" class="button hidden"><?php echo PrivateBin\i18n::_('Format'); ?>:
-						<select id="pasteFormatter" name="pasteFormatter"><?php
-foreach ($FORMATTER as $key => $value): ?>
+						<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" size="32" />
+					</div>
+<?php
+endif;
+?>
+					<div id="formatter" class="button hidden"><?php echo I18n::_('Format'); ?>:
+						<select id="pasteFormatter" name="pasteFormatter">
+<?php
+foreach ($FORMATTER as $key => $value):
+?>
 							<option value="<?php echo $key; ?>"<?php
-    if ($key == $FORMATTERDEFAULT): ?> selected="selected"<?php
-    endif; ?>><?php echo $value; ?></option><?php
-endforeach; ?>
+    if ($key == $FORMATTERDEFAULT):
+?> selected="selected"<?php
+    endif;
+?>><?php echo $value; ?></option>
+<?php
+endforeach;
+?>
 						</select>
-					</div><?php
-if (strlen($LANGUAGESELECTION)): ?>
+					</div>
+<?php
+if (strlen($LANGUAGESELECTION)):
+?>
 					<div id="language" class="button">
-						<select name="lang"><?php
-    foreach ($LANGUAGES as $key => $value): ?>
+						<select name="lang">
+<?php
+    foreach ($LANGUAGES as $key => $value):
+?>
 							<option class="reloadlink" onclick="document.cookie='lang=<?php echo $key; ?>';" value="<?php echo $key; ?>"<?php
-        if ($key == $LANGUAGESELECTION): ?> selected="selected"<?php
-        endif; ?>><?php echo $value[0]; ?> (<?php echo $value[1]; ?>)</option><?php
-    endforeach; ?>
+        if ($key == $LANGUAGESELECTION):
+?> selected="selected"<?php
+        endif;
+?>><?php echo $value[0]; ?> (<?php echo $value[1]; ?>)</option>
+<?php
+    endforeach;
+?>
 						</select>
-					</div><?php
-endif; ?>
+					</div>
+<?php
+endif;
+?>
 				</div>
 				<div id="pasteresult" class="hidden">
 					<div id="deletelink"></div>
-					<div id="pastelink"><?php
-if (strlen($URLSHORTENER)): ?>
-						<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>"><img src="img/icon_shorten.png" width="13" height="15" /><?php echo PrivateBin\i18n::_('Shorten URL'); ?></button><?php
-endif; ?>
+					<div id="pastelink">
+<?php
+if (strlen($URLSHORTENER)):
+?>
+						<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>"><img src="img/icon_shorten.png" width="13" height="15" /><?php echo I18n::_('Shorten URL'); ?></button>
+<?php
+endif;
+?>
 					</div>
-				</div><?php
-if ($FILEUPLOAD): ?>
-				<div id="attachment" class="hidden"><a><?php echo PrivateBin\i18n::_('Download attachment'); ?></a></div>
+				</div>
+<?php
+if ($FILEUPLOAD):
+?>
+				<div id="attachment" class="hidden"><a><?php echo I18n::_('Download attachment'); ?></a></div>
 				<div id="attach" class="hidden">
-					<span id="clonedfile" class="hidden"><?php echo PrivateBin\i18n::_('Cloned file attached.'); ?></span>
-					<span id="filewrap"><?php echo PrivateBin\i18n::_('Attach a file'); ?>: <input type="file" id="file" name="file" /></span>
-					<button id="fileremovebutton"><?php echo PrivateBin\i18n::_('Remove attachment'); ?></button>
-				</div><?php
-endif; ?>
+					<span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
+					<span id="filewrap"><?php echo I18n::_('Attach a file'); ?>: <input type="file" id="file" name="file" /></span>
+					<button id="fileremovebutton"><?php echo I18n::_('Remove attachment'); ?></button>
+				</div>
+<?php
+endif;
+?>
 				<div id="preview" class="hidden">
-					<button id="messageedit"><?php echo PrivateBin\i18n::_('Editor'); ?></button>
-					<button id="messagepreview"><?php echo PrivateBin\i18n::_('Preview'); ?></button>
+					<button id="messageedit"><?php echo I18n::_('Editor'); ?></button>
+					<button id="messagepreview"><?php echo I18n::_('Preview'); ?></button>
 				</div>
 				<div id="image" class="hidden"></div>
 				<div id="prettymessage" class="hidden">
@@ -148,7 +211,7 @@ endif; ?>
 		</section>
 		<section>
 			<div id="discussion" class="hidden">
-				<h4 class="title"><?php echo PrivateBin\i18n::_('Discussion'); ?></h4>
+				<h4 class="title"><?php echo I18n::_('Discussion'); ?></h4>
 				<div id="comments"></div>
 			</div>
 		</section>

+ 8 - 8
tst/bootstrap.php → tst/Bootstrap.php

@@ -1,6 +1,6 @@
 <?php
 
-use PrivateBin\serversalt;
+use PrivateBin\Persistence\ServerSalt;
 
 error_reporting(E_ALL | E_STRICT);
 
@@ -20,7 +20,7 @@ if (!is_file(CONF)) {
 
 require PATH . 'vendor/autoload.php';
 
-class helper
+class Helper
 {
     /**
      * example ID of a paste
@@ -162,23 +162,23 @@ class helper
      * @param string $path
      * @throws Exception
      */
-    public static function rmdir($path)
+    public static function rmDir($path)
     {
         $path .= DIRECTORY_SEPARATOR;
         $dir = dir($path);
         while (false !== ($file = $dir->read())) {
             if ($file != '.' && $file != '..') {
                 if (is_dir($path . $file)) {
-                    self::rmdir($path . $file);
+                    self::rmDir($path . $file);
                 } elseif (is_file($path . $file)) {
-                    if (!@unlink($path . $file)) {
+                    if (!unlink($path . $file)) {
                         throw new Exception('Error deleting file "' . $path . $file . '".');
                     }
                 }
             }
         }
         $dir->close();
-        if (!@rmdir($path)) {
+        if (!rmdir($path)) {
             throw new Exception('Error deleting directory "' . $path . '".');
         }
     }
@@ -256,12 +256,12 @@ class helper
      * @param bool $return
      * @return void|string
      */
-    public static function var_export_min($var, $return = false)
+    public static function varExportMin($var, $return = false)
     {
         if (is_array($var)) {
             $toImplode = array();
             foreach ($var as $key => $value) {
-                $toImplode[] = var_export($key, true) . ' => ' . self::var_export_min($value, true);
+                $toImplode[] = var_export($key, true) . ' => ' . self::varExportMin($value, true);
             }
             $code = 'array(' . implode(', ', $toImplode) . ')';
             if ($return) {

+ 21 - 21
tst/configuration.php → tst/ConfigurationTest.php

@@ -1,8 +1,8 @@
 <?php
 
-use PrivateBin\configuration;
+use PrivateBin\Configuration;
 
-class configurationTest extends PHPUnit_Framework_TestCase
+class ConfigurationTest extends PHPUnit_Framework_TestCase
 {
     private $_options;
 
@@ -11,7 +11,7 @@ class configurationTest extends PHPUnit_Framework_TestCase
     public function setUp()
     {
         /* Setup Routine */
-        helper::confBackup();
+        Helper::confBackup();
         $this->_options = configuration::getDefaults();
         $this->_options['model_options']['dir'] = PATH . $this->_options['model_options']['dir'];
         $this->_options['traffic']['dir'] = PATH . $this->_options['traffic']['dir'];
@@ -22,27 +22,27 @@ class configurationTest extends PHPUnit_Framework_TestCase
     public function tearDown()
     {
         /* Tear Down Routine */
-        helper::confRestore();
+        Helper::confRestore();
     }
 
     public function testDefaultConfigFile()
     {
         $this->assertTrue(copy(CONF . '.bak', CONF), 'copy default configuration file');
-        $conf = new configuration;
+        $conf = new Configuration;
         $this->assertEquals($this->_options, $conf->get(), 'default configuration is correct');
     }
 
     public function testHandleFreshConfigFile()
     {
         helper::createIniFile(CONF, $this->_options);
-        $conf = new configuration;
+        $conf = new Configuration;
         $this->assertEquals($this->_options, $conf->get(), 'newly generated configuration is correct');
     }
 
     public function testHandleMissingConfigFile()
     {
         @unlink(CONF);
-        $conf = new configuration;
+        $conf = new Configuration;
         $this->assertEquals($this->_options, $conf->get(), 'returns correct defaults on missing file');
     }
 
@@ -53,13 +53,13 @@ class configurationTest extends PHPUnit_Framework_TestCase
     public function testHandleBlankConfigFile()
     {
         file_put_contents(CONF, '');
-        new configuration;
+        new Configuration;
     }
 
     public function testHandleMinimalConfigFile()
     {
         file_put_contents(CONF, $this->_minimalConfig);
-        $conf = new configuration;
+        $conf = new Configuration;
         $this->assertEquals($this->_options, $conf->get(), 'returns correct defaults on empty file');
     }
 
@@ -70,7 +70,7 @@ class configurationTest extends PHPUnit_Framework_TestCase
     public function testHandleInvalidSection()
     {
         file_put_contents(CONF, $this->_minimalConfig);
-        $conf = new configuration;
+        $conf = new Configuration;
         $conf->getKey('foo', 'bar');
     }
 
@@ -81,14 +81,14 @@ class configurationTest extends PHPUnit_Framework_TestCase
     public function testHandleInvalidKey()
     {
         file_put_contents(CONF, $this->_minimalConfig);
-        $conf = new configuration;
+        $conf = new Configuration;
         $conf->getKey('foo');
     }
 
     public function testHandleGetKey()
     {
         file_put_contents(CONF, $this->_minimalConfig);
-        $conf = new configuration;
+        $conf = new Configuration;
         $this->assertEquals($this->_options['main']['sizelimit'], $conf->getKey('sizelimit'), 'get default size');
     }
 
@@ -103,8 +103,8 @@ class configurationTest extends PHPUnit_Framework_TestCase
         $options['main']['fileupload'] = 'false';
         $options['expire_options']['foo'] = 'bar';
         $options['formatter_options'][] = 'foo';
-        helper::createIniFile(CONF, $options);
-        $conf = new configuration;
+        Helper::createIniFile(CONF, $options);
+        $conf = new Configuration;
         $original_options['expire_options']['foo'] = intval('bar');
         $original_options['formatter_options'][0] = 'foo';
         $this->assertEquals($original_options, $conf->get(), 'incorrect types are corrected');
@@ -117,7 +117,7 @@ class configurationTest extends PHPUnit_Framework_TestCase
         unset($options['expire_options']['1year']);
         unset($options['expire_options']['never']);
         helper::createIniFile(CONF, $options);
-        $conf = new configuration;
+        $conf = new Configuration;
         $options['expire']['default'] = '5min';
         $this->assertEquals($options, $conf->get(), 'not overriding "missing" subkeys');
     }
@@ -126,13 +126,13 @@ class configurationTest extends PHPUnit_Framework_TestCase
     {
         $options = $this->_options;
         $options['model']['class'] = 'zerobin_data';
-        helper::createIniFile(CONF, $options);
-        $conf = new configuration;
-        $this->assertEquals('PrivateBin\data\data', $conf->getKey('class', 'model'), 'old data class gets renamed');
+        Helper::createIniFile(CONF, $options);
+        $conf = new Configuration;
+        $this->assertEquals('Filesystem', $conf->getKey('class', 'model'), 'old data class gets renamed');
 
         $options['model']['class'] = 'zerobin_db';
-        helper::createIniFile(CONF, $options);
-        $conf = new configuration;
-        $this->assertEquals('PrivateBin\data\db', $conf->getKey('class', 'model'), 'old db class gets renamed');
+        Helper::createIniFile(CONF, $options);
+        $conf = new Configuration;
+        $this->assertEquals('Database', $conf->getKey('class', 'model'), 'old db class gets renamed');
     }
 }

+ 21 - 15
tst/configGenerator.php → tst/ConfigurationTestGenerator.php

@@ -10,12 +10,12 @@
  *         a fork bomb. Please save your work before executing this script.
  */
 
-include 'bootstrap.php';
+include 'Bootstrap.php';
 
 $vrd  = array('view', 'read', 'delete');
 $vcud = array('view', 'create', 'read', 'delete');
 
-new configurationTestGenerator(array(
+new ConfigurationTestGenerator(array(
     'main/discussion' => array(
         array(
             'setting' => true,
@@ -355,7 +355,7 @@ new configurationTestGenerator(array(
     ),
 ));
 
-class configurationTestGenerator
+class ConfigurationTestGenerator
 {
     /**
      * endless loop protection, since we're working with a recursive function,
@@ -405,7 +405,7 @@ class configurationTestGenerator
         $code = $this->_getHeader();
         foreach ($this->_configurations as $key => $conf) {
             $fullOptions = array_replace_recursive($defaultOptions, $conf['options']);
-            $options = helper::var_export_min($fullOptions, true);
+            $options = Helper::varExportMin($fullOptions, true);
             foreach ($conf['affects'] as $step) {
                 $testCode = $preCode = array();
                 foreach ($conf['tests'] as $tests) {
@@ -437,7 +437,7 @@ class configurationTestGenerator
                             if (is_string($arg) && strpos($arg, '$') === 0) {
                                 $args[] = $arg;
                             } else {
-                                $args[] = helper::var_export_min($arg, true);
+                                $args[] = Helper::varExportMin($arg, true);
                             }
                         }
                         $testCode[] = array($test['type'], implode(', ', $args));
@@ -449,7 +449,7 @@ class configurationTestGenerator
             }
         }
         $code .= '}' . PHP_EOL;
-        file_put_contents('configurationCombinations.php', $code);
+        file_put_contents('ConfigurationCombinationsTest.php', $code);
     }
 
     /**
@@ -464,26 +464,32 @@ class configurationTestGenerator
 /**
  * DO NOT EDIT: This file is generated automatically using configGenerator.php
  */
-class configurationCombinationsTest extends PHPUnit_Framework_TestCase
+
+use PrivateBin\Data\Filesystem;
+
+class ConfigurationCombinationsTest extends PHPUnit_Framework_TestCase
 {
+    private $_conf;
+
     private $_model;
 
-    private $_conf;
+    private $_path;
 
     public function setUp()
     {
         /* Setup Routine */
-        helper::confBackup();
-
-        $this->_model = privatebin_data::getInstance(array('dir' => PATH . 'data'));
-        serversalt::setPath(PATH . 'data');
+        Helper::confBackup();
+        $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
+        $this->_model = Filesystem::getInstance(array('dir' => $this->_path));
+        serversalt::setPath($this->_path);
         $this->reset();
     }
 
     public function tearDown()
     {
         /* Tear Down Routine */
-        helper::confRestore();
+        Helper::confRestore();
+        Helper::rmDir($this->_path);
 }
 
     public function reset($configuration = array())
@@ -493,7 +499,7 @@ class configurationCombinationsTest extends PHPUnit_Framework_TestCase
         $_SERVER = array();
         if ($this->_model->exists(helper::getPasteId()))
             $this->_model->delete(helper::getPasteId());
-        helper::createIniFile(CONF, $configuration);
+        Helper::createIniFile(CONF, $configuration);
     }
 
 
@@ -665,7 +671,7 @@ EOT;
             array_key_exists($option, $configuration['options'][$section]) &&
             $configuration['options'][$section][$option] === $setting['setting']
         ) {
-            $val = helper::var_export_min($setting['setting'], true);
+            $val = Helper::varExportMin($setting['setting'], true);
             throw new Exception("Endless loop or error in options detected: option '$option' already exists with setting '$val' in one of the configurations!");
         }
         $configuration['options'][$section][$option] = $setting['setting'];

+ 61 - 58
tst/privatebin/db.php → tst/Data/DatabaseTest.php

@@ -1,11 +1,13 @@
 <?php
 
-use PrivateBin\data\db;
+use PrivateBin\Data\Database;
 
-class privatebin_dbTest extends PHPUnit_Framework_TestCase
+class DatabaseTest extends PHPUnit_Framework_TestCase
 {
     private $_model;
 
+    private $_path;
+
     private $_options = array(
         'dsn' => 'sqlite::memory:',
         'usr' => null,
@@ -16,68 +18,69 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
     public function setUp()
     {
         /* Setup Routine */
-        $this->_model = db::getInstance($this->_options);
+        $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
+        $this->_model = Database::getInstance($this->_options);
     }
 
     public function tearDown()
     {
         /* Tear Down Routine */
-        if (is_dir(PATH . 'data')) {
-            helper::rmdir(PATH . 'data');
+        if (is_dir($this->_path)) {
+            Helper::rmDir($this->_path);
         }
     }
 
     public function testDatabaseBasedDataStoreWorks()
     {
-        $this->_model->delete(helper::getPasteId());
+        $this->_model->delete(Helper::getPasteId());
 
         // storing pastes
-        $paste = helper::getPaste(array('expire_date' => 1344803344));
-        $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste does not yet exist');
-        $this->assertTrue($this->_model->create(helper::getPasteId(), $paste), 'store new paste');
-        $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists after storing it');
-        $this->assertFalse($this->_model->create(helper::getPasteId(), $paste), 'unable to store the same paste twice');
-        $this->assertEquals(json_decode(json_encode($paste)), $this->_model->read(helper::getPasteId()));
+        $paste = Helper::getPaste(array('expire_date' => 1344803344));
+        $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
+        $this->assertTrue($this->_model->create(Helper::getPasteId(), $paste), 'store new paste');
+        $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');
+        $this->assertFalse($this->_model->create(Helper::getPasteId(), $paste), 'unable to store the same paste twice');
+        $this->assertEquals(json_decode(json_encode($paste)), $this->_model->read(Helper::getPasteId()));
 
         // storing comments
-        $this->assertFalse($this->_model->existsComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId()), 'comment does not yet exist');
-        $this->assertTrue($this->_model->createComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId(), helper::getComment()) !== false, 'store comment');
-        $this->assertTrue($this->_model->existsComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId()), 'comment exists after storing it');
-        $comment = json_decode(json_encode(helper::getComment()));
-        $comment->id = helper::getCommentId();
-        $comment->parentid = helper::getPasteId();
+        $this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does not yet exist');
+        $this->assertTrue($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment()) !== false, 'store comment');
+        $this->assertTrue($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment exists after storing it');
+        $comment = json_decode(json_encode(Helper::getComment()));
+        $comment->id = Helper::getCommentId();
+        $comment->parentid = Helper::getPasteId();
         $this->assertEquals(
             array($comment->meta->postdate => $comment),
-            $this->_model->readComments(helper::getPasteId())
+            $this->_model->readComments(Helper::getPasteId())
         );
 
         // deleting pastes
-        $this->_model->delete(helper::getPasteId());
-        $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste successfully deleted');
-        $this->assertFalse($this->_model->existsComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId()), 'comment was deleted with paste');
-        $this->assertFalse($this->_model->read(helper::getPasteId()), 'paste can no longer be found');
+        $this->_model->delete(Helper::getPasteId());
+        $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted');
+        $this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment was deleted with paste');
+        $this->assertFalse($this->_model->read(Helper::getPasteId()), 'paste can no longer be found');
     }
 
     public function testDatabaseBasedAttachmentStoreWorks()
     {
-        $this->_model->delete(helper::getPasteId());
-        $original = $paste = helper::getPasteWithAttachment(array('expire_date' => 1344803344));
+        $this->_model->delete(Helper::getPasteId());
+        $original = $paste = Helper::getPasteWithAttachment(array('expire_date' => 1344803344));
         $paste['meta']['burnafterreading'] = $original['meta']['burnafterreading'] = true;
         $paste['meta']['attachment'] = $paste['attachment'];
         $paste['meta']['attachmentname'] = $paste['attachmentname'];
         unset($paste['attachment'], $paste['attachmentname']);
-        $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste does not yet exist');
-        $this->assertTrue($this->_model->create(helper::getPasteId(), $paste), 'store new paste');
-        $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists after storing it');
-        $this->assertFalse($this->_model->create(helper::getPasteId(), $paste), 'unable to store the same paste twice');
-        $this->assertEquals(json_decode(json_encode($original)), $this->_model->read(helper::getPasteId()));
+        $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
+        $this->assertTrue($this->_model->create(Helper::getPasteId(), $paste), 'store new paste');
+        $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');
+        $this->assertFalse($this->_model->create(Helper::getPasteId(), $paste), 'unable to store the same paste twice');
+        $this->assertEquals(json_decode(json_encode($original)), $this->_model->read(Helper::getPasteId()));
     }
 
     public function testPurge()
     {
-        $this->_model->delete(helper::getPasteId());
-        $expired = helper::getPaste(array('expire_date' => 1344803344));
-        $paste = helper::getPaste(array('expire_date' => time() + 3600));
+        $this->_model->delete(Helper::getPasteId());
+        $expired = Helper::getPaste(array('expire_date' => 1344803344));
+        $paste = Helper::getPaste(array('expire_date' => time() + 3600));
         $keys = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'x', 'y', 'z');
         $ids = array();
         foreach ($keys as $key) {
@@ -107,7 +110,7 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
      */
     public function testGetIbmInstance()
     {
-        db::getInstance(array(
+        Database::getInstance(array(
             'dsn' => 'ibm:', 'usr' => null, 'pwd' => null,
             'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
         ));
@@ -118,7 +121,7 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
      */
     public function testGetInformixInstance()
     {
-        db::getInstance(array(
+        Database::getInstance(array(
             'dsn' => 'informix:', 'usr' => null, 'pwd' => null,
             'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
         ));
@@ -129,7 +132,7 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
      */
     public function testGetMssqlInstance()
     {
-        db::getInstance(array(
+        Database::getInstance(array(
             'dsn' => 'mssql:', 'usr' => null, 'pwd' => null,
             'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
         ));
@@ -140,7 +143,7 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
      */
     public function testGetMysqlInstance()
     {
-        db::getInstance(array(
+        Database::getInstance(array(
             'dsn' => 'mysql:', 'usr' => null, 'pwd' => null,
             'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
         ));
@@ -151,7 +154,7 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
      */
     public function testGetOciInstance()
     {
-        db::getInstance(array(
+        Database::getInstance(array(
             'dsn' => 'oci:', 'usr' => null, 'pwd' => null,
             'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
         ));
@@ -162,7 +165,7 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
      */
     public function testGetPgsqlInstance()
     {
-        db::getInstance(array(
+        Database::getInstance(array(
             'dsn' => 'pgsql:', 'usr' => null, 'pwd' => null,
             'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
         ));
@@ -174,7 +177,7 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
      */
     public function testGetFooInstance()
     {
-        db::getInstance(array(
+        Database::getInstance(array(
             'dsn' => 'foo:', 'usr' => null, 'pwd' => null, 'opt' => null
         ));
     }
@@ -187,7 +190,7 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
     {
         $options = $this->_options;
         unset($options['dsn']);
-        db::getInstance($options);
+        Database::getInstance($options);
     }
 
     /**
@@ -198,7 +201,7 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
     {
         $options = $this->_options;
         unset($options['usr']);
-        db::getInstance($options);
+        Database::getInstance($options);
     }
 
     /**
@@ -209,7 +212,7 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
     {
         $options = $this->_options;
         unset($options['pwd']);
-        db::getInstance($options);
+        Database::getInstance($options);
     }
 
     /**
@@ -220,19 +223,19 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
     {
         $options = $this->_options;
         unset($options['opt']);
-        db::getInstance($options);
+        Database::getInstance($options);
     }
 
     public function testOldAttachments()
     {
-        mkdir(PATH . 'data');
-        $path = PATH . 'data' . DIRECTORY_SEPARATOR . 'attachement-test.sq3';
-        @unlink($path);
+        mkdir($this->_path);
+        $path = $this->_path . DIRECTORY_SEPARATOR . 'attachement-test.sq3';
+        if (is_file($path)) unlink($path);
         $this->_options['dsn'] = 'sqlite:' . $path;
         $this->_options['tbl'] = 'bar_';
-        $model = db::getInstance($this->_options);
+        $model = Database::getInstance($this->_options);
 
-        $original = $paste = helper::getPasteWithAttachment(array('expire_date' => 1344803344));
+        $original = $paste = Helper::getPasteWithAttachment(array('expire_date' => 1344803344));
         $paste['meta']['attachment'] = $paste['attachment'];
         $paste['meta']['attachmentname'] = $paste['attachmentname'];
         unset($paste['attachment'], $paste['attachmentname']);
@@ -247,7 +250,7 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
         $statement = $db->prepare('INSERT INTO bar_paste VALUES(?,?,?,?,?,?,?,?,?)');
         $statement->execute(
             array(
-                helper::getPasteId(),
+                Helper::getPasteId(),
                 $paste['data'],
                 $paste['meta']['postdate'],
                 1344803344,
@@ -260,17 +263,17 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
         );
         $statement->closeCursor();
 
-        $this->assertTrue($model->exists(helper::getPasteId()), 'paste exists after storing it');
-        $this->assertEquals(json_decode(json_encode($original)), $model->read(helper::getPasteId()));
+        $this->assertTrue($model->exists(Helper::getPasteId()), 'paste exists after storing it');
+        $this->assertEquals(json_decode(json_encode($original)), $model->read(Helper::getPasteId()));
 
-        helper::rmdir(PATH . 'data');
+        Helper::rmDir($this->_path);
     }
 
     public function testTableUpgrade()
     {
-        mkdir(PATH . 'data');
-        $path = PATH . 'data' . DIRECTORY_SEPARATOR . 'db-test.sq3';
-        @unlink($path);
+        mkdir($this->_path);
+        $path = $this->_path . DIRECTORY_SEPARATOR . 'db-test.sq3';
+        if (is_file($path)) unlink($path);
         $this->_options['dsn'] = 'sqlite:' . $path;
         $this->_options['tbl'] = 'foo_';
         $db = new PDO(
@@ -298,7 +301,7 @@ class privatebin_dbTest extends PHPUnit_Framework_TestCase
             'vizhash BLOB, ' .
             "postdate INT );"
         );
-        db::getInstance($this->_options);
-        helper::rmdir(PATH . 'data');
+        $this->assertInstanceOf(Database::class, Database::getInstance($this->_options));
+        Helper::rmDir($this->_path);
     }
 }

+ 31 - 31
tst/privatebin/data.php → tst/Data/FilesystemTest.php

@@ -1,8 +1,8 @@
 <?php
 
-use PrivateBin\data\data;
+use PrivateBin\Data\Filesystem;
 
-class privatebin_dataTest extends PHPUnit_Framework_TestCase
+class FilesystemTest extends PHPUnit_Framework_TestCase
 {
     private $_model;
 
@@ -12,65 +12,65 @@ class privatebin_dataTest extends PHPUnit_Framework_TestCase
     {
         /* Setup Routine */
         $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
-        $this->_model = data::getInstance(array('dir' => $this->_path));
+        $this->_model = Filesystem::getInstance(array('dir' => $this->_path));
     }
 
     public function tearDown()
     {
         /* Tear Down Routine */
-        helper::rmdir($this->_path);
+        Helper::rmDir($this->_path);
     }
 
     public function testFileBasedDataStoreWorks()
     {
-        $this->_model->delete(helper::getPasteId());
+        $this->_model->delete(Helper::getPasteId());
 
         // storing pastes
-        $paste = helper::getPaste(array('expire_date' => 1344803344));
-        $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste does not yet exist');
-        $this->assertTrue($this->_model->create(helper::getPasteId(), $paste), 'store new paste');
-        $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists after storing it');
-        $this->assertFalse($this->_model->create(helper::getPasteId(), $paste), 'unable to store the same paste twice');
-        $this->assertEquals(json_decode(json_encode($paste)), $this->_model->read(helper::getPasteId()));
+        $paste = Helper::getPaste(array('expire_date' => 1344803344));
+        $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
+        $this->assertTrue($this->_model->create(Helper::getPasteId(), $paste), 'store new paste');
+        $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');
+        $this->assertFalse($this->_model->create(Helper::getPasteId(), $paste), 'unable to store the same paste twice');
+        $this->assertEquals(json_decode(json_encode($paste)), $this->_model->read(Helper::getPasteId()));
 
         // storing comments
-        $this->assertFalse($this->_model->existsComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId()), 'comment does not yet exist');
-        $this->assertTrue($this->_model->createComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId(), helper::getComment()) !== false, 'store comment');
-        $this->assertTrue($this->_model->existsComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId()), 'comment exists after storing it');
-        $comment = json_decode(json_encode(helper::getComment()));
-        $comment->id = helper::getCommentId();
-        $comment->parentid = helper::getPasteId();
+        $this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does not yet exist');
+        $this->assertTrue($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment()) !== false, 'store comment');
+        $this->assertTrue($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment exists after storing it');
+        $comment = json_decode(json_encode(Helper::getComment()));
+        $comment->id = Helper::getCommentId();
+        $comment->parentid = Helper::getPasteId();
         $this->assertEquals(
             array($comment->meta->postdate => $comment),
-            $this->_model->readComments(helper::getPasteId())
+            $this->_model->readComments(Helper::getPasteId())
         );
 
         // deleting pastes
-        $this->_model->delete(helper::getPasteId());
-        $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste successfully deleted');
-        $this->assertFalse($this->_model->existsComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId()), 'comment was deleted with paste');
-        $this->assertFalse($this->_model->read(helper::getPasteId()), 'paste can no longer be found');
+        $this->_model->delete(Helper::getPasteId());
+        $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted');
+        $this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment was deleted with paste');
+        $this->assertFalse($this->_model->read(Helper::getPasteId()), 'paste can no longer be found');
     }
 
     public function testFileBasedAttachmentStoreWorks()
     {
-        $this->_model->delete(helper::getPasteId());
-        $original = $paste = helper::getPasteWithAttachment(array('expire_date' => 1344803344));
+        $this->_model->delete(Helper::getPasteId());
+        $original = $paste = Helper::getPasteWithAttachment(array('expire_date' => 1344803344));
         $paste['meta']['attachment'] = $paste['attachment'];
         $paste['meta']['attachmentname'] = $paste['attachmentname'];
         unset($paste['attachment'], $paste['attachmentname']);
-        $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste does not yet exist');
-        $this->assertTrue($this->_model->create(helper::getPasteId(), $paste), 'store new paste');
-        $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists after storing it');
-        $this->assertFalse($this->_model->create(helper::getPasteId(), $paste), 'unable to store the same paste twice');
-        $this->assertEquals(json_decode(json_encode($original)), $this->_model->read(helper::getPasteId()));
+        $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
+        $this->assertTrue($this->_model->create(Helper::getPasteId(), $paste), 'store new paste');
+        $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');
+        $this->assertFalse($this->_model->create(Helper::getPasteId(), $paste), 'unable to store the same paste twice');
+        $this->assertEquals(json_decode(json_encode($original)), $this->_model->read(Helper::getPasteId()));
     }
 
     public function testPurge()
     {
         mkdir($this->_path . DIRECTORY_SEPARATOR . '00', 0777, true);
-        $expired = helper::getPaste(array('expire_date' => 1344803344));
-        $paste = helper::getPaste(array('expire_date' => time() + 3600));
+        $expired = Helper::getPaste(array('expire_date' => 1344803344));
+        $paste = Helper::getPaste(array('expire_date' => time() + 3600));
         $keys = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'x', 'y', 'z');
         $ids = array();
         foreach ($keys as $key) {

+ 81 - 0
tst/FilterTest.php

@@ -0,0 +1,81 @@
+<?php
+
+use PrivateBin\Filter;
+
+class FilterTest extends PHPUnit_Framework_TestCase
+{
+    public function testFilterStripsSlashesDeeply()
+    {
+        $this->assertEquals(
+            array("f'oo", "b'ar", array("fo'o", "b'ar")),
+            Filter::stripslashesDeep(array("f\\'oo", "b\\'ar", array("fo\\'o", "b\\'ar")))
+        );
+    }
+
+    public function testFilterMakesTimesHumanlyReadable()
+    {
+        $this->assertEquals('5 minutes', Filter::formatHumanReadableTime('5min'));
+        $this->assertEquals('90 seconds', Filter::formatHumanReadableTime('90sec'));
+        $this->assertEquals('1 week', Filter::formatHumanReadableTime('1week'));
+        $this->assertEquals('6 months', Filter::formatHumanReadableTime('6months'));
+    }
+
+    /**
+     * @expectedException Exception
+     * @expectedExceptionCode 30
+     */
+    public function testFilterFailTimesHumanlyReadable()
+    {
+        Filter::formatHumanReadableTime('five_minutes');
+    }
+
+    public function testFilterMakesSizesHumanlyReadable()
+    {
+        $this->assertEquals('1 B', Filter::formatHumanReadableSize(1));
+        $this->assertEquals('1 000 B', Filter::formatHumanReadableSize(1000));
+        $this->assertEquals('1.00 KiB', Filter::formatHumanReadableSize(1024));
+        $this->assertEquals('1.21 KiB', Filter::formatHumanReadableSize(1234));
+        $exponent = 1024;
+        $this->assertEquals('1 000.00 KiB', Filter::formatHumanReadableSize(1000 * $exponent));
+        $this->assertEquals('1.00 MiB', Filter::formatHumanReadableSize(1024 * $exponent));
+        $this->assertEquals('1.21 MiB', Filter::formatHumanReadableSize(1234 * $exponent));
+        $exponent *= 1024;
+        $this->assertEquals('1 000.00 MiB', Filter::formatHumanReadableSize(1000 * $exponent));
+        $this->assertEquals('1.00 GiB', Filter::formatHumanReadableSize(1024 * $exponent));
+        $this->assertEquals('1.21 GiB', Filter::formatHumanReadableSize(1234 * $exponent));
+        $exponent *= 1024;
+        $this->assertEquals('1 000.00 GiB', Filter::formatHumanReadableSize(1000 * $exponent));
+        $this->assertEquals('1.00 TiB', Filter::formatHumanReadableSize(1024 * $exponent));
+        $this->assertEquals('1.21 TiB', Filter::formatHumanReadableSize(1234 * $exponent));
+        $exponent *= 1024;
+        $this->assertEquals('1 000.00 TiB', Filter::formatHumanReadableSize(1000 * $exponent));
+        $this->assertEquals('1.00 PiB', Filter::formatHumanReadableSize(1024 * $exponent));
+        $this->assertEquals('1.21 PiB', Filter::formatHumanReadableSize(1234 * $exponent));
+        $exponent *= 1024;
+        $this->assertEquals('1 000.00 PiB', Filter::formatHumanReadableSize(1000 * $exponent));
+        $this->assertEquals('1.00 EiB', Filter::formatHumanReadableSize(1024 * $exponent));
+        $this->assertEquals('1.21 EiB', Filter::formatHumanReadableSize(1234 * $exponent));
+        $exponent *= 1024;
+        $this->assertEquals('1 000.00 EiB', Filter::formatHumanReadableSize(1000 * $exponent));
+        $this->assertEquals('1.00 ZiB', Filter::formatHumanReadableSize(1024 * $exponent));
+        $this->assertEquals('1.21 ZiB', Filter::formatHumanReadableSize(1234 * $exponent));
+        $exponent *= 1024;
+        $this->assertEquals('1 000.00 ZiB', Filter::formatHumanReadableSize(1000 * $exponent));
+        $this->assertEquals('1.00 YiB', Filter::formatHumanReadableSize(1024 * $exponent));
+        $this->assertEquals('1.21 YiB', Filter::formatHumanReadableSize(1234 * $exponent));
+    }
+
+    public function testSlowEquals()
+    {
+        $this->assertTrue(Filter::slowEquals('foo', 'foo'), 'same string');
+        $this->assertFalse(Filter::slowEquals('foo', true), 'string and boolean');
+        $this->assertFalse(Filter::slowEquals('foo', 0), 'string and integer');
+        $this->assertFalse(Filter::slowEquals('123foo', 123), 'string and integer');
+        $this->assertFalse(Filter::slowEquals('123foo', '123'), 'different strings');
+        $this->assertFalse(Filter::slowEquals('6', ' 6'), 'strings with space');
+        $this->assertFalse(Filter::slowEquals('4.2', '4.20'), 'floats as strings');
+        $this->assertFalse(Filter::slowEquals('1e3', '1000'), 'integers as strings');
+        $this->assertFalse(Filter::slowEquals('9223372036854775807', '9223372036854775808'), 'large integers as strings');
+        $this->assertFalse(Filter::slowEquals('61529519452809720693702583126814', '61529519452809720000000000000000'), 'larger integers as strings');
+    }
+}

+ 26 - 26
tst/i18n.php → tst/I18nTest.php

@@ -1,8 +1,8 @@
 <?php
 
-use PrivateBin\i18n;
+use PrivateBin\I18n;
 
-class i18nTest extends PHPUnit_Framework_TestCase
+class I18nTest extends PHPUnit_Framework_TestCase
 {
     private $_translations = array();
 
@@ -24,59 +24,59 @@ class i18nTest extends PHPUnit_Framework_TestCase
     {
         $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'foobar';
         $messageId = 'It does not matter if the message ID exists';
-        i18n::loadTranslations();
-        $this->assertEquals($messageId, i18n::_($messageId), 'fallback to en');
+        I18n::loadTranslations();
+        $this->assertEquals($messageId, I18n::_($messageId), 'fallback to en');
     }
 
     public function testCookieLanguageDeDetection()
     {
         $_COOKIE['lang'] = 'de';
-        i18n::loadTranslations();
-        $this->assertEquals($this->_translations['en'], i18n::_('en'), 'browser language de');
-        $this->assertEquals('0 Stunden', i18n::_('%d hours', 0), '0 hours in german');
-        $this->assertEquals('1 Stunde',  i18n::_('%d hours', 1), '1 hour in german');
-        $this->assertEquals('2 Stunden', i18n::_('%d hours', 2), '2 hours in french');
+        I18n::loadTranslations();
+        $this->assertEquals($this->_translations['en'], I18n::_('en'), 'browser language de');
+        $this->assertEquals('0 Stunden', I18n::_('%d hours', 0), '0 hours in german');
+        $this->assertEquals('1 Stunde',  I18n::_('%d hours', 1), '1 hour in german');
+        $this->assertEquals('2 Stunden', I18n::_('%d hours', 2), '2 hours in french');
     }
 
     public function testBrowserLanguageDeDetection()
     {
         $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-CH,de;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
-        i18n::loadTranslations();
-        $this->assertEquals($this->_translations['en'], i18n::_('en'), 'browser language de');
-        $this->assertEquals('0 Stunden', i18n::_('%d hours', 0), '0 hours in german');
-        $this->assertEquals('1 Stunde',  i18n::_('%d hours', 1), '1 hour in german');
-        $this->assertEquals('2 Stunden', i18n::_('%d hours', 2), '2 hours in french');
+        I18n::loadTranslations();
+        $this->assertEquals($this->_translations['en'], I18n::_('en'), 'browser language de');
+        $this->assertEquals('0 Stunden', I18n::_('%d hours', 0), '0 hours in german');
+        $this->assertEquals('1 Stunde',  I18n::_('%d hours', 1), '1 hour in german');
+        $this->assertEquals('2 Stunden', I18n::_('%d hours', 2), '2 hours in french');
     }
 
     public function testBrowserLanguageFrDetection()
     {
         $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'fr-CH,fr;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
-        i18n::loadTranslations();
-        $this->assertEquals('fr', i18n::_('en'), 'browser language fr');
-        $this->assertEquals('0 heure',  i18n::_('%d hours', 0), '0 hours in french');
-        $this->assertEquals('1 heure',  i18n::_('%d hours', 1), '1 hour in french');
-        $this->assertEquals('2 heures', i18n::_('%d hours', 2), '2 hours in french');
+        I18n::loadTranslations();
+        $this->assertEquals('fr', I18n::_('en'), 'browser language fr');
+        $this->assertEquals('0 heure',  I18n::_('%d hours', 0), '0 hours in french');
+        $this->assertEquals('1 heure',  I18n::_('%d hours', 1), '1 hour in french');
+        $this->assertEquals('2 heures', I18n::_('%d hours', 2), '2 hours in french');
     }
 
     public function testBrowserLanguagePlDetection()
     {
         $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'pl;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
-        i18n::loadTranslations();
-        $this->assertEquals('pl', i18n::_('en'), 'browser language pl');
-        $this->assertEquals('2 godzina', i18n::_('%d hours', 2), 'hours in polish');
+        I18n::loadTranslations();
+        $this->assertEquals('pl', I18n::_('en'), 'browser language pl');
+        $this->assertEquals('2 godzina', I18n::_('%d hours', 2), 'hours in polish');
     }
 
     public function testBrowserLanguageAnyDetection()
     {
         $_SERVER['HTTP_ACCEPT_LANGUAGE'] = '*';
-        i18n::loadTranslations();
-        $this->assertTrue(strlen(i18n::_('en')) == 2, 'browser language any');
+        I18n::loadTranslations();
+        $this->assertTrue(strlen(I18n::_('en')) == 2, 'browser language any');
     }
 
     public function testVariableInjection()
     {
         $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'foobar';
-        i18n::loadTranslations();
-        $this->assertEquals('some string + 1', i18n::_('some %s + %d', 'string', 1), 'browser language en');
+        I18n::loadTranslations();
+        $this->assertEquals('some string + 1', I18n::_('some %s + %d', 'string', 1), 'browser language en');
     }
 }

+ 74 - 59
tst/jsonApi.php → tst/JsonApiTest.php

@@ -1,26 +1,31 @@
 <?php
 
-use PrivateBin\data\data;
-use PrivateBin\privatebin;
-use PrivateBin\request;
-use PrivateBin\serversalt;
+use PrivateBin\Data\Filesystem;
+use PrivateBin\PrivateBin;
+use PrivateBin\Request;
+use PrivateBin\Persistence\ServerSalt;
 
-class jsonApiTest extends PHPUnit_Framework_TestCase
+class JsonApiTest extends PHPUnit_Framework_TestCase
 {
     protected $_model;
 
+    protected $_path;
+
     public function setUp()
     {
         /* Setup Routine */
-        $this->_model = data::getInstance(array('dir' => PATH . 'data'));
-        serversalt::setPath(PATH . 'data');
+        Helper::confBackup();
+        $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
+        $this->_model = Filesystem::getInstance(array('dir' => $this->_path));
+        ServerSalt::setPath($this->_path);
         $this->reset();
     }
 
     public function tearDown()
     {
         /* Tear Down Routine */
-        helper::confRestore();
+        Helper::confRestore();
+        Helper::rmDir($this->_path);
     }
 
     public function reset()
@@ -28,10 +33,16 @@ class jsonApiTest extends PHPUnit_Framework_TestCase
         $_POST = array();
         $_GET = array();
         $_SERVER = array();
-        if ($this->_model->exists(helper::getPasteId())) {
-            $this->_model->delete(helper::getPasteId());
+        if ($this->_model->exists(Helper::getPasteId())) {
+            $this->_model->delete(Helper::getPasteId());
         }
-        helper::confRestore();
+        Helper::confRestore();
+        $options = parse_ini_file(CONF, true);
+        $options['purge']['dir'] = $this->_path;
+        $options['traffic']['dir'] = $this->_path;
+        $options['model_options']['dir'] = $this->_path;
+        Helper::confBackup();
+        Helper::createIniFile(CONF, $options);
     }
 
     /**
@@ -42,14 +53,14 @@ class jsonApiTest extends PHPUnit_Framework_TestCase
         $this->reset();
         $options = parse_ini_file(CONF, true);
         $options['traffic']['limit'] = 0;
-        helper::confBackup();
-        helper::createIniFile(CONF, $options);
-        $_POST = helper::getPaste();
+        Helper::confBackup();
+        Helper::createIniFile(CONF, $options);
+        $_POST = Helper::getPaste();
         $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
         $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
-        new privatebin;
+        new PrivateBin;
         $content = ob_get_contents();
         ob_end_clean();
         $response = json_decode($content, true);
@@ -72,24 +83,24 @@ class jsonApiTest extends PHPUnit_Framework_TestCase
         $this->reset();
         $options = parse_ini_file(CONF, true);
         $options['traffic']['limit'] = 0;
-        helper::confBackup();
-        helper::createIniFile(CONF, $options);
-        $paste = helper::getPaste();
+        Helper::confBackup();
+        Helper::createIniFile(CONF, $options);
+        $paste = Helper::getPaste();
         unset($paste['meta']);
         $file = tempnam(sys_get_temp_dir(), 'FOO');
         file_put_contents($file, http_build_query($paste));
-        request::setInputStream($file);
-        $_SERVER['QUERY_STRING'] = helper::getPasteId();
+        Request::setInputStream($file);
+        $_SERVER['QUERY_STRING'] = Helper::getPasteId();
         $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
         $_SERVER['REQUEST_METHOD'] = 'PUT';
         $_SERVER['REMOTE_ADDR'] = '::1';
         ob_start();
-        new privatebin;
+        new PrivateBin;
         $content = ob_get_contents();
         ob_end_clean();
         $response = json_decode($content, true);
         $this->assertEquals(0, $response['status'], 'outputs status');
-        $this->assertEquals(helper::getPasteId(), $response['id'], 'outputted paste ID matches input');
+        $this->assertEquals(Helper::getPasteId(), $response['id'], 'outputted paste ID matches input');
         $this->assertStringEndsWith('?' . $response['id'], $response['url'], 'returned URL points to new paste');
         $this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
         $paste = $this->_model->read($response['id']);
@@ -106,24 +117,24 @@ class jsonApiTest extends PHPUnit_Framework_TestCase
     public function testDelete()
     {
         $this->reset();
-        $this->_model->create(helper::getPasteId(), helper::getPaste());
-        $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists before deleting data');
-        $paste = $this->_model->read(helper::getPasteId());
+        $this->_model->create(Helper::getPasteId(), Helper::getPaste());
+        $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data');
+        $paste = $this->_model->read(Helper::getPasteId());
         $file = tempnam(sys_get_temp_dir(), 'FOO');
         file_put_contents($file, http_build_query(array(
-            'deletetoken' => hash_hmac('sha256', helper::getPasteId(), $paste->meta->salt),
+            'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste->meta->salt),
         )));
-        request::setInputStream($file);
-        $_SERVER['QUERY_STRING'] = helper::getPasteId();
+        Request::setInputStream($file);
+        $_SERVER['QUERY_STRING'] = Helper::getPasteId();
         $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
         $_SERVER['REQUEST_METHOD'] = 'DELETE';
         ob_start();
-        new privatebin;
+        new PrivateBin;
         $content = ob_get_contents();
         ob_end_clean();
         $response = json_decode($content, true);
         $this->assertEquals(0, $response['status'], 'outputs status');
-        $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste successfully deleted');
+        $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted');
     }
 
     /**
@@ -132,23 +143,23 @@ class jsonApiTest extends PHPUnit_Framework_TestCase
     public function testDeleteWithPost()
     {
         $this->reset();
-        $this->_model->create(helper::getPasteId(), helper::getPaste());
-        $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists before deleting data');
-        $paste = $this->_model->read(helper::getPasteId());
+        $this->_model->create(Helper::getPasteId(), Helper::getPaste());
+        $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data');
+        $paste = $this->_model->read(Helper::getPasteId());
         $_POST = array(
             'action' => 'delete',
-            'deletetoken' => hash_hmac('sha256', helper::getPasteId(), $paste->meta->salt),
+            'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste->meta->salt),
         );
-        $_SERVER['QUERY_STRING'] = helper::getPasteId();
+        $_SERVER['QUERY_STRING'] = Helper::getPasteId();
         $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
         $_SERVER['REQUEST_METHOD'] = 'POST';
         ob_start();
-        new privatebin;
+        new PrivateBin;
         $content = ob_get_contents();
         ob_end_clean();
         $response = json_decode($content, true);
         $this->assertEquals(0, $response['status'], 'outputs status');
-        $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste successfully deleted');
+        $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted');
     }
 
     /**
@@ -157,21 +168,25 @@ class jsonApiTest extends PHPUnit_Framework_TestCase
     public function testRead()
     {
         $this->reset();
-        $paste = helper::getPasteWithAttachment();
-        $this->_model->create(helper::getPasteId(), $paste);
-        $_SERVER['QUERY_STRING'] = helper::getPasteId();
+        $paste = Helper::getPasteWithAttachment();
+        $paste['meta']['attachment'] = $paste['attachment'];
+        $paste['meta']['attachmentname'] = $paste['attachmentname'];
+        unset($paste['attachment']);
+        unset($paste['attachmentname']);
+        $this->_model->create(Helper::getPasteId(), $paste);
+        $_SERVER['QUERY_STRING'] = Helper::getPasteId();
         $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
         ob_start();
-        new privatebin;
+        new PrivateBin;
         $content = ob_get_contents();
         ob_end_clean();
         $response = json_decode($content, true);
         $this->assertEquals(0, $response['status'], 'outputs success status');
-        $this->assertEquals(helper::getPasteId(), $response['id'], 'outputs data correctly');
+        $this->assertEquals(Helper::getPasteId(), $response['id'], 'outputs data correctly');
         $this->assertStringEndsWith('?' . $response['id'], $response['url'], 'returned URL points to new paste');
         $this->assertEquals($paste['data'], $response['data'], 'outputs data correctly');
-        $this->assertEquals($paste['attachment'], $response['attachment'], 'outputs attachment correctly');
-        $this->assertEquals($paste['attachmentname'], $response['attachmentname'], 'outputs attachmentname correctly');
+        $this->assertEquals($paste['meta']['attachment'], $response['attachment'], 'outputs attachment correctly');
+        $this->assertEquals($paste['meta']['attachmentname'], $response['attachmentname'], 'outputs attachmentname correctly');
         $this->assertEquals($paste['meta']['formatter'], $response['meta']['formatter'], 'outputs format correctly');
         $this->assertEquals($paste['meta']['postdate'], $response['meta']['postdate'], 'outputs postdate correctly');
         $this->assertEquals($paste['meta']['opendiscussion'], $response['meta']['opendiscussion'], 'outputs opendiscussion correctly');
@@ -185,11 +200,11 @@ class jsonApiTest extends PHPUnit_Framework_TestCase
     public function testJsonLdPaste()
     {
         $this->reset();
-        $paste = helper::getPasteWithAttachment();
-        $this->_model->create(helper::getPasteId(), $paste);
+        $paste = Helper::getPasteWithAttachment();
+        $this->_model->create(Helper::getPasteId(), $paste);
         $_GET['jsonld'] = 'paste';
         ob_start();
-        new privatebin;
+        new PrivateBin;
         $content = ob_get_contents();
         ob_end_clean();
         $this->assertEquals(str_replace(
@@ -205,11 +220,11 @@ class jsonApiTest extends PHPUnit_Framework_TestCase
     public function testJsonLdComment()
     {
         $this->reset();
-        $paste = helper::getPasteWithAttachment();
-        $this->_model->create(helper::getPasteId(), $paste);
+        $paste = Helper::getPasteWithAttachment();
+        $this->_model->create(Helper::getPasteId(), $paste);
         $_GET['jsonld'] = 'comment';
         ob_start();
-        new privatebin;
+        new PrivateBin;
         $content = ob_get_contents();
         ob_end_clean();
         $this->assertEquals(str_replace(
@@ -225,11 +240,11 @@ class jsonApiTest extends PHPUnit_Framework_TestCase
     public function testJsonLdPasteMeta()
     {
         $this->reset();
-        $paste = helper::getPasteWithAttachment();
-        $this->_model->create(helper::getPasteId(), $paste);
+        $paste = Helper::getPasteWithAttachment();
+        $this->_model->create(Helper::getPasteId(), $paste);
         $_GET['jsonld'] = 'pastemeta';
         ob_start();
-        new privatebin;
+        new PrivateBin;
         $content = ob_get_contents();
         ob_end_clean();
         $this->assertEquals(str_replace(
@@ -245,11 +260,11 @@ class jsonApiTest extends PHPUnit_Framework_TestCase
     public function testJsonLdCommentMeta()
     {
         $this->reset();
-        $paste = helper::getPasteWithAttachment();
-        $this->_model->create(helper::getPasteId(), $paste);
+        $paste = Helper::getPasteWithAttachment();
+        $this->_model->create(Helper::getPasteId(), $paste);
         $_GET['jsonld'] = 'commentmeta';
         ob_start();
-        new privatebin;
+        new PrivateBin;
         $content = ob_get_contents();
         ob_end_clean();
         $this->assertEquals(str_replace(
@@ -265,11 +280,11 @@ class jsonApiTest extends PHPUnit_Framework_TestCase
     public function testJsonLdInvalid()
     {
         $this->reset();
-        $paste = helper::getPasteWithAttachment();
-        $this->_model->create(helper::getPasteId(), $paste);
+        $paste = Helper::getPasteWithAttachment();
+        $this->_model->create(Helper::getPasteId(), $paste);
         $_GET['jsonld'] = '../cfg/conf.ini';
         ob_start();
-        new privatebin;
+        new PrivateBin;
         $content = ob_get_contents();
         ob_end_clean();
         $this->assertEquals('{}', $content, 'does not output nasty data');

+ 65 - 65
tst/model.php → tst/ModelTest.php

@@ -1,12 +1,12 @@
 <?php
 
-use PrivateBin\configuration;
-use PrivateBin\data\db;
-use PrivateBin\model;
-use PrivateBin\model\paste;
-use PrivateBin\vizhash16x16;
+use PrivateBin\Configuration;
+use PrivateBin\Data\Database;
+use PrivateBin\Model;
+use PrivateBin\Model\Paste;
+use PrivateBin\Vizhash16x16;
 
-class modelTest extends PHPUnit_Framework_TestCase
+class ModelTest extends PHPUnit_Framework_TestCase
 {
     private $_conf;
 
@@ -15,11 +15,11 @@ class modelTest extends PHPUnit_Framework_TestCase
     public function setUp()
     {
         /* Setup Routine */
-        helper::confRestore();
+        Helper::confRestore();
         $options = parse_ini_file(CONF, true);
         $options['purge']['limit'] = 0;
         $options['model'] = array(
-            'class' => 'privatebin_db',
+            'class' => 'Database',
         );
         $options['model_options'] = array(
             'dsn' => 'sqlite::memory:',
@@ -27,10 +27,10 @@ class modelTest extends PHPUnit_Framework_TestCase
             'pwd' => null,
             'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
         );
-        helper::confBackup();
-        helper::createIniFile(CONF, $options);
-        $this->_conf = new configuration;
-        $this->_model = new model($this->_conf);
+        Helper::confBackup();
+        Helper::createIniFile(CONF, $options);
+        $this->_conf = new Configuration;
+        $this->_model = new Model($this->_conf);
         $_SERVER['REMOTE_ADDR'] = '::1';
     }
 
@@ -42,9 +42,9 @@ class modelTest extends PHPUnit_Framework_TestCase
     public function testBasicWorkflow()
     {
         // storing pastes
-        $pasteData = helper::getPaste();
-        $this->_model->getPaste(helper::getPasteId())->delete();
-        $paste = $this->_model->getPaste(helper::getPasteId());
+        $pasteData = Helper::getPaste();
+        $this->_model->getPaste(Helper::getPasteId())->delete();
+        $paste = $this->_model->getPaste(Helper::getPasteId());
         $this->assertFalse($paste->exists(), 'paste does not yet exist');
 
         $paste = $this->_model->getPaste();
@@ -53,7 +53,7 @@ class modelTest extends PHPUnit_Framework_TestCase
         $paste->setFormatter($pasteData['meta']['formatter']);
         $paste->store();
 
-        $paste = $this->_model->getPaste(helper::getPasteId());
+        $paste = $this->_model->getPaste(Helper::getPasteId());
         $this->assertTrue($paste->exists(), 'paste exists after storing it');
         $paste = $paste->get();
         $this->assertEquals($pasteData['data'], $paste->data);
@@ -62,25 +62,25 @@ class modelTest extends PHPUnit_Framework_TestCase
         }
 
         // storing comments
-        $commentData = helper::getComment();
-        $paste = $this->_model->getPaste(helper::getPasteId());
-        $comment = $paste->getComment(helper::getPasteId(), helper::getCommentId());
+        $commentData = Helper::getComment();
+        $paste = $this->_model->getPaste(Helper::getPasteId());
+        $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId());
         $this->assertFalse($comment->exists(), 'comment does not yet exist');
 
-        $comment = $paste->getComment(helper::getPasteId());
+        $comment = $paste->getComment(Helper::getPasteId());
         $comment->setData($commentData['data']);
         $comment->setNickname($commentData['meta']['nickname']);
         $comment->store();
 
-        $comment = $paste->getComment(helper::getPasteId(), helper::getCommentId());
+        $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId());
         $this->assertTrue($comment->exists(), 'comment exists after storing it');
         $comment = $comment->get();
         $this->assertEquals($commentData['data'], $comment->data);
         $this->assertEquals($commentData['meta']['nickname'], $comment->meta->nickname);
 
         // deleting pastes
-        $this->_model->getPaste(helper::getPasteId())->delete();
-        $paste = $this->_model->getPaste(helper::getPasteId());
+        $this->_model->getPaste(Helper::getPasteId())->delete();
+        $paste = $this->_model->getPaste(Helper::getPasteId());
         $this->assertFalse($paste->exists(), 'paste successfully deleted');
         $this->assertEquals(array(), $paste->getComments(), 'comment was deleted with paste');
     }
@@ -91,9 +91,9 @@ class modelTest extends PHPUnit_Framework_TestCase
      */
     public function testPasteDuplicate()
     {
-        $pasteData = helper::getPaste();
+        $pasteData = Helper::getPaste();
 
-        $this->_model->getPaste(helper::getPasteId())->delete();
+        $this->_model->getPaste(Helper::getPasteId())->delete();
         $paste = $this->_model->getPaste();
         $paste->setData($pasteData['data']);
         $paste->setOpendiscussion();
@@ -113,9 +113,9 @@ class modelTest extends PHPUnit_Framework_TestCase
      */
     public function testCommentDuplicate()
     {
-        $pasteData = helper::getPaste();
-        $commentData = helper::getComment();
-        $this->_model->getPaste(helper::getPasteId())->delete();
+        $pasteData = Helper::getPaste();
+        $commentData = Helper::getComment();
+        $this->_model->getPaste(Helper::getPasteId())->delete();
 
         $paste = $this->_model->getPaste();
         $paste->setData($pasteData['data']);
@@ -123,12 +123,12 @@ class modelTest extends PHPUnit_Framework_TestCase
         $paste->setFormatter($pasteData['meta']['formatter']);
         $paste->store();
 
-        $comment = $paste->getComment(helper::getPasteId());
+        $comment = $paste->getComment(Helper::getPasteId());
         $comment->setData($commentData['data']);
         $comment->setNickname($commentData['meta']['nickname']);
         $comment->store();
 
-        $comment = $paste->getComment(helper::getPasteId());
+        $comment = $paste->getComment(Helper::getPasteId());
         $comment->setData($commentData['data']);
         $comment->setNickname($commentData['meta']['nickname']);
         $comment->store();
@@ -136,9 +136,9 @@ class modelTest extends PHPUnit_Framework_TestCase
 
     public function testImplicitDefaults()
     {
-        $pasteData = helper::getPaste();
-        $commentData = helper::getComment();
-        $this->_model->getPaste(helper::getPasteId())->delete();
+        $pasteData = Helper::getPaste();
+        $commentData = Helper::getComment();
+        $this->_model->getPaste(Helper::getPasteId())->delete();
 
         $paste = $this->_model->getPaste();
         $paste->setData($pasteData['data']);
@@ -147,34 +147,34 @@ class modelTest extends PHPUnit_Framework_TestCase
         // not setting a formatter, should use default one
         $paste->store();
 
-        $paste = $this->_model->getPaste(helper::getPasteId())->get(); // ID was set based on data
+        $paste = $this->_model->getPaste(Helper::getPasteId())->get(); // ID was set based on data
         $this->assertEquals(true, property_exists($paste->meta, 'burnafterreading') && $paste->meta->burnafterreading, 'burn after reading takes precendence');
         $this->assertEquals(false, property_exists($paste->meta, 'opendiscussion') && $paste->meta->opendiscussion, 'opendiscussion is disabled');
         $this->assertEquals($this->_conf->getKey('defaultformatter'), $paste->meta->formatter, 'default formatter is set');
 
-        $this->_model->getPaste(helper::getPasteId())->delete();
+        $this->_model->getPaste(Helper::getPasteId())->delete();
         $paste = $this->_model->getPaste();
         $paste->setData($pasteData['data']);
         $paste->setBurnafterreading('0');
         $paste->setOpendiscussion();
         $paste->store();
 
-        $vz = new vizhash16x16();
+        $vz = new Vizhash16x16();
         $pngdata = 'data:image/png;base64,' . base64_encode($vz->generate($_SERVER['REMOTE_ADDR']));
-        $comment = $paste->getComment(helper::getPasteId());
+        $comment = $paste->getComment(Helper::getPasteId());
         $comment->setData($commentData['data']);
         $comment->setNickname($commentData['meta']['nickname']);
         $comment->store();
 
-        $comment = $paste->getComment(helper::getPasteId(), helper::getCommentId())->get();
+        $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId())->get();
         $this->assertEquals($pngdata, $comment->meta->vizhash, 'nickname triggers vizhash to be set');
     }
 
     public function testPasteIdValidation()
     {
-        $this->assertTrue(paste::isValidId('a242ab7bdfb2581a'), 'valid paste id');
-        $this->assertFalse(paste::isValidId('foo'), 'invalid hex values');
-        $this->assertFalse(paste::isValidId('../bar/baz'), 'path attack');
+        $this->assertTrue(Paste::isValidId('a242ab7bdfb2581a'), 'valid paste id');
+        $this->assertFalse(Paste::isValidId('foo'), 'invalid hex values');
+        $this->assertFalse(Paste::isValidId('../bar/baz'), 'path attack');
     }
 
     /**
@@ -184,14 +184,14 @@ class modelTest extends PHPUnit_Framework_TestCase
     public function testInvalidComment()
     {
         $paste = $this->_model->getPaste();
-        $paste->getComment(helper::getPasteId());
+        $paste->getComment(Helper::getPasteId());
     }
 
     public function testExpiration()
     {
-        $pasteData = helper::getPaste();
-        $this->_model->getPaste(helper::getPasteId())->delete();
-        $paste = $this->_model->getPaste(helper::getPasteId());
+        $pasteData = Helper::getPaste();
+        $this->_model->getPaste(Helper::getPasteId())->delete();
+        $paste = $this->_model->getPaste(Helper::getPasteId());
         $this->assertFalse($paste->exists(), 'paste does not yet exist');
 
         $paste = $this->_model->getPaste();
@@ -209,22 +209,22 @@ class modelTest extends PHPUnit_Framework_TestCase
      */
     public function testCommentDeletion()
     {
-        $pasteData = helper::getPaste();
-        $this->_model->getPaste(helper::getPasteId())->delete();
+        $pasteData = Helper::getPaste();
+        $this->_model->getPaste(Helper::getPasteId())->delete();
 
         $paste = $this->_model->getPaste();
         $paste->setData($pasteData['data']);
         $paste->store();
-        $paste->getComment(helper::getPasteId())->delete();
+        $paste->getComment(Helper::getPasteId())->delete();
     }
 
     public function testPurge()
     {
-        $conf = new configuration;
-        $store = db::getInstance($conf->getSection('model_options'));
-        $store->delete(helper::getPasteId());
-        $expired = helper::getPaste(array('expire_date' => 1344803344));
-        $paste = helper::getPaste(array('expire_date' => time() + 3600));
+        $conf = new Configuration;
+        $store = Database::getInstance($conf->getSection('model_options'));
+        $store->delete(Helper::getPasteId());
+        $expired = Helper::getPaste(array('expire_date' => 1344803344));
+        $paste = Helper::getPaste(array('expire_date' => time() + 3600));
         $keys = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'x', 'y', 'z');
         $ids = array();
         foreach ($keys as $key) {
@@ -262,13 +262,13 @@ class modelTest extends PHPUnit_Framework_TestCase
             'pwd' => null,
             'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
         );
-        helper::confBackup();
-        helper::createIniFile(CONF, $options);
-        $model = new model(new configuration);
+        Helper::confBackup();
+        Helper::createIniFile(CONF, $options);
+        $model = new Model(new Configuration);
 
-        $pasteData = helper::getPaste();
-        $this->_model->getPaste(helper::getPasteId())->delete();
-        $paste = $model->getPaste(helper::getPasteId());
+        $pasteData = Helper::getPaste();
+        $this->_model->getPaste(Helper::getPasteId())->delete();
+        $paste = $model->getPaste(Helper::getPasteId());
         $this->assertFalse($paste->exists(), 'paste does not yet exist');
 
         $paste = $model->getPaste();
@@ -277,7 +277,7 @@ class modelTest extends PHPUnit_Framework_TestCase
         $paste->setFormatter($pasteData['meta']['formatter']);
         $paste->store();
 
-        $paste = $model->getPaste(helper::getPasteId());
+        $paste = $model->getPaste(Helper::getPasteId());
         $this->assertTrue($paste->exists(), 'paste exists after storing it');
         $paste = $paste->get();
         $this->assertEquals($pasteData['data'], $paste->data);
@@ -286,17 +286,17 @@ class modelTest extends PHPUnit_Framework_TestCase
         }
 
         // storing comments
-        $commentData = helper::getComment();
-        $paste = $model->getPaste(helper::getPasteId());
-        $comment = $paste->getComment(helper::getPasteId(), helper::getCommentId());
+        $commentData = Helper::getComment();
+        $paste = $model->getPaste(Helper::getPasteId());
+        $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId());
         $this->assertFalse($comment->exists(), 'comment does not yet exist');
 
-        $comment = $paste->getComment(helper::getPasteId());
+        $comment = $paste->getComment(Helper::getPasteId());
         $comment->setData($commentData['data']);
         $comment->setNickname($commentData['meta']['nickname']);
         $comment->store();
 
-        $comment = $paste->getComment(helper::getPasteId(), helper::getCommentId());
+        $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId());
         $this->assertTrue($comment->exists(), 'comment exists after storing it');
         $comment = $comment->get();
         $this->assertEquals($commentData['data'], $comment->data);

+ 41 - 0
tst/Persistence/PurgeLimiterTest.php

@@ -0,0 +1,41 @@
+<?php
+
+use PrivateBin\Persistence\PurgeLimiter;
+
+class PurgeLimiterTest extends PHPUnit_Framework_TestCase
+{
+    private $_path;
+
+    public function setUp()
+    {
+        /* Setup Routine */
+        $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
+        if (!is_dir($this->_path)) {
+            mkdir($this->_path);
+        }
+        PurgeLimiter::setPath($this->_path);
+    }
+
+    public function tearDown()
+    {
+        /* Tear Down Routine */
+        Helper::rmDir($this->_path);
+    }
+
+    public function testLimit()
+    {
+        // initialize it
+        PurgeLimiter::canPurge();
+
+        // try setting it
+        PurgeLimiter::setLimit(1);
+        $this->assertEquals(false, PurgeLimiter::canPurge());
+        sleep(2);
+        $this->assertEquals(true, PurgeLimiter::canPurge());
+
+        // disable it
+        PurgeLimiter::setLimit(0);
+        PurgeLimiter::canPurge();
+        $this->assertEquals(true, PurgeLimiter::canPurge());
+    }
+}

+ 24 - 21
tst/serversalt.php → tst/Persistence/ServerSaltTest.php

@@ -1,8 +1,8 @@
 <?php
 
-use PrivateBin\serversalt;
+use PrivateBin\Persistence\ServerSalt;
 
-class serversaltTest extends PHPUnit_Framework_TestCase
+class ServerSaltTest extends PHPUnit_Framework_TestCase
 {
     private $_path;
 
@@ -15,11 +15,11 @@ class serversaltTest extends PHPUnit_Framework_TestCase
     public function setUp()
     {
         /* Setup Routine */
-        $this->_path = PATH . 'data';
+        $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
         if (!is_dir($this->_path)) {
             mkdir($this->_path);
         }
-        serversalt::setPath($this->_path);
+        ServerSalt::setPath($this->_path);
 
         $this->_otherPath = $this->_path . DIRECTORY_SEPARATOR . 'foo';
 
@@ -34,14 +34,14 @@ class serversaltTest extends PHPUnit_Framework_TestCase
     {
         /* Tear Down Routine */
         chmod($this->_invalidPath, 0700);
-        helper::rmdir($this->_path);
+        Helper::rmDir($this->_path);
     }
 
     public function testGeneration()
     {
         // generating new salt
-        serversalt::setPath($this->_path);
-        $salt = serversalt::get();
+        ServerSalt::setPath($this->_path);
+        $salt = ServerSalt::get();
 
         // mcrypt mock
         if (!function_exists('mcrypt_create_iv')) {
@@ -60,14 +60,14 @@ class serversaltTest extends PHPUnit_Framework_TestCase
                 }
                 return hex2bin($randomSalt);
             }
-            $this->assertNotEquals($salt, serversalt::generate());
+            $this->assertNotEquals($salt, ServerSalt::generate());
         }
 
         // try setting a different path and resetting it
-        serversalt::setPath($this->_otherPath);
-        $this->assertNotEquals($salt, serversalt::get());
-        serversalt::setPath($this->_path);
-        $this->assertEquals($salt, serversalt::get());
+        ServerSalt::setPath($this->_otherPath);
+        $this->assertNotEquals($salt, ServerSalt::get());
+        ServerSalt::setPath($this->_path);
+        $this->assertEquals($salt, ServerSalt::get());
     }
 
     /**
@@ -78,8 +78,8 @@ class serversaltTest extends PHPUnit_Framework_TestCase
     {
         // try setting an invalid path
         chmod($this->_invalidPath, 0000);
-        serversalt::setPath($this->_invalidPath);
-        serversalt::get();
+        ServerSalt::setPath($this->_invalidPath);
+        ServerSalt::get();
     }
 
     /**
@@ -92,8 +92,8 @@ class serversaltTest extends PHPUnit_Framework_TestCase
         chmod($this->_invalidPath, 0700);
         file_put_contents($this->_invalidFile, '');
         chmod($this->_invalidFile, 0000);
-        serversalt::setPath($this->_invalidPath);
-        serversalt::get();
+        ServerSalt::setPath($this->_invalidPath);
+        ServerSalt::get();
     }
 
     /**
@@ -104,11 +104,14 @@ class serversaltTest extends PHPUnit_Framework_TestCase
     {
         // try setting an invalid file
         chmod($this->_invalidPath, 0700);
-        @unlink($this->_invalidFile);
+        if (is_file($this->_invalidFile)) {
+            chmod($this->_invalidFile, 0600);
+            unlink($this->_invalidFile);
+        }
         file_put_contents($this->_invalidPath . DIRECTORY_SEPARATOR . '.htaccess', '');
         chmod($this->_invalidPath, 0500);
-        serversalt::setPath($this->_invalidPath);
-        serversalt::get();
+        ServerSalt::setPath($this->_invalidPath);
+        ServerSalt::get();
     }
 
     /**
@@ -119,7 +122,7 @@ class serversaltTest extends PHPUnit_Framework_TestCase
     {
         // try creating an invalid path
         chmod($this->_invalidPath, 0000);
-        serversalt::setPath($this->_invalidPath . DIRECTORY_SEPARATOR . 'baz');
-        serversalt::get();
+        ServerSalt::setPath($this->_invalidPath . DIRECTORY_SEPARATOR . 'baz');
+        ServerSalt::get();
     }
 }

+ 12 - 12
tst/trafficlimiter.php → tst/Persistence/TrafficLimiterTest.php

@@ -1,8 +1,8 @@
 <?php
 
-use PrivateBin\trafficlimiter;
+use PrivateBin\Persistence\TrafficLimiter;
 
-class trafficlimiterTest extends PHPUnit_Framework_TestCase
+class TrafficLimiterTest extends PHPUnit_Framework_TestCase
 {
     private $_path;
 
@@ -10,30 +10,30 @@ class trafficlimiterTest extends PHPUnit_Framework_TestCase
     {
         /* Setup Routine */
         $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'trafficlimit';
-        trafficlimiter::setPath($this->_path);
+        TrafficLimiter::setPath($this->_path);
     }
 
     public function tearDown()
     {
         /* Tear Down Routine */
-        helper::rmdir($this->_path . DIRECTORY_SEPARATOR);
+        Helper::rmDir($this->_path . DIRECTORY_SEPARATOR);
     }
 
     public function testTrafficGetsLimited()
     {
-        $this->assertEquals($this->_path, trafficlimiter::getPath());
+        $this->assertEquals($this->_path, TrafficLimiter::getPath());
         $file = 'baz';
-        $this->assertEquals($this->_path . DIRECTORY_SEPARATOR . $file, trafficlimiter::getPath($file));
-        trafficlimiter::setLimit(4);
+        $this->assertEquals($this->_path . DIRECTORY_SEPARATOR . $file, TrafficLimiter::getPath($file));
+        TrafficLimiter::setLimit(4);
         $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
-        $this->assertTrue(trafficlimiter::canPass(), 'first request may pass');
+        $this->assertTrue(TrafficLimiter::canPass(), 'first request may pass');
         sleep(1);
-        $this->assertFalse(trafficlimiter::canPass(), 'second request is to fast, may not pass');
+        $this->assertFalse(TrafficLimiter::canPass(), 'second request is to fast, may not pass');
         sleep(4);
-        $this->assertTrue(trafficlimiter::canPass(), 'third request waited long enough and may pass');
+        $this->assertTrue(TrafficLimiter::canPass(), 'third request waited long enough and may pass');
         $_SERVER['REMOTE_ADDR'] = '2001:1620:2057:dead:beef::cafe:babe';
-        $this->assertTrue(trafficlimiter::canPass(), 'fourth request has different ip and may pass');
+        $this->assertTrue(TrafficLimiter::canPass(), 'fourth request has different ip and may pass');
         $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
-        $this->assertFalse(trafficlimiter::canPass(), 'fifth request is to fast, may not pass');
+        $this->assertFalse(TrafficLimiter::canPass(), 'fifth request is to fast, may not pass');
     }
 }

Різницю між файлами не показано, бо вона завелика
+ 223 - 214
tst/PrivateBinTest.php


+ 13 - 19
tst/privatebinWithDb.php → tst/PrivateBinWithDbTest.php

@@ -1,13 +1,13 @@
 <?php
 
-use PrivateBin\data\db;
-use PrivateBin\privatebin;
-use PrivateBin\serversalt;
-use PrivateBin\trafficlimiter;
+use PrivateBin\Data\Database;
+use PrivateBin\PrivateBin;
+use PrivateBin\Persistence\ServerSalt;
+use PrivateBin\Persistence\TrafficLimiter;
 
-require_once 'privatebin.php';
+require_once 'PrivateBinTest.php';
 
-class privatebinWithDbTest extends privatebinTest
+class PrivateBinWithDbTest extends PrivateBinTest
 {
     private $_options = array(
         'usr' => null,
@@ -18,8 +18,6 @@ class privatebinWithDbTest extends privatebinTest
         ),
     );
 
-    private $_path;
-
     public function setUp()
     {
         /* Setup Routine */
@@ -27,28 +25,24 @@ class privatebinWithDbTest extends privatebinTest
         if (!is_dir($this->_path)) {
             mkdir($this->_path);
         }
+        ServerSalt::setPath($this->_path);
         $this->_options['dsn'] = 'sqlite:' . $this->_path . DIRECTORY_SEPARATOR . 'tst.sq3';
-        $this->_model = db::getInstance($this->_options);
+        $this->_model = Database::getInstance($this->_options);
         $this->reset();
     }
 
-    public function tearDown()
-    {
-        /* Tear Down Routine */
-        parent::tearDown();
-        helper::rmdir($this->_path);
-    }
-
     public function reset()
     {
         parent::reset();
         // but then inject a db config
         $options = parse_ini_file(CONF, true);
         $options['model'] = array(
-            'class' => 'privatebin_db',
+            'class' => 'Database',
         );
+        $options['purge']['dir'] = $this->_path;
+        $options['traffic']['dir'] = $this->_path;
         $options['model_options'] = $this->_options;
-        helper::confBackup();
-        helper::createIniFile(CONF, $options);
+        Helper::confBackup();
+        Helper::createIniFile(CONF, $options);
     }
 }

+ 14 - 14
tst/request.php → tst/RequestTest.php

@@ -1,8 +1,8 @@
 <?php
 
-use PrivateBin\request;
+use PrivateBin\Request;
 
-class requestTest extends PHPUnit_Framework_TestCase
+class RequestTest extends PHPUnit_Framework_TestCase
 {
     public function setUp()
     {
@@ -25,7 +25,7 @@ class requestTest extends PHPUnit_Framework_TestCase
     {
         $this->reset();
         $_SERVER['REQUEST_METHOD'] = 'GET';
-        $request = new request;
+        $request = new Request;
         $this->assertFalse($request->isJsonApiCall(), 'is HTML call');
         $this->assertEquals('view', $request->getOperation());
     }
@@ -35,7 +35,7 @@ class requestTest extends PHPUnit_Framework_TestCase
         $this->reset();
         $_SERVER['REQUEST_METHOD'] = 'GET';
         $_SERVER['QUERY_STRING'] = 'foo';
-        $request = new request;
+        $request = new Request;
         $this->assertFalse($request->isJsonApiCall(), 'is HTML call');
         $this->assertEquals('foo', $request->getParam('pasteid'));
         $this->assertEquals('read', $request->getOperation());
@@ -47,7 +47,7 @@ class requestTest extends PHPUnit_Framework_TestCase
         $_SERVER['REQUEST_METHOD'] = 'GET';
         $_GET['pasteid'] = 'foo';
         $_GET['deletetoken'] = 'bar';
-        $request = new request;
+        $request = new Request;
         $this->assertFalse($request->isJsonApiCall(), 'is HTML call');
         $this->assertEquals('delete', $request->getOperation());
         $this->assertEquals('foo', $request->getParam('pasteid'));
@@ -61,8 +61,8 @@ class requestTest extends PHPUnit_Framework_TestCase
         $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
         $file = tempnam(sys_get_temp_dir(), 'FOO');
         file_put_contents($file, 'data=foo');
-        request::setInputStream($file);
-        $request = new request;
+        Request::setInputStream($file);
+        $request = new Request;
         $this->assertTrue($request->isJsonApiCall(), 'is JSON Api call');
         $this->assertEquals('create', $request->getOperation());
         $this->assertEquals('foo', $request->getParam('data'));
@@ -74,7 +74,7 @@ class requestTest extends PHPUnit_Framework_TestCase
         $_SERVER['REQUEST_METHOD'] = 'POST';
         $_SERVER['HTTP_ACCEPT'] = 'application/json, text/javascript, */*; q=0.01';
         $_POST['attachment'] = 'foo';
-        $request = new request;
+        $request = new Request;
         $this->assertTrue($request->isJsonApiCall(), 'is JSON Api call');
         $this->assertEquals('create', $request->getOperation());
         $this->assertEquals('foo', $request->getParam('attachment'));
@@ -86,7 +86,7 @@ class requestTest extends PHPUnit_Framework_TestCase
         $_SERVER['REQUEST_METHOD'] = 'GET';
         $_SERVER['HTTP_ACCEPT'] = 'application/json, text/javascript, */*; q=0.01';
         $_SERVER['QUERY_STRING'] = 'foo';
-        $request = new request;
+        $request = new Request;
         $this->assertTrue($request->isJsonApiCall(), 'is JSON Api call');
         $this->assertEquals('foo', $request->getParam('pasteid'));
         $this->assertEquals('read', $request->getOperation());
@@ -99,7 +99,7 @@ class requestTest extends PHPUnit_Framework_TestCase
         $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
         $_SERVER['QUERY_STRING'] = 'foo';
         $_POST['deletetoken'] = 'bar';
-        $request = new request;
+        $request = new Request;
         $this->assertTrue($request->isJsonApiCall(), 'is JSON Api call');
         $this->assertEquals('delete', $request->getOperation());
         $this->assertEquals('foo', $request->getParam('pasteid'));
@@ -112,7 +112,7 @@ class requestTest extends PHPUnit_Framework_TestCase
         $_SERVER['REQUEST_METHOD'] = 'GET';
         $_SERVER['HTTP_ACCEPT'] = 'text/html,text/html; charset=UTF-8,application/xhtml+xml, application/xml;q=0.9,*/*;q=0.8, text/csv,application/json';
         $_SERVER['QUERY_STRING'] = 'foo';
-        $request = new request;
+        $request = new Request;
         $this->assertFalse($request->isJsonApiCall(), 'is HTML call');
         $this->assertEquals('foo', $request->getParam('pasteid'));
         $this->assertEquals('read', $request->getOperation());
@@ -124,7 +124,7 @@ class requestTest extends PHPUnit_Framework_TestCase
         $_SERVER['REQUEST_METHOD'] = 'GET';
         $_SERVER['HTTP_ACCEPT'] = 'application/xhtml+xml,text/html,text/html; charset=UTF-8, application/xml;q=0.9,*/*;q=0.8, text/csv,application/json';
         $_SERVER['QUERY_STRING'] = 'foo';
-        $request = new request;
+        $request = new Request;
         $this->assertFalse($request->isJsonApiCall(), 'is HTML call');
         $this->assertEquals('foo', $request->getParam('pasteid'));
         $this->assertEquals('read', $request->getOperation());
@@ -136,7 +136,7 @@ class requestTest extends PHPUnit_Framework_TestCase
         $_SERVER['REQUEST_METHOD'] = 'GET';
         $_SERVER['HTTP_ACCEPT'] = 'text/plain,text/csv, application/xml;q=0.9, application/json, text/html,text/html; charset=UTF-8,application/xhtml+xml, */*;q=0.8';
         $_SERVER['QUERY_STRING'] = 'foo';
-        $request = new request;
+        $request = new Request;
         $this->assertTrue($request->isJsonApiCall(), 'is JSON Api call');
         $this->assertEquals('foo', $request->getParam('pasteid'));
         $this->assertEquals('read', $request->getOperation());
@@ -148,7 +148,7 @@ class requestTest extends PHPUnit_Framework_TestCase
         $_SERVER['REQUEST_METHOD'] = 'GET';
         $_SERVER['HTTP_ACCEPT'] = 'text/plain,text/csv, application/xml;q=0.9, */*;q=0.8';
         $_SERVER['QUERY_STRING'] = 'foo';
-        $request = new request;
+        $request = new Request;
         $this->assertFalse($request->isJsonApiCall(), 'is HTML call');
         $this->assertEquals('foo', $request->getParam('pasteid'));
         $this->assertEquals('read', $request->getOperation());

+ 21 - 20
tst/sjcl.php → tst/SjclTest.php

@@ -1,30 +1,31 @@
 <?php
 
-use PrivateBin\sjcl;
+use PrivateBin\Sjcl;
 
-class sjclTest extends PHPUnit_Framework_TestCase
+class SjclTest extends PHPUnit_Framework_TestCase
 {
     public function testSjclValidatorValidatesCorrectly()
     {
-        $paste = helper::getPasteWithAttachment();
-        $this->assertTrue(sjcl::isValid($paste['data']), 'valid sjcl');
-        $this->assertTrue(sjcl::isValid($paste['attachment']), 'valid sjcl');
-        $this->assertTrue(sjcl::isValid($paste['attachmentname']), 'valid sjcl');
-        $this->assertTrue(sjcl::isValid(helper::getComment()['data']), 'valid sjcl');
+        $paste = Helper::getPasteWithAttachment();
+        $this->assertTrue(Sjcl::isValid($paste['data']), 'valid sjcl');
+        $this->assertTrue(Sjcl::isValid($paste['attachment']), 'valid sjcl');
+        $this->assertTrue(Sjcl::isValid($paste['attachmentname']), 'valid sjcl');
+        $this->assertTrue(Sjcl::isValid(Helper::getComment()['data']), 'valid sjcl');
 
-        $this->assertTrue(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'valid sjcl');
-        $this->assertFalse(sjcl::isValid('{"iv":"$","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of iv');
-        $this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"$","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of salt');
-        $this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","salt":"Gx1vA2/gQ3U","ct":"$"}'), 'invalid base64 encoding of ct');
-        $this->assertFalse(sjcl::isValid('{"iv":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'iv to long');
-        $this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'salt to long');
-        $this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA","foo":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA="}'), 'invalid additional key');
-        $this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":0.9,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'unsupported version');
-        $this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":100,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'not enough iterations');
-        $this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":127,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid key size');
-        $this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":63,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid tag length');
-        $this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"!#@","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid mode');
-        $this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"!#@","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid cipher');
+        $this->assertTrue(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'valid sjcl');
+        $this->assertFalse(Sjcl::isValid('{"iv":"$","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of iv');
+        $this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"$","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of salt');
+        $this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"$"}'), 'invalid base64 encoding of ct');
+        $this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"bm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhCg=="}'), 'low ct entropy');
+        $this->assertFalse(Sjcl::isValid('{"iv":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'iv to long');
+        $this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'salt to long');
+        $this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA","foo":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA="}'), 'invalid additional key');
+        $this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":0.9,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'unsupported version');
+        $this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":100,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'not enough iterations');
+        $this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":127,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid key size');
+        $this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":63,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid tag length');
+        $this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"!#@","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid mode');
+        $this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"!#@","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid cipher');
         // @note adata is not validated, except as part of the total message length
     }
 }

+ 6 - 6
tst/view.php → tst/ViewTest.php

@@ -1,9 +1,9 @@
 <?php
 
-use PrivateBin\i18n;
-use PrivateBin\view;
+use PrivateBin\I18n;
+use PrivateBin\View;
 
-class viewTest extends PHPUnit_Framework_TestCase
+class ViewTest extends PHPUnit_Framework_TestCase
 {
     private static $error = 'foo bar';
 
@@ -32,7 +32,7 @@ class viewTest extends PHPUnit_Framework_TestCase
     public function setUp()
     {
         /* Setup Routine */
-        $page = new view;
+        $page = new View;
         $page->assign('CIPHERDATA', helper::getPaste()['data']);
         $page->assign('ERROR', self::$error);
         $page->assign('STATUS', self::$status);
@@ -50,7 +50,7 @@ class viewTest extends PHPUnit_Framework_TestCase
         $page->assign('BASE64JSVERSION', '2.1.9');
         $page->assign('NOTICE', 'example');
         $page->assign('LANGUAGESELECTION', '');
-        $page->assign('LANGUAGES', i18n::getLanguageLabels(i18n::getAvailableLanguages()));
+        $page->assign('LANGUAGES', I18n::getLanguageLabels(i18n::getAvailableLanguages()));
         $page->assign('EXPIRE', self::$expire);
         $page->assign('EXPIREDEFAULT', self::$expire_default);
         $page->assign('EXPIRECLONE', true);
@@ -109,7 +109,7 @@ class viewTest extends PHPUnit_Framework_TestCase
      */
     public function testMissingTemplate()
     {
-        $test = new view;
+        $test = new View;
         $test->draw('123456789 does not exist!');
     }
 }

+ 7 - 10
tst/vizhash16x16.php → tst/Vizhash16x16Test.php

@@ -1,9 +1,9 @@
 <?php
 
-use PrivateBin\serversalt;
-use PrivateBin\vizhash16x16;
+use PrivateBin\Persistence\ServerSalt;
+use PrivateBin\Vizhash16x16;
 
-class vizhash16x16Test extends PHPUnit_Framework_TestCase
+class Vizhash16x16Test extends PHPUnit_Framework_TestCase
 {
     private $_file;
 
@@ -12,27 +12,24 @@ class vizhash16x16Test extends PHPUnit_Framework_TestCase
     public function setUp()
     {
         /* Setup Routine */
-        $this->_path = PATH . 'data';
+        $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
         if (!is_dir($this->_path)) {
             mkdir($this->_path);
         }
         $this->_file = $this->_path . DIRECTORY_SEPARATOR . 'vizhash.png';
-        serversalt::setPath($this->_path);
+        ServerSalt::setPath($this->_path);
     }
 
     public function tearDown()
     {
         /* Tear Down Routine */
         chmod($this->_path, 0700);
-        if (!@unlink($this->_file)) {
-            throw new Exception('Error deleting file "' . $this->_file . '".');
-        }
-        helper::rmdir($this->_path);
+        Helper::rmDir($this->_path);
     }
 
     public function testVizhashGeneratesUniquePngsPerIp()
     {
-        $vz = new vizhash16x16();
+        $vz = new Vizhash16x16();
         $pngdata = $vz->generate('127.0.0.1');
         file_put_contents($this->_file, $pngdata);
         $finfo = new finfo(FILEINFO_MIME_TYPE);

+ 0 - 81
tst/filter.php

@@ -1,81 +0,0 @@
-<?php
-
-use PrivateBin\filter;
-
-class filterTest extends PHPUnit_Framework_TestCase
-{
-    public function testFilterStripsSlashesDeeply()
-    {
-        $this->assertEquals(
-            array("f'oo", "b'ar", array("fo'o", "b'ar")),
-            filter::stripslashes_deep(array("f\\'oo", "b\\'ar", array("fo\\'o", "b\\'ar")))
-        );
-    }
-
-    public function testFilterMakesTimesHumanlyReadable()
-    {
-        $this->assertEquals('5 minutes', filter::time_humanreadable('5min'));
-        $this->assertEquals('90 seconds', filter::time_humanreadable('90sec'));
-        $this->assertEquals('1 week', filter::time_humanreadable('1week'));
-        $this->assertEquals('6 months', filter::time_humanreadable('6months'));
-    }
-
-    /**
-     * @expectedException Exception
-     * @expectedExceptionCode 30
-     */
-    public function testFilterFailTimesHumanlyReadable()
-    {
-        filter::time_humanreadable('five_minutes');
-    }
-
-    public function testFilterMakesSizesHumanlyReadable()
-    {
-        $this->assertEquals('1 B', filter::size_humanreadable(1));
-        $this->assertEquals('1 000 B', filter::size_humanreadable(1000));
-        $this->assertEquals('1.00 KiB', filter::size_humanreadable(1024));
-        $this->assertEquals('1.21 KiB', filter::size_humanreadable(1234));
-        $exponent = 1024;
-        $this->assertEquals('1 000.00 KiB', filter::size_humanreadable(1000 * $exponent));
-        $this->assertEquals('1.00 MiB', filter::size_humanreadable(1024 * $exponent));
-        $this->assertEquals('1.21 MiB', filter::size_humanreadable(1234 * $exponent));
-        $exponent *= 1024;
-        $this->assertEquals('1 000.00 MiB', filter::size_humanreadable(1000 * $exponent));
-        $this->assertEquals('1.00 GiB', filter::size_humanreadable(1024 * $exponent));
-        $this->assertEquals('1.21 GiB', filter::size_humanreadable(1234 * $exponent));
-        $exponent *= 1024;
-        $this->assertEquals('1 000.00 GiB', filter::size_humanreadable(1000 * $exponent));
-        $this->assertEquals('1.00 TiB', filter::size_humanreadable(1024 * $exponent));
-        $this->assertEquals('1.21 TiB', filter::size_humanreadable(1234 * $exponent));
-        $exponent *= 1024;
-        $this->assertEquals('1 000.00 TiB', filter::size_humanreadable(1000 * $exponent));
-        $this->assertEquals('1.00 PiB', filter::size_humanreadable(1024 * $exponent));
-        $this->assertEquals('1.21 PiB', filter::size_humanreadable(1234 * $exponent));
-        $exponent *= 1024;
-        $this->assertEquals('1 000.00 PiB', filter::size_humanreadable(1000 * $exponent));
-        $this->assertEquals('1.00 EiB', filter::size_humanreadable(1024 * $exponent));
-        $this->assertEquals('1.21 EiB', filter::size_humanreadable(1234 * $exponent));
-        $exponent *= 1024;
-        $this->assertEquals('1 000.00 EiB', filter::size_humanreadable(1000 * $exponent));
-        $this->assertEquals('1.00 ZiB', filter::size_humanreadable(1024 * $exponent));
-        $this->assertEquals('1.21 ZiB', filter::size_humanreadable(1234 * $exponent));
-        $exponent *= 1024;
-        $this->assertEquals('1 000.00 ZiB', filter::size_humanreadable(1000 * $exponent));
-        $this->assertEquals('1.00 YiB', filter::size_humanreadable(1024 * $exponent));
-        $this->assertEquals('1.21 YiB', filter::size_humanreadable(1234 * $exponent));
-    }
-
-    public function testSlowEquals()
-    {
-        $this->assertTrue(filter::slow_equals('foo', 'foo'), 'same string');
-        $this->assertFalse(filter::slow_equals('foo', true), 'string and boolean');
-        $this->assertFalse(filter::slow_equals('foo', 0), 'string and integer');
-        $this->assertFalse(filter::slow_equals('123foo', 123), 'string and integer');
-        $this->assertFalse(filter::slow_equals('123foo', '123'), 'different strings');
-        $this->assertFalse(filter::slow_equals('6', ' 6'), 'strings with space');
-        $this->assertFalse(filter::slow_equals('4.2', '4.20'), 'floats as strings');
-        $this->assertFalse(filter::slow_equals('1e3', '1000'), 'integers as strings');
-        $this->assertFalse(filter::slow_equals('9223372036854775807', '9223372036854775808'), 'large integers as strings');
-        $this->assertFalse(filter::slow_equals('61529519452809720693702583126814', '61529519452809720000000000000000'), 'larger integers as strings');
-    }
-}

+ 3 - 3
tst/phpunit.xml

@@ -1,13 +1,13 @@
-<phpunit bootstrap="bootstrap.php" colors="true">
+<phpunit bootstrap="Bootstrap.php" colors="true">
 	<testsuite name="PrivateBin Test Suite">
 		<directory suffix=".php">./</directory>
-		<exclude>configGenerator.php</exclude>
+		<exclude>ConfigurationTestGenerator.php</exclude>
 	</testsuite>
 	<filter>
 		<whitelist>
 			<directory suffix=".php">../lib</directory>
 			<exclude>
-				<file>../lib/data/AbstractData.php</file>
+				<file>../lib/Data/AbstractData.php</file>
 			</exclude>
 		</whitelist>
 	</filter>

+ 0 - 41
tst/purgelimiter.php

@@ -1,41 +0,0 @@
-<?php
-
-use PrivateBin\purgelimiter;
-
-class purgelimiterTest extends PHPUnit_Framework_TestCase
-{
-    private $_path;
-
-    public function setUp()
-    {
-        /* Setup Routine */
-        $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
-        if (!is_dir($this->_path)) {
-            mkdir($this->_path);
-        }
-        purgelimiter::setPath($this->_path);
-    }
-
-    public function tearDown()
-    {
-        /* Tear Down Routine */
-        helper::rmdir($this->_path);
-    }
-
-    public function testLimit()
-    {
-        // initialize it
-        purgelimiter::canPurge();
-
-        // try setting it
-        purgelimiter::setLimit(1);
-        $this->assertEquals(false, purgelimiter::canPurge());
-        sleep(2);
-        $this->assertEquals(true, purgelimiter::canPurge());
-
-        // disable it
-        purgelimiter::setLimit(0);
-        purgelimiter::canPurge();
-        $this->assertEquals(true, purgelimiter::canPurge());
-    }
-}

+ 0 - 49
tst/test.ini

@@ -1,49 +0,0 @@
-[main]
-discussion = true
-opendiscussion = true
-syntaxhighlighting = true
-burnafterreadingselected = true
-password = true
-sizelimit = 10
-template = "page"
-base64version = "2.1.9"
-syntaxhighlightingtheme = "sons-of-obsidian"
-
-[expire]
-default = "1week"
-
-[expire_options]
-5min = "300"
-10min = "600"
-1hour = "3600"
-1day = "86400"
-1week = "604800"
-1month = "2592000"
-1year = "31536000"
-never = "0"
-
-[expire_labels]
-5min = "5 minutes"
-10min = "10 minutes"
-1hour = "1 hour"
-1day = "1 day"
-1week = "1 week"
-1month = "1 month"
-1year = "1 year"
-never = "Never"
-
-[traffic]
-limit = 0
-dir = "../data"
-
-[model]
-class = "privatebin_db"
-
-[model_options]
-dsn = "sqlite:../data/db.sq3"
-usr = ""
-pwd = ""
-opt = array (
-  12 => '1',
-)
-

Деякі файли не було показано, через те що забагато файлів було змінено