diff --git a/.gitattributes b/.gitattributes index 096de3d..9c8fa78 100644 --- a/.gitattributes +++ b/.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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d3f586..a1fe6fb 100644 --- a/CHANGELOG.md +++ b/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 diff --git a/CREDITS.md b/CREDITS.md index 20c9dfe..7460a2c 100644 --- a/CREDITS.md +++ b/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 diff --git a/cfg/conf.ini.sample b/cfg/conf.ini.sample index 81339ed..10fd56d 100644 --- a/cfg/conf.ini.sample +++ b/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 diff --git a/index.php b/index.php index ec40497..14553f9 100644 --- a/index.php +++ b/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; diff --git a/lib/configuration.php b/lib/Configuration.php similarity index 93% rename from lib/configuration.php rename to lib/Configuration.php index b80b147..15c35a1 100644 --- a/lib/configuration.php +++ b/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]; } diff --git a/lib/data/AbstractData.php b/lib/Data/AbstractData.php similarity index 99% rename from lib/data/AbstractData.php rename to lib/Data/AbstractData.php index 6f99f3d..5631d87 100644 --- a/lib/data/AbstractData.php +++ b/lib/Data/AbstractData.php @@ -10,7 +10,7 @@ * @version 0.22 */ -namespace PrivateBin\data; +namespace PrivateBin\Data; /** * privatebin_abstract diff --git a/lib/data/db.php b/lib/Data/Database.php similarity index 98% rename from lib/data/db.php rename to lib/Data/Database.php index 0c572ea..f5aa8be 100644 --- a/lib/data/db.php +++ b/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) ); } diff --git a/lib/data/data.php b/lib/Data/Filesystem.php similarity index 87% rename from lib/data/data.php rename to lib/Data/Filesystem.php index 4482638..60b15d4 100644 --- a/lib/data/data.php +++ b/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); - - // 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); - } + $pastedir = self::_dataid2path($pasteid); + if (is_dir($pastedir)) { + // Delete the paste itself. + if (is_file($pastedir . $pasteid)) { + unlink($pastedir . $pasteid); } - $dir->close(); - // Delete the discussion directory. - @rmdir($discdir); + // 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); + } } } @@ -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')) { diff --git a/lib/filter.php b/lib/Filter.php similarity index 84% rename from lib/filter.php rename to lib/Filter.php index 06af9c2..568f124 100644 --- a/lib/filter.php +++ b/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++) { diff --git a/lib/i18n.php b/lib/I18n.php similarity index 99% rename from lib/i18n.php rename to lib/I18n.php index 6a9a8dc..4a4fc3a 100644 --- a/lib/i18n.php +++ b/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()); } /** diff --git a/lib/model.php b/lib/Model.php similarity index 74% rename from lib/model.php rename to lib/Model.php index de79bb3..0a39f68 100644 --- a/lib/model.php +++ b/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') ); } diff --git a/lib/model/AbstractModel.php b/lib/Model/AbstractModel.php similarity index 96% rename from lib/model/AbstractModel.php rename to lib/Model/AbstractModel.php index af834f4..767e7d1 100644 --- a/lib/model/AbstractModel.php +++ b/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. */ diff --git a/lib/model/comment.php b/lib/Model/Comment.php similarity index 91% rename from lib/model/comment.php rename to lib/Model/Comment.php index 786a7ba..7ea08e5 100644 --- a/lib/model/comment.php +++ b/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); } diff --git a/lib/model/paste.php b/lib/Model/Paste.php similarity index 94% rename from lib/model/paste.php rename to lib/Model/Paste.php index e18211e..180d74b 100644 --- a/lib/model/paste.php +++ b/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; diff --git a/lib/persistence.php b/lib/Persistence/AbstractPersistence.php similarity index 97% rename from lib/persistence.php rename to lib/Persistence/AbstractPersistence.php index e42f117..a888089 100644 --- a/lib/persistence.php +++ b/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 diff --git a/lib/purgelimiter.php b/lib/Persistence/PurgeLimiter.php similarity index 86% rename from lib/purgelimiter.php rename to lib/Persistence/PurgeLimiter.php index 8261b9a..c76a4d9 100644 --- a/lib/purgelimiter.php +++ b/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')); diff --git a/lib/serversalt.php b/lib/Persistence/ServerSalt.php similarity index 85% rename from lib/serversalt.php rename to lib/Persistence/ServerSalt.php index 60a9930..a8a6614 100644 --- a/lib/serversalt.php +++ b/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, - '' + '' ); } return self::$_salt; diff --git a/lib/trafficlimiter.php b/lib/Persistence/TrafficLimiter.php similarity index 91% rename from lib/trafficlimiter.php rename to lib/Persistence/TrafficLimiter.php index 0c49a66..36c7025 100644 --- a/lib/trafficlimiter.php +++ b/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)) { diff --git a/lib/privatebin.php b/lib/PrivateBin.php similarity index 90% rename from lib/privatebin.php rename to lib/PrivateBin.php index d2a70b9..e4d91e8 100644 --- a/lib/privatebin.php +++ b/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); diff --git a/lib/request.php b/lib/Request.php similarity index 94% rename from lib/request.php rename to lib/Request.php index fec1054..90e1744 100644 --- a/lib/request.php +++ b/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 diff --git a/lib/sjcl.php b/lib/Sjcl.php similarity index 99% rename from lib/sjcl.php rename to lib/Sjcl.php index 2d2981f..5b62681 100644 --- a/lib/sjcl.php +++ b/lib/Sjcl.php @@ -13,11 +13,11 @@ namespace PrivateBin; /** - * sjcl + * Sjcl * * Provides SJCL validation function. */ -class sjcl +class Sjcl { /** * SJCL validator diff --git a/lib/view.php b/lib/View.php similarity index 98% rename from lib/view.php rename to lib/View.php index d420e75..1876ac4 100644 --- a/lib/view.php +++ b/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 diff --git a/lib/vizhash16x16.php b/lib/Vizhash16x16.php similarity index 97% rename from lib/vizhash16x16.php rename to lib/Vizhash16x16.php index 54e4cfd..53f0346 100644 --- a/lib/vizhash16x16.php +++ b/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(); } /** diff --git a/tpl/bootstrap-compact.php b/tpl/bootstrap-compact.php index c2858e1..9c895bc 100644 --- a/tpl/bootstrap-compact.php +++ b/tpl/bootstrap-compact.php @@ -1,32 +1,46 @@ - +
-