Intial Commit, maybe with errors ! Not tested on a web-server !

This commit is contained in:
Emmanuel ROY 2019-11-09 10:33:06 +01:00
commit ec1d41e8d4
16 changed files with 3043 additions and 0 deletions

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8" ?>
<brute-force-attack>
</brute-force-attack>

View File

@ -0,0 +1,384 @@
<?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 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;
}
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;
}
}
static function toISO8859($text, $option = self::WITHOUT_ICONV) {
return self::toWin1252($text, $option);
}
static function toLatin1($text, $option = self::WITHOUT_ICONV) {
return self::toWin1252($text, $option);
}
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;
}
protected static function strlen($text){
return (function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) ?
mb_strlen($text,'8bit') : strlen($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];
}
public static function encode($encodingLabel, $text)
{
$encodingLabel = self::normalizeEncoding($encodingLabel);
if($encodingLabel == 'ISO-8859-1') return self::toLatin1($text);
return self::toUTF8($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;
}
/****/
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;
}
}

103
app/class/encoding.readme Normal file
View File

@ -0,0 +1,103 @@
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">

View File

@ -0,0 +1,317 @@
<?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
*
* @internal
* @return int The number of bytes
*/
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
*
* @see _strlen()
*
* @param string $binary_string The input string
* @param int $start
* @param int $length
*
* @internal
* @return string The substring
*/
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;
}
}
}

81
app/class/password.readme Normal file
View File

