├── .gitignore ├── src ├── Plugin.php ├── Notice.php └── Login.php ├── readme.txt ├── wp-haveibeenpwned.php ├── README.md ├── composer.json ├── classes └── dependencies │ └── wpupdatephp │ └── wp-update-php │ └── src │ └── WPUpdatePhp.php └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor -------------------------------------------------------------------------------- /src/Plugin.php: -------------------------------------------------------------------------------- 1 | login = new Login(); 16 | $this->login->setup(); 17 | 18 | $this->notice = new Notice(); 19 | $this->notice->setup(); 20 | } 21 | } -------------------------------------------------------------------------------- /src/Notice.php: -------------------------------------------------------------------------------- 1 |

WARNING: Your password has been compromised and it is recommended you change your password immediately.

'; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | === Have I Been Pwned === 2 | Contributors: coenjacobs 3 | Tags: haveibeenpwned, security, passwords 4 | Requires at least: 4.4 5 | Tested up to: 5.2 6 | Stable tag: 0.1.1 7 | License: GPLv2 8 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 9 | 10 | This WordPress plugin checks if the password for each user account has been compromised via haveibeenpwned.com, as soon as the user logs in. 11 | 12 | == Description == 13 | 14 | This WordPress plugin checks if the password for each user account has been compromised via haveibeenpwned.com, as soon as the user logs in. 15 | 16 | == Changelog == 17 | 18 | = 0.1.1 = 19 | * Strips erroneous htmlspecialchars() call which prevents creating proper hashes before sending to the API. 20 | 21 | = 0.1.0 = 22 | * Initial release 23 | -------------------------------------------------------------------------------- /src/Login.php: -------------------------------------------------------------------------------- 1 | setup(); 23 | } 24 | 25 | return $plugin; 26 | } 27 | 28 | $checker = new HIBP_WPUpdatePhp('5.4'); 29 | $checker->set_plugin_name('Have I Been Pwned'); 30 | 31 | if ( $checker->does_it_meet_required_php_version() ) { 32 | require('vendor/autoload.php'); 33 | 34 | add_action( 'plugins_loaded', '_haveibeenpwned' ); 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Have I Been Pwned 2 | This WordPress plugin checks if the password for each user account has been compromised via [haveibeenpwned.com](https://haveibeenpwned.com/), as soon as the user logs in. This will never send the actual password of your users, but it rather fetches a list to do the check locally. If the users password appears to be compromised, the user will be notified via an admin notice. 3 | 4 | ## How does this work? 5 | When a user logs in, the first five characters of the hash made of a password are sent to the haveibeenpwned.com API. This API then returns a list of hashes of compromised passwords, all starting with the five characters provided. The check to see if the actual password used is on the list, is done locally and the password of the user is never being posted anywhere. Not even in hashed form. 6 | 7 | ## What is haveibeenpwned.com? 8 | The website haveibeenpwned allows everyone to easily search through compromised sets of data, often sourced from leaked or hacked data. This data often contains usernames, passwords, email addresses and other personal data. [Troy Hunt](https://www.troyhunt.com/) is a well known security researcher and makes this data available for anyone to search and check if their data is potentially being compromised. -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coenjacobs/wp-haveibeenpwned", 3 | "type": "wordpress-plugin", 4 | "authors": [ 5 | { 6 | "name": "Coen Jacobs", 7 | "email": "coenjacobs@gmail.com" 8 | } 9 | ], 10 | "autoload": { 11 | "classmap": [ 12 | "classes" 13 | ], 14 | "psr-4": { 15 | "CoenJacobs\\HaveIBeenPwned\\": "src/" 16 | } 17 | }, 18 | "minimum-stability": "dev", 19 | "prefer-stable": true, 20 | "require": { 21 | "xrstf/composer-php52": "^1.0", 22 | "wpupdatephp/wp-update-php": "^1.1" 23 | }, 24 | "require-dev": { 25 | "coenjacobs/mozart": "^0.2.1" 26 | }, 27 | "extra": { 28 | "mozart": { 29 | "dep_namespace": "CoenJacobs\\HaveIBeenPwned", 30 | "dep_directory": "/src/Dependencies/", 31 | "classmap_directory": "/classes/dependencies/", 32 | "classmap_prefix": "HIBP_", 33 | "packages": [ 34 | "wpupdatephp/wp-update-php" 35 | ] 36 | } 37 | }, 38 | "scripts": { 39 | "post-install-cmd": [ 40 | "xrstf\\Composer52\\Generator::onPostInstallCmd", 41 | "\"vendor/bin/mozart\" compose", 42 | "composer dumpautoload" 43 | ], 44 | "post-update-cmd": [ 45 | "xrstf\\Composer52\\Generator::onPostInstallCmd", 46 | "\"vendor/bin/mozart\" compose", 47 | "composer dumpautoload" 48 | ], 49 | "post-autoload-dump": [ 50 | "xrstf\\Composer52\\Generator::onPostInstallCmd" 51 | ] 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /classes/dependencies/wpupdatephp/wp-update-php/src/WPUpdatePhp.php: -------------------------------------------------------------------------------- 1 | minimum_version = $minimum_version; 30 | $this->recommended_version = $recommended_version; 31 | } 32 | 33 | /** 34 | * Set the plugin name for the admin notice. 35 | * 36 | * @param string $name Name of the plugin to be used in admin notices. 37 | */ 38 | public function set_plugin_name( $name ) { 39 | $this->plugin_name = $name; 40 | } 41 | 42 | /** 43 | * Check given PHP version against minimum required version. 44 | * 45 | * @param string $version Optional. PHP version to check against. 46 | * Default is the current PHP version as a string in 47 | * "major.minor.release[extra]" notation. 48 | * @return bool True if supplied PHP version meets minimum required version. 49 | */ 50 | public function does_it_meet_required_php_version( $version = PHP_VERSION ) { 51 | if ( $this->version_passes_requirement( $this->minimum_version, $version ) ) { 52 | return true; 53 | } 54 | 55 | $this->load_version_notice( array( $this, 'minimum_admin_notice' ) ); 56 | return false; 57 | } 58 | 59 | /** 60 | * Check given PHP version against recommended version. 61 | * 62 | * @param string $version Optional. PHP version to check against. 63 | * Default is the current PHP version as a string in 64 | * "major.minor.release[extra]" notation. 65 | * @return bool True if supplied PHP version meets recommended version. 66 | */ 67 | public function does_it_meet_recommended_php_version( $version = PHP_VERSION ) { 68 | if ( $this->version_passes_requirement( $this->recommended_version, $version ) ) { 69 | return true; 70 | } 71 | 72 | $this->load_version_notice( array( $this, 'recommended_admin_notice' ) ); 73 | return false; 74 | } 75 | 76 | /** 77 | * Check that one PHP version is less than or equal to another. 78 | * 79 | * @param string $requirement The baseline version of PHP. 80 | * @param string $version The given version of PHP. 81 | * @return bool True if the requirement is less than or equal to given version. 82 | */ 83 | private function version_passes_requirement( $requirement, $version ) { 84 | return version_compare( $requirement, $version, '<=' ); 85 | } 86 | 87 | /** 88 | * Conditionally hook in an admin notice. 89 | * 90 | * @param callable $callback Callable that displays admin notice. 91 | */ 92 | private function load_version_notice( $callback ) { 93 | if ( is_admin() && ! defined( 'DOING_AJAX' ) ) { 94 | add_action( 'admin_notices', $callback ); 95 | add_action( 'network_admin_notices', $callback ); 96 | } 97 | } 98 | 99 | /** 100 | * Return the string to be shown in the admin notice. 101 | * 102 | * This is based on the level (`recommended` or default `minimum`) of the 103 | * notice. This will also add the plugin name to the notice string, if set. 104 | * 105 | * @param string $level Optional. Admin notice level, `recommended` or `minimum`. 106 | * Default is `minimum`. 107 | * @return string 108 | */ 109 | public function get_admin_notice( $level = 'minimum' ) { 110 | if ( 'recommended' === $level ) { 111 | if ( ! empty( $this->plugin_name ) ) { 112 | return '

