@ -1,395 +0,0 @@ | |||
<?php | |||
/* | |||
Copyright (c) 2008 Sebastián Grignoli | |||
All rights reserved. | |||
Redistribution and use in source and binary forms, with or without | |||
modification, are permitted provided that the following conditions | |||
are met: | |||
1. Redistributions of source code must retain the above copyright | |||
notice, this list of conditions and the following disclaimer. | |||
2. Redistributions in binary form must reproduce the above copyright | |||
notice, this list of conditions and the following disclaimer in the | |||
documentation and/or other materials provided with the distribution. | |||
3. Neither the name of copyright holders nor the names of its | |||
contributors may be used to endorse or promote products derived | |||
from this software without specific prior written permission. | |||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS | |||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
/** | |||
* @author "Sebastián Grignoli" <grignoli@gmail.com> | |||
* @package Encoding | |||
* @version 2.0 | |||
* @link https://github.com/neitanod/forceutf8 | |||
* @example https://github.com/neitanod/forceutf8 | |||
* @license Revised BSD | |||
*/ | |||
class Encoding | |||
{ | |||
const ICONV_TRANSLIT = "TRANSLIT"; | |||
const ICONV_IGNORE = "IGNORE"; | |||
const WITHOUT_ICONV = ""; | |||
protected static $win1252ToUtf8 = array( | |||
128 => "\xe2\x82\xac", | |||
130 => "\xe2\x80\x9a", | |||
131 => "\xc6\x92", | |||
132 => "\xe2\x80\x9e", | |||
133 => "\xe2\x80\xa6", | |||
134 => "\xe2\x80\xa0", | |||
135 => "\xe2\x80\xa1", | |||
136 => "\xcb\x86", | |||
137 => "\xe2\x80\xb0", | |||
138 => "\xc5\xa0", | |||
139 => "\xe2\x80\xb9", | |||
140 => "\xc5\x92", | |||
142 => "\xc5\xbd", | |||
145 => "\xe2\x80\x98", | |||
146 => "\xe2\x80\x99", | |||
147 => "\xe2\x80\x9c", | |||
148 => "\xe2\x80\x9d", | |||
149 => "\xe2\x80\xa2", | |||
150 => "\xe2\x80\x93", | |||
151 => "\xe2\x80\x94", | |||
152 => "\xcb\x9c", | |||
153 => "\xe2\x84\xa2", | |||
154 => "\xc5\xa1", | |||
155 => "\xe2\x80\xba", | |||
156 => "\xc5\x93", | |||
158 => "\xc5\xbe", | |||
159 => "\xc5\xb8" | |||
); | |||
protected static $brokenUtf8ToUtf8 = array( | |||
"\xc2\x80" => "\xe2\x82\xac", | |||
"\xc2\x82" => "\xe2\x80\x9a", | |||
"\xc2\x83" => "\xc6\x92", | |||
"\xc2\x84" => "\xe2\x80\x9e", | |||
"\xc2\x85" => "\xe2\x80\xa6", | |||
"\xc2\x86" => "\xe2\x80\xa0", | |||
"\xc2\x87" => "\xe2\x80\xa1", | |||
"\xc2\x88" => "\xcb\x86", | |||
"\xc2\x89" => "\xe2\x80\xb0", | |||
"\xc2\x8a" => "\xc5\xa0", | |||
"\xc2\x8b" => "\xe2\x80\xb9", | |||
"\xc2\x8c" => "\xc5\x92", | |||
"\xc2\x8e" => "\xc5\xbd", | |||
"\xc2\x91" => "\xe2\x80\x98", | |||
"\xc2\x92" => "\xe2\x80\x99", | |||
"\xc2\x93" => "\xe2\x80\x9c", | |||
"\xc2\x94" => "\xe2\x80\x9d", | |||
"\xc2\x95" => "\xe2\x80\xa2", | |||
"\xc2\x96" => "\xe2\x80\x93", | |||
"\xc2\x97" => "\xe2\x80\x94", | |||
"\xc2\x98" => "\xcb\x9c", | |||
"\xc2\x99" => "\xe2\x84\xa2", | |||
"\xc2\x9a" => "\xc5\xa1", | |||
"\xc2\x9b" => "\xe2\x80\xba", | |||
"\xc2\x9c" => "\xc5\x93", | |||
"\xc2\x9e" => "\xc5\xbe", | |||
"\xc2\x9f" => "\xc5\xb8" | |||
); | |||
protected static $utf8ToWin1252 = array( | |||
"\xe2\x82\xac" => "\x80", | |||
"\xe2\x80\x9a" => "\x82", | |||
"\xc6\x92" => "\x83", | |||
"\xe2\x80\x9e" => "\x84", | |||
"\xe2\x80\xa6" => "\x85", | |||
"\xe2\x80\xa0" => "\x86", | |||
"\xe2\x80\xa1" => "\x87", | |||
"\xcb\x86" => "\x88", | |||
"\xe2\x80\xb0" => "\x89", | |||
"\xc5\xa0" => "\x8a", | |||
"\xe2\x80\xb9" => "\x8b", | |||
"\xc5\x92" => "\x8c", | |||
"\xc5\xbd" => "\x8e", | |||
"\xe2\x80\x98" => "\x91", | |||
"\xe2\x80\x99" => "\x92", | |||
"\xe2\x80\x9c" => "\x93", | |||
"\xe2\x80\x9d" => "\x94", | |||
"\xe2\x80\xa2" => "\x95", | |||
"\xe2\x80\x93" => "\x96", | |||
"\xe2\x80\x94" => "\x97", | |||
"\xcb\x9c" => "\x98", | |||
"\xe2\x84\xa2" => "\x99", | |||
"\xc5\xa1" => "\x9a", | |||
"\xe2\x80\xba" => "\x9b", | |||
"\xc5\x93" => "\x9c", | |||
"\xc5\xbe" => "\x9e", | |||
"\xc5\xb8" => "\x9f" | |||
); | |||
static function toISO8859($text, $option = self::WITHOUT_ICONV) | |||
{ | |||
return self::toWin1252($text, $option); | |||
} | |||
static function toWin1252($text, $option = self::WITHOUT_ICONV) | |||
{ | |||
if (is_array($text)) { | |||
foreach ($text as $k => $v) { | |||
$text[$k] = self::toWin1252($v, $option); | |||
} | |||
return $text; | |||
} elseif (is_string($text)) { | |||
return static::utf8_decode($text, $option); | |||
} else { | |||
return $text; | |||
} | |||
} | |||
protected static function utf8_decode($text, $option = self::WITHOUT_ICONV) | |||
{ | |||
if ($option == self::WITHOUT_ICONV || !function_exists('iconv')) { | |||
$o = utf8_decode( | |||
str_replace(array_keys(self::$utf8ToWin1252), array_values(self::$utf8ToWin1252), self::toUTF8($text)) | |||
); | |||
} else { | |||
$o = iconv("UTF-8", "Windows-1252" . ($option == self::ICONV_TRANSLIT ? '//TRANSLIT' : ($option == self::ICONV_IGNORE ? '//IGNORE' : '')), $text); | |||
} | |||
return $o; | |||
} | |||
static function toUTF8($text) | |||
{ | |||
/** | |||
* Function \ForceUTF8\Encoding::toUTF8 | |||
* | |||
* This function leaves UTF8 characters alone, while converting almost all non-UTF8 to UTF8. | |||
* | |||
* It assumes that the encoding of the original string is either Windows-1252 or ISO 8859-1. | |||
* | |||
* It may fail to convert characters to UTF-8 if they fall into one of these scenarios: | |||
* | |||
* 1) when any of these characters: ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞß | |||
* are followed by any of these: ("group B") | |||
* ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶•¸¹º»¼½¾¿ | |||
* For example: %ABREPRESENT%C9%BB. «REPRESENTÉ» | |||
* The "«" (%AB) character will be converted, but the "É" followed by "»" (%C9%BB) | |||
* is also a valid unicode character, and will be left unchanged. | |||
* | |||
* 2) when any of these: àáâãäåæçèéêëìíîï are followed by TWO chars from group B, | |||
* 3) when any of these: ðñòó are followed by THREE chars from group B. | |||
* | |||
* @name toUTF8 | |||
* @param string $text Any string. | |||
* @return string The same string, UTF8 encoded | |||
* | |||
*/ | |||
if (is_array($text)) { | |||
foreach ($text as $k => $v) { | |||
$text[$k] = self::toUTF8($v); | |||
} | |||
return $text; | |||
} | |||
if (!is_string($text)) { | |||
return $text; | |||
} | |||
$max = self::strlen($text); | |||
$buf = ""; | |||
for ($i = 0; $i < $max; $i++) { | |||
$c1 = $text{$i}; | |||
if ($c1 >= "\xc0") { //Should be converted to UTF8, if it's not UTF8 already | |||
$c2 = $i + 1 >= $max ? "\x00" : $text{$i + 1}; | |||
$c3 = $i + 2 >= $max ? "\x00" : $text{$i + 2}; | |||
$c4 = $i + 3 >= $max ? "\x00" : $text{$i + 3}; | |||
if ($c1 >= "\xc0" & $c1 <= "\xdf") { //looks like 2 bytes UTF8 | |||
if ($c2 >= "\x80" && $c2 <= "\xbf") { //yeah, almost sure it's UTF8 already | |||
$buf .= $c1 . $c2; | |||
$i++; | |||
} else { //not valid UTF8. Convert it. | |||
$cc1 = (chr(ord($c1) / 64) | "\xc0"); | |||
$cc2 = ($c1 & "\x3f") | "\x80"; | |||
$buf .= $cc1 . $cc2; | |||
} | |||
} elseif ($c1 >= "\xe0" & $c1 <= "\xef") { //looks like 3 bytes UTF8 | |||
if ($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf") { //yeah, almost sure it's UTF8 already | |||
$buf .= $c1 . $c2 . $c3; | |||
$i = $i + 2; | |||
} else { //not valid UTF8. Convert it. | |||
$cc1 = (chr(ord($c1) / 64) | "\xc0"); | |||
$cc2 = ($c1 & "\x3f") | "\x80"; | |||
$buf .= $cc1 . $cc2; | |||
} | |||
} elseif ($c1 >= "\xf0" & $c1 <= "\xf7") { //looks like 4 bytes UTF8 | |||
if ($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf" && $c4 >= "\x80" && $c4 <= "\xbf") { //yeah, almost sure it's UTF8 already | |||
$buf .= $c1 . $c2 . $c3 . $c4; | |||
$i = $i + 3; | |||
} else { //not valid UTF8. Convert it. | |||
$cc1 = (chr(ord($c1) / 64) | "\xc0"); | |||
$cc2 = ($c1 & "\x3f") | "\x80"; | |||
$buf .= $cc1 . $cc2; | |||
} | |||
} else { //doesn't look like UTF8, but should be converted | |||
$cc1 = (chr(ord($c1) / 64) | "\xc0"); | |||
$cc2 = (($c1 & "\x3f") | "\x80"); | |||
$buf .= $cc1 . $cc2; | |||
} | |||
} elseif (($c1 & "\xc0") == "\x80") { // needs conversion | |||
if (isset(self::$win1252ToUtf8[ord($c1)])) { //found in Windows-1252 special cases | |||
$buf .= self::$win1252ToUtf8[ord($c1)]; | |||
} else { | |||
$cc1 = (chr(ord($c1) / 64) | "\xc0"); | |||
$cc2 = (($c1 & "\x3f") | "\x80"); | |||
$buf .= $cc1 . $cc2; | |||
} | |||
} else { // it doesn't need conversion | |||
$buf .= $c1; | |||
} | |||
} | |||
return $buf; | |||
} | |||
protected static function strlen($text) | |||
{ | |||
return (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload')) & 2) ? | |||
mb_strlen($text, '8bit') : strlen($text); | |||
} | |||
static function fixUTF8($text, $option = self::WITHOUT_ICONV) | |||
{ | |||
if (is_array($text)) { | |||
foreach ($text as $k => $v) { | |||
$text[$k] = self::fixUTF8($v, $option); | |||
} | |||
return $text; | |||
} | |||
if (!is_string($text)) { | |||
return $text; | |||
} | |||
$last = ""; | |||
while ($last <> $text) { | |||
$last = $text; | |||
$text = self::toUTF8(static::utf8_decode($text, $option)); | |||
} | |||
$text = self::toUTF8(static::utf8_decode($text, $option)); | |||
return $text; | |||
} | |||
static function UTF8FixWin1252Chars($text) | |||
{ | |||
// If you received an UTF-8 string that was converted from Windows-1252 as it was ISO8859-1 | |||
// (ignoring Windows-1252 chars from 80 to 9F) use this function to fix it. | |||
// See: http://en.wikipedia.org/wiki/Windows-1252 | |||
return str_replace(array_keys(self::$brokenUtf8ToUtf8), array_values(self::$brokenUtf8ToUtf8), $text); | |||
} | |||
static function removeBOM($str = "") | |||
{ | |||
if (substr($str, 0, 3) == pack("CCC", 0xef, 0xbb, 0xbf)) { | |||
$str = substr($str, 3); | |||
} | |||
return $str; | |||
} | |||
public static function encode($encodingLabel, $text) | |||
{ | |||
$encodingLabel = self::normalizeEncoding($encodingLabel); | |||
if ($encodingLabel == 'ISO-8859-1') return self::toLatin1($text); | |||
return self::toUTF8($text); | |||
} | |||
public static function normalizeEncoding($encodingLabel) | |||
{ | |||
$encoding = strtoupper($encodingLabel); | |||
$encoding = preg_replace('/[^a-zA-Z0-9\s]/', '', $encoding); | |||
$equivalences = array( | |||
'ISO88591' => 'ISO-8859-1', | |||
'ISO8859' => 'ISO-8859-1', | |||
'ISO' => 'ISO-8859-1', | |||
'LATIN1' => 'ISO-8859-1', | |||
'LATIN' => 'ISO-8859-1', | |||
'UTF8' => 'UTF-8', | |||
'UTF' => 'UTF-8', | |||
'WIN1252' => 'ISO-8859-1', | |||
'WINDOWS1252' => 'ISO-8859-1' | |||
); | |||
if (empty($equivalences[$encoding])) { | |||
return 'UTF-8'; | |||
} | |||
return $equivalences[$encoding]; | |||
} | |||
static function toLatin1($text, $option = self::WITHOUT_ICONV) | |||
{ | |||
return self::toWin1252($text, $option); | |||
} | |||
/****/ | |||
public static function destructionH4x0RChaine($chaine) | |||
{ | |||
return preg_replace('#[\x00-\x1F\x7F-\x9F/\\\\]#', '', $chaine); | |||
} | |||
public static function protectionDoubleQuote($chaine) | |||
{ | |||
$chaine = preg_replace('/"(\w+)"/', '« ${1} »', $chaine); | |||
$chaine = preg_replace('#"#', '_', $chaine); | |||
return $chaine; | |||
} | |||
public static function protectionSimpleQuote($chaine) | |||
{ | |||
$chaine = preg_replace("#'#", '_', $chaine); | |||
return $chaine; | |||
} | |||
public static function myUrlEncode($string) | |||
{ | |||
$replacements = array('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D'/*, '%2B'*/, '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D'); | |||
$entities = array('!', '*', "'", "(", ")", ";", ":", "@", "&", "="/*, "+"*/, "$", ",", "/", "?", "%", "#", "[", "]"); | |||
$string = urlencode($string); | |||
$string = str_replace($entities, $replacements, $string); | |||
return $string; | |||
} | |||
public static function myUrlDecode($string) | |||
{ | |||
$entities = array('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D'/*, '%2B'*/, '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D'); | |||
$replacements = array('!', '*', "'", "(", ")", ";", ":", "@", "&", "="/*, "+"*/, "$", ",", "/", "?", "%", "#", "[", "]"); | |||
$string = str_replace($entities, $replacements, $string); | |||
$string = urldecode($string); | |||
return $string; | |||
} | |||
} |
@ -1,103 +0,0 @@ | |||
forceutf8 | |||
========= | |||
PHP Class Encoding featuring popular \ForceUTF8\Encoding::toUTF8() function --formerly known as forceUTF8()-- that fixes mixed encoded strings. | |||
Description | |||
=========== | |||
If you apply the PHP function utf8_encode() to an already-UTF8 string it will return a garbled UTF8 string. | |||
This class addresses this issue and provides a handy static function called \ForceUTF8\Encoding::toUTF8(). | |||
You don't need to know what the encoding of your strings is. It can be Latin1 (ISO 8859-1), Windows-1252 or UTF8, or the string can have a mix of them. \ForceUTF8\Encoding::toUTF8() will convert everything to UTF8. | |||
Sometimes you have to deal with services that are unreliable in terms of encoding, possibly mixing UTF8 and Latin1 in the same string. | |||
Update: | |||
I've included another function, \ForceUTF8\Encoding::fixUTF8(), which will fix the double (or multiple) encoded UTF8 string that looks garbled. | |||
Usage: | |||
====== | |||
use \ForceUTF8\Encoding; | |||
$utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string); | |||
$latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string); | |||
also: | |||
$utf8_string = Encoding::fixUTF8($garbled_utf8_string); | |||
Examples: | |||
use \ForceUTF8\Encoding; | |||
echo Encoding::fixUTF8("Fédération Camerounaise de Football\n"); | |||
echo Encoding::fixUTF8("Fédération Camerounaise de Football\n"); | |||
echo Encoding::fixUTF8("Fédération Camerounaise de Football\n"); | |||
echo Encoding::fixUTF8("Fédération Camerounaise de Football\n"); | |||
will output: | |||
Fédération Camerounaise de Football | |||
Fédération Camerounaise de Football | |||
Fédération Camerounaise de Football | |||
Fédération Camerounaise de Football | |||
Options: | |||
======== | |||
By default, `Encoding::fixUTF8` will use the `Encoding::WITHOUT_ICONV` flag, signalling that iconv should not be used to fix garbled UTF8 strings. | |||
This class also provides options for iconv processing, such as `Encoding::ICONV_TRANSLIT` and `Encoding::ICONV_IGNORE` to enable these flags when the iconv class is utilized. The functionality of such flags are documented in the [PHP iconv documentation](http://php.net/manual/en/function.iconv.php). | |||
Examples: | |||
use \ForceUTF8\Encoding; | |||
$str = "Fédération Camerounaise—de—Football\n"; // Uses U+2014 which is invalid ISO8859-1 but exists in Win1252 | |||
echo Encoding::fixUTF8($str); // Will break U+2014 | |||
echo Encoding::fixUTF8($str, Encoding::ICONV_IGNORE); // Will preserve U+2014 | |||
echo Encoding::fixUTF8($str, Encoding::ICONV_TRANSLIT); // Will preserve U+2014 | |||
will output: | |||
Fédération Camerounaise?de?Football | |||
Fédération Camerounaise—de—Football | |||
Fédération Camerounaise—de—Football | |||
while: | |||
use \ForceUTF8\Encoding; | |||
$str = "čęėįšųūž"; // Uses several characters not present in ISO8859-1 / Win1252 | |||
echo Encoding::fixUTF8($str); // Will break invalid characters | |||
echo Encoding::fixUTF8($str, Encoding::ICONV_IGNORE); // Will remove invalid characters, keep those present in Win1252 | |||
echo Encoding::fixUTF8($str, Encoding::ICONV_TRANSLIT); // Will trasliterate invalid characters, keep those present in Win1252 | |||
will output: | |||
???????? | |||
šž | |||
ceeišuuž | |||
Install via composer: | |||
===================== | |||
Edit your composer.json file to include the following: | |||
```json | |||
{ | |||
"require": { | |||
"neitanod/forceutf8": "~2.0" | |||
} | |||
} | |||
``` | |||
Tips: | |||
===== | |||
You can tip me with Bitcoin if you want. :) | |||
<img src="resources/wallet.jpg" width="225" alt="1Awfu4TZpy99H7Pyzt1mooxU1aP2mJVdHP"> |
@ -1,324 +0,0 @@ | |||
<?php | |||
/** | |||
* A Compatibility library with PHP 5.5's simplified password hashing API. | |||
* | |||
* @author Anthony Ferrara <ircmaxell@php.net> | |||
* @license http://www.opensource.org/licenses/mit-license.html MIT License | |||
* @copyright 2012 The Authors | |||
*/ | |||
namespace { | |||
if (!defined('PASSWORD_BCRYPT')) { | |||
/** | |||
* PHPUnit Process isolation caches constants, but not function declarations. | |||
* So we need to check if the constants are defined separately from | |||
* the functions to enable supporting process isolation in userland | |||
* code. | |||
*/ | |||
define('PASSWORD_BCRYPT', 1); | |||
define('PASSWORD_DEFAULT', PASSWORD_BCRYPT); | |||
define('PASSWORD_BCRYPT_DEFAULT_COST', 10); | |||
} | |||
if (!function_exists('password_hash')) { | |||
/** | |||
* Hash the password using the specified algorithm | |||
* | |||
* @param string $password The password to hash | |||
* @param int $algo The algorithm to use (Defined by PASSWORD_* constants) | |||
* @param array $options The options for the algorithm to use | |||
* | |||
* @return string|false The hashed password, or false on error. | |||
*/ | |||
function password_hash($password, $algo, array $options = array()) | |||
{ | |||
if (!function_exists('crypt')) { | |||
trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING); | |||
return null; | |||
} | |||
if (is_null($password) || is_int($password)) { | |||
$password = (string)$password; | |||
} | |||
if (!is_string($password)) { | |||
trigger_error("password_hash(): Password must be a string", E_USER_WARNING); | |||
return null; | |||
} | |||
if (!is_int($algo)) { | |||
trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING); | |||
return null; | |||
} | |||
$resultLength = 0; | |||
switch ($algo) { | |||
case PASSWORD_BCRYPT: | |||
$cost = PASSWORD_BCRYPT_DEFAULT_COST; | |||
if (isset($options['cost'])) { | |||
$cost = (int)$options['cost']; | |||
if ($cost < 4 || $cost > 31) { | |||
trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING); | |||
return null; | |||
} | |||
} | |||
// The length of salt to generate | |||
$raw_salt_len = 16; | |||
// The length required in the final serialization | |||
$required_salt_len = 22; | |||
$hash_format = sprintf("$2y$%02d$", $cost); | |||
// The expected length of the final crypt() output | |||
$resultLength = 60; | |||
break; | |||
default: | |||
trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING); | |||
return null; | |||
} | |||
$salt_req_encoding = false; | |||
if (isset($options['salt'])) { | |||
switch (gettype($options['salt'])) { | |||
case 'NULL': | |||
case 'boolean': | |||
case 'integer': | |||
case 'double': | |||
case 'string': | |||
$salt = (string)$options['salt']; | |||
break; | |||
case 'object': | |||
if (method_exists($options['salt'], '__tostring')) { | |||
$salt = (string)$options['salt']; | |||
break; | |||
} | |||
case 'array': | |||
case 'resource': | |||
default: | |||
trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING); | |||
return null; | |||
} | |||
if (PasswordCompat\binary\_strlen($salt) < $required_salt_len) { | |||
trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", PasswordCompat\binary\_strlen($salt), $required_salt_len), E_USER_WARNING); | |||
return null; | |||
} elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) { | |||
$salt_req_encoding = true; | |||
} | |||
} else { | |||
$buffer = ''; | |||
$buffer_valid = false; | |||
if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) { | |||
$buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM); | |||
if ($buffer) { | |||
$buffer_valid = true; | |||
} | |||
} | |||
if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) { | |||
$strong = false; | |||
$buffer = openssl_random_pseudo_bytes($raw_salt_len, $strong); | |||
if ($buffer && $strong) { | |||
$buffer_valid = true; | |||
} | |||
} | |||
if (!$buffer_valid && @is_readable('/dev/urandom')) { | |||
$file = fopen('/dev/urandom', 'r'); | |||
$read = 0; | |||
$local_buffer = ''; | |||
while ($read < $raw_salt_len) { | |||
$local_buffer .= fread($file, $raw_salt_len - $read); | |||
$read = PasswordCompat\binary\_strlen($local_buffer); | |||
} | |||
fclose($file); | |||
if ($read >= $raw_salt_len) { | |||
$buffer_valid = true; | |||
} | |||
$buffer = str_pad($buffer, $raw_salt_len, "\0") ^ str_pad($local_buffer, $raw_salt_len, "\0"); | |||
} | |||
if (!$buffer_valid || PasswordCompat\binary\_strlen($buffer) < $raw_salt_len) { | |||
$buffer_length = PasswordCompat\binary\_strlen($buffer); | |||
for ($i = 0; $i < $raw_salt_len; $i++) { | |||
if ($i < $buffer_length) { | |||
$buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255)); | |||
} else { | |||
$buffer .= chr(mt_rand(0, 255)); | |||
} | |||
} | |||
} | |||
$salt = $buffer; | |||
$salt_req_encoding = true; | |||
} | |||
if ($salt_req_encoding) { | |||
// encode string with the Base64 variant used by crypt | |||
$base64_digits = | |||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; | |||
$bcrypt64_digits = | |||
'./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; | |||
$base64_string = base64_encode($salt); | |||
$salt = strtr(rtrim($base64_string, '='), $base64_digits, $bcrypt64_digits); | |||
} | |||
$salt = PasswordCompat\binary\_substr($salt, 0, $required_salt_len); | |||
$hash = $hash_format . $salt; | |||
$ret = crypt($password, $hash); | |||
if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != $resultLength) { | |||
return false; | |||
} | |||
return $ret; | |||
} | |||
/** | |||
* Get information about the password hash. Returns an array of the information | |||
* that was used to generate the password hash. | |||
* | |||
* array( | |||
* 'algo' => 1, | |||
* 'algoName' => 'bcrypt', | |||
* 'options' => array( | |||
* 'cost' => PASSWORD_BCRYPT_DEFAULT_COST, | |||
* ), | |||
* ) | |||
* | |||
* @param string $hash The password hash to extract info from | |||
* | |||
* @return array The array of information about the hash. | |||
*/ | |||
function password_get_info($hash) | |||
{ | |||
$return = array( | |||
'algo' => 0, | |||
'algoName' => 'unknown', | |||
'options' => array(), | |||
); | |||
if (PasswordCompat\binary\_substr($hash, 0, 4) == '$2y$' && PasswordCompat\binary\_strlen($hash) == 60) { | |||
$return['algo'] = PASSWORD_BCRYPT; | |||
$return['algoName'] = 'bcrypt'; | |||
list($cost) = sscanf($hash, "$2y$%d$"); | |||
$return['options']['cost'] = $cost; | |||
} | |||
return $return; | |||
} | |||
/** | |||
* Determine if the password hash needs to be rehashed according to the options provided | |||
* | |||
* If the answer is true, after validating the password using password_verify, rehash it. | |||
* | |||
* @param string $hash The hash to test | |||
* @param int $algo The algorithm used for new password hashes | |||
* @param array $options The options array passed to password_hash | |||
* | |||
* @return boolean True if the password needs to be rehashed. | |||
*/ | |||
function password_needs_rehash($hash, $algo, array $options = array()) | |||
{ | |||
$info = password_get_info($hash); | |||
if ($info['algo'] !== (int)$algo) { | |||
return true; | |||
} | |||
switch ($algo) { | |||
case PASSWORD_BCRYPT: | |||
$cost = isset($options['cost']) ? (int)$options['cost'] : PASSWORD_BCRYPT_DEFAULT_COST; | |||
if ($cost !== $info['options']['cost']) { | |||
return true; | |||
} | |||
break; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Verify a password against a hash using a timing attack resistant approach | |||
* | |||
* @param string $password The password to verify | |||
* @param string $hash The hash to verify against | |||
* | |||
* @return boolean If the password matches the hash | |||
*/ | |||
function password_verify($password, $hash) | |||
{ | |||
if (!function_exists('crypt')) { | |||
trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING); | |||
return false; | |||
} | |||
$ret = crypt($password, $hash); | |||
if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != PasswordCompat\binary\_strlen($hash) || PasswordCompat\binary\_strlen($ret) <= 13) { | |||
return false; | |||
} | |||
$status = 0; | |||
for ($i = 0; $i < PasswordCompat\binary\_strlen($ret); $i++) { | |||
$status |= (ord($ret[$i]) ^ ord($hash[$i])); | |||
} | |||
return $status === 0; | |||
} | |||
} | |||
} | |||
namespace PasswordCompat\binary { | |||
if (!function_exists('PasswordCompat\\binary\\_strlen')) { | |||
/** | |||
* Count the number of bytes in a string | |||
* | |||
* We cannot simply use strlen() for this, because it might be overwritten by the mbstring extension. | |||
* In this case, strlen() will count the number of *characters* based on the internal encoding. A | |||
* sequence of bytes might be regarded as a single multibyte character. | |||
* | |||
* @param string $binary_string The input string | |||
* | |||
* @return int The number of bytes | |||
* @internal | |||
*/ | |||
function _strlen($binary_string) | |||
{ | |||
if (function_exists('mb_strlen')) { | |||
return mb_strlen($binary_string, '8bit'); | |||
} | |||
return strlen($binary_string); | |||
} | |||
/** | |||
* Get a substring based on byte limits | |||
* | |||
* @param string $binary_string The input string | |||
* @param int $start | |||
* @param int $length | |||
* | |||
* @return string The substring | |||
* @internal | |||
* @see _strlen() | |||
* | |||
*/ | |||
function _substr($binary_string, $start, $length) | |||
{ | |||
if (function_exists('mb_substr')) { | |||
return mb_substr($binary_string, $start, $length, '8bit'); | |||
} | |||
return substr($binary_string, $start, $length); | |||
} | |||
/** | |||
* Check if current PHP version is compatible with the library | |||
* | |||
* @return boolean the check result | |||
*/ | |||
function check() | |||
{ | |||
static $pass = NULL; | |||
if (is_null($pass)) { | |||
if (function_exists('crypt')) { | |||
$hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG'; | |||
$test = crypt("password", $hash); | |||
$pass = $test == $hash; | |||
} else { | |||
$pass = false; | |||
} | |||
} | |||
return $pass; | |||
} | |||
} | |||
} |
@ -1,81 +0,0 @@ | |||
password_compat | |||
=============== | |||
[](https://travis-ci.org/ircmaxell/password_compat) [](https://codeclimate.com/github/ircmaxell/password_compat) | |||
This library is intended to provide forward compatibility with the [password_*](http://php.net/password) functions that ship with PHP 5.5. | |||
See [the RFC](https://wiki.php.net/rfc/password_hash) for more detailed information. | |||
Requirements | |||
============ | |||
This library requires `PHP >= 5.3.7` OR a version that has the `$2y` fix backported into it (such as RedHat provides). Note that Debian's 5.3.3 version is **NOT** supported. | |||
The runtime checks have been removed due to this version issue. To see if password_compat is available for your system, run the included `version-test.php`. If it outputs "Pass", you can safely use the library. If not, you cannot. | |||
If you attempt to use password-compat on an unsupported version, attempts to create or verify hashes will return `false`. You have been warned! | |||
The reason for this is that PHP prior to 5.3.7 contains a [security issue with its BCRYPT implementation](http://php.net/security/crypt_blowfish.php). Therefore, it's highly recommended that you upgrade to a newer version of PHP prior to using this layer. | |||
Installation | |||
============ | |||
To install, simply `require` the `password.php` file under `lib`. | |||
You can also install it via `Composer` by using the [Packagist archive](http://packagist.org/packages/ircmaxell/password-compat). | |||
Usage | |||
===== | |||
**Creating Password Hashes** | |||
To create a password hash from a password, simply use the `password_hash` function. | |||
````PHP | |||
$hash = password_hash($password, PASSWORD_BCRYPT); | |||
```` | |||
Note that the algorithm that we chose is `PASSWORD_BCRYPT`. That's the current strongest algorithm supported. This is the `BCRYPT` crypt algorithm. It produces a 60 character hash as the result. | |||
`BCRYPT` also allows for you to define a `cost` parameter in the options array. This allows for you to change the CPU cost of the algorithm: | |||
````PHP | |||
$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 10)); | |||
```` | |||
That's the same as the default. The cost can range from `4` to `31`. I would suggest that you use the highest cost that you can, while keeping response time reasonable (I target between 0.1 and 0.5 seconds for a hash, depending on use-case). | |||
Another algorithm name is supported: | |||
````PHP | |||
PASSWORD_DEFAULT | |||
```` | |||
This will use the strongest algorithm available to PHP at the current time. Presently, this is the same as specifying `PASSWORD_BCRYPT`. But in future versions of PHP, it may be updated to use a stronger algorithm if one is introduced. It can also be changed if a problem is identified with the BCRYPT algorithm. Note that if you use this option, you are **strongly** encouraged to store it in a `VARCHAR(255)` column to avoid truncation issues if a future algorithm increases the length of the generated hash. | |||
It is very important that you should check the return value of `password_hash` prior to storing it, because `false` or `null` may be returned if it encountered an error. | |||
**Verifying Password Hashes** | |||
To verify a hash created by `password_hash`, simply call: | |||
````PHP | |||
if (password_verify($password, $hash)) { | |||
/* Valid */ | |||
} else { | |||
/* Invalid */ | |||
} | |||
```` | |||
That's all there is to it. | |||
**Rehashing Passwords** | |||
From time to time you may update your hashing parameters (algorithm, cost, etc). So a function to determine if rehashing is necessary is available: | |||
````PHP | |||
if (password_verify($password, $hash)) { | |||
if (password_needs_rehash($hash, $algorithm, $options)) { | |||
$hash = password_hash($password, $algorithm, $options); | |||
/* Store new hash in db */ | |||
} | |||
} | |||
```` | |||
Security Vulnerabilities | |||
======================== | |||
If you have found a security issue, please contact the author directly at [ircmaxell@php.net](mailto:ircmaxell@php.net). |
@ -0,0 +1,42 @@ | |||
<?php | |||
class StringCompat | |||
{ | |||
public static function destructionH4x0RChaine($chaine) | |||
{ | |||
return preg_replace('#[\x00-\x1F\x7F-\x9F/\\\\]#', '', $chaine); | |||
} | |||
public static function protectionDoubleQuote($chaine) | |||
{ | |||
$chaine = preg_replace('/"(\w+)"/', '« ${1} »', $chaine); | |||
$chaine = preg_replace('#"#', '_', $chaine); | |||
return $chaine; | |||
} | |||
public static function protectionSimpleQuote($chaine) | |||
{ | |||
$chaine = preg_replace("#'#", '_', $chaine); | |||
return $chaine; | |||
} | |||
public static function myUrlEncode($string) | |||
{ | |||
$replacements = array('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D'/*, '%2B'*/, '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D'); | |||
$entities = array('!', '*', "'", "(", ")", ";", ":", "@", "&", "="/*, "+"*/, "$", ",", "/", "?", "%", "#", "[", "]"); | |||
$string = urlencode($string); | |||
$string = str_replace($entities, $replacements, $string); | |||
return $string; | |||
} | |||
public static function myUrlDecode($string) | |||
{ | |||
$entities = array('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D'/*, '%2B'*/, '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D'); | |||
$replacements = array('!', '*', "'", "(", ")", ";", ":", "@", "&", "="/*, "+"*/, "$", ",", "/", "?", "%", "#", "[", "]"); | |||
$string = str_replace($entities, $replacements, $string); | |||
$string = urldecode($string); | |||
return $string; | |||
} | |||
} |
@ -0,0 +1,6 @@ | |||
<?php | |||
$title = 'Attendez! Gougou<inf>cherche</sup>Le And co© cherche le résultat pour vous'; | |||
$metaDesc = 'Voici le résultat de votre recherche a partir d\'une Bide-Badass page'; | |||
$dateCreation = '20150517'; | |||
$dateRevision = '20150517'; |
@ -0,0 +1,11 @@ | |||
<h2><?php echo $title?></h2> | |||
<div id="cse-search-results"></div> | |||
<script type="text/javascript"> | |||
var googleSearchIframeName = "cse-search-results"; | |||
var googleSearchFormName = "cse-search-box"; | |||
var googleSearchFrameWidth = 800; | |||
var googleSearchDomain = "www.google.fr"; | |||
var googleSearchPath = "/cse"; | |||
</script> | |||
<script type="text/javascript" src="http://www.google.com/afsonline/show_afs_search.js"></script> | |||
@ -0,0 +1,11 @@ | |||
{ | |||
"autoload": { | |||
"psr-4": { | |||
"\\":"./app/class" | |||
} | |||
}, | |||
"require": { | |||
"neitanod/forceutf8": "~2.0", | |||
"ircmaxell/password-compat": "^1.0" | |||
} | |||
} |
@ -0,0 +1,20 @@ | |||
<?php | |||
require dirname(dirname(__FILE__)). DIRECTORY_SEPARATOR . "vendor" . DIRECTORY_SEPARATOR . "autoload.php"; | |||
define('PUBLIC_PATH', dirname(__FILE__)); | |||
define('APPLICATION_PATH', dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . "app"); | |||
define('PAGES_PATH', APPLICATION_PATH . DIRECTORY_SEPARATOR . "page"); | |||
define('LAYOUT_PATH', APPLICATION_PATH . DIRECTORY_SEPARATOR . "layout"); | |||
require APPLICATION_PATH . DIRECTORY_SEPARATOR . 'session.php'; | |||
//pour chaque page et mise en tampon | |||
ob_start(); | |||
require_once PAGES_PATH . DIRECTORY_SEPARATOR . 'Gougou-search-results.php'; | |||
require_once PAGES_PATH . DIRECTORY_SEPARATOR . 'Gougou-search-results.phtml'; | |||
$content = ob_get_contents(); | |||
ob_end_clean(); | |||
require_once LAYOUT_PATH . DIRECTORY_SEPARATOR . $layout . '.phtml'; |