Différents liens sur PHP:
Voici une petite fonction PHP qui permet de retourner le numéro de la dernière semaine de l'année en cours.
<?php
function lastWeekNumberOfYear(){
$year = date('Y');
$week_count = date('W', strtotime($year . '-12-31'));
if ($week_count == '01'){
$week_count = date('W', strtotime($year . '-12-24'));
}
return intval($week_count);
}
La fonction preg_match permet d'effectuer une recherche dans une chaine de caractères et renvoie TRUE si le texte cherché est trouvé sinon FALSE.
Cela permet d'effectuer des controles sur des saisies clavier.
<?php preg_match("#^[0-9]{6}$#","123456"); ?>
// Renvoie TRUE car 123456 est bien un nombre de 6 chiffres.
Explications :
#^[0-9]{6}$#
Le caractère # correspond aux délimiteurs du texte à chercher.
Le caractère ^ indique que la recherche doit s'effectuer à partir du début de la chaine de texte.
Le caractère $ indique que la recherche doit s'effectuer jusqu'à la fin de la chaine de texte.
La classe de caractères [0-9] indique que les caractères recherchés dans la chaine de texte doivent être des chiffres allant de 0 à 9.
Le quantificateur {6} indique le nombre exact de caractères à rechercher dans la chaine de texte.
Autres exemples :
<?php preg_match("#^[0-9]{6}$#","123A56"); ?>
// Renvoie FALSE car il y a un 'A' dans la chaine de caractères.
<?php preg_match("#^[0-9]{6}$#","12345"); ?>
// Renvoie également FALSE car il n'y a que 5 chiffres dans la chaine de caractères '12345'
<?php preg_match("#^[0-9]{6}#","546781A"); ?>
// Renvoie TRUE car la recherche demandée s'effectue uniquement à partir du début de la chaine de caractères (suppression du caractère $) et que celle çi doit donc commencer par 6 chiffres allant de 0 à 9.
<?php preg_match("#^[-.\w]{1,}@[-.\w]{2,}\.[a-zA-Z]{2,4}$#","toto@gmail.com"); ?>
// Renvoie TRUE car le texte 'toto@gmail.com' correspond bien à une adresse mail.
Explications :
#^[-.\w]{1,}@[-.\w]{2,}\.[a-zA-Z]{2,4}$#
Nous retrouvons toujours nos délimiteurs #
Nous retrouvons également nos symboles de dédut ^ et de fin $ de recherche
Notre adresse mail doit être de la forme xxxx@xxxx.xxxx
Le début de l'adresse (à la gauche de l' @) peut contenir des caractères allant de 'A' à 'Z' (minuscule et majuscule), un point '.', un tiret haut '-', un tiret bas '_' et des chiffres allant de 0 à 9 et doit contenir au minimum 1 caractère. Pour indiquer tout cela, nous inscrivons donc :
[-.\w]{1,}
La classe de caractères contient donc le '-' (toujours le placer en première position dans une classe de caractères) suivi du '.' et enfin du raccourci '\w' correspondant à la même chose que [a-zA-Z0-9_], c'est à dire toutes les lettres de l'alphabet minuscule et majuscule, tous les chiffres et le tiret bas '_'. Le tout suivi du quantificateur {1,} indiquant qu'il doit y avoir au minimum 1 caractère.
Il faut ensuite indiquer le caractère @
Ensuite, le nom de domaine doit avoir les mêmes caractéristiques que le début de l'adresse mais doit comporter au minimum 2 caractères, nous inscrivons donc :
[-.\w]{2,}
Nous retrouvons la même classe de caractères que pour le début de l'adresse mais nous modifions le quantificateur {2,} pour indiquer qu'il doit y avoir au minimum 2 caractères.
Nous indiquons ensuite le point '.' mais celui çi doit être échappé car en PCRE, il correspond à un métacaractère indiquant 'n'importe quel caractère'.
\.
Enfin, nous controlons l'extension du nom de domaine. Celui çi ne doit contenir que des lettres et avoir au minimum 2 caractères et au maximum 4. Nous indiquons donc :
[a-zA-Z]{2,4}
Nous retrouvons la classe [a-zA-Z] indiquant toutes les lettres de l'alphabet en minuscule et en majuscule ainsi que le quantificateur {2,4} indiquant un minimum de caractères de 2 et un maximum de 4.
Connexion à une base de données MySql
<?php
try
{
$bdd = new PDO('mysql:host=localhost;dbname=test','user','password');
}
catch(Exception $e)
{
die('Erreur :'.$e->getMessage());
}
?>
Exécuter une requête simple
<?php
$req = $bdd->query('SELECT id, nom, prenom FROM carnet WHERE id >= 1 AND id <= 10 ORDER BY id') or die (print_r($bdd->errorInfo()));
?>
Préparer et exécuter une requête avec des variables
<?php
$req = $bdd->prepare('SELECT id, nom, prenom FROM carnet WHERE id >= :idMin AND id <= :idMax ORDER BY id') or die (print_r($bdd->errorInfo()));
$req->execute(array(
'idMin'=> $_POST['postIdMin'],
'idMax' => $_GET['getIdMax']
));
?>
Lire le résultat d'une requête
<?php
while($donnees = $req->fetch())
{
echo $donnees['id'].'<br />';
echo $donnees['nom'].'<br />';
echo $donnees['prenom'];
}
?>
Fermer la requête
<?php
$req->closeCursor();
?>
La bibliothèque Monolog permet de journaliser différentes informations lors de l'exécution de scripts PHP.
Son intégration via un framework de développement tel que Symfony, CakePHP se fait de manière quasi automatique mais s'il s'agit de l'utiliser dans un script fait à la main, c'est un petit peu plus compliqué.
Voici ma méthode (qui peut certainement être améliorée):
Cette bibliothèque pouvant être utilisée dans plusieurs projets, j'ai donc décidé de l'installer dans un dossier commun à tous mes projets web (/var/www/).
Je vais donc l'installer dans le dossier /var/www/commun
$ cd /var/www
$ mkdir commun
$ chown -R www-data:www-data commun
$ cd commun
Cette bibliothèque utilisant les namespaces, il est nécessaire d'installer la bibliothèque ClassLoader qui va nous permettre d'utiliser tout simplement les namespaces dans nos différents scripts.
Toutes les installations seront faites à l'aide de la commande git
$ apt-get install git
$ git clone https://github.com/symfony/ClassLoader.git
$ git clone https://github.com/Seldaek/monolog.git
$ git clone https://github.com/php-fig/log.git
Trois projets sont donc installés dans le dossier commun
Pour protéger l'accès à ce dossier (/var/www/commun):
$ echo "Deny From All" > .htaccess
Pour l'utilisation des namespaces, il est nécessaire de créer un fichier de paramétrage des namespaces (toujours dans le dossier /var/www/commun):
$ cat monolog.php
<?php
require_once __DIR__.'/ClassLoader/ClassLoader.php';
use Symfony\Component\ClassLoader\ClassLoader;
$loader = new ClassLoader();
$loader->register();
$loader->addPrefix('Monolog', __DIR__.'/monolog/src');
$loader->addPrefix('Psr', __DIR__.'/log');
Ce fichier intègre donc la classe ClassLoader.php et configure les namespaces Monolog & Psr nécessaire à l'utilisation de la bibliothèque monolog.
L'installation et le paramétrage est terminé, passons à la manière d'utiliser cette bibliothèque.
Je vais créer un projet test ainsi que deux fichiers index.php et init_log.php.
Le fichier index.php contiendra mon projet et le fichier init_log.php la configuration du fichier de log de mon projet.
$ cd /var/www
$ mkdir test
$ chown -R www-data:www-data test
$ cd test
Pour la documentation de monolog, tout est expliqué sur la page github du projet https://github.com/Seldaek/monolog
Détail de ma configuration:
$ nl init_log.php
1 <?php
2 require_once '/var/www/commun/monolog.php';
3 use Monolog\Logger;
4 use Monolog\Handler\RotatingFileHandler;
5 use Monolog\Handler\StreamHandler;
6 use Monolog\Formatter\LineFormatter;
7 $dateFormat = "Y-m-d H:i:s";
8 $output = "[%datetime%] %channel% %level_name%: %message% %context% %extra%\n";
9 $formatter = new LineFormatter($output, $dateFormat);
10 $stream = new StreamHandler(__DIR__.'/test.log', Logger::DEBUG); // Pour obtenir un fichier de log global
11 // $stream = new RotatingFileHandler(__DIR__.'/test.log', Logger::DEBUG); // Pour obtenir un fichier de log par jour (fichier horodaté)
12 $stream->setFormatter($formatter);
13 $logger = new Logger('test');
14 $logger->pushHandler($stream);
Ligne 2, j'inclus le fichier monolog.php qui contient toute la configuration de monolog.
Ligne 3 à 6, déclaration des différents use comme indiqué surla page du projet.
Ligne 7 à 9, je redéfini le format des données dans les logs.
Ligne 10 ou 11, permet d'indiquer l'emplacement du fichier de log ainsi que la manière dont il sera nommé et le niveau de log (DEBUG, INFO, WARNING etc etc...). Comme indiqué dans les commentaires, soit un fichier de log global (test.log), soit un fichier de log journalier et horodaté (test-2015-08-14.log).
Ligne 12, affectation du format défini au fichier de log.
Ligne 13 à 14, création d'un nouveau logger nommé test (avec le nom du projet par exemple).
Il est possible d'avoir un seul fichier de log commun pour plusieurs projets. Du coup, il sera facile de parser le fichier de log en se basant sur le nom du projet indiqué lors de la création du logger (ligne 13)
Utilisation dans mon fichier index.php:
$ cat index.php
<?php
require_once __DIR__.'/init_log.php';
...
$logger->addInfo('Connexion', array(
'User' => $user,
'Nom' => $nom,
'Prénom' => $prenom,
));
J'inclus mon fichier init_log.php et j'écris tout ce que je veux dans mon fichier de log à l'aide de la commande $logger->addInfo().
Le premier paramètre est une chaine de texte et le second un tableau.
Difficile de faire plus simple.
igalerie est une application php qui permet de créer des galeries d'images en ligne.
L'ajout d'images dans la galerie peut se faire via ftp (très pratique) mais il faut obligatoirement exécuter une fonction pour que les images soient affichées dans la galerie.
Cette fonction est disponible via un bouton accessible uniquement dans la section administration du site.
Il est donc nécessaire d'être authentifié pour exécuter cette fonction.
Pour effectuer ce scan automatiquement à intervalle régulière, j'ai donc mis au point le script php suivant avec l'extension curl.
Ce script est disponible ici .
$ nl curl.igalerie.php
1 <?php
2 session_start();
3 $site = "https://adresse.de.mon.site.igalerie.fr";
4 $lien = "/login";
5 $lien3 = "/admin/?q=ftp";
6 $path_cookie = '/tmp/cookie.'.session_id().'.txt';
7 if (file_exists(realpath($path_cookie))) unlink($path_cookie);
8 if (!file_exists(realpath($path_cookie))) touch($path_cookie);
9 $curl = curl_init();
10 $postfields = array();
11 $postfields['auth_login'] = 'mon.user';
12 $postfields['auth_password'] = 'mon.password';
13 $postfields['submit'] = 'Valider';
14 $postfields = http_build_query($postfields);
15 curl_setopt($curl, CURLOPT_URL, $site.$lien);
16 curl_setopt($curl, CURLOPT_COOKIEFILE, realpath($path_cookie));
17 curl_setopt($curl, CURLOPT_COOKIEJAR, realpath($path_cookie));
18 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
19 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
20 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
21 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
22 curl_setopt($curl, CURLOPT_HEADER, true);
23 curl_setopt($curl, CURLOPT_POST, true);
24 curl_setopt($curl, CURLOPT_POSTFIELDS, $postfields);
25 curl_setopt($curl, CURLOPT_COOKIESESSION, true);
26 $return = curl_exec($curl);
27 $headers = curl_getinfo($curl);
28 if (!$headers['http_code'] == '200'){
29 echo "Erreur Step 1";
30 exit(1);
31 }
32 curl_setopt($curl, CURLOPT_URL, $site.$lien3);
33 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
34 curl_setopt($curl, CURLOPT_COOKIEFILE, realpath($path_cookie));
35 curl_setopt($curl, CURLOPT_COOKIEJAR, realpath($path_cookie));
36 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
37 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
38 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
39 curl_setopt($curl, CURLOPT_HEADER, true);
40 curl_setopt($curl, CURLOPT_COOKIESESSION, true);
41 $return = curl_exec($curl);
42 $headers = curl_getinfo($curl);
43 if (!$headers['http_code'] == '200'){
44 echo "Erreur Step 2";
45 exit(1);
46 }
47 $dom = new DOMDocument;
48 @$dom->loadHTML($return);
49 $inputs = $dom->getElementsByTagName('input');
50 foreach ($inputs as $input) {
51 $cle = $input->getAttribute('name');
52 $valeur = "";
53 if($cle=="anticsrf"){
54 $valeur = $input->getAttribute('value');
55 }
56 if(!$valeur=="") break;
57 }
58 $postfields = array();
59 $postfields['publish_images'] = 'on';
60 $postfields['anticsrf'] = "$valeur";
61 $postfields['action'] = 'scan';
62 $postfields = http_build_query($postfields);
63 curl_setopt($curl, CURLOPT_URL, $site.$lien3);
64 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
65 curl_setopt($curl, CURLOPT_COOKIEFILE, realpath($path_cookie));
66 curl_setopt($curl, CURLOPT_COOKIEJAR, realpath($path_cookie));
67 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
68 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
69 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
70 curl_setopt($curl, CURLOPT_HEADER, true);
71 curl_setopt($curl, CURLOPT_COOKIESESSION, true);
72 curl_setopt($curl, CURLOPT_POST, true);
73 curl_setopt($curl, CURLOPT_POSTFIELDS, $postfields);
74 $return = curl_exec($curl);
75 $headers = curl_getinfo($curl);
76 if (!$headers['http_code'] == '200'){
77 echo "Erreur Step 3";
78 exit(1);
79 }
80 @$dom->loadHTML($return);
81 $div = $dom->getElementById('ftp_report');
82 $ps = $div->getElementsByTagName('p');
83 foreach ($ps as $p => $value) {
84 echo "$value->nodeValue\n";
85 }
86 curl_close($curl);
87 exit(0);
Quelques petites explications :
Ligne 4 : adresse http(s) de la galerie.
Ligne 5 : lien qui permet d'accéder à la page d'authentification.
Ligne 6 : lien qui permet d'accéder à la page du scan ftp.
Ligne 8 à 10 : initialisation du cookie de session.
Ligne 12 : initialisation de l'extension curl.
Ligne 14 à 20 : initialisation du formulaire d'authentification.
Ligne 22 à 35 : validation du formulaire d'authentification.
Le formulaire permettant le scan des albums étant protégé par un champ anti-csrf , il est nécessaire de récupérer la valeur de ce champ avant de poster le formulaire.
Ligne 42 à 53 : récupération du contenu de la page contenant le formulaire permettant le scan des albums.
Ligne 60 à 70 : on parse le contenu de la page afin de récupérer la valeur du champ "anticsrf".
Ligne 72 à 78 : initialisation du formulaire de scan.
Ligne 80 à 93 : validation du formulaire de scan.
Ligne 100 à 106 : on parse le contenu de la page, après validation du formulaire, afin de récupérer le rapport du scan et on l'affiche sur la sortie standard.
Ligne 108 à 110 : on ferme la connexion curl et on quitte le script.
Pour l'exécuter :
$ php curl.igalerie.php
Pour ne pas afficher le rapport :
$ php curl.igalerie.php >/dev/null
Pour envoyer le rapport par mail :
$ php curl.igalerie.php | mail -s "Rapport Scan Auto Igalerie" moi@domain.com
Une entrée crontab pour l'automatisation.
phpSysInfo est un script PHP qui permet d'afficher, dans un navigateur, l'état complet du serveur sur lequel il est exécuté.
Une démo est disponible ici http://phpsysinfo.sourceforge.net/phpsysinfo/index.php?disp=bootstrap
Adresse du site officiel http://phpsysinfo.github.io/phpsysinfo/
Pour le téléchargement, les sources sont disponibles sur GitHub https://github.com/phpsysinfo/phpsysinfo
L'installation est ultra simple.
Il suffit de cloner les sources GIT dans un répertoire du serveur accessible en web.
De faire une copie du fichier phpsysinfo.ini.new en phpsysinfo.ini
D'éditer le fichier phpsysinfo.ini afin d'effectuer les réglages désirés
Et enfin, ouvrir son navigateur et ouvrir l'url correspondante
# cd /var/www
# git clone https://github.com/phpsysinfo/phpsysinfo.git
# cd phpsysinfo
# cp -a phpsysinfo.ini.new phpsysinfo.ini
Les données sont également accessible en XML /xml.php?plugin=complete ou en JSON /xml.php?plugin=complete&json
Une application pour Android est également disponible http://rk4an.github.io/psiandroid/