' . $this->plugin_name . ' recommends a PHP version higher than ' . $this->recommended_version . '. Read more information about how you can update.

'; 113 | } else { 114 | return '

This plugin recommends a PHP version higher than ' . $this->recommended_version . '. Read more information about how you can update.

'; 115 | } 116 | } 117 | 118 | if ( ! empty( $this->plugin_name ) ) { 119 | return '

Unfortunately, ' . $this->plugin_name . ' cannot run on PHP versions older than ' . $this->minimum_version . '. Read more information about how you can update.

'; 120 | } else { 121 | return '

Unfortunately, this plugin cannot run on PHP versions older than ' . $this->minimum_version . '. Read more information about how you can update.

'; 122 | } 123 | } 124 | 125 | /** 126 | * Method hooked into admin_notices when minimum required PHP version is not 127 | * available to show this in a notice. 128 | * 129 | * @hook admin_notices 130 | */ 131 | public function minimum_admin_notice() { 132 | echo '
'; 133 | echo $this->get_admin_notice( 'minimum' ); 134 | echo '
'; 135 | } 136 | 137 | /** 138 | * Method hooked into admin_notices when recommended PHP version is not 139 | * available to show this in a notice. 140 | * 141 | * @hook admin_notices 142 | */ 143 | public function recommended_admin_notice() { 144 | echo '
'; 145 | echo $this->get_admin_notice( 'recommended' ); 146 | echo '
'; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "7771bddf43c87abe39fb8a37e909c49e", 8 | "packages": [ 9 | { 10 | "name": "wpupdatephp/wp-update-php", 11 | "version": "1.1.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/WPupdatePHP/wp-update-php.git", 15 | "reference": "6c80444de04d8c688e3b42e164e40527b487a357" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/WPupdatePHP/wp-update-php/zipball/6c80444de04d8c688e3b42e164e40527b487a357", 20 | "reference": "6c80444de04d8c688e3b42e164e40527b487a357", 21 | "shasum": "" 22 | }, 23 | "require-dev": { 24 | "phpspec/phpspec": "~2.0" 25 | }, 26 | "type": "library", 27 | "autoload": { 28 | "classmap": [ 29 | "src" 30 | ] 31 | }, 32 | "notification-url": "https://packagist.org/downloads/", 33 | "license": [ 34 | "GPL-2.0+" 35 | ], 36 | "description": "Library to be bundled with WordPress plugins to enforce users to upgrade to PHP 5.4 hosting", 37 | "time": "2017-03-08T09:50:34+00:00" 38 | }, 39 | { 40 | "name": "xrstf/composer-php52", 41 | "version": "v1.0.20", 42 | "source": { 43 | "type": "git", 44 | "url": "https://github.com/composer-php52/composer-php52.git", 45 | "reference": "bd41459d5e27df8d33057842b32377c39e97a5a8" 46 | }, 47 | "dist": { 48 | "type": "zip", 49 | "url": "https://api.github.com/repos/composer-php52/composer-php52/zipball/bd41459d5e27df8d33057842b32377c39e97a5a8", 50 | "reference": "bd41459d5e27df8d33057842b32377c39e97a5a8", 51 | "shasum": "" 52 | }, 53 | "type": "library", 54 | "extra": { 55 | "branch-alias": { 56 | "dev-default": "1.x-dev" 57 | } 58 | }, 59 | "autoload": { 60 | "psr-0": { 61 | "xrstf\\Composer52": "lib/" 62 | } 63 | }, 64 | "notification-url": "https://packagist.org/downloads/", 65 | "license": [ 66 | "MIT" 67 | ], 68 | "time": "2016-04-16T21:52:24+00:00" 69 | } 70 | ], 71 | "packages-dev": [ 72 | { 73 | "name": "coenjacobs/mozart", 74 | "version": "0.2.1", 75 | "source": { 76 | "type": "git", 77 | "url": "https://github.com/coenjacobs/mozart.git", 78 | "reference": "6c217eec3c5be6a51925e137db15b0745b473f13" 79 | }, 80 | "dist": { 81 | "type": "zip", 82 | "url": "https://api.github.com/repos/coenjacobs/mozart/zipball/6c217eec3c5be6a51925e137db15b0745b473f13", 83 | "reference": "6c217eec3c5be6a51925e137db15b0745b473f13", 84 | "shasum": "" 85 | }, 86 | "require": { 87 | "league/flysystem": "^1.0", 88 | "php": ">=5.5.0", 89 | "symfony/console": "^3.2", 90 | "symfony/finder": "^3.2" 91 | }, 92 | "require-dev": { 93 | "coenjacobs/php-composter-phpcs": "^0.1.0", 94 | "phpunit/phpunit": "^4.0" 95 | }, 96 | "bin": [ 97 | "bin/mozart" 98 | ], 99 | "type": "library", 100 | "autoload": { 101 | "psr-4": { 102 | "CoenJacobs\\Mozart\\": "src/" 103 | } 104 | }, 105 | "notification-url": "https://packagist.org/downloads/", 106 | "license": [ 107 | "MIT" 108 | ], 109 | "authors": [ 110 | { 111 | "name": "Coen Jacobs", 112 | "email": "coenjacobs@gmail.com" 113 | } 114 | ], 115 | "time": "2017-12-04T10:28:32+00:00" 116 | }, 117 | { 118 | "name": "league/flysystem", 119 | "version": "1.0.42", 120 | "source": { 121 | "type": "git", 122 | "url": "https://github.com/thephpleague/flysystem.git", 123 | "reference": "09eabc54e199950041aef258a85847676496fe8e" 124 | }, 125 | "dist": { 126 | "type": "zip", 127 | "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/09eabc54e199950041aef258a85847676496fe8e", 128 | "reference": "09eabc54e199950041aef258a85847676496fe8e", 129 | "shasum": "" 130 | }, 131 | "require": { 132 | "php": ">=5.5.9" 133 | }, 134 | "conflict": { 135 | "league/flysystem-sftp": "<1.0.6" 136 | }, 137 | "require-dev": { 138 | "ext-fileinfo": "*", 139 | "phpspec/phpspec": "^3.4", 140 | "phpunit/phpunit": "^5.7" 141 | }, 142 | "suggest": { 143 | "ext-fileinfo": "Required for MimeType", 144 | "ext-ftp": "Allows you to use FTP server storage", 145 | "ext-openssl": "Allows you to use FTPS server storage", 146 | "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", 147 | "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", 148 | "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", 149 | "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", 150 | "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", 151 | "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", 152 | "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", 153 | "league/flysystem-webdav": "Allows you to use WebDAV storage", 154 | "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter", 155 | "spatie/flysystem-dropbox": "Allows you to use Dropbox storage", 156 | "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications" 157 | }, 158 | "type": "library", 159 | "extra": { 160 | "branch-alias": { 161 | "dev-master": "1.1-dev" 162 | } 163 | }, 164 | "autoload": { 165 | "psr-4": { 166 | "League\\Flysystem\\": "src/" 167 | } 168 | }, 169 | "notification-url": "https://packagist.org/downloads/", 170 | "license": [ 171 | "MIT" 172 | ], 173 | "authors": [ 174 | { 175 | "name": "Frank de Jonge", 176 | "email": "info@frenky.net" 177 | } 178 | ], 179 | "description": "Filesystem abstraction: Many filesystems, one API.", 180 | "keywords": [ 181 | "Cloud Files", 182 | "WebDAV", 183 | "abstraction", 184 | "aws", 185 | "cloud", 186 | "copy.com", 187 | "dropbox", 188 | "file systems", 189 | "files", 190 | "filesystem", 191 | "filesystems", 192 | "ftp", 193 | "rackspace", 194 | "remote", 195 | "s3", 196 | "sftp", 197 | "storage" 198 | ], 199 | "time": "2018-01-27T16:03:56+00:00" 200 | }, 201 | { 202 | "name": "psr/log", 203 | "version": "1.0.2", 204 | "source": { 205 | "type": "git", 206 | "url": "https://github.com/php-fig/log.git", 207 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" 208 | }, 209 | "dist": { 210 | "type": "zip", 211 | "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 212 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 213 | "shasum": "" 214 | }, 215 | "require": { 216 | "php": ">=5.3.0" 217 | }, 218 | "type": "library", 219 | "extra": { 220 | "branch-alias": { 221 | "dev-master": "1.0.x-dev" 222 | } 223 | }, 224 | "autoload": { 225 | "psr-4": { 226 | "Psr\\Log\\": "Psr/Log/" 227 | } 228 | }, 229 | "notification-url": "https://packagist.org/downloads/", 230 | "license": [ 231 | "MIT" 232 | ], 233 | "authors": [ 234 | { 235 | "name": "PHP-FIG", 236 | "homepage": "http://www.php-fig.org/" 237 | } 238 | ], 239 | "description": "Common interface for logging libraries", 240 | "homepage": "https://github.com/php-fig/log", 241 | "keywords": [ 242 | "log", 243 | "psr", 244 | "psr-3" 245 | ], 246 | "time": "2016-10-10T12:19:37+00:00" 247 | }, 248 | { 249 | "name": "symfony/console", 250 | "version": "v3.4.4", 251 | "source": { 252 | "type": "git", 253 | "url": "https://github.com/symfony/console.git", 254 | "reference": "26b6f419edda16c19775211987651cb27baea7f1" 255 | }, 256 | "dist": { 257 | "type": "zip", 258 | "url": "https://api.github.com/repos/symfony/console/zipball/26b6f419edda16c19775211987651cb27baea7f1", 259 | "reference": "26b6f419edda16c19775211987651cb27baea7f1", 260 | "shasum": "" 261 | }, 262 | "require": { 263 | "php": "^5.5.9|>=7.0.8", 264 | "symfony/debug": "~2.8|~3.0|~4.0", 265 | "symfony/polyfill-mbstring": "~1.0" 266 | }, 267 | "conflict": { 268 | "symfony/dependency-injection": "<3.4", 269 | "symfony/process": "<3.3" 270 | }, 271 | "require-dev": { 272 | "psr/log": "~1.0", 273 | "symfony/config": "~3.3|~4.0", 274 | "symfony/dependency-injection": "~3.4|~4.0", 275 | "symfony/event-dispatcher": "~2.8|~3.0|~4.0", 276 | "symfony/lock": "~3.4|~4.0", 277 | "symfony/process": "~3.3|~4.0" 278 | }, 279 | "suggest": { 280 | "psr/log": "For using the console logger", 281 | "symfony/event-dispatcher": "", 282 | "symfony/lock": "", 283 | "symfony/process": "" 284 | }, 285 | "type": "library", 286 | "extra": { 287 | "branch-alias": { 288 | "dev-master": "3.4-dev" 289 | } 290 | }, 291 | "autoload": { 292 | "psr-4": { 293 | "Symfony\\Component\\Console\\": "" 294 | }, 295 | "exclude-from-classmap": [ 296 | "/Tests/" 297 | ] 298 | }, 299 | "notification-url": "https://packagist.org/downloads/", 300 | "license": [ 301 | "MIT" 302 | ], 303 | "authors": [ 304 | { 305 | "name": "Fabien Potencier", 306 | "email": "fabien@symfony.com" 307 | }, 308 | { 309 | "name": "Symfony Community", 310 | "homepage": "https://symfony.com/contributors" 311 | } 312 | ], 313 | "description": "Symfony Console Component", 314 | "homepage": "https://symfony.com", 315 | "time": "2018-01-29T09:03:43+00:00" 316 | }, 317 | { 318 | "name": "symfony/debug", 319 | "version": "v4.0.4", 320 | "source": { 321 | "type": "git", 322 | "url": "https://github.com/symfony/debug.git", 323 | "reference": "c77bb31d0f6310a2ac11e657475d396a92e5dc54" 324 | }, 325 | "dist": { 326 | "type": "zip", 327 | "url": "https://api.github.com/repos/symfony/debug/zipball/c77bb31d0f6310a2ac11e657475d396a92e5dc54", 328 | "reference": "c77bb31d0f6310a2ac11e657475d396a92e5dc54", 329 | "shasum": "" 330 | }, 331 | "require": { 332 | "php": "^7.1.3", 333 | "psr/log": "~1.0" 334 | }, 335 | "conflict": { 336 | "symfony/http-kernel": "<3.4" 337 | }, 338 | "require-dev": { 339 | "symfony/http-kernel": "~3.4|~4.0" 340 | }, 341 | "type": "library", 342 | "extra": { 343 | "branch-alias": { 344 | "dev-master": "4.0-dev" 345 | } 346 | }, 347 | "autoload": { 348 | "psr-4": { 349 | "Symfony\\Component\\Debug\\": "" 350 | }, 351 | "exclude-from-classmap": [ 352 | "/Tests/" 353 | ] 354 | }, 355 | "notification-url": "https://packagist.org/downloads/", 356 | "license": [ 357 | "MIT" 358 | ], 359 | "authors": [ 360 | { 361 | "name": "Fabien Potencier", 362 | "email": "fabien@symfony.com" 363 | }, 364 | { 365 | "name": "Symfony Community", 366 | "homepage": "https://symfony.com/contributors" 367 | } 368 | ], 369 | "description": "Symfony Debug Component", 370 | "homepage": "https://symfony.com", 371 | "time": "2018-01-18T22:19:33+00:00" 372 | }, 373 | { 374 | "name": "symfony/finder", 375 | "version": "v3.4.4", 376 | "source": { 377 | "type": "git", 378 | "url": "https://github.com/symfony/finder.git", 379 | "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f" 380 | }, 381 | "dist": { 382 | "type": "zip", 383 | "url": "https://api.github.com/repos/symfony/finder/zipball/613e26310776f49a1773b6737c6bd554b8bc8c6f", 384 | "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f", 385 | "shasum": "" 386 | }, 387 | "require": { 388 | "php": "^5.5.9|>=7.0.8" 389 | }, 390 | "type": "library", 391 | "extra": { 392 | "branch-alias": { 393 | "dev-master": "3.4-dev" 394 | } 395 | }, 396 | "autoload": { 397 | "psr-4": { 398 | "Symfony\\Component\\Finder\\": "" 399 | }, 400 | "exclude-from-classmap": [ 401 | "/Tests/" 402 | ] 403 | }, 404 | "notification-url": "https://packagist.org/downloads/", 405 | "license": [ 406 | "MIT" 407 | ], 408 | "authors": [ 409 | { 410 | "name": "Fabien Potencier", 411 | "email": "fabien@symfony.com" 412 | }, 413 | { 414 | "name": "Symfony Community", 415 | "homepage": "https://symfony.com/contributors" 416 | } 417 | ], 418 | "description": "Symfony Finder Component", 419 | "homepage": "https://symfony.com", 420 | "time": "2018-01-03T07:37:34+00:00" 421 | }, 422 | { 423 | "name": "symfony/polyfill-mbstring", 424 | "version": "v1.7.0", 425 | "source": { 426 | "type": "git", 427 | "url": "https://github.com/symfony/polyfill-mbstring.git", 428 | "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" 429 | }, 430 | "dist": { 431 | "type": "zip", 432 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", 433 | "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", 434 | "shasum": "" 435 | }, 436 | "require": { 437 | "php": ">=5.3.3" 438 | }, 439 | "suggest": { 440 | "ext-mbstring": "For best performance" 441 | }, 442 | "type": "library", 443 | "extra": { 444 | "branch-alias": { 445 | "dev-master": "1.7-dev" 446 | } 447 | }, 448 | "autoload": { 449 | "psr-4": { 450 | "Symfony\\Polyfill\\Mbstring\\": "" 451 | }, 452 | "files": [ 453 | "bootstrap.php" 454 | ] 455 | }, 456 | "notification-url": "https://packagist.org/downloads/", 457 | "license": [ 458 | "MIT" 459 | ], 460 | "authors": [ 461 | { 462 | "name": "Nicolas Grekas", 463 | "email": "p@tchwork.com" 464 | }, 465 | { 466 | "name": "Symfony Community", 467 | "homepage": "https://symfony.com/contributors" 468 | } 469 | ], 470 | "description": "Symfony polyfill for the Mbstring extension", 471 | "homepage": "https://symfony.com", 472 | "keywords": [ 473 | "compatibility", 474 | "mbstring", 475 | "polyfill", 476 | "portable", 477 | "shim" 478 | ], 479 | "time": "2018-01-30T19:27:44+00:00" 480 | } 481 | ], 482 | "aliases": [], 483 | "minimum-stability": "dev", 484 | "stability-flags": [], 485 | "prefer-stable": true, 486 | "prefer-lowest": false, 487 | "platform": [], 488 | "platform-dev": [] 489 | } 490 | --------------------------------------------------------------------------------