diff --git a/.gitignore b/.gitignore index 0323182..8172e1c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,12 @@ -# Ignore data/, tmp/ and vendor/ -data/ -!lib/data/ -tmp/ -vendor/ # Ignore for safety .htaccess .htpasswd +# Ignore data/ and vendor/ +data/ +vendor/ # Ignore unit testing logs, api docs and eclipse project files -tst/log/ doc/ -composer.lock +tst/log/ .settings .buildpath .project diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b2c0bd..7ebaef2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ * ADDED: re-introduced URL shortener support (optional), which was removed back in version 0.16 for privacy concerns * ADDED: Preview tab, helpful for writing markdown code or check source code rendering * ADDED: Automatic purging of expired pastes, done on paste creation - * ADDED: Option to disable vizhashs in discussions (will only affect newly created pastes) + * ADDED: Option to disable icons in discussions (will only affect newly created pastes) * ADDED: Composer support * CHANGED: Renamed the ZeroBin fork to PrivateBin * CHANGED: Removed unmaintained RainTPL template engine, replacing the templates with straight forward PHP files @@ -14,7 +14,9 @@ * 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: Introduced content security policy header to reduce cross site scripting (XSS) risks - * CHANGED: Refactored PHP code to conform to PSR-4 and PSR-2 standards. + * CHANGED: Refactored PHP code to conform to PSR-4 and PSR-2 standards + * CHANGED: Switched to Identicons as the default for comments with nicknames + * CHANGED: Vizhash is now optional and based on (128 byte) SHA512 HMAC instead of (144 bytes) combination of MD5, SHA1 and a reversal of that string * 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/LICENSE.md b/LICENSE.md index 2e7e76f..4d4f243 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -4,8 +4,9 @@ PrivateBin consists of PHP and JS code which was originally written by Sébastie Sauvage in 2012 and falls unter the Zlib/libpng license. Also included are libraries that fall under the GPLv2 (SJCL, rawinflate, rawdeflate), BSD 2-clause (SJCL), BSD 3-clause (base64.js version 2.1.9, Showdown), MIT -(base64.js version 1.7, Bootstrap), Apache (prettify.js) and CC-BY (favicon, -icon, logo) licenses. All of these license terms can be found here below: +(base64.js version 1.7, Bootstrap, Identicon), Apache (prettify.js) and CC-BY +(favicon, icon, logo) licenses. All of these license terms can be found here +below: ## Zlib/libpng license for PrivateBin @@ -440,6 +441,28 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## MIT License for Identicon + +Copyright © 2013 Benjamin Laugueux + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + ## Apache License for prettify.js _Version 2.0, January 2004_ diff --git a/cfg/conf.ini.sample b/cfg/conf.ini.sample index 9606264..6321069 100644 --- a/cfg/conf.ini.sample +++ b/cfg/conf.ini.sample @@ -1,11 +1,6 @@ -; PrivateBin -; -; a zero-knowledge paste bin -; -; @link https://github.com/PrivateBin/PrivateBin -; @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) -; @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License -; @version 0.22 +; config file for PrivateBin +; +; An explanation of each setting can be find online at https://github.com/PrivateBin/PrivateBin/wiki/Configuration. [main] ; enable or disable the discussion feature, defaults to true @@ -53,18 +48,19 @@ languageselection = false ; the pastes encryption key ; urlshortener = "https://shortener.example.com/api?link=" -; (optional) vizhash is a weak mechanism to detect if a comment was from a -; different user when the same username was used in a comment. It is based on -; the IP and might be used to get the posters IP if the server salt is leaked -; and a rainbow table is generated for all IPs. Enabled by default. -; vizhash = false +; (optional) IP based icons are a weak mechanism to detect if a comment was from +; a different user when the same username was used in a comment. It might be +; used to get the IP of a non anonymous comment poster if the server salt is +; leaked and a SHA256 HMAC rainbow table is generated for all (relevant) IPs. +; Can be set to one these values: none / vizhash / identicon (default). +; icon = none ; Content Security Policy headers allow a website to restrict what sources are ; allowed to be accessed in its context. You need to change this if you added ; custom scripts from third-party domains to your templates, e.g. tracking ; scripts or run your site behind certain DDoS-protection services. ; Check the documentation at https://content-security-policy.com/ -cspheader = "default-src 'none'; connect-src *; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self';" +cspheader = "default-src 'none'; connect-src *; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:;" ; stay compatible with PrivateBin Alpha 0.19, less secure ; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of diff --git a/composer.json b/composer.json index ccad6bd..60374a3 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ } ], "require": { - "php": "^5.2.6 || ^7.0" + "php": "^5.3 || ^7.0", + "yzalis/identicon": "^1.1" }, "require-dev": { "codacy/coverage": "dev-master", diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..a81b864 --- /dev/null +++ b/composer.lock @@ -0,0 +1,858 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "e3520dc72004bd92b2bd0b0febf71c7f", + "content-hash": "ac3ea1f44998ea42345107fd21d6a2e0", + "packages": [ + { + "name": "yzalis/identicon", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/yzalis/Identicon.git", + "reference": "a99fc2a3d018512f7914bc6f972952536c0f309b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yzalis/Identicon/zipball/a99fc2a3d018512f7914bc6f972952536c0f309b", + "reference": "a99fc2a3d018512f7914bc6f972952536c0f309b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "fzaninotto/faker": "1.2.*@dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-0": { + "Identicon": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benjamin Laugueux", + "email": "benjamin@yzalis.com" + } + ], + "description": "Create awesome unique avatar.", + "homepage": "http://identicon-php.org", + "keywords": [ + "avatar", + "identicon", + "image" + ], + "time": "2014-07-13 09:19:12" + } + ], + "packages-dev": [ + { + "name": "codacy/coverage", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/codacy/php-codacy-coverage.git", + "reference": "92194b1ece3379e56bb1f95d6f540fc6244d9946" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codacy/php-codacy-coverage/zipball/92194b1ece3379e56bb1f95d6f540fc6244d9946", + "reference": "92194b1ece3379e56bb1f95d6f540fc6244d9946", + "shasum": "" + }, + "require": { + "gitonomy/gitlib": "~0.1", + "php": ">=5.3.3", + "symfony/console": "~2.5|~3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.5" + }, + "bin": [ + "bin/codacycoverage" + ], + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jakob Pupke", + "email": "jakob.pupke@gmail.com" + } + ], + "description": "Sends PHP test coverage information to Codacy.", + "homepage": "https://github.com/codacy/php-codacy-coverage", + "time": "2016-07-07 15:33:12" + }, + { + "name": "codeclimate/php-test-reporter", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/codeclimate/php-test-reporter.git", + "reference": "68786c391d2b859054046a7b7ed07c64e7b741a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codeclimate/php-test-reporter/zipball/68786c391d2b859054046a7b7ed07c64e7b741a1", + "reference": "68786c391d2b859054046a7b7ed07c64e7b741a1", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3", + "satooshi/php-coveralls": "^1.0", + "symfony/console": "^2.0|^3.0" + }, + "require-dev": { + "ext-xdebug": "*", + "phpunit/phpunit": "3.7.*@stable", + "tm/tooly-composer-script": "^1.0" + }, + "bin": [ + "composer/bin/test-reporter" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.3.x-dev" + }, + "tools": { + "box": { + "url": "https://github.com/box-project/box2/releases/download/2.7.2/box-2.7.2.phar", + "only-dev": true + } + } + }, + "autoload": { + "psr-4": { + "CodeClimate\\PhpTestReporter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Code Climate", + "email": "hello@codeclimate.com", + "homepage": "https://codeclimate.com" + } + ], + "description": "PHP client for reporting test coverage to Code Climate", + "homepage": "https://github.com/codeclimate/php-test-reporter", + "keywords": [ + "codeclimate", + "coverage" + ], + "time": "2016-08-09 19:41:51" + }, + { + "name": "gitonomy/gitlib", + "version": "v0.1.8", + "source": { + "type": "git", + "url": "https://github.com/gitonomy/gitlib.git", + "reference": "f575b8f7da917ade7890c6aa705fa22545690389" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/gitonomy/gitlib/zipball/f575b8f7da917ade7890c6aa705fa22545690389", + "reference": "f575b8f7da917ade7890c6aa705fa22545690389", + "shasum": "" + }, + "require": { + "symfony/process": "^2.3|^3.0" + }, + "require-dev": { + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Add some log" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Gitonomy\\Git\\": "src/Gitonomy/Git/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alexandre Salomé", + "email": "alexandre.salome@gmail.com", + "homepage": "http://alexandre-salome.fr" + }, + { + "name": "Julien DIDIER", + "email": "genzo.wm@gmail.com", + "homepage": "http://www.jdidier.net" + } + ], + "description": "Library for accessing git", + "homepage": "http://gitonomy.com", + "time": "2015-12-01 22:25:57" + }, + { + "name": "guzzle/guzzle", + "version": "v3.9.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle3.git", + "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", + "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3.3", + "symfony/event-dispatcher": "~2.1" + }, + "replace": { + "guzzle/batch": "self.version", + "guzzle/cache": "self.version", + "guzzle/common": "self.version", + "guzzle/http": "self.version", + "guzzle/inflection": "self.version", + "guzzle/iterator": "self.version", + "guzzle/log": "self.version", + "guzzle/parser": "self.version", + "guzzle/plugin": "self.version", + "guzzle/plugin-async": "self.version", + "guzzle/plugin-backoff": "self.version", + "guzzle/plugin-cache": "self.version", + "guzzle/plugin-cookie": "self.version", + "guzzle/plugin-curlauth": "self.version", + "guzzle/plugin-error-response": "self.version", + "guzzle/plugin-history": "self.version", + "guzzle/plugin-log": "self.version", + "guzzle/plugin-md5": "self.version", + "guzzle/plugin-mock": "self.version", + "guzzle/plugin-oauth": "self.version", + "guzzle/service": "self.version", + "guzzle/stream": "self.version" + }, + "require-dev": { + "doctrine/cache": "~1.3", + "monolog/monolog": "~1.0", + "phpunit/phpunit": "3.7.*", + "psr/log": "~1.0", + "symfony/class-loader": "~2.1", + "zendframework/zend-cache": "2.*,<2.3", + "zendframework/zend-log": "2.*,<2.3" + }, + "suggest": { + "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.9-dev" + } + }, + "autoload": { + "psr-0": { + "Guzzle": "src/", + "Guzzle\\Tests": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Guzzle Community", + "homepage": "https://github.com/guzzle/guzzle/contributors" + } + ], + "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "abandoned": "guzzlehttp/guzzle", + "time": "2015-03-18 18:23:50" + }, + { + "name": "psr/log", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2012-12-21 11:40:51" + }, + { + "name": "satooshi/php-coveralls", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/satooshi/php-coveralls.git", + "reference": "da51d304fe8622bf9a6da39a8446e7afd432115c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/da51d304fe8622bf9a6da39a8446e7afd432115c", + "reference": "da51d304fe8622bf9a6da39a8446e7afd432115c", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-simplexml": "*", + "guzzle/guzzle": "^2.8|^3.0", + "php": ">=5.3.3", + "psr/log": "^1.0", + "symfony/config": "^2.1|^3.0", + "symfony/console": "^2.1|^3.0", + "symfony/stopwatch": "^2.0|^3.0", + "symfony/yaml": "^2.0|^3.0" + }, + "suggest": { + "symfony/http-kernel": "Allows Symfony integration" + }, + "bin": [ + "bin/coveralls" + ], + "type": "library", + "autoload": { + "psr-4": { + "Satooshi\\": "src/Satooshi/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kitamura Satoshi", + "email": "with.no.parachute@gmail.com", + "homepage": "https://www.facebook.com/satooshi.jp" + } + ], + "description": "PHP client library for Coveralls API", + "homepage": "https://github.com/satooshi/php-coveralls", + "keywords": [ + "ci", + "coverage", + "github", + "test" + ], + "time": "2016-01-20 17:35:46" + }, + { + "name": "symfony/config", + "version": "v3.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "a7630397b91be09cdd2fe57fd13612e258700598" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/a7630397b91be09cdd2fe57fd13612e258700598", + "reference": "a7630397b91be09cdd2fe57fd13612e258700598", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/filesystem": "~2.8|~3.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2016-07-26 08:04:17" + }, + { + "name": "symfony/console", + "version": "v3.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "f9e638e8149e9e41b570ff092f8007c477ef0ce5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/f9e638e8149e9e41b570ff092f8007c477ef0ce5", + "reference": "f9e638e8149e9e41b570ff092f8007c477ef0ce5", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2016-07-26 08:04:17" + }, + { + "name": "symfony/event-dispatcher", + "version": "v2.8.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "889983a79a043dfda68f38c38b6dba092dd49cd8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/889983a79a043dfda68f38c38b6dba092dd49cd8", + "reference": "889983a79a043dfda68f38c38b6dba092dd49cd8", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.0,>=2.0.5|~3.0.0", + "symfony/dependency-injection": "~2.6|~3.0.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/stopwatch": "~2.3|~3.0.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2016-07-28 16:56:28" + }, + { + "name": "symfony/filesystem", + "version": "v3.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "bb29adceb552d202b6416ede373529338136e84f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/bb29adceb552d202b6416ede373529338136e84f", + "reference": "bb29adceb552d202b6416ede373529338136e84f", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2016-07-20 05:44:26" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "dff51f72b0706335131b00a7f49606168c582594" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", + "reference": "dff51f72b0706335131b00a7f49606168c582594", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2016-05-18 14:26:46" + }, + { + "name": "symfony/process", + "version": "v3.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "04c2dfaae4ec56a5c677b0c69fac34637d815758" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/04c2dfaae4ec56a5c677b0c69fac34637d815758", + "reference": "04c2dfaae4ec56a5c677b0c69fac34637d815758", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2016-07-28 11:13:48" + }, + { + "name": "symfony/stopwatch", + "version": "v3.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "bb42806b12c5f89db4ebf64af6741afe6d8457e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/bb42806b12c5f89db4ebf64af6741afe6d8457e1", + "reference": "bb42806b12c5f89db4ebf64af6741afe6d8457e1", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Stopwatch Component", + "homepage": "https://symfony.com", + "time": "2016-06-29 05:41:56" + }, + { + "name": "symfony/yaml", + "version": "v3.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "1819adf2066880c7967df7180f4f662b6f0567ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/1819adf2066880c7967df7180f4f662b6f0567ac", + "reference": "1819adf2066880c7967df7180f4f662b6f0567ac", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2016-07-17 14:02:08" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "codacy/coverage": 20, + "codeclimate/php-test-reporter": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^5.3 || ^7.0" + }, + "platform-dev": [] +} diff --git a/css/bootstrap/privatebin.css b/css/bootstrap/privatebin.css index 4c32591..d51c3ba 100644 --- a/css/bootstrap/privatebin.css +++ b/css/bootstrap/privatebin.css @@ -17,11 +17,19 @@ body.navbar-spacing { margin: 0 8px; } +.nav.navbar-nav > li { + margin-left: 8px; +} + .navbar-brand { padding: 3px; padding-left: 8px; } +.navbar-form { + padding: 0; +} + .dropdown-menu > li > label, .dropdown-menu > li > div { clear: both; display: block; @@ -49,10 +57,6 @@ body.navbar-spacing { margin-right: 8px; } -.dropdown > #expiration { - margin-left: 8px; -} - #image img { max-width: 100%; height: auto; diff --git a/lib/Configuration.php b/lib/Configuration.php index 44a35d6..9d979eb 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -50,8 +50,8 @@ class Configuration 'languageselection' => false, 'languagedefault' => '', 'urlshortener' => '', - 'vizhash' => true, - 'cspheader' => 'default-src \'none\'; connect-src *; script-src \'self\'; style-src \'self\'; font-src \'self\'; img-src \'self\';', + 'icon' => 'identicon', + 'cspheader' => 'default-src \'none\'; connect-src *; script-src \'self\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data:;', 'zerobincompatibility' => false, ), 'expire' => array( diff --git a/lib/I18n.php b/lib/I18n.php index 4a4fc3a..7f2fe87 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -143,7 +143,7 @@ class I18n // check if the lang cookie was set and that language exists if (array_key_exists('lang', $_COOKIE) && in_array($_COOKIE['lang'], $availableLanguages)) { - $match = $availableLanguages[array_search($_COOKIE['lang'], $availableLanguages)]; + $match = $_COOKIE['lang']; } // find a translation file matching the browsers language preferences else { diff --git a/lib/Model/Comment.php b/lib/Model/Comment.php index 7ea08e5..600e61e 100644 --- a/lib/Model/Comment.php +++ b/lib/Model/Comment.php @@ -10,11 +10,12 @@ * @version 0.22 */ -namespace PrivateBin\model; +namespace PrivateBin\Model; use PrivateBin\Sjcl; use PrivateBin\Persistence\TrafficLimiter; use PrivateBin\Vizhash16x16; +use Identicon\Identicon; use Exception; /** @@ -192,17 +193,26 @@ class Comment extends AbstractModel } $this->_data->meta->nickname = $nickname; - if ($this->_conf->getKey('vizhash')) { - // Generation of the anonymous avatar (Vizhash): - // 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()); + // If a nickname is provided, we generate an icon based on a SHA512 HMAC + // of the users IP. (We assume that if the user did not enter a nickname, + // the user wants to be anonymous and we will not generate an icon.) + $icon = $this->_conf->getKey('icon'); + if ($icon != 'none') { + $pngdata = ''; + $hmac = TrafficLimiter::getHash(); + if ($icon == 'identicon') { + $identicon = new Identicon(); + $pngdata = $identicon->getImageDataUri($hmac, 16); + } elseif ($icon == 'vizhash') { + $vh = new Vizhash16x16(); + $pngdata = 'data:image/png;base64,' . base64_encode( + $vh->generate($hmac) + ); + } if ($pngdata != '') { - $this->_data->meta->vizhash = 'data:image/png;base64,' . base64_encode($pngdata); + $this->_data->meta->vizhash = $pngdata; } - // Once the avatar is generated, we do not keep the IP address, nor its hash. } + // Once the icon is generated, we do not keep the IP address hash. } } diff --git a/lib/Persistence/ServerSalt.php b/lib/Persistence/ServerSalt.php index a8a6614..2f7d9bb 100644 --- a/lib/Persistence/ServerSalt.php +++ b/lib/Persistence/ServerSalt.php @@ -49,7 +49,6 @@ class ServerSalt extends AbstractPersistence $randomSalt = bin2hex(mcrypt_create_iv(256, MCRYPT_DEV_URANDOM)); } else { // fallback to mt_rand() - for ($i = 0; $i < 256; ++$i) { $randomSalt .= base_convert(mt_rand(), 10, 16); } diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index 36c7025..ee4efd0 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -73,15 +73,16 @@ class TrafficLimiter extends AbstractPersistence } /** - * get the current visitors IP address + * get a HMAC of the current visitors IP address * * @access public * @static + * @param string $algo * @return string */ - public static function getIp() + public static function getHash($algo = 'sha512') { - return $_SERVER[self::$_ipKey]; + return hash_hmac($algo, $_SERVER[self::$_ipKey], ServerSalt::get()); } /** @@ -101,8 +102,6 @@ class TrafficLimiter extends AbstractPersistence return true; } - $ip = hash_hmac('sha256', self::getIp(), ServerSalt::get()); - $file = 'traffic_limiter.php'; if (!self::_exists($file)) { self::_store( @@ -117,17 +116,19 @@ class TrafficLimiter extends AbstractPersistence $now = time(); $tl = $GLOBALS['traffic_limiter']; - // purge file of expired IPs to keep it small + // purge file of expired hashes to keep it small foreach ($tl as $key => $time) { if ($time + self::$_limit < $now) { unset($tl[$key]); } } - if (array_key_exists($ip, $tl) && ($tl[$ip] + self::$_limit >= $now)) { + // this hash is used as an array key, hence a shorter hash is used + $hash = self::getHash('sha256'); + if (array_key_exists($hash, $tl) && ($tl[$hash] + self::$_limit >= $now)) { $result = false; } else { - $tl[$ip] = time(); + $tl[$hash] = time(); $result = true; } self::_store( diff --git a/lib/View.php b/lib/View.php index 1876ac4..c5f0ea2 100644 --- a/lib/View.php +++ b/lib/View.php @@ -11,6 +11,7 @@ */ namespace PrivateBin; + use Exception; /** diff --git a/lib/Vizhash16x16.php b/lib/Vizhash16x16.php index 53f0346..6c1b615 100644 --- a/lib/Vizhash16x16.php +++ b/lib/Vizhash16x16.php @@ -13,8 +13,6 @@ namespace PrivateBin; -use PrivateBin\Persistence\ServerSalt; - /** * Vizhash16x16 * @@ -60,14 +58,6 @@ class Vizhash16x16 */ private $height; - /** - * salt used when generating the image - * - * @access private - * @var string - */ - private $salt; - /** * constructor * @@ -78,12 +68,13 @@ class Vizhash16x16 { $this->width = 16; $this->height = 16; - $this->salt = ServerSalt::get(); } /** * Generate a 16x16 png corresponding to $text. * + * The given text should to be 128 to 150 characters long + * * @access public * @param string $text * @return string PNG data. Or empty string if GD is not available. @@ -94,44 +85,35 @@ class Vizhash16x16 return ''; } - // We hash the input string. - $hash=hash('sha1', $text.$this->salt).hash('md5', $text.$this->salt); - $hash=$hash.strrev($hash); # more data to make graphics - $hashlen=strlen($hash); + $textlen = strlen($text); // We convert the hash into an array of integers. - $this->VALUES=array(); - for ($i=0; $i<$hashlen; $i=$i+2) { - array_push($this->VALUES, hexdec(substr($hash, $i, 2))); + $this->VALUES = array(); + for ($i = 0; $i < $textlen; $i = $i + 2) { + array_push($this->VALUES, hexdec(substr($text, $i, 2))); } - $this->VALUES_INDEX=0; // to walk the array. + $this->VALUES_INDEX = 0; // to walk the array. // Then use these integers to drive the creation of an image. $image = imagecreatetruecolor($this->width, $this->height); - $r0 = $this->getInt(); - $r=$r0; - $g0 = $this->getInt(); - $g=$g0; - $b0 = $this->getInt(); - $b=$b0; + $r = $r0 = $this->getInt(); + $g = $g0 = $this->getInt(); + $b = $b0 = $this->getInt(); // First, create an image with a specific gradient background. - $op='v'; - if (($this->getInt()%2)==0) { - $op='h'; + $op = 'v'; + if (($this->getInt() % 2) == 0) { + $op = 'h'; }; $image = $this->degrade($image, $op, array($r0, $g0, $b0), array(0, 0, 0)); - for ($i=0; $i<7; $i=$i+1) { - $action=$this->getInt(); + for ($i = 0; $i < 7; ++$i) { + $action = $this->getInt(); $color = imagecolorallocate($image, $r, $g, $b); - $r = ($r0 + $this->getInt()/25)%256; - $g = ($g0 + $this->getInt()/25)%256; - $b = ($b0 + $this->getInt()/25)%256; - $r0=$r; - $g0=$g; - $b0=$b; + $r = $r0 = ($r0 + $this->getInt() / 25) % 256; + $g = $g0 = ($g0 + $this->getInt() / 25) % 256; + $b = $b0 = ($b0 + $this->getInt() / 25) % 256; $this->drawshape($image, $action, $color); } @@ -154,8 +136,8 @@ class Vizhash16x16 */ private function getInt() { - $v= $this->VALUES[$this->VALUES_INDEX]; - $this->VALUES_INDEX++; + $v = $this->VALUES[$this->VALUES_INDEX]; + ++$this->VALUES_INDEX; $this->VALUES_INDEX %= count($this->VALUES); // Warp around the array return $v; } @@ -168,7 +150,7 @@ class Vizhash16x16 */ private function getX() { - return $this->width*$this->getInt()/256; + return $this->width * $this->getInt() / 256; } /** @@ -179,7 +161,7 @@ class Vizhash16x16 */ private function getY() { - return $this->height*$this->getInt()/256; + return $this->height * $this->getInt() / 256; } /** @@ -197,7 +179,7 @@ class Vizhash16x16 */ private function degrade($img, $direction, $color1, $color2) { - if ($direction=='h') { + if ($direction == 'h') { $size = imagesx($img); $sizeinv = imagesy($img); } else { @@ -205,15 +187,15 @@ class Vizhash16x16 $sizeinv = imagesx($img); } $diffs = array( - (($color2[0]-$color1[0])/$size), - (($color2[1]-$color1[1])/$size), - (($color2[2]-$color1[2])/$size) - ); - for ($i=0;$i<$size;$i++) { - $r = $color1[0]+($diffs[0]*$i); - $g = $color1[1]+($diffs[1]*$i); - $b = $color1[2]+($diffs[2]*$i); - if ($direction=='h') { + (($color2[0] - $color1[0]) / $size), + (($color2[1] - $color1[1]) / $size), + (($color2[2] - $color1[2]) / $size) + ); + for ($i = 0; $i < $size; ++$i) { + $r = $color1[0] + ($diffs[0] * $i); + $g = $color1[1] + ($diffs[1] * $i); + $b = $color1[2] + ($diffs[2] * $i); + if ($direction == 'h') { imageline($img, $i, 0, $i, $sizeinv, imagecolorallocate($img, $r, $g, $b)); } else { imageline($img, 0, $i, $sizeinv, $i, imagecolorallocate($img, $r, $g, $b)); @@ -233,7 +215,7 @@ class Vizhash16x16 */ private function drawshape($image, $action, $color) { - switch ($action%7) { + switch ($action % 7) { case 0: ImageFilledRectangle($image, $this->getX(), $this->getY(), $this->getX(), $this->getY(), $color); break; @@ -242,11 +224,12 @@ class Vizhash16x16 ImageFilledEllipse($image, $this->getX(), $this->getY(), $this->getX(), $this->getY(), $color); break; case 3: - $points = array($this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY(),$this->getX(), $this->getY()); + $points = array($this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY()); ImageFilledPolygon($image, $points, 4, $color); break; default: - $start=$this->getInt()*360/256; $end=$start+$this->getInt()*180/256; + $start = $this->getInt() * 360 /256; + $end = $start + $this->getInt() * 180 / 256; ImageFilledArc($image, $this->getX(), $this->getY(), $this->getX(), $this->getY(), $start, $end, $color, IMG_ARC_PIE); } } diff --git a/privatebin b/privatebin deleted file mode 120000 index 127be32..0000000 --- a/privatebin +++ /dev/null @@ -1 +0,0 @@ -privatebin \ No newline at end of file diff --git a/tst/ModelTest.php b/tst/ModelTest.php index 6213690..9ddfd17 100644 --- a/tst/ModelTest.php +++ b/tst/ModelTest.php @@ -5,7 +5,9 @@ use PrivateBin\Data\Database; use PrivateBin\Model; use PrivateBin\Model\Paste; use PrivateBin\Persistence\ServerSalt; +use PrivateBin\Persistence\TrafficLimiter; use PrivateBin\Vizhash16x16; +use Identicon\Identicon; class ModelTest extends PHPUnit_Framework_TestCase { @@ -167,13 +169,13 @@ class ModelTest extends PHPUnit_Framework_TestCase $paste->setOpendiscussion(); $paste->store(); - $vz = new Vizhash16x16(); - $pngdata = 'data:image/png;base64,' . base64_encode($vz->generate($_SERVER['REMOTE_ADDR'])); $comment = $paste->getComment(Helper::getPasteId()); $comment->setData($commentData['data']); $comment->setNickname($commentData['meta']['nickname']); $comment->store(); + $identicon = new Identicon(); + $pngdata = $identicon->getImageDataUri(TrafficLimiter::getHash(), 16); $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId())->get(); $this->assertEquals($pngdata, $comment->meta->vizhash, 'nickname triggers vizhash to be set'); } @@ -260,9 +262,9 @@ class ModelTest extends PHPUnit_Framework_TestCase public function testCommentWithDisabledVizhash() { $options = parse_ini_file(CONF, true); - $options['main']['vizhash'] = false; + $options['main']['icon'] = 'none'; $options['model'] = array( - 'class' => 'privatebin_db', + 'class' => 'Database', ); $options['model_options'] = array( 'dsn' => 'sqlite::memory:', @@ -311,4 +313,80 @@ class ModelTest extends PHPUnit_Framework_TestCase $this->assertEquals($commentData['meta']['nickname'], $comment->meta->nickname); $this->assertFalse(property_exists($comment->meta, 'vizhash'), 'vizhash was not generated'); } + + public function testCommentIdenticon() + { + $options = parse_ini_file(CONF, true); + $options['main']['icon'] = 'identicon'; + $options['model'] = array( + 'class' => 'Database', + ); + $options['model_options'] = array( + 'dsn' => 'sqlite::memory:', + 'usr' => null, + 'pwd' => null, + 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), + ); + Helper::confBackup(); + Helper::createIniFile(CONF, $options); + $model = new Model(new Configuration); + + $pasteData = Helper::getPaste(); + $commentData = Helper::getComment(); + $model->getPaste(Helper::getPasteId())->delete(); + + $paste = $model->getPaste(); + $paste->setData($pasteData['data']); + $paste->setOpendiscussion(); + $paste->setFormatter($pasteData['meta']['formatter']); + $paste->store(); + + $comment = $paste->getComment(Helper::getPasteId()); + $comment->setData($commentData['data']); + $comment->setNickname($commentData['meta']['nickname']); + $comment->store(); + + $identicon = new Identicon(); + $pngdata = $identicon->getImageDataUri(TrafficLimiter::getHash(), 16); + $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId())->get(); + $this->assertEquals($pngdata, $comment->meta->vizhash, 'nickname triggers vizhash to be set'); + } + + public function testCommentVizhash() + { + $options = parse_ini_file(CONF, true); + $options['main']['icon'] = 'vizhash'; + $options['model'] = array( + 'class' => 'Database', + ); + $options['model_options'] = array( + 'dsn' => 'sqlite::memory:', + 'usr' => null, + 'pwd' => null, + 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION), + ); + Helper::confBackup(); + Helper::createIniFile(CONF, $options); + $model = new Model(new Configuration); + + $pasteData = Helper::getPaste(); + $commentData = Helper::getComment(); + $model->getPaste(Helper::getPasteId())->delete(); + + $paste = $model->getPaste(); + $paste->setData($pasteData['data']); + $paste->setOpendiscussion(); + $paste->setFormatter($pasteData['meta']['formatter']); + $paste->store(); + + $comment = $paste->getComment(Helper::getPasteId()); + $comment->setData($commentData['data']); + $comment->setNickname($commentData['meta']['nickname']); + $comment->store(); + + $vz = new Vizhash16x16(); + $pngdata = 'data:image/png;base64,' . base64_encode($vz->generate(TrafficLimiter::getHash())); + $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId())->get(); + $this->assertEquals($pngdata, $comment->meta->vizhash, 'nickname triggers vizhash to be set'); + } } diff --git a/tst/Vizhash16x16Test.php b/tst/Vizhash16x16Test.php index fbab0ec..76d2f95 100644 --- a/tst/Vizhash16x16Test.php +++ b/tst/Vizhash16x16Test.php @@ -30,11 +30,11 @@ class Vizhash16x16Test extends PHPUnit_Framework_TestCase public function testVizhashGeneratesUniquePngsPerIp() { $vz = new Vizhash16x16(); - $pngdata = $vz->generate('127.0.0.1'); + $pngdata = $vz->generate(hash('sha512', '127.0.0.1')); file_put_contents($this->_file, $pngdata); $finfo = new finfo(FILEINFO_MIME_TYPE); $this->assertEquals('image/png', $finfo->file($this->_file)); - $this->assertNotEquals($pngdata, $vz->generate('2001:1620:2057:dead:beef::cafe:babe')); - $this->assertEquals($pngdata, $vz->generate('127.0.0.1')); + $this->assertNotEquals($pngdata, $vz->generate(hash('sha512', '2001:1620:2057:dead:beef::cafe:babe'))); + $this->assertEquals($pngdata, $vz->generate(hash('sha512', '127.0.0.1'))); } } diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 5936f84..d0da43d 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -5,4 +5,29 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); -return array(); +return array( + 'Identicon\\Generator\\BaseGenerator' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/BaseGenerator.php', + 'Identicon\\Generator\\GdGenerator' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/GdGenerator.php', + 'Identicon\\Generator\\GeneratorInterface' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/GeneratorInterface.php', + 'Identicon\\Generator\\ImageMagickGenerator' => $vendorDir . '/yzalis/identicon/src/Identicon/Generator/ImageMagickGenerator.php', + 'Identicon\\Identicon' => $vendorDir . '/yzalis/identicon/src/Identicon/Identicon.php', + 'PrivateBin\\Configuration' => $baseDir . '/lib/Configuration.php', + 'PrivateBin\\Data\\AbstractData' => $baseDir . '/lib/Data/AbstractData.php', + 'PrivateBin\\Data\\Database' => $baseDir . '/lib/Data/Database.php', + 'PrivateBin\\Data\\Filesystem' => $baseDir . '/lib/Data/Filesystem.php', + 'PrivateBin\\Filter' => $baseDir . '/lib/Filter.php', + 'PrivateBin\\I18n' => $baseDir . '/lib/I18n.php', + 'PrivateBin\\Model' => $baseDir . '/lib/Model.php', + 'PrivateBin\\Model\\AbstractModel' => $baseDir . '/lib/Model/AbstractModel.php', + 'PrivateBin\\Model\\Comment' => $baseDir . '/lib/Model/Comment.php', + 'PrivateBin\\Model\\Paste' => $baseDir . '/lib/Model/Paste.php', + 'PrivateBin\\Persistence\\AbstractPersistence' => $baseDir . '/lib/Persistence/AbstractPersistence.php', + 'PrivateBin\\Persistence\\PurgeLimiter' => $baseDir . '/lib/Persistence/PurgeLimiter.php', + 'PrivateBin\\Persistence\\ServerSalt' => $baseDir . '/lib/Persistence/ServerSalt.php', + 'PrivateBin\\Persistence\\TrafficLimiter' => $baseDir . '/lib/Persistence/TrafficLimiter.php', + 'PrivateBin\\PrivateBin' => $baseDir . '/lib/PrivateBin.php', + 'PrivateBin\\Request' => $baseDir . '/lib/Request.php', + 'PrivateBin\\Sjcl' => $baseDir . '/lib/Sjcl.php', + 'PrivateBin\\View' => $baseDir . '/lib/View.php', + 'PrivateBin\\Vizhash16x16' => $baseDir . '/lib/Vizhash16x16.php', +); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php deleted file mode 100644 index 5ca408a..0000000 --- a/vendor/composer/autoload_files.php +++ /dev/null @@ -1,8 +0,0 @@ - array($vendorDir . '/psr/log'), - 'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'), - 'Guzzle\\Tests' => array($vendorDir . '/guzzle/guzzle/tests'), - 'Guzzle' => array($vendorDir . '/guzzle/guzzle/src'), - 'CodeClimate\\Component' => array($vendorDir . '/codeclimate/php-test-reporter/src'), - 'CodeClimate\\Bundle' => array($vendorDir . '/codeclimate/php-test-reporter/src'), + 'Identicon' => array($vendorDir . '/yzalis/identicon/src'), ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 7ea6c55..2695ad3 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -47,24 +47,6 @@ class ComposerAutoloaderInitDontChange $loader->register(true); - if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInitDontChange::$files; - } else { - $includeFiles = require __DIR__ . '/autoload_files.php'; - } - foreach ($includeFiles as $fileIdentifier => $file) { - composerRequireDontChange($fileIdentifier, $file); - } - return $loader; } } - -function composerRequireDontChange($fileIdentifier, $file) -{ - if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - require $file; - - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - } -} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index bad7819..d44a987 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -6,8 +6,6 @@ namespace Composer\Autoload; class ComposerStaticInitDontChange { - public static $files = array (); - public static $prefixLengthsPsr4 = array ( 'P' => array ( @@ -22,9 +20,42 @@ class ComposerStaticInitDontChange ), ); - public static $prefixesPsr0 = array (); + public static $prefixesPsr0 = array ( + 'I' => + array ( + 'Identicon' => + array ( + 0 => __DIR__ . '/..' . '/yzalis/identicon/src', + ), + ), + ); - public static $classMap = array (); + public static $classMap = array ( + 'Identicon\\Generator\\BaseGenerator' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/BaseGenerator.php', + 'Identicon\\Generator\\GdGenerator' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/GdGenerator.php', + 'Identicon\\Generator\\GeneratorInterface' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/GeneratorInterface.php', + 'Identicon\\Generator\\ImageMagickGenerator' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Generator/ImageMagickGenerator.php', + 'Identicon\\Identicon' => __DIR__ . '/..' . '/yzalis/identicon/src/Identicon/Identicon.php', + 'PrivateBin\\Configuration' => __DIR__ . '/../..' . '/lib/Configuration.php', + 'PrivateBin\\Data\\AbstractData' => __DIR__ . '/../..' . '/lib/Data/AbstractData.php', + 'PrivateBin\\Data\\Database' => __DIR__ . '/../..' . '/lib/Data/Database.php', + 'PrivateBin\\Data\\Filesystem' => __DIR__ . '/../..' . '/lib/Data/Filesystem.php', + 'PrivateBin\\Filter' => __DIR__ . '/../..' . '/lib/Filter.php', + 'PrivateBin\\I18n' => __DIR__ . '/../..' . '/lib/I18n.php', + 'PrivateBin\\Model' => __DIR__ . '/../..' . '/lib/Model.php', + 'PrivateBin\\Model\\AbstractModel' => __DIR__ . '/../..' . '/lib/Model/AbstractModel.php', + 'PrivateBin\\Model\\Comment' => __DIR__ . '/../..' . '/lib/Model/Comment.php', + 'PrivateBin\\Model\\Paste' => __DIR__ . '/../..' . '/lib/Model/Paste.php', + 'PrivateBin\\Persistence\\AbstractPersistence' => __DIR__ . '/../..' . '/lib/Persistence/AbstractPersistence.php', + 'PrivateBin\\Persistence\\PurgeLimiter' => __DIR__ . '/../..' . '/lib/Persistence/PurgeLimiter.php', + 'PrivateBin\\Persistence\\ServerSalt' => __DIR__ . '/../..' . '/lib/Persistence/ServerSalt.php', + 'PrivateBin\\Persistence\\TrafficLimiter' => __DIR__ . '/../..' . '/lib/Persistence/TrafficLimiter.php', + 'PrivateBin\\PrivateBin' => __DIR__ . '/../..' . '/lib/PrivateBin.php', + 'PrivateBin\\Request' => __DIR__ . '/../..' . '/lib/Request.php', + 'PrivateBin\\Sjcl' => __DIR__ . '/../..' . '/lib/Sjcl.php', + 'PrivateBin\\View' => __DIR__ . '/../..' . '/lib/View.php', + 'PrivateBin\\Vizhash16x16' => __DIR__ . '/../..' . '/lib/Vizhash16x16.php', + ); public static function getInitializer(ClassLoader $loader) { diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index fe51488..5f6150d 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1 +1,54 @@ -[] +[ + { + "name": "yzalis/identicon", + "version": "1.1.0", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/yzalis/Identicon.git", + "reference": "a99fc2a3d018512f7914bc6f972952536c0f309b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yzalis/Identicon/zipball/a99fc2a3d018512f7914bc6f972952536c0f309b", + "reference": "a99fc2a3d018512f7914bc6f972952536c0f309b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "fzaninotto/faker": "1.2.*@dev" + }, + "time": "2014-07-13 09:19:12", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Identicon": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benjamin Laugueux", + "email": "benjamin@yzalis.com" + } + ], + "description": "Create awesome unique avatar.", + "homepage": "http://identicon-php.org", + "keywords": [ + "avatar", + "identicon", + "image" + ] + } +] diff --git a/vendor/yzalis/identicon/src/Identicon/Generator/BaseGenerator.php b/vendor/yzalis/identicon/src/Identicon/Generator/BaseGenerator.php new file mode 100644 index 0000000..6805b1c --- /dev/null +++ b/vendor/yzalis/identicon/src/Identicon/Generator/BaseGenerator.php @@ -0,0 +1,241 @@ + + */ +class BaseGenerator +{ + /** + * @var mixed + */ + protected $generatedImage; + + /** + * @var integer + */ + protected $color; + + /** + * @var integer + */ + protected $backgroundColor; + + /** + * @var integer + */ + protected $size; + + /** + * @var integer + */ + protected $pixelRatio; + + /** + * @var string + */ + private $hash; + + /** + * @var array + */ + private $arrayOfSquare = array(); + + /** + * Set the image color + * + * @param string|array $color The color in hexa (6 chars) or rgb array + * + * @return this + */ + public function setColor($color) + { + if (null === $color) { + return $this; + } + + $this->color = $this->convertColor($color); + + return $this; + } + + /** + * Set the image background color + * + * @param string|array $backgroundColor The color in hexa (6 chars) or rgb array + * + * @return this + */ + public function setBackgroundColor($backgroundColor) + { + if (null === $backgroundColor) { + return $this; + } + + $this->backgroundColor = $this->convertColor($backgroundColor); + + return $this; + } + + private function convertColor($color) + { + $convertedColor = array(); + if (is_array($color)) { + $convertedColor[0] = $color[0]; + $convertedColor[1] = $color[1]; + $convertedColor[2] = $color[2]; + } else { + if (false !== strpos($color, '#')) { + $color = substr($color, 1); + } + $convertedColor[0] = hexdec(substr($color, 0, 2)); + $convertedColor[1] = hexdec(substr($color, 2, 2)); + $convertedColor[2] = hexdec(substr($color, 4, 2)); + } + + return $convertedColor; + } + + /** + * Get the color + * + * @return array + */ + public function getColor() + { + return $this->color; + } + + + /** + * Get the background color + * + * @return array + */ + public function getBackgroundColor() + { + return $this->backgroundColor; + } + + /** + * Convert the hash into an multidimensionnal array of boolean + * + * @return this + */ + private function convertHashToArrayOfBoolean() + { + preg_match_all('/(\w)(\w)/', $this->hash, $chars); + foreach ($chars[1] as $i => $char) { + if ($i % 3 == 0) { + $this->arrayOfSquare[$i/3][0] = $this->convertHexaToBoolean($char); + $this->arrayOfSquare[$i/3][4] = $this->convertHexaToBoolean($char); + } elseif ($i % 3 == 1) { + $this->arrayOfSquare[$i/3][1] = $this->convertHexaToBoolean($char); + $this->arrayOfSquare[$i/3][3] = $this->convertHexaToBoolean($char); + } else { + $this->arrayOfSquare[$i/3][2] = $this->convertHexaToBoolean($char); + } + ksort($this->arrayOfSquare[$i/3]); + } + + $this->color[0] = hexdec(array_pop($chars[1]))*16; + $this->color[1] = hexdec(array_pop($chars[1]))*16; + $this->color[2] = hexdec(array_pop($chars[1]))*16; + + return $this; + } + + /** + * Convert an heaxecimal number into a boolean + * + * @param string $hexa + * + * @return boolean + */ + private function convertHexaToBoolean($hexa) + { + return (bool) intval(round(hexdec($hexa)/10)); + } + + /** + * + * + * @return array + */ + public function getArrayOfSquare() + { + return $this->arrayOfSquare; + } + + /** + * Get the identicon string hash + * + * @return string + */ + public function getHash() + { + return $this->hash; + } + + /** + * Generate a hash fron the original string + * + * @param string $string + * + * @return this + */ + public function setString($string) + { + if (null === $string) { + throw new \Exception('The string cannot be null.'); + } + + $this->hash = md5($string); + + $this->convertHashToArrayOfBoolean(); + + return $this; + } + + /** + * Set the image size + * + * @param integer $size + * + * @return this + */ + public function setSize($size) + { + if (null === $size) { + return $this; + } + + $this->size = $size; + $this->pixelRatio = round($size / 5); + + return $this; + } + + /** + * Get the image size + * + * @return integer + */ + public function getSize() + { + return $this->size; + } + + /** + * Get the pixel ratio + * + * @return array + */ + public function getPixelRatio() + { + return $this->pixelRatio; + } +} diff --git a/vendor/yzalis/identicon/src/Identicon/Generator/GdGenerator.php b/vendor/yzalis/identicon/src/Identicon/Generator/GdGenerator.php new file mode 100644 index 0000000..ef7b90f --- /dev/null +++ b/vendor/yzalis/identicon/src/Identicon/Generator/GdGenerator.php @@ -0,0 +1,76 @@ + + */ +class GdGenerator extends BaseGenerator implements GeneratorInterface +{ + public function __construct() + { + if (!extension_loaded('gd')) { + throw new \Exception('GD does not appear to be avaliable in your PHP installation. Please try another generator'); + } + } + + private function generateImage() + { + // prepare image + $this->generatedImage = imagecreatetruecolor($this->getPixelRatio() * 5, $this->getPixelRatio() * 5); + + $rgbBackgroundColor = $this->getBackgroundColor(); + if (null === $rgbBackgroundColor) { + $background = imagecolorallocate($this->generatedImage, 0, 0, 0); + imagecolortransparent($this->generatedImage, $background); + } else { + $background = imagecolorallocate($this->generatedImage, $rgbBackgroundColor[0], $rgbBackgroundColor[1], $rgbBackgroundColor[2]); + imagefill($this->generatedImage, 0, 0, $background); + } + + // prepage color + $rgbColor = $this->getColor(); + $gdColor = imagecolorallocate($this->generatedImage, $rgbColor[0], $rgbColor[1], $rgbColor[2]); + + // draw content + foreach ($this->getArrayOfSquare() as $lineKey => $lineValue) { + foreach ($lineValue as $colKey => $colValue) { + if (true === $colValue) { + imagefilledrectangle($this->generatedImage, $colKey * $this->getPixelRatio(), $lineKey * $this->getPixelRatio(), ($colKey + 1) * $this->getPixelRatio(), ($lineKey + 1) * $this->getPixelRatio(), $gdColor); + } + } + } + + return $this; + } + + /** + * {@inheritDoc} + */ + public function getImageBinaryData($string, $size = null, $color = null, $backgroundColor = null) + { + ob_start(); + imagepng($this->getImageResource($string, $size, $color, $backgroundColor)); + $imageData = ob_get_contents(); + ob_end_clean(); + + return $imageData; + } + + /** + * {@inheritDoc} + */ + public function getImageResource($string, $size = null, $color = null, $backgroundColor = null) + { + $this + ->setString($string) + ->setSize($size) + ->setColor($color) + ->setBackgroundColor($backgroundColor) + ->generateImage(); + + return $this->generatedImage; + } +} diff --git a/vendor/yzalis/identicon/src/Identicon/Generator/GeneratorInterface.php b/vendor/yzalis/identicon/src/Identicon/Generator/GeneratorInterface.php new file mode 100644 index 0000000..78be7d4 --- /dev/null +++ b/vendor/yzalis/identicon/src/Identicon/Generator/GeneratorInterface.php @@ -0,0 +1,33 @@ + + */ +interface GeneratorInterface +{ + /** + * + * + * @param string $string + * @param integer $size + * @param array|string $color + * @param array|string $backgroundColor + * + * @return mixed + */ + function getImageBinaryData($string, $size = null, $color = null, $backgroundColor = null); + + /** + * + * + * @param string $string + * @param integer $size + * @param array|string $color + * @param array|string $backgroundColor + * + * @return string + */ + function getImageResource($string, $size = null, $color = null, $backgroundColor = null); +} diff --git a/vendor/yzalis/identicon/src/Identicon/Generator/ImageMagickGenerator.php b/vendor/yzalis/identicon/src/Identicon/Generator/ImageMagickGenerator.php new file mode 100644 index 0000000..f11c51d --- /dev/null +++ b/vendor/yzalis/identicon/src/Identicon/Generator/ImageMagickGenerator.php @@ -0,0 +1,80 @@ + + */ +class ImageMagickGenerator extends BaseGenerator implements GeneratorInterface +{ + public function __construct() + { + if (!extension_loaded('imagick')) { + throw new \Exception('ImageMagick does not appear to be avaliable in your PHP installation. Please try another generator'); + } + } + + private function generateImage() + { + $this->generatedImage = new \Imagick(); + $rgbBackgroundColor = $this->getBackgroundColor(); + + if (null === $rgbBackgroundColor) { + $background = 'none'; + } else { + $background = new \ImagickPixel("rgb($rgbBackgroundColor[0],$rgbBackgroundColor[1],$rgbBackgroundColor[2])"); + } + + $this->generatedImage->newImage($this->pixelRatio * 5, $this->pixelRatio * 5, $background, 'png'); + + // prepare color + $rgbColor = $this->getColor(); + $color = new \ImagickPixel("rgb($rgbColor[0],$rgbColor[1],$rgbColor[2])"); + + $draw = new \ImagickDraw(); + $draw->setFillColor($color); + + // draw the content + foreach ($this->getArrayOfSquare() as $lineKey => $lineValue) { + foreach ($lineValue as $colKey => $colValue) { + if (true === $colValue) { + $draw->rectangle( $colKey * $this->pixelRatio, $lineKey * $this->pixelRatio, ($colKey + 1) * $this->pixelRatio, ($lineKey + 1) * $this->pixelRatio); + } + } + } + + $this->generatedImage->drawImage($draw); + + return $this; + } + + /** + * {@inheritDoc} + */ + public function getImageBinaryData($string, $size = null, $color = null, $backgroundColor = null) + { + ob_start(); + echo $this->getImageResource($string, $size, $color, $backgroundColor); + $imageData = ob_get_contents(); + ob_end_clean(); + + return $imageData; + } + + /** + * {@inheritDoc} + */ + public function getImageResource($string, $size = null, $color = null, $backgroundColor = null) + { + $this + ->setString($string) + ->setSize($size) + ->setColor($color) + ->setBackgroundColor($backgroundColor) + ->generateImage(); + + return $this->generatedImage; + } +} diff --git a/vendor/yzalis/identicon/src/Identicon/Identicon.php b/vendor/yzalis/identicon/src/Identicon/Identicon.php new file mode 100644 index 0000000..c78ccc3 --- /dev/null +++ b/vendor/yzalis/identicon/src/Identicon/Identicon.php @@ -0,0 +1,100 @@ + + */ +class Identicon +{ + /** + * @var GeneratorInterface + */ + private $generator; + + public function __construct($generator = null) + { + if (null === $generator) { + $this->generator = new GdGenerator(); + } else { + $this->generator = $generator; + } + + } + + /** + * Set the image generetor + * + * @param GeneratorInterface $generator + * + * @throws \Exception + */ + public function setGenerator(GeneratorInterface $generator) + { + $this->generator = $generator; + + return $this; + } + + /** + * Display an Identicon image + * + * @param string $string + * @param integer $size + * @param string $color + * @param string $backgroundColor + */ + public function displayImage($string, $size = 64, $color = null, $backgroundColor = null) + { + header("Content-Type: image/png"); + echo $this->getImageData($string, $size, $color, $backgroundColor); + } + + /** + * Get an Identicon PNG image data + * + * @param string $string + * @param integer $size + * @param string $color + * @param string $backgroundColor + * + * @return string + */ + public function getImageData($string, $size = 64, $color = null, $backgroundColor = null) + { + return $this->generator->getImageBinaryData($string, $size, $color, $backgroundColor); + } + + /** + * Get an Identicon PNG image resource + * + * @param string $string + * @param integer $size + * @param string $color + * @param string $backgroundColor + * + * @return string + */ + public function getImageResource($string, $size = 64, $color = null, $backgroundColor = null) + { + return $this->generator->getImageResource($string, $size, $color, $backgroundColor); + } + + /** + * Get an Identicon PNG image data as base 64 encoded + * + * @param string $string + * @param integer $size + * @param string $color + * @param string $backgroundColor + * + * @return string + */ + public function getImageDataUri($string, $size = 64, $color = null, $backgroundColor = null) + { + return sprintf('data:image/png;base64,%s', base64_encode($this->getImageData($string, $size, $color, $backgroundColor))); + } +}