@ -0,0 +1,81 @@
password_compat
===============
[![Build Status](https://travis-ci.org/ircmaxell/password_compat.png?branch=master)](https://travis-ci.org/ircmaxell/password_compat) [![Code Climate](https://codeclimate.com/github/ircmaxell/password_compat/badges/gpa.svg)](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).

24
app/layout/footer.php Normal file
View File

@ -0,0 +1,24 @@
<footer>
<p>&copy; Unachieved <a href="http://www.evolutis.fr/">Evolutis</a> & <a href="http://www.ip-formation.com/">IP-formation</a> 2011 - develloped by Emmanuel ROY on an Debian dev2 original totally reindexed by sadness</p>
</footer>
<!-- JavaScript at the bottom for fast page loading -->
<script src="js/markdown.js"></script>
<script>
function Editor(input, preview) {
this.update = function () {
preview.innerHTML = markdown.toHTML(input.value);
};
input.editor = this;
this.update();
}
var $ = function (id) { return document.getElementById(id); };
new Editor($("text-input"), $("preview"));
</script>
</body>
</html>

72
app/layout/header.php Normal file
View File

@ -0,0 +1,72 @@
<!DOCTYPE html>
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!-- Consider adding a manifest.appcache: h5bp.com/d/Offline -->
<!--[if gt IE 8]><!--> <html class="no-js" lang="fr"> <!--<![endif]-->
<head>
<META charset="utf-8">
<META NAME="Category" CONTENT=""/>
<META NAME="Publisher" CONTENT="Emmanuel ROY"/>
<META NAME="Copyright" CONTENT="© - 2015 - Acksop"/>
<META NAME="Expires" CONTENT="Never Maybe!"/>
<META NAME="Distribution" CONTENT="Global"/>
<META NAME='Description' lang='<?php echo $lang; ?>' CONTENT="<?php echo $metaDesc ?>"/>
<META NAME='Identifier-URL' CONTENT="new.emmanuelroy.name/<?php echo $page['name'] ?>"/>
<?php
/*Rich META from google
<meta name="department" content="legal" />
<meta name="audience" content="all" />
<meta name="doc_status" content="draft" />
//a utiliser avec un syteme de classement utilisateur
<meta name="rating" content="5" />
//link: http://en.wikipedia.org/wiki/Smart_tag_%28Microsoft%29
<meta name="mssmarttagspreventparsing" content="..." />
//link: https://support.google.com/customsearch/answer/2595557?hl=fr
<meta name="verify-v1" content="..." />
*/
?>
<META NAME='Keywords' lang='fr' CONTENT="Art, Programming, Languages, Personnal Website, Curriculum Vitae Multimédia"/>
<META NAME="Author" CONTENT="<?php if(isset($auteur)){ echo $auteur; }else {echo 'Emmanuel ROY And More'; } ?>"/>
<META NAME="Reply-to" CONTENT="contact@emmanuelroy.name"/>
<META NAME="Date-Creation-yyyymmdd" CONTENT="<?php echo $dateCreation ?>"/>
<META NAME="Date-Revision-yyyymmdd" CONTENT="<?php echo $dateRevision ?>"/>
<META NAME="Revisit-After" CONTENT="365,333333333333333333333333333... - 1 days"/>
<META NAME="Robots" CONTENT="index, nofollow"/>
<META NAME="GOOGLEBOT" CONTENT="NOARCHIVE"/>
<META NAME="the-WAYBACK-MACHINE" CONTENT="ARCHIVE"/>
<!-- Use the .htaccess and remove these lines to avoid edge case issues.
More info: h5bp.com/i/378 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title><?php echo $title ?></title>
<!-- Mobile viewport optimized: h5bp.com/viewport -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Place favicon.ico and apple-touch-icon.png in the root directory: mathiasbynens.be/notes/touch-icons -->
<!--<link rel="stylesheet" href="/css/style.css" />-->
<!-- More ideas for your <head> here: h5bp.com/d/head-Tips -->
<!-- All JavaScript at the bottom, except this Modernizr build.
Modernizr enables HTML5 elements & feature detects for optimal performance.
Create your own custom Modernizr build: www.modernizr.com/download/ -->
<!-- <script src="/js/libs/modernizr-2.5.3.min.js"></script>-->
</head>
<body>
<!-- Prompt IE 6 users to install Chrome Frame. Remove this if you support IE 6.
chromium.org/developers/how-tos/chrome-frame-getting-started -->
<!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->

View File

@ -0,0 +1,21 @@
<?php include LAYOUT_PATH . DIRECTORY_SEPARATOR .'header.php';?>
<!--
<header>
<h2>Ceci est le header de la page <?php echo $page['name'] ?></h2>
</header>
-->
<br /><br /><br />
<?php echo $content ?>
<br /><br /><br />
<!--
<footer>
<h2>Ceci est le footer de la page <?php echo $page['name'] ?></h2>
</footer>
-->
<?php include LAYOUT_PATH . DIRECTORY_SEPARATOR .'footer.php';?>

View File

@ -0,0 +1,7 @@
<?php
$title = 'Envoi d\'un lien de veille et stokage en XML';
$metaDesc = 'CV - Emmanuel ROY - chatbot pour tinternet';
$dateCreation = '20191107';
$dateRevision = '20191107';
$encoding = 'utf-8';
$layout = 'layout_codage';

View File

@ -0,0 +1,29 @@
<form method="post" action="/traitementEnvoiLienVeilleTinternet.php">
<textarea id="text-input" oninput="this.editor.update()"
rows="6" cols="60">Type **Markdown** here.</textarea>
<div id="preview"> </div>
<textarea class='span8' name=message id=message tabindex="1" cols="80" rows="5" required><?php if(isset($_GET['message'])){echo Encoding::myUrlDecode($_GET['message']);}?></textarea>
<div class="clearfix" style="padding: 14px 200px;">
<input class="btn primary" name="password" type="password" id="password" tabindex="2" required />
</div>
<div class="clearfix" style="padding: 14px 200px;">
<input class="btn primary" name="submit" type="submit" id="submit" tabindex="3" value="Envoyer" />
</div>
</form>
<br /><br />
<div id='mattermostform_success'></div>
<?php
if(isset($_GET['envoiDuMessage'])){
if($_GET['envoiDuMessage'] == 'oui'){
echo "<p>La veille Mattermost as &eacute;t&eacute; correctement transmis.</p>";
}else{
echo "<p>La veille Mattermost n'as pas &eacute;t&eacute; transmis. Veuillez v&eacute;rifiez les informations que vous avez saisies ...</p>";
}
}
?>
</div>

6
app/parameters.php Normal file
View File

@ -0,0 +1,6 @@
<?php
define(HASH_ALGORITHM, PASSWORD_BCRYPT);
define(HASH,password_hash('xxxx-0000', HASH_ALGORITHM));

91
app/session.php Normal file
View File

@ -0,0 +1,91 @@
<?php
session_start();
/*RESTRICTION D'USAGE DU SITE PERSONNEL AU BLACK HAT HACKER */
//chargement en mémoire des anciennes attaques
$attempts = simplexml_load_file( APPLICATION_PATH . DIRECTORY_SEPARATOR ."bruteforce-logger.xml" , "SimpleXMLElement" , LIBXML_NOCDATA );
if($attempts->xpath("/brute-force-attack/attempt/from")) {
foreach ($attempts->xpath("/brute-force-attack/attempt/from") as $attempt) {
// Récupération des ip et test de corrélation actuelle
if ($attempt['from'] == $_SERVER['REMOTE_ADDR']) {
$page['action'] = 'default';
$page['name'] = 'error-brute-force-attack';
break;
}
}
}
/**/
/* ITERATION D'UNE POSSIBLE ATTAQUE BRUTE FORCE SUR UNE PAGE DE TRAITEMENT */
if ($page['action'] == 'traitementPOSTvar'){
if(isset($_SESSION['brute-force-attempt'])) {
$_SESSION['brute-force-attempt']++;
}else{
$_SESSION['brute-force-attempt']=1;
}
}
/**/
/* TESTS PERMETTANT DE DEFINIR CERTAINS CAS COMME ETANT DANGEREUX*/
if ( !isset($_SESSION['current-ip'])
|| !isset($_SESSION['current-time']) ){
//Ce test permet d'identifier ceux qui veulent faire un traitement sans provenir d'une page de formulaire
if($page['action'] == 'traitementPOSTvar'){
$page['action'] = 'default';
$page['name'] = 'error';
}
}else{
if( $_SESSION['last-ip'] !== $_SERVER['REMOTE_ADDR']
|| $_SESSION['last-time'] > $_SERVER['REQUEST_TIME'] ){
//ce test permet de verifier que le demandeur est bien le meme que celui qui provient d'un formulaire
$page['action'] = 'default';
$page['name'] = 'error';
}
if( $page['action'] == 'traitementPOSTvar' && $_SESSION['brute-force-attempt'] > 5 ){
//ce test permet de logger une attaque brute force sur un formulaire
$dom = new DOMDocument;
$dom->load(APPLICATION_PATH . DIRECTORY_SEPARATOR ."bruteforce-logger.xml");
$noeudBruteForce = $dom->getElementsByTagName("brute-force-attack")->item(0);
$attemptNode = $dom->createElement("attempt");
$dateNode = $dom->createElement("date");
$textNode = $dom->createTextNode(htmlentities($_SERVER['REQUEST_TIME']));
$dateNode->appendChild($textNode);
$attemptNode->appendChild($dateNode);
$ipNode = $dom->createElement("from");
$textNode = $dom->createTextNode(htmlentities($_SERVER['REMOTE_ADDR']));
$ipNode->appendChild($textNode);
$attemptNode->appendChild($ipNode);
$noeudBruteForce->appendChild($attemptNode);
$dom->save(APPLICATION_PATH . DIRECTORY_SEPARATOR ."bruteforce-logger.xml");
$page['action'] = 'default';
$page['name'] = 'error-brute-force-attack';
}
//mise en tampon des données courante de combat
$_SESSION['last-ip'] = $_SESSION['current-ip'];
$_SESSION['last-time'] = $_SESSION['current-time'];
}
/**/
//actualisation des données courante du temps réel
$_SESSION['current-ip'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['current-time'] = $_SERVER['REQUEST_TIME'];
$_SESSION['current-server'] = $_SERVER['SERVER_ADDR'];

21
public/index.php Normal file
View File

@ -0,0 +1,21 @@
<?php
define('PUBLIC_PATH' , dirname(__FILE__) );
define('APPLICATION_PATH' , dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . "app" );
define('CLASS_PATH' , APPLICATION_PATH . DIRECTORY_SEPARATOR . "class" );
define('PAGES_PATH' , APPLICATION_PATH . DIRECTORY_SEPARATOR . "page" );
define('LAYOUT_PATH' , APPLICATION_PATH . DIRECTORY_SEPARATOR . "layout" );
require_once CLASS_PATH . DIRECTORY_SEPARATOR . 'password.class.php';
require_once CLASS_PATH . DIRECTORY_SEPARATOR . 'encoding.class.php';
require APPLICATION_PATH . DIRECTORY_SEPARATOR . 'session.php';
//pour chaque page et mise en tampon
ob_start();
require_once PAGES_PATH . DIRECTORY_SEPARATOR . 'TINTERNET-chatbot.php' ;
require_once PAGES_PATH . DIRECTORY_SEPARATOR . 'TINTERNET-chatbot.phtml' ;
$content = ob_get_contents();
ob_end_clean();
require_once LAYOUT_PATH . DIRECTORY_SEPARATOR . $layout . '.phtml';

1725
public/js/markdown.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,149 @@
<?php
define('PUBLIC_PATH' , dirname(__FILE__));
define('APPLICATION_PATH' , dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . "app" );
define('CLASS_PATH' , APPLICATION_PATH . DIRECTORY_SEPARATOR . "class" );
require APPLICATION_PATH . DIRECTORY_SEPARATOR . "parameters.php";
require APPLICATION_PATH . DIRECTORY_SEPARATOR . 'session.php';
require_once CLASS_PATH . DIRECTORY_SEPARATOR . 'password.class.php';
require_once CLASS_PATH . DIRECTORY_SEPARATOR . 'encoding.class.php';
error_reporting(-1);
ini_set('display_errors', 1);
function passValide($password){
//password_hash('tototo', HASH_ALGORITHM)
if (password_verify($password, HASH)) {
if (password_needs_rehash(HASH, HASH_ALGORITHM)) {
$hash = password_hash($password, HASH_ALGORITHM);
$file = "";
$lines = file(APPLICATION_PATH . DIRECTORY_SEPARATOR . "parameters.php");
foreach ($lines as $line_num => $line) {
if(preg_match("#define\(HASH,(.*)\)#",$line,$matches)){
$newline = preg_replace("#define\(HASH,(.*)\)#","define(HASH,'$hash')",$line);
}else{
$newline = $line;
}
if ($newline != "") {
$file .= $newline . "\n";
}
}
/* Store new hash in parameters file */
file_put_contents(APPLICATION_PATH . DIRECTORY_SEPARATOR . "parameters.php",$file);
}
}
//try fallback passengers
if (password_verify($password,HASH)) {
return true;
} else {
return false;
}
}
//https://code.tutsplus.com/tutorials/8-regular-expressions-you-should-know--net-6149
function extractLink($message){
preg_match_all("#((?:https?:\/\/)?(?:[\da-z\.-]+)\.(?:[a-z\.]{2,6})(?:[\/\w \.-]*)*\/?)#",$message,$matches);
return $matches;
}
function extractText($message){
$links = extractLink($message);
array_shift($links);
foreach ($links as $link) {
if ($link != "") {
$message = preg_replace("#$link[0]#"," ... ",$message);
}
}
return $message;
}
/**************************************************************************************************************/
/******************* TEST COTÉ SERVEUR POUR L'ENVOI DU MESSAGE *********************************************/
$message = Encoding::fixUTF8(Encoding::protectionDoubleQuote(Encoding::protectionSimpleQuote($_POST['message'])));
if (passValide($_POST['password']) && $_POST['message'] != ""){
$hookMattermost = "http://{your-mattermost-site}/hooks/xxx-generatedkey-xxx";
$payload = <<<EOD
payload={
"channel": "bot-tests",
"username": "acksop",
"text": "$message"
}
EOD;
$json = <<<EOD
{
"channel": "bot-tests",
"username": "acksop",
"text": "$message"
}
EOD;
$commandURL = "curl -i -X POST --data-urlencode '$payload' $hookMattermost";
$commandJSON = "curl -i -X POST -H 'Content-Type: application/json' -d '$json' $hookMattermost";
echo "<pre>";
print_r($commandJSON);
echo "</pre><pre>";
print_r($commandURL);
$dom = new DOMDocument;
$dom->load(PUBLIC_PATH . DIRECTORY_SEPARATOR ."veilleTinternet.xml");
$noeudVeille = $dom->getElementsByTagName("veille")->item(0);
$messageNode = $dom->createElement("message");
$myOriginalTextNode = $dom->createElement("originel");
$textNode = $dom->createTextNode(htmlentities($message));
$myOriginalTextNode->appendChild($textNode);
$messageNode->appendChild($myOriginalTextNode);
$myTextNode = $dom->createElement("text");
$textNode = $dom->createTextNode(htmlentities(extractText($message)));
$myTextNode->appendChild($textNode);
$messageNode->appendChild($myTextNode);
$myLinksNode = $dom->createElement("links");
$links = extractLink($message);
array_shift($links);
foreach($links as $link) {
if($link != "") {
$myLinkNode = $dom->createElement("link");
$textNode = $dom->createTextNode(htmlentities($link[0]));
$myLinkNode->appendChild($textNode);
$myLinksNode->appendChild($myLinkNode);
}
}
$messageNode->appendChild($myLinksNode);
//$dom->insertBefore( $messageNode, $noeudVeille );
$noeudVeille->appendChild($messageNode);
$dom->save(PUBLIC_PATH . DIRECTORY_SEPARATOR ."veilleTinternet.xml");
shell_exec($commandJSON);
shell_exec($commandURL);
die();
if(isset($_POST['ajax'])){
echo "Votre Lien as &eacute;t&eacute; correctement transmis. Vous receverez une r&eacute;ponse dans les prochains jours.";
}else{
header("Location: /index.php?envoiDuMessage=oui");
}
}else{
if(isset($_POST['ajax'])){
echo "Votre Lien n'as pas &eacute;t&eacute; transmis. Veuillez v&eacute;rifiez les informations que vous avez saisies ...";
}else{
header("Location: /index.php?envoiDuMessage=non&message=".Encoding::myUrlEncode($message));
}
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<veille>
<message>
<originel>test http://new.emmanuelroy.name</originel>
<text>test</text>
<links>
<link>http://new.emmanuelroy.name</link>
</links>
</message>
</veille>