Compare commits

...

558 commits

Author SHA1 Message Date
Anael MOBILIA
f8252e4425 Ajout d'une constante pour le nombre d'affichages par jour étant totalement abusif + remontée dans le cron de chaque heure 2024-12-20 01:03:33 +01:00
Anael MOBILIA
2616a68778 Fix tests 2024-12-20 00:51:36 +01:00
Anael MOBILIA
793ae79e6c Fix typos 2024-12-20 00:46:18 +01:00
Anael MOBILIA
3a6fcb6366 Ajout de la détection des images dont le nombre d'affichages est clairement abusif. 2024-12-20 00:45:10 +01:00
Anael MOBILIA
3681e2264b Fix codeStyle 2024-12-09 22:28:43 +01:00
Anael MOBILIA
4294c9bfa3 #45 - Ne pas bloquer l'image 404 si l'image demandée n'existe plus 2024-12-09 22:22:05 +01:00
Anael MOBILIA
610ef1deb2 Avoir toutes les erreurs PHP
Cf https://github.com/shivammathur/setup-php/issues/450
2024-12-09 01:09:32 +01:00
Anael MOBILIA
f431c3b69e Fix tests 2024-12-09 01:01:47 +01:00
Anael MOBILIA
14cced79f9 Ne pas générer d'email lorsque c'est PhpUnit 2024-12-09 00:50:48 +01:00
Anael MOBILIA
1fa288198a Fix tests - besoin d'une image sur le disque 2024-12-09 00:45:11 +01:00
Anael MOBILIA
1ddf88519a Fix #45 - détection des userAgent 2024-12-09 00:39:03 +01:00
Anael MOBILIA
a42f472301 Fix tests - double chargement de la config 2024-12-09 00:33:34 +01:00
Anael MOBILIA
9c13d4cff4 Fix tests 2024-12-09 00:28:25 +01:00
Anael MOBILIA
af4ac289f9 Fix tests 2024-12-09 00:25:58 +01:00
Anael MOBILIA
7c74e2e080 Ajout de PHP 8.4 dans les tests 2024-12-09 00:22:44 +01:00
Anael MOBILIA
19f8763129 Fix tests / codestyle 2024-12-09 00:22:30 +01:00
Anael MOBILIA
673492abe8 #45 : ajout de la possiblité de bloquer des images en fonction des User-Agent utilisés 2024-12-09 00:15:05 +01:00
Anael MOBILIA
5c0af81225 Gestion du tri des images 2024-11-11 18:49:20 +01:00
Anael MOBILIA
f5a90ebcd6 Fix valeur par défaut 2024-11-11 18:43:05 +01:00
Anael MOBILIA
03afea0772 Ajout de la date d'envoi du message 2024-11-11 18:31:01 +01:00
Anael MOBILIA
ea809f670c Bootstrap++ 2024-11-10 23:07:59 +01:00
Anael MOBILIA
bfdca5deff Stats : ajout du nombre total d'images dans le temps 2024-11-10 22:57:00 +01:00
Anael MOBILIA
1fac38bd54 Ajout d'index pour optimiser les performances de recherche pour les abus 2024-11-10 22:56:21 +01:00
Anael MOBILIA
ebc9028fb9 Relever toutes les erreurs 2024-11-10 22:55:35 +01:00
Anael MOBILIA
c19e83bfa9 Fix notice si tâche cron 2024-11-10 22:54:24 +01:00
Anael MOBILIA
a76cebf46f lastUpload : mise en exergue des images qui ont un état particulier + standardisation du code 2024-11-10 22:53:52 +01:00
Anael MOBILIA
fc763d96d1 Abuse : ajout de la liste des images approuvables + filtres bloquées / approuvées 2024-11-10 22:53:52 +01:00
Anael MOBILIA
003d978b38 Gestion du chargement multiple d'images pour ne pas effectuer des requêtes SQL en boucle 2024-11-10 22:44:47 +01:00
Anael MOBILIA
7384f93f4a Update doc d'install 2024-11-10 20:35:46 +01:00
Anael MOBILIA
bbe62bc134 Gestion des extensions des images en minuscules 2024-10-08 03:00:07 +02:00
Anael MOBILIA
62d45a9fd9 upload : toujours optimiser l'image (permettra de comparer son hash avec celles déjà stockées) 2024-10-08 03:00:03 +02:00
Anael MOBILIA
09c725c451 Tor : En cas d'erreur, par défaut, faire confiance à l'IP 2024-10-08 02:59:59 +02:00
Anael MOBILIA
0b94e0f789 getNbDoublons() -> getNbUsages()
+ harmonisation de code
2024-10-08 02:59:54 +02:00
Anael MOBILIA
200fd93450 Code cleanup 2024-10-08 02:59:50 +02:00
Anael MOBILIA
779130c08f Factorisation de code 2024-10-08 02:59:46 +02:00
Anael MOBILIA
352e5f44c4 Meilleure gestion du message d'erreur 2024-10-08 02:59:42 +02:00
Anael MOBILIA
941442f5ea Meilleure vérification des attributs + fix tests 2024-10-08 02:59:39 +02:00
Anael MOBILIA
0b66c3f7c6 Le namespace de PHPUnit est désormais "PHPUnitPHAR" => génériser la détection 2024-10-08 02:59:34 +02:00
Anael MOBILIA
d5426fe324 Tests : fix + codeStyle
A noter : pour certains types d'images, PHP change les entêtes de fichier en fonction des libs installées sur le serveur.
On ne compare plus le résultat à un fichier déjà fourni, mais on vérifie les caractéristiques du fichier généré. #38
2024-10-08 02:59:29 +02:00
Anael MOBILIA
33fe810af1 Certaines images sont envoyées plusieurs fois d'affilée -> dédoublonner la liste 2024-03-25 23:14:57 +01:00
Anael MOBILIA
4274601a2c Meilleure protection du paramètre 2024-03-25 23:14:27 +01:00
Anael MOBILIA
28bba299ba Effacer les logs de connexion au bout d'un an 2024-03-08 22:22:41 +01:00
Anael MOBILIA
44a321fd9e Meilleure description du script 2024-03-08 22:22:05 +01:00
Anael MOBILIA
1de0d48e1d Fix tests 2024-03-08 22:02:51 +01:00
Anael MOBILIA
9b6a4ae061 Fix codeStyle 2024-03-08 21:49:33 +01:00
Anael MOBILIA
49ce8a95d6 Fix #43 : la définition du statut approuvé / bloqué est contaminant pour les images possédant le même MD5 2024-03-08 21:48:03 +01:00
Anael MOBILIA
c978a35134 Amélioration des debug 2024-02-22 22:01:13 +01:00
Anael MOBILIA
204563ba11 Ne mettre à jour la liste des noeuds Tor que si on a pu la récupérer 2024-02-22 22:00:10 +01:00
Anael MOBILIA
d0909b42ca Fix codestyle 2024-02-15 23:43:26 +01:00
Anael MOBILIA
28837c75aa Ajout d'une projection d'utilisation de l'image pour prédire les images qui risquent de dépasser les limites d'affichage autorisées 2024-02-15 23:26:56 +01:00
Anael MOBILIA
94ff35cc9f Fix tests 2024-02-15 23:25:16 +01:00
Anael MOBILIA
dd583f55cd Ne pas charger systématiquement le template pour pouvoir faire un redirect si création de compte OK 2024-02-15 21:56:06 +01:00
Anael MOBILIA
c0c67c8956 Avoir le détail des paramètres des méthodes dans les stack traces 2024-02-15 21:55:27 +01:00
Anael MOBILIA
b3e8da9149 Fix error_handler + création d'une Exception custom pour l'application 2024-02-15 21:55:07 +01:00
Anael MOBILIA
cc26a494cb Fix tests 2024-02-07 00:55:29 +01:00
Anael MOBILIA
f3e5fdd2b2 Fix tests 2024-02-07 00:51:18 +01:00
Anael MOBILIA
27975e72e8 Code cleanup 2024-02-07 00:42:04 +01:00
Anael MOBILIA
c3d3580498 Fix tests 2024-02-07 00:41:30 +01:00
Anael MOBILIA
f71d25067b Fix tests 2024-02-07 00:33:34 +01:00
Anael MOBILIA
e7c4468d29 Fix tests 2024-02-07 00:30:20 +01:00
Anael MOBILIA
fe1d1d93eb PHPUnit 10 -> 11 2024-02-07 00:20:18 +01:00
Anael MOBILIA
12cce10500 Fix tests 2024-02-06 23:51:07 +01:00
Anael MOBILIA
f4afe87a3d Update des github action 2024-02-06 23:47:46 +01:00
Anael MOBILIA
7e49c50bc0 Code cleanup 2024-02-06 23:20:01 +01:00
Anael MOBILIA
e2999844dd Deps++ 2024-02-06 21:54:34 +01:00
Anael MOBILIA
8254167cc2 Passage à PHP8.3 + code clean 2024-02-06 21:44:28 +01:00
Anael MOBILIA
36cabb1fcd Ajout d'un error_handler en complément du exception_handler 2024-02-06 21:00:27 +01:00
Anael MOBILIA
e98571db9e Fix warning float/int (PHP 8.3) 2024-02-06 20:59:57 +01:00
Anael MOBILIA
4a9597ab3c Formatage 2024-02-04 00:25:09 +01:00
Anael MOBILIA
879f93b826 Fix texte 2024-02-04 00:24:58 +01:00
Anael MOBILIA
19c30e044c Fix rendu sur écrans plus petits 2024-02-04 00:24:38 +01:00
Anael MOBILIA
58a2786a14 N'afficher un warning pour les images webp animées que si un traitement est demandé 2024-02-02 22:06:20 +01:00
Anael MOBILIA
47991395af Ne pas effectuer de traitement si une erreur est rencontrée en amont. 2024-01-27 22:52:37 +01:00
Anael MOBILIA
3d850bd348 PHP ne gère pas les images webp animées.
-> Ne pas faire de modification sur ces fichiers
Fix #42
2024-01-26 23:08:15 +01:00
Anael MOBILIA
d375fee38c Year++ 2024-01-15 00:29:33 +01:00
Anael MOBILIA
ad566db4d5 v2.5 2024-01-15 00:24:02 +01:00
Anael MOBILIA
1082e20b7b Prise en charge du format WEBP 2024-01-15 00:23:36 +01:00
Anael MOBILIA
6cd8e71916 Factorisation de variables dans la configuration du projet 2024-01-14 23:28:06 +01:00
Anael MOBILIA
e190ed45a0 Gestion des abus : bloquer l'envoi d'images sur le site au bout d'un certain nombre d'images bloquées 2024-01-10 16:15:13 +01:00
Anael MOBILIA
201730adbe Désactiver tous les boutons de la page d'accueil si on a un problème d'espace disque ou avec l'adresse IP 2024-01-10 16:13:09 +01:00
Anael MOBILIA
d57980783d Ajout de abuse_network dans le jeu de données de tests 2024-01-10 15:52:06 +01:00
Anael MOBILIA
a85af1bf18 Harmonisation de variables 2024-01-10 15:46:00 +01:00
Anael MOBILIA
b1be8cbef7 Renommage de tables 2024-01-08 16:20:49 +01:00
Anael MOBILIA
4821839b5c Ajout de détails dans les CGU sur les images non autorisées 2024-01-02 21:54:43 +01:00
Anael MOBILIA
d1a1206f8c Calculer le réseau d'origine d'une image dès le moment où elle est créée pour éviter un abus entre l'envoi et le prochain cron abuse.php (permet de considérer comme suspecte une image dès son envoi et d'en limiter le nombre d'affichage en instantanné) 2023-12-31 04:18:17 +01:00
Anael MOBILIA
1ceacda262 Forcer l'utilisation du domaine en www 2023-12-30 02:36:33 +01:00
Anael MOBILIA
d9b8ff2ca0 Fix SQL (',' restait en fin de chaîne) 2023-12-23 22:23:19 +01:00
Anael MOBILIA
04864fa8eb Update icône 2023-12-23 02:30:47 +01:00
Anael MOBILIA
b0075a9f43 N'inclure un placholder vide que si aucune donnée n'a été retournée 2023-12-23 02:30:28 +01:00
Anael MOBILIA
91d9cffc29 Suite de 45cbebe9 2023-12-23 02:23:13 +01:00
Anael MOBILIA
d112eaa7c7 Le seuil réduit d'affichages avant blocage des images suspectes n'était pris en compte que dans le cron. Désormais chaque image possède sa réputation également et peut donc être bloquée dès qu'elle est trop affichée (en prenant en compte le seuil réduit) 2023-12-23 02:19:22 +01:00
Anael MOBILIA
45cbebe978 ForkMeOnGithub -> passage en bootstrap icon 2023-12-23 01:53:48 +01:00
Anael MOBILIA
c5180cec26 .htaccess, simplification des redirections image-heberg.fr.cr + HTTPS 2023-12-23 01:44:37 +01:00
Anael MOBILIA
a234af3645 Bootstrap icons - gérer l'emplacement des fichiers de fonts 2023-12-23 01:44:09 +01:00
Anael MOBILIA
0051501576 Bootstrap icons 1.10.5 -> 1.11.2 2023-12-23 01:28:04 +01:00
Anael MOBILIA
8c67f1ec0d Admin - liste des réseaux suspects 2023-12-23 01:18:36 +01:00
Anael MOBILIA
55636553a5 Ne pas remonter les images signalées dans les images trop affichées (elles sont déjà bloquées) 2023-12-14 23:34:03 +01:00
Anael MOBILIA
dcc4ab0d24 v2.4 2023-12-03 01:05:54 +01:00
Anael MOBILIA
a5e658218d Fix GIF - utilisation uniquement de la première frame 2023-12-03 00:44:25 +01:00
Anael MOBILIA
33a6e7e2fc Ajout debug PHPUNIT 2023-11-21 01:18:03 +01:00
Anael MOBILIA
d38e64a717 Fix mauvais calcul date de dernière utilisation suite à 2e3d9b10 2023-11-21 01:07:10 +01:00
Anael MOBILIA
f140db4c28 #15 - Ajout nsfwjs 2023-11-21 01:04:33 +01:00
Anael MOBILIA
e924a68057 Ajout de boutons sur les actions des images 2023-11-18 23:45:33 +01:00
Anael MOBILIA
5ff3d7b351 Meilleurs gestion de la grille + ajout lien avec <img> 2023-11-18 23:29:39 +01:00
Anael MOBILIA
58a85b4bb3 Ajout liste des derniers fichiers envoyés 2023-11-16 22:42:37 +01:00
Anael MOBILIA
efc0417c8a id est déjà indéxé via la PRIMARY KEY 2023-11-16 20:43:18 +01:00
Anael MOBILIA
a05da69b33 Prendre en compte les affichages des miniatures dans le nombre total d'affichage d'une image 2023-11-15 01:48:15 +01:00
Anael MOBILIA
1a85248e61 Images suspectes : utiliser également le MD5 2023-11-15 01:45:24 +01:00
Anael MOBILIA
4ec93dcdef Certains fichiers ont des noms avec un encodage incohérent : remplacer les caractères mal encodés (au lieu de retourner vide) 2023-11-15 01:21:05 +01:00
Anael MOBILIA
cf086d358c Ajout d'une division des seuils d'affichage pour les images suspectes 2023-11-12 03:47:49 +01:00
Anael MOBILIA
822744611f Forcer le HTTPS 2023-11-12 03:05:27 +01:00
Anael MOBILIA
f4f6772e1d Ne pas lever un mail d'alerte si l'admin vérifie une image déjà trop affichée 2023-11-12 02:24:34 +01:00
Anael MOBILIA
6c3dd07040 Stats d'affichage : ne mettre à jour que les champs nombre d'affichage et date pour améliorer les performances (évite également d'écraser le statut bloqué d'une image en cas de flood) 2023-11-10 01:12:07 +01:00
Anael MOBILIA
0d4bbb5e40 Suppression phpDoc inutile 2023-11-10 01:07:19 +01:00
Anael MOBILIA
264e278c4c trimer la valeur 2023-11-10 00:42:32 +01:00
Anael MOBILIA
ccf1dbf54e Filtrer plus large en IPv6 (Orange fournit un /56 et non pas un /64) 2023-11-04 01:39:52 +01:00
Anael MOBILIA
9f37c75096 Trier par date d'arrivée 2023-11-04 01:01:05 +01:00
Anael MOBILIA
4dbbf40c6e Pouvoir bloquer une image précédemment approuvée 2023-11-04 00:35:36 +01:00
Anael MOBILIA
3a94acccad Renommage méthode 2023-11-03 23:58:51 +01:00
Anael MOBILIA
5805ab41d8 Schèma de BDD : optimisation du type de champ 2023-11-03 22:56:59 +01:00
Anael MOBILIA
992505172f Gestion du cas aucune miniature / affichage (int + int + null => null) 2023-11-02 22:48:40 +01:00
Anael MOBILIA
dac7c3c1ba Recharger l'image pour ne pas écraser les modifs faites par le cron 2023-11-02 22:48:11 +01:00
Anael MOBILIA
cb1f4bbdf2 Test des dernières fonctions anti abus 2023-11-01 23:41:40 +01:00
Anael MOBILIA
19b5bc9eb7 Codestyle 2023-11-01 23:18:27 +01:00
Anael MOBILIA
415ec17b72 Comptabiliser également les affichages des miniatures pour le nombre d'affichage par jour 2023-11-01 23:07:24 +01:00
Anael MOBILIA
8a218658a6 Tracer l'image ayant généré l'appel au cron 2023-11-01 22:54:32 +01:00
Anael MOBILIA
511a3b0531 Vérifier si l'image n'a pas été trop affichée lorsqu'on l'affiche 2023-10-31 23:01:38 +01:00
Anael MOBILIA
9ec1fa358e Amélioration index 2023-10-31 22:45:21 +01:00
Anael MOBILIA
06ba72b1e6 Détection des abus : ajout d'une recherche sur le réseau IP utilisé 2023-10-29 22:32:58 +01:00
Anael MOBILIA
242472cc81 Ajout d'un champ de recherche sur le nom dans le système dans l'admin / gestion des abus 2023-10-29 20:57:07 +01:00
Anael MOBILIA
a0bf03c9e2 Détection des abus : ajout des images suspectes dans les notifications 2023-10-26 22:19:26 +02:00
Anael MOBILIA
23a025137e Détection des abus : la première journée échappait à la détection 2023-10-20 23:04:20 +02:00
Anael MOBILIA
48c1120241 GUI : information si l'image est bloquée ou validée 2023-10-16 21:54:38 +02:00
Anael MOBILIA
a34e0f53eb Barrer les images déjà bloquées 2023-10-15 00:57:37 +02:00
Anael MOBILIA
4fd35d642a Ajout d'un champ de recherche dans l'admin / gestion des abus 2023-10-15 00:50:05 +02:00
Anael MOBILIA
03c1b66c70 Factorisation de code 2023-10-15 00:34:12 +02:00
Anael MOBILIA
648ef10ab6 Abuse - ajout des images potentiellement suspectes 2023-10-13 01:45:00 +02:00
Anael MOBILIA
1aa2a1578f Champs md5 => 32 chrs + index && formatage 2023-10-13 01:34:40 +02:00
Anael MOBILIA
975880f637 Une adresse IPv6 fera au plus 45 chr 2023-10-13 01:33:42 +02:00
Anael MOBILIA
4cbc55f0ce Abuse - Ajout de l'ID du propriétaire de l'image 2023-10-13 00:45:05 +02:00
Anael MOBILIA
ec6921bbd7 Factorisation des tableaux 2023-10-13 00:23:39 +02:00
Anael MOBILIA
b26a044b77 PSR-12 2023-10-13 00:13:29 +02:00
Anael MOBILIA
66580c5a71 Nettoyage du code avec phpinspectionsea
https://github.com/kalessil/phpinspectionsea
2023-10-12 23:22:33 +02:00
Anael MOBILIA
e31f3e5cd6 Ajout des images bloquées + tri par "gravité" (warning -> signalé -> bloqué) 2023-10-12 22:38:43 +02:00
Anael MOBILIA
174b60c371 MàJ des notes suite à e8a5ee85e2 2023-10-10 22:44:21 +02:00
Anael MOBILIA
7c52ba9a27 Aligner le calcul PHP sur celui du SQL qui est plus avantageux pour les utilisateurs (toute journée entamée est comptabilisée) 2023-09-05 22:58:59 +02:00
Anael MOBILIA
893ddf63f9 Calcul par jour entier pour mieux gérer les premières heures d'une image 2023-08-27 22:35:26 +02:00
Anael MOBILIA
e8a5ee85e2 fontawesome -> bootstrap icons 2023-08-26 02:22:40 +02:00
Anael MOBILIA
b33b45b197 Crons : amélioration du log 2023-08-26 01:31:22 +02:00
Anael MOBILIA
f0089f7ff9 Bootstrap++ 2023-08-26 01:21:05 +02:00
Anael MOBILIA
550d70564b Blocage automatique des images qui abusent clairement du service 2023-08-26 01:13:20 +02:00
Anael MOBILIA
3c9ac61691 Crons : appeler directement les méthodes au lieu de simuler l'utilisation des pages de l'admin 2023-08-26 00:53:27 +02:00
Anael MOBILIA
c789bde9ad Fix var name 2023-08-26 00:31:01 +02:00
Anael MOBILIA
74c36ee5bd Meilleure gestion de l'exécution des scripts via un cron 2023-08-26 00:11:16 +02:00
Anael MOBILIA
d76d670b1a Qualité de code ++ 2023-08-25 23:58:47 +02:00
Anael MOBILIA
c575ffc744 Harmonisation des séparateurs de chaînes en PHP 2023-08-25 23:45:43 +02:00
Anael MOBILIA
fc6840769f Fix test 2023-08-25 02:31:35 +02:00
Anael MOBILIA
c337df2df1 Mieux récupèrer le contenu du buffer de sortie 2023-08-25 02:29:14 +02:00
Anael MOBILIA
fbbf89fab7 Mettre le path pour les require du cron 2023-08-25 02:28:17 +02:00
Anael MOBILIA
b56675d95b Générer une erreur si on ne peur pas charger le fichier du cron 2023-08-25 01:31:30 +02:00
Anael MOBILIA
48532249ec Abuse : meilleure vérification du nom du fichier + variable d'état pour savoir si une image a été bloquée automatiquement 2023-08-25 01:19:17 +02:00
Anael MOBILIA
ff17798ce2 On utilise pas le retour de sauver() 2023-08-25 01:17:36 +02:00
Anael MOBILIA
e74e4b3695 Ajout de lien https depuis l'admin (on a le cookie de session de l'admin si on forceDisplay=1 2023-08-24 03:43:47 +02:00
Anael MOBILIA
36e2d34cee Bloquer l'accès au répertoire cron 2023-08-24 03:43:47 +02:00
Anael MOBILIA
28cf0b4937 Ajout d'un cron pour superviser les comportements anormaux d'affichage 2023-08-24 03:43:47 +02:00
Anael MOBILIA
909533a984 Ajout de la notion d'image approuvée (ne peut pas être bloquée automatiquement et ne remonte pas dans les images à comportement étrange) 2023-08-24 02:49:08 +02:00
Anael MOBILIA
5b880f1f16 Admin - vue Abuse (images signalées et images trop affichées) 2023-08-24 01:50:21 +02:00
Anael MOBILIA
5452768a82 Meilleure gestion pour les images jamais affichées 2023-08-24 01:36:05 +02:00
Anael MOBILIA
8050e80553 Permettre à l'administrateur d'afficher des images bloquée (?forceDisplay=1 2023-08-24 01:09:54 +02:00
Anael MOBILIA
9d29488894 Permettre à l'administrateur d'afficher des images bloquée (?forceDisplay=1) 2023-08-24 01:06:58 +02:00
Anael MOBILIA
041427dc68 Nettoyer les paramètres passés dans le nom de l'image (sinon image non trouvée) 2023-08-24 01:06:17 +02:00
Anael MOBILIA
9fa757fc7e Utiliser le nom du site dans les mails d'erreur 2023-08-24 00:31:59 +02:00
Anael MOBILIA
7707108a22 Découpage en helpers abstract 2023-08-24 00:30:13 +02:00
Anael MOBILIA
3af8bbd8db Mise en avant signalement abus 2023-08-24 00:04:36 +02:00
Anael MOBILIA
d99fce555e Fix var name 2023-08-23 23:52:01 +02:00
Anael MOBILIA
1116aa3b11 Fix test 2023-08-20 23:01:27 +02:00
Anael MOBILIA
8dc98ebeae Fix test 2023-08-20 21:49:26 +02:00
Anael MOBILIA
a0bec132b3 Fix test 2023-08-20 21:46:48 +02:00
Anael MOBILIA
7ac18b725b Fix test 2023-08-20 21:43:42 +02:00
Anael MOBILIA
51371c59fa Fix test - Image n'était plus créée car déjà existante dans la BDD 2023-08-20 21:26:53 +02:00
Anael MOBILIA
ea19ceabf2 Parallélisation des tests 2023-08-20 02:28:29 +02:00
Anael MOBILIA
513dbe49a2 Fix test 2023-08-20 02:25:43 +02:00
Anael MOBILIA
f8f94bad00 Fix test 2023-08-20 02:22:58 +02:00
Anael MOBILIA
9b12884cdb Fix comparaison 2023-08-20 02:19:20 +02:00
Anael MOBILIA
91b38e4f9f Fix comparaison 2023-08-20 02:16:32 +02:00
Anael MOBILIA
5d730d00ac Afficher le MD5 du fichier envoyé (debug) 2023-08-20 02:15:50 +02:00
Anael MOBILIA
570326c946 Fix pour phpunit v10 (PHP > 8.0) 2023-08-20 02:11:57 +02:00
Anael MOBILIA
cddb893f6c Fix SQL 2023-08-20 02:02:38 +02:00
Anael MOBILIA
ce75af0197 Passage à la nouvelle version de checkout (node12 -> node16) 2023-08-20 02:00:50 +02:00
Anael MOBILIA
f07d42db2c Bloquer l'image lors de l'envoi si son MD5 est déjà bloqué par ailleurs 2023-08-20 01:53:51 +02:00
Anael MOBILIA
4333ce57c1 year++ 2023-08-19 04:04:51 +02:00
Anael MOBILIA
1615c078e2 Masquer les informations sensibles lors de l'affichage des erreurs à l'utilisateur 2023-08-19 01:05:42 +02:00
Anael MOBILIA
5fa5c9df58 Fix nom de la variable à utiliser 2023-08-18 22:17:05 +02:00
Anael MOBILIA
3d08eeef91 Permettre de charger les ressources par new_name, MD5 et ID.
-> permet d'avoir plusieurs miniatures pour une même image
-> permet de gérer l'effacement depuis des MD5
2022-12-18 03:53:59 +01:00
Anael MOBILIA
5cfcf45834 Fix comparaison 2022-12-18 03:30:49 +01:00
Anael MOBILIA
8ee02c6a9e Fix data 2022-12-18 03:25:02 +01:00
Anael MOBILIA
289c728b5b Alignement de la conf avec celle d'OVH 2022-12-18 03:13:02 +01:00
Anael MOBILIA
17d274a4db Afficher la configuration (strict_mode) myqsl de github 2022-12-18 03:10:34 +01:00
Anael MOBILIA
7280704638 Amélioration schéma BDD avec pilotage des valeurs par défaut dans le code 2022-12-18 02:58:02 +01:00
Anael MOBILIA
9b8e235563 php lint 2022-12-18 02:47:27 +01:00
Anael MOBILIA
2e3d9b1051 Utiliser '0000-00-00' au lieu de null 2022-12-18 02:26:22 +01:00
Anael MOBILIA
3f8b83b264 Fix test DisplayPics (vérification de la présence de l'image sur le disque) 2022-12-18 02:15:24 +01:00
Anael MOBILIA
d3b1ab9429 Fix test AbuseTest (si l'image n'a pas été affichée, comment la signaler ?) 2022-12-18 02:10:54 +01:00
Anael MOBILIA
c7ba7d09d9 Fix tests 2022-12-18 02:05:22 +01:00
Anael MOBILIA
3c128e6f5b PHP 7.4 est EOL 2022-12-18 01:57:47 +01:00
Anael MOBILIA
dd8006b2ac Fix comparaison 2022-12-18 01:56:31 +01:00
Anael MOBILIA
24248776f0 Préserver z_cache également (utilisé pour lister les @ IP de TOR) 2022-12-18 01:50:29 +01:00
Anael MOBILIA
0c02740618 Fix liste de toutes les miniatures 2022-12-18 01:50:08 +01:00
Anael MOBILIA
d318877a0b Fix Exception non définie 2022-12-18 01:49:38 +01:00
Anael MOBILIA
b1f1fe494b Formatage 2022-12-18 01:49:17 +01:00
Anael MOBILIA
1f0228c03a Afficher une 404 si le fichier existe en BDD mais pas sur le disque 2022-12-18 01:16:42 +01:00
Anael MOBILIA
76811ea9ce Cohérence des noms des champs en BDD 2022-12-18 01:10:32 +01:00
Anael MOBILIA
e093329b2e Passer l'email en minuscules en BDD 2022-12-18 00:44:05 +01:00
Anael MOBILIA
0d95fbcbc7 Suppression des comptes jamais utilisés (admin + cron) 2022-12-18 00:18:18 +01:00
Anael MOBILIA
daf564afbc Gestion des pluriels automatiquement 2022-12-18 00:04:13 +01:00
Anael MOBILIA
5331d07263 Gestion des pluriels automatiquement 2022-12-17 23:54:58 +01:00
Anael MOBILIA
ad1d20a16f Ne pas permettre de créer plusieurs comptes avec le même email 2022-12-17 23:21:49 +01:00
Anael MOBILIA
79908f73d8 Affichage de la version de PHP 2022-12-17 22:47:03 +01:00
Anael MOBILIA
d6f85509be Ajout vérification du PATH 2022-12-17 22:39:38 +01:00
Anael MOBILIA
71973b4c6b Throwable inclut Exception et Error (second type possible pour l'appel à la fonction) 2022-10-18 19:01:08 +02:00
Anael MOBILIA
53d289cb85 Vérifier l'existence d'un fichier avant de le supprimer 2022-10-18 18:58:24 +02:00
Anael MOBILIA
70b9016b60 PHP7.4 est requis pour typer les propriétés d'une classe
https://www.php.net/manual/en/language.oop5.properties.php#language.oop5.properties.typed-properties
2022-10-01 02:48:28 +02:00
Anael MOBILIA
aef8a4b4f3 Fix jeu de données 2022-10-01 02:42:49 +02:00
Anael MOBILIA
b0700f5587 Fix phpcs 2022-10-01 02:41:50 +02:00
Anael MOBILIA
2bd70e4f33 Définir une valeur pour le token 2022-10-01 02:39:06 +02:00
Anael MOBILIA
224c1abc7c Définir une valeur pour le token 2022-10-01 02:37:02 +02:00
Anael MOBILIA
f3be68cef2 year++ 2022-10-01 02:33:05 +02:00
Anael MOBILIA
6bd7f6b69b Ajout PHP8.1 2022-10-01 02:31:41 +02:00
Anael MOBILIA
5510aaff13 Fix code style 2022-10-01 02:31:04 +02:00
Anael MOBILIA
b86f02e2bb Valeur par défaut du token à "" 2022-10-01 02:20:04 +02:00
Anael MOBILIA
bc9a5f75be Typage++ 2022-10-01 02:07:01 +02:00
Anael MOBILIA
4080cc7fc8 Fix HTML 2022-10-01 01:50:35 +02:00
Anael MOBILIA
20e19a70ec Fix condition d'entrée initiale 2022-10-01 01:50:24 +02:00
Anael MOBILIA
5a327ca6cf Utiliser l'URL en HTTPS par défaut pour le contenu du site 2022-01-14 22:43:50 +01:00
Anael MOBILIA
f7749217e9 Lazy loading des images 2022-01-02 01:51:17 +01:00
Anael MOBILIA
dcf3496e7f Ouvrir les images dans un nouvel onglet 2021-12-21 01:40:33 +01:00
Anael MOBILIA
07bb91c402 Au moins une seconde doit s'écouler pour compléter un formulaire ! 2021-12-21 00:59:31 +01:00
Anael MOBILIA
8b0e44a26c Fix pluriels 2021-12-21 00:59:10 +01:00
Anael MOBILIA
83c8fb864f v2.2 2021-12-21 00:51:39 +01:00
Anael MOBILIA
aa6f0fccd0 Espace membre : affichage d'une miniature des images possédées en grille.
Génération automatique de la miniature si non existante
2021-12-21 00:46:58 +01:00
Anael MOBILIA
cdf84b65e6 Création d'une méthode getMiniatures() 2021-12-20 23:35:51 +01:00
Anael MOBILIA
2de440411d Ajout de la notion "is_preview" sur les miniatures 2021-12-20 23:35:11 +01:00
Anael MOBILIA
6bbc4023ff bootstrap 5.0.0-beta2 -> 5.1.3 2021-12-20 21:11:38 +01:00
Anael MOBILIA
eebe724c27 Fix typo 2021-12-20 21:02:05 +01:00
Anael MOBILIA
be6a8a8c53 Forcer le chemin du cron 2021-10-18 01:49:12 +02:00
Anael MOBILIA
ebd02dc2e0 Forcer le chemin du cron 2021-10-18 00:37:27 +02:00
Anael MOBILIA
7ccfb9e5ad Fournir un retour à l'utilisateur 2021-10-18 00:30:13 +02:00
Anael MOBILIA
57a136a601 Ne pas tester des versions de PHP non encore en production 2021-10-16 01:40:54 +02:00
Anael MOBILIA
09c19cf660 Fix GitHub Actions pour MySQL 8.0 2021-10-16 01:39:28 +02:00
Anael MOBILIA
7ffabf79f8 Fix phpcs 2021-10-16 01:23:24 +02:00
Anael MOBILIA
dcc8309ef5 Qualité du code 2021-10-16 01:07:09 +02:00
Anael MOBILIA
9de9c5b03d Fix tests automatiques (inclusion de fichiers pour les IP filtrées pour Tor) 2021-10-16 00:03:43 +02:00
Anael MOBILIA
36593471d4 Fix #17 : Ajout d'un cron pour effacer les images obsolètes de manière automatique 2021-10-15 23:57:09 +02:00
Anael MOBILIA
b99f9db280 Ajout de la notion de IS_CRON 2021-10-15 23:39:21 +02:00
Anael MOBILIA
9038726dc4 Fix #36 2021-10-15 23:29:04 +02:00
Anael MOBILIA
d45f71bce5 Ajout d'une option pour bloquer l'envoi d'images via Tor 2021-10-15 23:16:14 +02:00
Anael Mobilia
e80111c1be
Ajout d'un entête en cas d'image bloquée 2021-05-17 23:48:41 +02:00
Anael Mobilia
2beb107670 Gestion de memory_limit = - 1 (cas de Github Actions) 2021-03-03 23:26:24 +01:00
Anael Mobilia
7570356c4d Il faut définir le fuzz avant de charger l'image 2021-03-03 23:22:38 +01:00
Anael Mobilia
06091a2753 Afficher plus de détail sur la configuration PHP 2021-03-03 23:22:16 +01:00
Anael Mobilia
f1845a4afe Ajout d'un fuzz dans les comparaisons des images pour annuler les petites différences liées à la stack ImageMagick 2021-03-03 22:56:30 +01:00
Anael Mobilia
47e6202508 Regénération des images 2021-03-03 22:54:19 +01:00
Anael Mobilia
8a71b2ca02 Passage par un helper pour avoir uen image la plus identique possible 2021-02-28 05:22:14 +01:00
Anael Mobilia
62d454dec5 Fix paramètres (https://www.geeksforgeeks.org/php-imagick-thumbnailimage-function/) 2021-02-28 05:00:57 +01:00
Anael Mobilia
b2342b2192 Recharger les fichiers pour tenter de gommer les petites différences 2021-02-28 04:41:02 +01:00
Anael Mobilia
6218082614 Recharger les fichiers pour tenter de gommer les petites différences 2021-02-28 04:34:33 +01:00
Anael Mobilia
90d42535a7 memory_limit=0 est possible 2021-02-28 04:01:34 +01:00
Anael Mobilia
a4fcef9e29 Ajotu détail sur les erreurs + passage à méthodes natives assertBoolean 2021-02-28 03:50:11 +01:00
Anael Mobilia
eab4721259 Ajout debug 2021-02-28 03:21:03 +01:00
Anael Mobilia
76b941a7a4 Détection des cas incohérents pour le redimensionnement d'une image 2021-02-28 03:15:41 +01:00
Anael Mobilia
81856fd767 Mise à jour image test 2021-02-28 03:08:07 +01:00
Anael Mobilia
986a88a0cf Mise à jour image test 2021-02-28 02:59:43 +01:00
Anael Mobilia
a584d07d9b Mise à jour image test 2021-02-28 02:47:12 +01:00
Anael Mobilia
fbb73944d7 Pas de compression destructive des images 2021-02-28 02:31:53 +01:00
Anael Mobilia
41e5090397 Fix image de référence 2021-02-28 02:12:44 +01:00
Anael Mobilia
6938c6ead3 Le PDO MySQL n'est pas chargé sur l'image 20.04 / PHP 7.3 -> La forcer 2021-02-28 02:03:50 +01:00
Anael Mobilia
df1f2bd406 Passage ubuntu 20.04 pour avoir une version plus récente de Imagick 2021-02-28 01:45:17 +01:00
Anael Mobilia
31ccd56592 Ajout de la version d'Imagick 2021-02-28 01:39:10 +01:00
Anael Mobilia
17a85077f6 Ajout Imagick & rendu plus visuel 2021-02-28 01:37:54 +01:00
Anael Mobilia
51481cdf68 Suppression ancien debug 2021-02-28 01:08:05 +01:00
Anael Mobilia
81ab966624 Ajout dépendance imagick 2021-02-28 01:02:28 +01:00
Anael Mobilia
a2ab5fb039 PHPCS 2021-02-28 01:00:48 +01:00
Anael Mobilia
9cd486f86b Second lot Imagick pour les tests 2021-02-28 00:39:19 +01:00
Anael Mobilia
49e00cdc15 phpdoc 2021-02-28 00:37:40 +01:00
Anael Mobilia
49eff28e3f PHPCS 2021-02-28 00:37:30 +01:00
Anael Mobilia
3bc7e284c0 Fix #16 - Message de confirmation de suppression sur la page d'accueil 2021-02-28 00:37:04 +01:00
Anael Mobilia
a03dbd394d Premier lot d'images Imagick pour les tests 2021-02-28 00:36:11 +01:00
Anael Mobilia
4f319c045e On ne charge que les classes que l'on a 2021-02-27 23:56:30 +01:00
Anael Mobilia
22704b977b Rotation horaire est plus naturel 2021-02-27 23:31:33 +01:00
Anael Mobilia
bc669ed3dc Ajout imagick 2021-02-27 23:30:17 +01:00
Anael Mobilia
1f50e70f10 Passage à Imagick 2021-02-27 23:29:02 +01:00
Anael Mobilia
bdbaa428a5 PHPDoc 2021-02-27 23:28:30 +01:00
Anael Mobilia
8a7e446675 Réduction de la précision 2021-02-27 22:23:23 +01:00
Anael Mobilia
40f2f9d8e4 Ne pas prendre les fichiers pour améliorer les performances 2021-02-27 22:20:54 +01:00
Anael Mobilia
f44efed6cf Factorisation du code 2021-02-27 22:01:09 +01:00
Anael Mobilia
e28dc48e60 fontawesome 5.12 -> 5.15 2021-02-27 21:55:43 +01:00
Anael Mobilia
67198b5d34 Exclusion de l'erreur des require du fichier de conf générique 2021-02-27 21:42:15 +01:00
Anael Mobilia
23175e3131 Debug à false par défaut 2021-02-27 21:41:59 +01:00
Anael Mobilia
feea9a4233 PHPCS 2021-02-27 21:41:46 +01:00
Anael Mobilia
03e2c1d061 Exécution push, PR, manuelle pour les actions github 2021-02-27 21:14:45 +01:00
Anael Mobilia
9aa18e9b9e Pas d'accent dans le titre du runner 2021-02-27 21:13:13 +01:00
Anael Mobilia
d1379a3a97 Bootstrap 4 -> 5 2021-02-27 21:12:31 +01:00
Anael Mobilia
454fca732a Exécution sur toutes les branches 2021-02-27 21:12:04 +01:00
Anael Mobilia
3c3e26b846 PHP 7.1 n'est plus supporté 2021-02-27 21:03:41 +01:00
Anael Mobilia
590d396e1c bootstrap 4 -> 5 + suppression jQuery 2021-02-27 21:01:26 +01:00
Anael Mobilia
4dea3baa8b URL_CONFIG => en HTTPS 2021-02-27 21:01:03 +01:00
Anael Mobilia
e6b93903ae Ajout taille en Mo 2021-02-27 21:00:13 +01:00
Anael Mobilia
1714d10a6a TRAVIS -> PHPUNIT 2021-02-27 20:58:38 +01:00
Anael Mobilia
93cb95f413 Renommage TRAVIS -> PHPUNIT 2021-02-27 20:58:05 +01:00
Anael Mobilia
b2f5dc908a jQuery 3.4.1 -> 3.5.1 2021-02-27 17:56:52 +01:00
Anael Mobilia
e000c56787 jQuery -> Vanilla Javascript 2021-02-27 17:54:00 +01:00
Anael Mobilia
88c3de4a65 jQuery -> Vanilla Javascript 2021-02-27 17:53:23 +01:00
Anael Mobilia
c85caf8ba6 PSR-12 2021-02-27 17:38:47 +01:00
Anael Mobilia
32c0fc2c31 Ne pas traiter les ficheirs minifiés 2021-02-27 17:32:23 +01:00
Anael Mobilia
280e1fd120 Passage du lien github en pied de page 2021-02-27 17:23:26 +01:00
Anael Mobilia
c19f5f17de monSite.css ne doit pas être versionné (site local) 2021-02-27 16:45:52 +01:00
Anael Mobilia
6065823592 Le formulaire est englobé dans un if($maSession->checkFlag()) 2021-02-27 16:26:51 +01:00
Anael Mobilia
aaac7ed1ef PSR-12 2021-02-27 16:25:46 +01:00
Anael Mobilia
b302a61d16 Suppression de travis (passage à GiHub Actions uniquement 2021-02-27 16:25:16 +01:00
Anael Mobilia
c245a9e0f7 PHP 7.3 minimum (dernière version encore supportée) 2021-02-27 16:24:46 +01:00
Anael Mobilia
16c7d88405 Vérification PSR12 2021-02-27 15:49:13 +01:00
Anael Mobilia
3671ca371d Update copyright 2021-02-27 14:24:51 +01:00
Anael Mobilia
fd1aef69c9
Update phpunit.yml 2020-07-02 14:33:47 +02:00
Anael Mobilia
ad09233a10
Passage à github actions 2020-07-02 14:31:27 +02:00
Anael Mobilia
948961ddb3
Update phpunit.yml 2020-07-02 14:29:43 +02:00
Anael Mobilia
902806098a
Update phpunit.yml 2020-07-02 14:26:40 +02:00
Anael Mobilia
68094fa4a3
Update phpunit.yml 2020-07-02 14:22:16 +02:00
Anael Mobilia
2fc1de655a
Passage à github actions 2020-07-02 14:20:04 +02:00
Anael Mobilia
57c8bf2e20
Suppression PHP5.6 2020-07-02 14:02:01 +02:00
Anael Mobilia
417d207ff1
Suppression PHP5.6 2020-07-02 14:01:40 +02:00
Anael Mobilia
2358853548 Update libellés + fix use 2020-04-20 02:19:48 +02:00
Anael Mobilia
9f49b31bbf Libellés dynamiques 2020-04-20 02:11:55 +02:00
Anael Mobilia
0d8dbc277e Calcul du md5 final de l'image 2020-04-20 01:28:05 +02:00
Anael Mobilia
f8e1e64bcd Fix tests 2020-04-19 17:30:50 +02:00
Anael Mobilia
0e26e803e9 Mise à jour tests PHPCS 2020-04-19 17:25:47 +02:00
Anael Mobilia
a430870794 Suppression du namespace car conflit avec PHPUNIT... 2020-04-19 07:50:49 +02:00
Anael Mobilia
10e85c27e7
Delete abuseTest.php 2020-04-19 07:49:52 +02:00
Anael Mobilia
b2290e768b Suppression du namespace car conflit avec PHPUNIT... 2020-04-19 07:47:23 +02:00
Anael Mobilia
8e305fc93c
Delete membreTest.php 2020-04-19 07:43:53 +02:00
Anael Mobilia
55f77ee6e1
Delete installationTest.php 2020-04-19 07:43:46 +02:00
Anael Mobilia
3cd6232379
Delete imageUploadAndDeleteTest.php 2020-04-19 07:43:39 +02:00
Anael Mobilia
8091cf72aa
Delete imageObjectTest.php 2020-04-19 07:43:32 +02:00
Anael Mobilia
cad3eac1f8
Delete displayPicsTest.php 2020-04-19 07:43:24 +02:00
Anael Mobilia
8bed8c8020 PSR12 2020-04-19 07:41:44 +02:00
Anael Mobilia
d0cb5256c1 PHPCS : Pas d'erreur travis en cas de warnings 2020-04-19 07:32:10 +02:00
Anael Mobilia
6ea9943c21 PSR12 - namespace 2020-04-19 07:26:48 +02:00
Anael Mobilia
a580245dbc PSR12 2020-04-19 05:48:26 +02:00
Anael Mobilia
0361a7cb82 PSR12 2020-04-19 05:45:57 +02:00
Anael Mobilia
9ffb1203d8 PSR12 2020-04-19 05:41:41 +02:00
Anael Mobilia
d4c00c8d03 PSR12 2020-04-19 05:40:35 +02:00
Anael Mobilia
b1e534f713 envoyer => Submit pour harmonisation des formulaires 2020-04-19 03:40:37 +02:00
Anael Mobilia
d864360fbd Debug test 2020-04-19 03:37:16 +02:00
Anael Mobilia
a2460d1769 Fix test 2020-04-19 03:21:38 +02:00
Anael Mobilia
8c353f5c59 Fix test 2020-04-19 03:21:09 +02:00
Anael Mobilia
a6e5a82775 PSR12 - TRUE, FALSE and NULL must be lowercase 2020-04-19 03:18:07 +02:00
Anael Mobilia
97e69cfe8b Fix test 2020-04-19 03:13:58 +02:00
Anael Mobilia
49c58abfc4 PSR12 - Accolades 2020-04-19 03:05:59 +02:00
Anael Mobilia
0a5f75806c Fix tests 2020-04-19 03:00:50 +02:00
Anael Mobilia
ef443b3fde Fix SQL 2020-04-19 02:53:08 +02:00
Anael Mobilia
394d1f7983 Enregistrement du signalement pour toutes les images ayant le même MD5 2020-04-19 02:49:03 +02:00
Anael Mobilia
5cbc02de60 phpcs 2020-04-18 05:19:29 +02:00
Anael Mobilia
3e8ec97abd Ajout phpcs 2020-04-18 05:18:34 +02:00
Anael Mobilia
b9127dce91 Ajout phpcs 2020-04-18 05:14:15 +02:00
Anael Mobilia
4e4ed9ed5f Ajout phpcs 2020-04-18 05:10:52 +02:00
Anael Mobilia
e57e9dd41f Fix tests 2020-04-18 05:10:52 +02:00
Anael Mobilia
ca777b6606
Suppression codacy 2020-04-18 04:54:47 +02:00
Anael Mobilia
9e2b2ae8a2 Fix tests 2020-04-18 04:31:17 +02:00
Anael Mobilia
cd7ad7b751 Meilleure description stockage 2020-04-18 04:20:35 +02:00
Anael Mobilia
16bdbe57d3 Debug tests 2020-04-18 03:49:11 +02:00
Anael Mobilia
1c67d147b7 Debug tests 2020-04-18 03:46:19 +02:00
Anael Mobilia
6787220935 Debug tests 2020-04-18 03:42:18 +02:00
Anael Mobilia
6015861be4 Debug tests 2020-04-18 03:36:21 +02:00
Anael Mobilia
ec6b8b0dc7 Debug tests 2020-04-18 03:34:15 +02:00
Anael Mobilia
f2dda40d23 Update tests 2020-04-18 03:27:22 +02:00
Anael Mobilia
9b41589337 Cahmp fichier obligatoire 2020-04-18 03:27:08 +02:00
Anael Mobilia
fc225505c0 Fix $monRetour is undefined 2020-04-18 03:09:02 +02:00
Anael Mobilia
916f273026 Pause JPG images test
See #38
2020-04-18 03:01:16 +02:00
Anael Mobilia
c9d7204cad Update data set 2020-04-18 03:00:18 +02:00
Anael Mobilia
c499fecc9b Fix tests : chargement en mémoire des images pour comparaison 2020-04-18 02:31:44 +02:00
Anael Mobilia
36e82d7736 Fix tests : chargement en mémoire des images pour comparaison 2020-04-18 02:31:11 +02:00
Anael Mobilia
f228e1e82f Fix tests : chargement en mémoire des images pour comparaison 2020-04-18 02:11:44 +02:00
Anael Mobilia
a0be1d5ef7 Fix tests : chargement en mémoire des images pour comparaison 2020-04-18 02:04:53 +02:00
Anael Mobilia
ee66677a7b Fix tests : chargement en mémoire des images pour comparaison 2020-04-18 02:03:09 +02:00
Anael Mobilia
01fefd6bfc Update des images de tests avec les nouveaux paramétres de qualité 2020-04-18 01:54:57 +02:00
Anael Mobilia
733b97b3a1 Entrelacement en JPG & transparence en PNG 2020-04-18 01:48:27 +02:00
Anael Mobilia
19df8f4aa5 Séparation des tests dans plusieurs functions 2020-04-18 01:33:35 +02:00
Anael Mobilia
acb01fd28b Pas de modification des images GIF en fonction de la version de PHP 2020-04-18 01:31:32 +02:00
Anael Mobilia
86d4325384 Facilitation lecture tests images 2020-04-18 01:18:00 +02:00
Anael Mobilia
f528e448a0 Fix tests : mauvais types d'images...
Close #31
2020-04-18 01:04:13 +02:00
Anael Mobilia
d395dc42a6 Fix tests : mauvais types d'images...
Close #31
2020-04-18 00:59:53 +02:00
Anael Mobilia
12b33bb219 Mutualisation image pour tests 2020-04-18 00:37:33 +02:00
Anael Mobilia
9184205a0a fix tests 2020-04-18 00:27:21 +02:00
Anael Mobilia
746b3718bf fix tests 2020-04-18 00:20:16 +02:00
Anael Mobilia
347bf6f66d Fix fontawesome 2020-04-18 00:18:55 +02:00
Anael Mobilia
66b3c1b31e Fix tests PHP7.2+ 2020-04-18 00:15:28 +02:00
Anael Mobilia
ce2b7bc399 Fix tests PHP7.2+ 2020-04-18 00:03:00 +02:00
Anael Mobilia
2c821a4dea Suppression des miniatures non utilisées... 2020-04-17 23:41:47 +02:00
Anael Mobilia
0ab8b91640 Suppression des images non utilisées... 2020-04-17 23:39:16 +02:00
Anael Mobilia
9b367e115b Fix tests 2020-04-17 23:34:24 +02:00
Anael Mobilia
a685b8db04 Utilisation pour le fichier temporaire de getMd5 2020-04-17 23:32:24 +02:00
Anael Mobilia
862eaa5b82 Utilisation pour le fichier temporaire de getMd5 2020-04-17 23:24:06 +02:00
Anael Mobilia
240154d91e Ajout test getNbDoublons() 2020-04-17 23:19:55 +02:00
Anael Mobilia
735798fa23 Fix salt dans les tests.... 2020-04-17 22:47:07 +02:00
Anael Mobilia
315392ac55 Ajout vérification connexion du membre 2020-04-17 22:44:34 +02:00
Anael Mobilia
0809539d59 Debug tests... 2020-04-17 22:33:13 +02:00
Anael Mobilia
2bb0cdb72f Fix fopen/fwrite/fclose => file_put_contents() 2020-04-17 22:32:41 +02:00
Anael Mobilia
3f31c0c929 Fix fopen/fread/fclose => file_get_contents() 2020-04-17 22:29:29 +02:00
Anael Mobilia
93d53b9421 Suppression methode verifierRenvoiImage() qui n'est plus utilisée 2020-04-17 22:21:38 +02:00
Anael Mobilia
8fb121e0e2 Vérification de l'existence des images 2020-04-17 21:55:39 +02:00
Anael Mobilia
ca5129d4ea ID d'un utilsiateur est toujours un int 2020-04-17 21:37:07 +02:00
Anael Mobilia
87bc3b8182 Fix tests 2020-04-17 21:09:49 +02:00
Anael Mobilia
5e828c44ca Fix tests 2020-04-17 21:07:38 +02:00
Anael Mobilia
1efeb5e8f2 Création de l'image uniquement si pas d'erreurs ! 2020-04-17 21:04:55 +02:00
Anael Mobilia
0df59b70f4 Fix tests 2020-04-17 20:59:51 +02:00
Anael Mobilia
f0fecfe226 Enrgistrement de l'image après avoir effectué les traitements 2020-04-17 20:44:15 +02:00
Anael Mobilia
0e135d95d0 Factorisation de code pour les tests images 2020-04-17 20:35:01 +02:00
Anael Mobilia
6f61a48a93 typo 2020-04-17 20:18:23 +02:00
Anael Mobilia
c73dfe568e Simplification de la gestion des doublons vu que tout est fait en BDD derrière 2020-04-17 20:17:28 +02:00
Anael Mobilia
f7dad4f682 Factorisation du calcul du nombre de doublons + mise à jour pour image & miniatures 2020-04-17 20:15:31 +02:00
Anael Mobilia
ef3de045a4 Fix description 2020-04-17 19:01:21 +02:00
Anael Mobilia
175c859826 Fix tests suite à 47ede3728d 2020-04-13 06:16:33 +02:00
Anael Mobilia
47ede3728d Anti-flood sur formulaire de création de compte 2020-04-13 06:11:12 +02:00
Anael Mobilia
0e83ca0b09 Fix erreur au chargement de toutes les miniatures... 2020-04-13 06:04:04 +02:00
Anael Mobilia
d224cccb48 Mise à jour du message 2020-04-13 05:30:19 +02:00
Anael Mobilia
8b1ca8244d Fix test suite à 118fbc0923 2020-04-13 03:44:17 +02:00
Anael Mobilia
31681e4e28 Debug test 2020-04-13 03:38:15 +02:00
Anael Mobilia
fcd3b66825 Sauvegarde au niveau de l'action et non pas au niveau du setter utilisé également pour charger l'image 2020-04-13 03:28:07 +02:00
Anael Mobilia
dd9ce88164 Mise en place abuse pour bloquer les images
Implemente #14
2020-04-13 03:18:37 +02:00
Anael Mobilia
0f01412274 Pas de réaffichage du formulaire si le mail est envoyé 2020-04-13 03:16:59 +02:00
Anael Mobilia
dbff4aaf36 Gestion de la transparence des PNG
Fix #34
2020-04-13 02:39:13 +02:00
Anael Mobilia
d149f03340 Ajout d'une protection anti spam basique
Close #19
2020-04-13 02:33:30 +02:00
Anael Mobilia
118fbc0923 Protection anti-flood => passage à une méthode centralisée 2020-04-13 02:32:18 +02:00
Anael Mobilia
174d3c3cf7 static -> poo 2020-04-13 02:12:13 +02:00
Anael Mobilia
092cc72ed7 Placement des méthodes dans les bonnes classes 2020-04-13 02:08:29 +02:00
Anael Mobilia
93d2b56622 Fix typo 2020-04-13 02:00:06 +02:00
Anael Mobilia
81c02f9d1e Simplification formulaire contact 2020-04-13 01:55:54 +02:00
Anael Mobilia
ec3a1e6f9f Fix url 2020-04-13 01:52:37 +02:00
Anael Mobilia
b5098a1a80 Suppression du fichier map 2020-04-13 01:49:44 +02:00
Anael Mobilia
74f6d6fb2d
Gestion anciennes versions 2020-04-03 18:04:28 +02:00
Anael Mobilia
6e2ed4b7b0
Fix ancienne version 2020-04-03 18:03:11 +02:00
Anael Mobilia
1a915420cb
Fix pour environnement de tests 2020-04-03 17:56:38 +02:00
Anael Mobilia
78f96c10e5
Typo 2020-04-03 17:55:46 +02:00
Anael Mobilia
de52cf0d8b
Delete failureTest.php 2020-04-03 17:55:19 +02:00
Anael Mobilia
5a08b7f0f1
Gestion de l'environnement de tests 2020-04-03 17:53:25 +02:00
Anael Mobilia
b54d70cd35
Test de travis 2020-04-03 17:44:41 +02:00
Anael Mobilia
60057dbb9f
Update travis conf (bettre failures management) 2020-04-03 17:39:24 +02:00
Anael Mobilia
a0bbd5eab7
Fix new build config on travis 2020-04-03 17:32:42 +02:00
Anael Mobilia
461e1a2f40
Fix new build config on travais 2020-04-03 17:26:39 +02:00
Anael Mobilia
afc0719de4
Fix new build config on travais 2020-04-03 17:25:15 +02:00
Anael MOBILIA
d0a3883186 Fix rendu sur petit écran 2020-02-21 09:18:20 +01:00
Anael MOBILIA
79c9f00242 w3c 2020-02-21 09:14:18 +01:00
Anael MOBILIA
e47ff2b386 Adaptation du footer en fonction de la taille de l'écran 2020-02-21 09:13:43 +01:00
Anael MOBILIA
7ec635ae76 Ajout lien signaler une image dans le footer 2020-02-21 09:00:38 +01:00
Anael MOBILIA
adb2569798 Update copyright 2020-01-29 02:04:45 +01:00
Anael MOBILIA
446a5fbad4 Vérification de l'installation
Close #18
Close #27
2020-01-29 02:00:07 +01:00
Anael MOBILIA
1e834b569b Suppression du répertoire includes depuis de nombreuses versions... 2020-01-29 00:25:51 +01:00
Anael MOBILIA
2b8078a6ce Typo 2020-01-28 23:53:20 +01:00
Anael MOBILIA
7d77add39f Mise à jour notes de version 2020-01-28 23:51:58 +01:00
Anael MOBILIA
5b9d616830 usleep sur la connexion 2020-01-28 23:45:14 +01:00
Anael MOBILIA
fe7868e9e0 FontAwesome 5.12 + suppression de brands & regular (non utilisées) 2020-01-28 23:38:47 +01:00
Anael MOBILIA
5fdb4041a1 Update version PHP 2019-12-19 11:13:10 +01:00
Anael MOBILIA
87190f8d4e Update conf travis 2019-12-19 11:11:47 +01:00
Anael MOBILIA
9f99f7c33c Rendu mon compte sur une seule ligne 2019-12-19 10:44:05 +01:00
Anael MOBILIA
4eaeabd5bc Fix couleur par défaut 2019-12-19 10:20:19 +01:00
Anael Mobilia
041ffb7230
Merge pull request #32 from AnaelMobilia/bootstrap4
Bootstrap 3 -> 4
2019-12-19 09:57:10 +01:00
Anael MOBILIA
a0ddad71c6 Bootstrap 3 -> 4
Fix Issues #21 #22 #23
2019-12-19 09:50:13 +01:00
Anael Mobilia
6c6d051019
fix markdown 2019-11-25 23:55:19 +01:00
Anael Mobilia
9503ddaefd Ajout d'un type MIME systématique 2019-11-25 23:44:14 +01:00
Anael Mobilia
8660203f50 Ajout prise en charge PHP7.2, PHP7.3 + note sur versions PHP dépreciées 2019-11-25 23:33:53 +01:00
Anael Mobilia
fea6b79e18 Ajout ressources pour test PHP > 7.1 2019-11-25 23:25:01 +01:00
Anael Mobilia
1e984104d6
Générisation du fichier 2019-10-30 19:38:00 +01:00
Anael Mobilia
00acb3bf91
Ajout des thèmes bootswatch 2019-10-30 16:31:08 +01:00
Anael MOBILIA
78c687c767 v2.0.4 2019-10-29 22:52:51 +01:00
Anael MOBILIA
8273599ef0 Suppression des fichiers de configuration de l'IDE 2019-10-29 22:49:47 +01:00
Anael MOBILIA
712dec3538 Ajout note favicon 2019-10-29 22:42:00 +01:00
Anael MOBILIA
cc304f3195 Harmnisation nom des variables 2019-10-29 22:41:51 +01:00
Anael MOBILIA
026a05bcd8 Mise à jour gitignore 2019-10-29 22:40:00 +01:00
Anael MOBILIA
cb8b3870d8 Création arborescence 2019-10-29 22:38:50 +01:00
Anael MOBILIA
93c9988b25 Suppression du lien vers offre OVH spécifique 2019-10-29 22:36:13 +01:00
Anael MOBILIA
41b059d2f8 Séparation des variables de configuration des configurations techniques de l'outil 2019-10-29 22:35:29 +01:00
Anael MOBILIA
1060494e7d Générisation du css
ticket #26
2019-10-29 22:07:44 +01:00
Anael MOBILIA
62482b941b Générisation du css
ticket #26
2019-10-29 21:55:02 +01:00
Anael MOBILIA
52285defd4 Création d'un fichier de style dédié aux modifications de l'instance
ticket #26
2019-10-29 21:51:46 +01:00
Anael Mobilia
9868580f15
Update templateV2Bottom.php 2019-10-29 21:37:54 +01:00
Anael Mobilia
768eaab967
Ajout auteur 2019-10-28 13:22:30 +01:00
Anael MOBILIA
bd89326664 bootstrap 3.3.7 -> 3.4.1 2019-10-28 08:57:08 +01:00
Anael MOBILIA
58c5cfa960 Simplification 2019-10-28 08:05:41 +01:00
Anael MOBILIA
8f4c245057 Amélioration du rendu visuel 2019-10-27 22:12:47 +01:00
Anael MOBILIA
f18b4df0a0 Ajout d'un header pour valider le type mime 2019-10-27 22:12:18 +01:00
Anael MOBILIA
1878ced0e1 Remove .map link 2019-10-27 22:07:37 +01:00
Anael MOBILIA
f1d830867b fix typo 2019-10-27 21:46:28 +01:00
Anael MOBILIA
bdf92f6720 v2.0.3 2019-10-27 21:25:53 +01:00
Anael MOBILIA
2449e08d9f Fix for travis 2019-10-27 21:18:41 +01:00
Anael MOBILIA
821bb0793e Ajout d'un script de validation basique de l'installation
Fix #20
2019-10-27 21:13:15 +01:00
Anael MOBILIA
b138a4c6ba Gestion des versions de phpunit avec travis 2019-10-27 20:41:23 +01:00
Anael MOBILIA
d158be6eb0 Utilisation du nom du site pour les mails envoyés 2019-10-27 20:24:17 +01:00
Anael MOBILIA
48474711b6 jquery 3.3.1 -> 3.4.1 2019-10-27 20:03:47 +01:00
Anael MOBILIA
9a7d9b7587 Mysql 5.7 strict mode
#25
2019-10-27 19:42:43 +01:00
Anael MOBILIA
aa2cb812da Générisation des ficheirs de conf 2019-10-27 19:11:38 +01:00
Anael MOBILIA
cb566c0610 Mise à niveau du fichier de conf en mirroir // config example 2019-10-27 19:08:37 +01:00
Anael MOBILIA
679d9c8b38 configV2.php -> config.php (suppression de l'historicité du fichier) 2019-10-24 17:01:27 +02:00
Anael MOBILIA
ebf149bd89 #20 - Fix Warning: Division by zero si le service n'a jamais été utilisé 2019-10-24 16:50:24 +02:00
whitesource-bolt-for-github[bot]
888bb238f6 Migrate WhiteSource configuration file to json format 2019-05-17 21:06:54 +00:00
Anael MOBILIA
03de659f6a Fix too many requests by amazon robots 2019-05-17 23:06:44 +02:00
Anael MOBILIA
4dcc9b482a Tests - Images png >= 7.2 2019-02-14 09:34:15 +01:00
Anael MOBILIA
c39f405a10 fix nb images / tests 2019-02-14 08:33:44 +01:00
Anael MOBILIA
67a2adcc30 Fix SQL 2019-02-14 08:30:24 +01:00
Anael MOBILIA
6cbde9995e Test blocage image si signalée 2019-02-14 08:27:09 +01:00
Anael MOBILIA
c102d1fe38 Pas d'affichage des images signalées 2019-02-14 08:21:54 +01:00
Anael MOBILIA
eeed903c2f IsSignalee() => isSignalee() 2019-02-14 08:16:51 +01:00
Anael MOBILIA
c0b1182157 Separate tests for PHP 7.2 (as the image* libs changed...) 2019-02-12 16:53:22 +01:00
Anael MOBILIA
93b1101461 Prepare tests for php > 7.1 2019-02-12 16:46:13 +01:00
Anael MOBILIA
3b1ed085e7 Prepare tests for php > 7.1 2019-02-12 16:40:36 +01:00
Anael MOBILIA
d61a1ddb9a Fix BDD tests 2019-02-12 16:26:51 +01:00
Anael MOBILIA
9ed6f21eff Ajout de la notion de signalée pour les images 2019-02-12 16:25:07 +01:00
Anael MOBILIA
f40e5fafff isBloque() => isBloquee() 2019-02-12 16:20:10 +01:00
Anael MOBILIA
756ce4ede0 images : bloque -> isBloquee & ajout isSignalee 2019-02-12 16:18:04 +01:00
Anael MOBILIA
f6f80d6acb Remove debug code 2019-02-01 22:19:09 +01:00
Anael MOBILIA
4774a43fdc Remove debug code 2019-02-01 22:18:48 +01:00
Anael MOBILIA
a4d5f1fe25 Add php 7.3 & nightly on travis 2019-02-01 22:11:23 +01:00
Anael MOBILIA
04eb54829b backport update of config ba2fed1136 2019-02-01 22:10:33 +01:00
Anael MOBILIA
6c0fe20556 Suppression du scheme http / https 2019-02-01 20:21:15 +01:00
Anael MOBILIA
7cb2622af0 Fin de 6121edc487 2019-01-27 18:46:07 +01:00
Anael MOBILIA
ac4caed563 Update todo 2019-01-27 18:23:44 +01:00
Anael MOBILIA
8f4e5fd3bb v2.0.2 2019-01-27 18:21:32 +01:00
Anael MOBILIA
6121edc487 Suppression de la gestion des referer (aucune information utile n'est obtenue : > 99% du traffic provient en HTTPS sans referer...) 2019-01-27 18:12:30 +01:00
Anael MOBILIA
22e9e14dcf Add details on number 2019-01-27 14:11:54 +01:00
Anael MOBILIA
c682d196b3 Fix never use file is NEVER (not for the last xxx days) 2019-01-27 13:25:28 +01:00
Anael MOBILIA
c8d5509aa4 update jquery 2019-01-27 11:55:51 +01:00
Anael MOBILIA
6be1748cb5 Update copyright 2019-01-27 11:53:38 +01:00
Anael MOBILIA
fba0e93265 Ajout de la ligne de config de ba2fed1136 2019-01-27 11:34:15 +01:00
whitesource-bolt-for-github[bot]
52c94c9770 Initial WhiteSource configuration file 2018-12-13 13:18:40 +00:00
Anael Mobilia
f3ba992363 PHP 7.2 n'est pas pris en charge (tests travis HS) 2018-08-29 01:57:15 +02:00
Anael Mobilia
6b15e2ae8e PHP 7.2 n'est pas pris en charge (tests travis HS) 2018-08-29 01:51:27 +02:00
Anael Mobilia
f6731cfa89 Suppression de la gestion du referer dans l'exécution des tests automatiques 2018-08-29 01:48:05 +02:00
Anael Mobilia
313d66844e Fix SQL 2018-08-29 01:42:47 +02:00
Anael Mobilia
7ba5ea80b3 Travis - affichage version mysql 2018-08-29 01:41:50 +02:00
Anael Mobilia
2504567d4a Fix travis 2018-08-29 01:32:53 +02:00
Anael Mobilia
08936688c8 Fix boucle htaccess faisant perdre le REQUEST_URI (donc pas d'affichage d'image) 2018-08-29 01:24:31 +02:00
Anael Mobilia
98e2fc1812 Ajout crédits pour bouton fork me on GitHub 2018-06-29 23:16:42 +02:00
Anael Mobilia
e52237388a Ajout crédits pour bouton fork me on GitHub 2018-06-29 23:16:17 +02:00
Anael Mobilia
e5157a0520 Ajout bouton fork me on GitHub 2018-06-29 23:08:21 +02:00
Anael Mobilia
ba2fed1136 Ajout d'un quota d'espace disque pour un blocage dynamique de l'envoi de fichiers 2018-06-29 22:38:31 +02:00
Anael Mobilia
d112912efd Optimisation SQL 2018-06-29 22:05:54 +02:00
Anael Mobilia
22b59165e3 MàJ changelog 2018-06-29 22:00:20 +02:00
Anael Mobilia
d4dfebb9fc - Passage en var dynamique des délais avant effacement des fichiers
- Mise à jour des CGU en dynamique
- Prise en compte de l'affichage des miniatures pour la date de dernière activité
2018-06-29 21:59:16 +02:00
Anael Mobilia
867605488d Fix redirection HTTPS 2018-06-29 21:32:04 +02:00
Anael Mobilia
e04cddf2c1 Fix pas de chargement de l'utilisateur object... 2018-06-12 22:19:40 +02:00
Anael Mobilia
09a702b189 Ajout d'un index 2018-06-12 21:03:43 +02:00
Anael Mobilia
03d9e13800 Ajout d'un index 2018-06-12 20:59:09 +02:00
Anael Mobilia
352e92ba57 Fix undefined notice sur HTTP_REFERER si accès direct 2018-06-12 20:31:39 +02:00
Anael Mobilia
52416756fb Suivi des appels des images 2018-06-08 21:15:42 +02:00
Anael Mobilia
bc5326e474 Ajout lien vers ovh 2018-06-08 21:13:52 +02:00
Anael Mobilia
82dd1b93dc Désactivation de l'envoi d'image 2018-06-08 21:11:06 +02:00
Anael Mobilia
868097e3e4 fix undefined index si pas de referer 2018-06-08 21:07:46 +02:00
Anael Mobilia
731e6a7a8e Amélioration affichage 2018-06-05 20:12:41 +02:00
Anael Mobilia
1a21ee6873 Tri par nb de visites 2018-06-05 20:08:05 +02:00
Anael Mobilia
0066255b0c Referer peut être null 2018-06-03 03:38:48 +02:00
146 changed files with 10034 additions and 6030 deletions

30
.github/workflows/phpcs.yml vendored Normal file
View file

@ -0,0 +1,30 @@
# This is a basic workflow to help you get started with Actions
name: PHP_CodeSniffer - Qualité du code
# Controls when the action will run.
# Triggers the workflow on push or pull request events
# Allows you to run this workflow manually from the Actions tab
on: [push, pull_request, workflow_dispatch]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: cs2pr, phpcs
- name: Run phpcs
run: |
phpcs --version
phpcs -q --standard=$GITHUB_WORKSPACE/.phpcs_ruleset.xml --report=checkstyle $GITHUB_WORKSPACE | cs2pr

57
.github/workflows/phpunit.yml vendored Normal file
View file

@ -0,0 +1,57 @@
name: PHPUnit - Tests de l'application
on: [ push, pull_request, workflow_dispatch ]
jobs:
run:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [ '8.3', '8.4' ]
name: PHP ${{ matrix.php-versions }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configuration PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: imagick, pdo_mysql
tools: phpunit
ini-values: error_reporting=E_ALL, display_errors=On
- name: Lancement de MySQL
run: sudo systemctl start mysql.service
- name: Informations sur l'environnement
run: |
php --version
mysql -V
phpunit --version
php -r 'echo Imagick::getVersion()["versionString"];'
php -r 'echo phpinfo();'
mysql -u root -proot -e "SELECT @@GLOBAL.sql_mode global, @@SESSION.sql_mode session"
- name: Mise en place de l'environnement
run: |
mysql -u root -proot -e "SET GLOBAL sql_mode = 'NO_ENGINE_SUBSTITUTION';"
mysql -u root -proot -e "alter user 'root'@'localhost' identified with mysql_native_password by 'root';"
mysql -u root -proot -e "CREATE DATABASE imageheberg;"
mysql -u root -proot imageheberg < database.sql
sh -c "mv __tests/config/config.php config/"
sh -c "mv __tests/ipv*.txt files/z_cache/"
# Pour ImageUploadAndDeleteTest
sh -c "find files/ -name _dummy -type f -delete"
# Pour AbuseTest
sh -c "mv __tests/images/image_33.png files/d/d0a77eeeff5ef764505fe5b119b913bf"
# Injection des données
mysql -u root -proot imageheberg < __tests/data.sql
# Adaptation à l'environnement actuel
php '__tests/_bootstrap.php'
- name: Test de l'application - phpunit v11
if: ${{ matrix.php-versions != '8.0' }}
run: phpunit --colors --display-warnings --display-errors __tests/

7
.gitignore vendored
View file

@ -1,2 +1,5 @@
/config/configV2.php
/nbproject/
/.idea/
/config/config.php
/nbproject/
/template/css/monSite.css
/template/images/monSite.ico

View file

@ -1,5 +1,5 @@
#/*
#* Copyright 2008-2017 Anael Mobilia
#* Copyright 2008-2024 Anael MOBILIA
#*
#* This file is part of image-heberg.fr.
#*
@ -23,29 +23,27 @@ Options -Indexes
# Ré-écriture d'URL
RewriteEngine On
# Redirection systématique - si requise - vers www.image-heberg.fr
# HTTPS
RewriteCond %{HTTPS} on
# Redirection systématique - si requise - vers **www**.image-heberg.fr
RewriteCond %{HTTP_HOST} image-heberg\.fr\.cr [NC,OR]
RewriteCond %{HTTP_HOST} ^image-heberg\.fr [NC]
RewriteRule (.*) https://www.image-heberg.fr/$1 [R=301,L,NE]
# HTTP
RewriteCond %{HTTP_HOST} image-heberg\.fr\.cr [NC,OR]
RewriteCond %{HTTP_HOST} ^image-heberg\.fr [NC]
RewriteRule (.*) http://www.image-heberg.fr/$1 [R=301,L,NE]
# Protection des répertoires classes, config, __tests, includes
RewriteCond %{REQUEST_URI} ^/classes/ [OR]
RewriteCond %{REQUEST_URI} ^/config/ [OR]
RewriteCond %{REQUEST_URI} ^/__tests/ [OR]
RewriteCond %{REQUEST_URI} ^/includes/
RewriteRule .* - [F]
# Images : redirection pour affichage
RewriteCond %{REQUEST_URI} ^/files/
RewriteRule .* displayPics.php [L]
# HTTPS obligatoire pour le site (hors affichage image)
RewriteCond %{HTTPS} off
RewriteCond !%{REQUEST_URI} ^/files/
RewriteRule (.*) https://www.image-heberg.fr/$1 [R=301,L,NE]
RewriteCond %{REQUEST_URI} !^/files/
RewriteRule (.*) https://www.image-heberg.fr/$1 [R=301,L,NE]
# Protection des répertoires classes, config, cron, __tests
RewriteCond %{REQUEST_URI} ^/classes/ [OR]
RewriteCond %{REQUEST_URI} ^/config/ [OR]
RewriteCond %{REQUEST_URI} ^/cron/ [OR]
RewriteCond %{REQUEST_URI} ^/__tests/
RewriteRule .* - [F]
# Bootstrap icons - fichiers de fonts
RewriteCond %{REQUEST_URI} ^/template/css/fonts/
RewriteRule .*/(fonts/.*) https://www.image-heberg.fr/template/$1 [L,NE]
# Images : redirection pour affichage
RewriteCond %{REQUEST_URI} ^/files/
RewriteRule .* displayPics.php [END]

20
.phpcs_ruleset.xml Normal file
View file

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<ruleset name="myRuleset">
<description>Regles pour le projet.</description>
<!-- Ne pas traiter les fichiers minifiés -->
<exclude-pattern>*.min.*</exclude-pattern>
<!-- Inclure PSR-12 -->
<rule ref="PSR12">
<!-- Exclure les CRLF (gérés par git => core.autocrlf=true ) -->
<exclude name="Generic.Files.LineEndings.InvalidEOLChar" />
<!-- Exclure la longueur des lignes -->
<exclude name="Generic.Files.LineLength.TooLong" />
</rule>
<!-- Exclure les fichiers de conf qui ont un require sur le fichier générique à la fin -->
<rule ref="PSR1.Files.SideEffects.FoundWithSymbols">
<exclude-pattern>*/config/*.php</exclude-pattern>
<exclude-pattern>*/cron/*.php</exclude-pattern>
</rule>
</ruleset>

View file

@ -1,46 +0,0 @@
#/*
# * Copyright 2008-2018 Anael Mobilia
# *
# * This file is part of image-heberg.fr.
# *
# * image-heberg.fr is free software: you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation, either version 3 of the License, or
# * (at your option) any later version.
# *
# * image-heberg.fr is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
# */
# Language
language: php
# Versions de PHP testées
php:
- '5.6'
- '7.0'
- '7.1'
- '7.2'
# Autres prérequis
services:
- mysql
# Créer la BDD avant de commencer
before_script:
# Création de la BDD
- mysql -e "CREATE DATABASE imageheberg;"
# Injection des tables de base
- mysql imageheberg < database.sql
# Copie du fichier de configuration
- sh -c "mv __tests/config/configV2.php config/"
# Insertion d'un jeu de données de test
- mysql imageheberg < __tests/data.sql
script:
- phpunit --version
- phpunit --colors --debug __tests/

8
.whitesource Normal file
View file

@ -0,0 +1,8 @@
{
"generalSettings": {
"shouldScanRepo": true
},
"checkRunSettings": {
"vulnerableCheckRunConclusionLevel": "success"
}
}

View file

@ -1,21 +1,33 @@
[![Build Status](https://travis-ci.org/AnaelMobilia/image-heberg.fr.svg?branch=master)](https://travis-ci.org/AnaelMobilia/image-heberg.fr)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/d61a46162db94e0b8a053f4bb5dbc62f)](https://www.codacy.com/app/AnaelMobilia/image-heberg-fr?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=AnaelMobilia/image-heberg.fr&amp;utm_campaign=Badge_Grade)
# image-heberg.fr
Service d'hébergement d'images en ligne
# Configuration requise
- PHP 5.6 ou plus récent
- MySQL
- Serveur web comprenant les fichiers .htaccess
- PHP 8.3 [*(Préférez une version de PHP maintenue !)*](https://www.php.net/supported-versions.php)
- Imagick
- MySQL ou MariaDB
- Serveur web gérant les fichiers .htaccess
# Installation
- Créer une base de données à partir du fichier database.sql
- Copier les fichiers dans le répertoire du serveur web
- Renommer le fichier configV2_empty.php en configV2.php et compléter les différents champs
- Renommer le fichier config_empty.php en config.php et compléter les différents champs
- Ajouter votre favicon dans template/images/monSite.ico
- Ajouter votre css dans template/css/monSite.css
- Configurer l'URL du site dans le fichier .htaccess
- Se connecter avec le compte admin / password. Ce compte est le compte de l'administrateur du site. (pensez à mettre à jour l'adresse mail associée !)
- Valider l'installation de base en appelant le fichier install.php (example.com/install.php)
- Mettre en place un cron sur cron/updateTorIp.php, cron/cleanImages.php, cron/cleanAccounts.php, cron/abuse.php
- Se connecter avec le compte admin / password. Ce compte est le compte de l'administrateur du site.
- Modifier le mot de passe du compte
- Mettre à jour l'adresse email associée
# Changer de thème
- Choisir un thème sur [bootswatch](https://bootswatch.com/)
- Télécharger le fichier bootstrap.min.css
- Remplacer le contenu du fichier templates/css/boostrap-x.y.z.min.css par le fichier téléchargé
- Si souhaité, ajouter du code CSS spécifique dans le fichier templates/css/monSite.css
# Stockage des images
- Les images sont stockées dans le répertoire /files ou /files/thumbs en fonction de leur type.
- Chaque image est stockée sous forme de md5 (correspondance en BDD)
- Pour limiter le nombre de fichiers par répertoire, chaque image est stockée dans un sous répertoire qui est la première lettre de son md5
- Chaque image est stockée sous le nom du md5 de son fichier d'origine (correspondance en BDD)
- Pour limiter le nombre de fichiers par répertoire, chaque image est stockée dans un sous répertoire qui est la première lettre de son md5

455
__tests/AbuseTest.php Normal file
View file

@ -0,0 +1,455 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHebergTests;
use ImageHeberg\HelperAbuse;
use ImageHeberg\ImageObject;
use ImageHeberg\HelperAdmin;
use ImageHeberg\RessourceObject;
use ImageHeberg\UtilisateurObject;
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
use PHPUnit\Framework\TestCase;
class AbuseTest extends TestCase
{
/**
* Signalement d'une image
*/
#[RunInSeparateProcess]
public function testAbuse(): void
{
require 'config/config.php';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['flag'] = true;
$_POST['userMail'] = 'john.doe@example.com';
$_POST['urlImage'] = 'https://www.example.com/files/image_15.png';
ob_start();
require 'abuse.php';
ob_end_clean();
$imageBloquee = new ImageObject('image_15.png');
$imageMemeMd5 = new ImageObject('image_16.png');
$this->assertEmpty(
$msgErreur,
__FUNCTION__ . ' ne devrait pas lever de message d\'erreur - Erreur : ' . $msgErreur
);
$this->assertTrue(
$imageBloquee->isSignalee(),
'Image signalée doit l\'être'
);
$this->assertTrue(
$imageMemeMd5->isSignalee(),
'Image avec même MD5 qu\'une image signalée doit l\'être également'
);
}
/**
* Renvoi d'une image bloquée et demande de son affichage
*/
#[RunInSeparateProcess]
public function testAbuseRenvoiImage(): void
{
require 'config/config.php';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['flag'] = true;
$_FILES['fichier']['size'] = 146;
$_FILES['fichier']['name'] = 'imageDejaBloquee.gif';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEmpty(
$msgErreur,
__FUNCTION__ . ' ne devrait pas lever de message d\'erreur - Erreur : ' . $msgErreur
);
$this->assertEmpty(
$msgWarning,
__FUNCTION__ . ' ne devrait pas lever de message de warning - Warning : ' . $msgWarning
);
$this->assertTrue(
$monImage->isBloquee(),
'Renvoi image déjà bloquée doit être isBloquée en BDD'
);
}
/**
* Signalement d'une image approuvée
*/
#[RunInSeparateProcess]
public function testAbuseImageApprouvee(): void
{
require 'config/config.php';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['flag'] = true;
$_POST['userMail'] = 'john.doe@example.com';
$_POST['urlImage'] = 'https://www.example.com/files/_image_404.png';
ob_start();
require 'abuse.php';
ob_end_clean();
$imageSignalee = new ImageObject('_image_404.png');
$this->assertEmpty(
$msgErreur,
__FUNCTION__ . ' ne devrait pas lever de message d\'erreur - Erreur : ' . $msgErreur
);
$this->assertFalse(
$imageSignalee->isSignalee(),
'Image approuvée qui est signalée ne doit pas être bloquée'
);
}
/**
* Approbation d'une image signalée
*/
#[RunInSeparateProcess]
public function testAbuseImageSignaleePuisApprouvee(): void
{
require 'config/config.php';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
// Flagguer l'image comme signalée
$image = new ImageObject('_image_banned.png');
$image->setSignalee(true);
$image->sauver();
// Se connecter en tant que l'admin
$monMembre = new UtilisateurObject();
$monMembre->connexion('admin', 'password');
// Approuver l'image dans l'admin
$_GET['approuver'] = '1';
$_GET['idImage'] = '2';
ob_start();
require 'admin/abuse.php';
ob_end_clean();
$image = new ImageObject('_image_banned.png');
$this->assertFalse(
$image->isSignalee(),
'Image signalée qui est approuvée ne doit plus être signalée'
);
}
/**
* Renvoi d'une image déjà bloquée
*/
#[RunInSeparateProcess]
public function testAbuseImageRenvoiImageBloqueeDepuisReseauMalveillant(): void
{
require 'config/config.php';
$imagesAvantEnvoi = HelperAdmin::getImagesPotentiellementIndesirables();
$_SERVER['REMOTE_ADDR'] = '10.10.10.11';
$_POST['Submit'] = 1;
$_SESSION['flag'] = true;
$_FILES['fichier']['size'] = 146;
$_FILES['fichier']['name'] = 'imageDejaBloquee.gif';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
ob_start();
require 'upload.php';
ob_end_clean();
$imagesApresEnvoi = HelperAdmin::getImagesPotentiellementIndesirables();
$this->assertEmpty(
$msgErreur,
__FUNCTION__ . ' ne devrait pas lever de message d\'erreur - Erreur : ' . $msgErreur
);
$this->assertEmpty(
$msgWarning,
__FUNCTION__ . ' ne devrait pas lever de message de warning - Warning : ' . $msgWarning
);
$this->assertEquals(
$imagesAvantEnvoi->count(),
$imagesApresEnvoi->count(),
'Le renvoi d\'une image bloquée doit être bloqué'
);
}
/**
* Envoi d'une image depuis le même réseau qu'une image bloquée
*/
#[RunInSeparateProcess]
public function testAbuseImageEnvoiDepuisReseauMalveillant(): void
{
require 'config/config.php';
$imagesAvantEnvoi = HelperAdmin::getImagesPotentiellementIndesirables();
$_SERVER['REMOTE_ADDR'] = '10.10.10.11';
$_POST['Submit'] = 1;
$_SESSION['flag'] = true;
$_FILES['fichier']['size'] = 146;
$_FILES['fichier']['name'] = 'rotation_original.gif';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
ob_start();
require 'upload.php';
ob_end_clean();
$imagesApresEnvoi = HelperAdmin::getImagesPotentiellementIndesirables();
$this->assertEmpty(
$msgErreur,
__FUNCTION__ . ' ne devrait pas lever de message d\'erreur - Erreur : ' . $msgErreur
);
$this->assertEmpty(
$msgWarning,
__FUNCTION__ . ' ne devrait pas lever de message de warning - Warning : ' . $msgWarning
);
$this->assertEquals(
($imagesAvantEnvoi->count() + 1),
$imagesApresEnvoi->count(),
'L\'image envoyée devrait être considérée comme potentiellement indésirable : ' . var_export($imagesApresEnvoi, true)
);
}
/**
* Image avec une miniature ENORMEMENT affichée
*/
#[RunInSeparateProcess]
public function testAbuseImageMiniatureTropAffichee(): void
{
require 'config/config.php';
$images = HelperAdmin::getImagesTropAffichees(_ABUSE_NB_AFFICHAGES_PAR_JOUR_BLOCAGE_AUTO_);
$this->assertNotEmpty(
$images,
'Les affichages des miniatures doivent compter dans les affichages d\'une image pour la détection des abus : ' . var_export($images, true)
);
}
/**
* Division des seuils de détection pour une image envoyée du même réseau qu'une image déjà bloquée
*/
#[RunInSeparateProcess]
public function testAbuseDivisionSeuilDetectionSiReseauMalveillant(): void
{
require 'config/config.php';
// Liste des images suspectes
$listeImagesSuspectes = HelperAdmin::getImagesPotentiellementIndesirables();
$imagesTropAffichees = HelperAdmin::getImagesTropAffichees((_ABUSE_NB_AFFICHAGES_PAR_JOUR_WARNING_ / _ABUSE_DIVISION_SEUILS_SI_SUSPECT_), true);
$this->assertContains(
'image_20.gif',
$listeImagesSuspectes,
'L\'image 19 est suspecte car envoyée d\'un même réseau que l\'image 18'
);
$this->assertContains(
'image_20.gif',
$imagesTropAffichees,
'L\'image 19 a été trop affichée -> WARNING (elle est suspecte)'
);
}
/**
* Réputation des adresses IP basées sur les images déjà bloquées pour leur réseau
*/
#[RunInSeparateProcess]
public function testAbuseReputationIp(): void
{
require 'config/config.php';
// Adresse IP ayant envoyé les fichiers bloqués
$this->assertEquals(
5,
HelperAbuse::checkIpReputation('192.168.0.1'),
'Le réseau 192.168.0.0/24 a 5 images bloquées'
);
// Adresse IP du même réseau que celle ayant envoyé les fichiers bloqués
$this->assertEquals(
5,
HelperAbuse::checkIpReputation('192.168.0.100'),
'Le réseau 192.168.0.0/24 a 5 images bloquées'
);
// Adresse IP random qui n'a pas d'images bloqués
$this->assertEquals(
0,
HelperAbuse::checkIpReputation('2a01:ab51:8880:e010:1da5:be67:6a52:a5bf'),
'Aucune image bloquée dans le réseau de cette adresse IP'
);
}
/**
* Projection du nombre d'affichage d'une image pour détecter une atteinte de limite ultérieure
*/
#[RunInSeparateProcess]
public function testAbuseProjectionAffichages(): void
{
require 'config/config.php';
$images = HelperAdmin::getImagesTropAffichees(_ABUSE_NB_AFFICHAGES_PAR_JOUR_BLOCAGE_AUTO_, false, true);
$this->assertContains(
'image_27.png',
$images,
'L\'image 27 doit être détectée comme dépassant le nombre d\'affichage en projection : ' . var_export($images, true)
);
}
/**
* Le blocage d'une image bloque toutes celles partageant le même MD5
*/
#[RunInSeparateProcess]
public function testAbuseContaminationMD5Blocage(): void
{
require 'config/config.php';
$monImage = new ImageObject('28', RessourceObject::SEARCH_BY_ID);
$monImage->bloquer();
$image28 = new ImageObject('28', RessourceObject::SEARCH_BY_ID);
$image29 = new ImageObject('29', RessourceObject::SEARCH_BY_ID);
$this->assertTrue(
$image28->isBloquee(),
'L\'image 28 doit être bloquée'
);
$this->assertTrue(
$image29->isBloquee(),
'L\'image 29 doit être bloquée'
);
$this->assertFalse(
$image28->isApprouvee(),
'L\'image 28 ne doit pas être approuvée'
);
$this->assertFalse(
$image29->isApprouvee(),
'L\'image 29 ne doit pas être approuvée'
);
}
/**
* L'approbation d'une image approuve toutes celles partageant le même MD5
*/
#[RunInSeparateProcess]
public function testAbuseContaminationMD5Approbation(): void
{
require 'config/config.php';
$monImage = new ImageObject('30', RessourceObject::SEARCH_BY_ID);
$monImage->approuver();
$image30 = new ImageObject('30', RessourceObject::SEARCH_BY_ID);
$image31 = new ImageObject('31', RessourceObject::SEARCH_BY_ID);
$image32 = new ImageObject('32', RessourceObject::SEARCH_BY_ID);
$this->assertFalse(
$image30->isBloquee(),
'L\'image 30 ne doit pas être bloquée'
);
$this->assertFalse(
$image31->isBloquee(),
'L\'image 31 ne doit pas être bloquée'
);
$this->assertFalse(
$image32->isBloquee(),
'L\'image 32 ne doit pas être bloquée'
);
$this->assertFalse(
$image30->isSignalee(),
'L\'image 30 ne doit pas être signalée'
);
$this->assertFalse(
$image31->isSignalee(),
'L\'image 31 ne doit pas être signalée'
);
$this->assertFalse(
$image32->isSignalee(),
'L\'image 32 ne doit pas être signalée'
);
$this->assertTrue(
$image30->isApprouvee(),
'L\'image 30 doit être approuvée'
);
$this->assertTrue(
$image31->isApprouvee(),
'L\'image 31 doit être approuvée'
);
$this->assertTrue(
$image32->isApprouvee(),
'L\'image 32 doit être approuvée'
);
}
/**
* Une image demandée par un User-Agent suspect doit être signalée.
*/
#[RunInSeparateProcess]
public function testBlocageParUserAgent(): void
{
require 'config/config.php';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['HTTP_USER_AGENT'] = 'someUserAgentNumberOne';
$_SERVER['REQUEST_URI'] = 'files/image_33.png';
$monImage = new ImageObject('33', RessourceObject::SEARCH_BY_ID);
$this->assertFalse(
$monImage->isSignalee(),
'L\'image ne doit pas être signalée de base.'
);
ob_start();
require 'displayPics.php';
ob_end_clean();
$monImage = new ImageObject('33', RessourceObject::SEARCH_BY_ID);
$this->assertTrue(
$monImage->isSignalee(),
'Signalement de l\'image basé sur le User-Agent présenté'
);
}
/**
* Projection du nombre d'affichage d'une image pour détecter une atteinte de limite ultérieure
*/
#[RunInSeparateProcess]
public function testAbuseNombreAffichagesAbusifs(): void
{
require 'config/config.php';
$images = HelperAdmin::getImagesTropAffichees(_ABUSE_NB_AFFICHAGES_PAR_JOUR_ABUSIF_, false, true, true);
$this->assertContains(
'image_34.png',
$images,
'L\'image 34 doit être détectée comme ayant un nombre d\'affichages abusif : ' . var_export($images, true)
);
}
}

139
__tests/DisplayPicsTest.php Normal file
View file

@ -0,0 +1,139 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHebergTests;
use ImageHeberg\RessourceObject;
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
use PHPUnit\Framework\TestCase;
class DisplayPicsTest extends TestCase
{
/**
* Affichage d'une image inexistante
*/
#[RunInSeparateProcess]
public function testImageInexistante(): void
{
require 'config/config.php';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_URI'] = 'files/fichierInexistant.jpg';
ob_start();
require 'displayPics.php';
ob_end_clean();
/* @var $monObjet RessourceObject */
$this->assertEquals(
_IMAGE_404_,
$monObjet->getNomNouveau(),
'image_404 si inexistante'
);
}
/**
* Affichage d'une image inexistante
*/
#[RunInSeparateProcess]
public function testMiniatureInexistante(): void
{
require 'config/config.php';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_URI'] = 'files/thumbs/fichierInexistant.jpg';
ob_start();
require 'displayPics.php';
ob_end_clean();
/* @var $monObjet RessourceObject */
$this->assertEquals(
_IMAGE_404_,
$monObjet->getNomNouveau(),
'image_404 si inexistante'
);
}
/**
* Affichage d'une image inexistante
*/
#[RunInSeparateProcess]
public function testRepertoireInexistant(): void
{
require 'config/config.php';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_URI'] = 'files/repertoireInexistant/fichierInexistant.jpg';
ob_start();
require 'displayPics.php';
ob_end_clean();
/* @var $monObjet RessourceObject */
$this->assertEquals(
_IMAGE_404_,
$monObjet->getNomNouveau(),
'image_404 si mauvais sous répertoire'
);
}
/**
* Affichage d'une image bloquée
*/
#[RunInSeparateProcess]
public function testImageBloquee(): void
{
require 'config/config.php';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_URI'] = 'files/image_10.png';
ob_start();
require 'displayPics.php';
ob_end_clean();
/* @var $monObjet RessourceObject */
$this->assertEquals(
_IMAGE_BAN_,
$monObjet->getNomNouveau(),
'image_ban si image bloquée'
);
}
/**
* Affichage d'une image signaléee
*/
#[RunInSeparateProcess]
public function testImageSignalee(): void
{
require 'config/config.php';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_URI'] = 'files/image_18.png';
ob_start();
require 'displayPics.php';
ob_end_clean();
/* @var $monObjet RessourceObject */
$this->assertEquals(
_IMAGE_BAN_,
$monObjet->getNomNouveau(),
'image_ban si image signalée'
);
}
}

278
__tests/ImageObjectTest.php Normal file
View file

@ -0,0 +1,278 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHebergTests;
use ImageHeberg\ImageObject;
use ImagickException;
use ImagickPixelException;
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
use PHPUnit\Framework\TestCase;
use Imagick;
/**
* L'entête des fichiers contient des informations sur la bibliothéque système les ayant produit
* <CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), quality = 100
*/
class ImageObjectTest extends TestCase
{
// Rotation pour les images
private const array ROTATION_ANGLES = [0, 90, 180, 270];
// Couleurs des 4 coins : HG / BG / BD / HD
private const array ROTATION_COULEURS = [
0 => [
'r' => 255,
'g' => 0,
'b' => 0,
],
1 => [
'r' => 0,
'g' => 255,
'b' => 0,
],
2 => [
'r' => 0,
'g' => 0,
'b' => 255,
],
3 => [
'r' => 255,
'g' => 255,
'b' => 255,
],
];
// Dimensions d'origine de l'image
private const array ROTATION_DIM_ORIGINE = [640, 150];
/**
* Les couleurs des images sont conservées à +/- 1 point de valeur
* @param array $reference Couleur de référence
* @param array $valeur Couleur à comparer
* @return bool
*/
private function compareColor(array $reference, array $valeur): bool
{
$monRetour = true;
foreach ($reference as $key => $value) {
if (
$valeur[$key] !== $value
&& $valeur[$key] !== ($value - 1)
&& $valeur[$key] !== ($value + 1)
) {
$monRetour = false;
break;
}
}
// Debug
if (!$monRetour) {
echo PHP_EOL . 'Expected : ' . var_export($reference, true) . PHP_EOL . 'Actual : ' . var_export($valeur, true) . PHP_EOL;
}
return $monRetour;
}
/**
* Rotation des images
* @throws ImagickPixelException
* @throws ImagickException
*/
#[RunInSeparateProcess]
public function testRotationImages(): void
{
require 'config/config.php';
$monImage = new ImageObject();
foreach (_ACCEPTED_EXTENSIONS_ as $uneExtension) {
foreach (self::ROTATION_ANGLES as $unAngle) {
$monImage->rotation(
$unAngle,
_PATH_TESTS_IMAGES_ . 'rotation_original.' . $uneExtension,
_PATH_TESTS_OUTPUT_ . 'rotation_original-' . $unAngle . '.' . $uneExtension
);
// Calcul des dimensions théoriques
$indiceLargeur = (($unAngle % 180) === 0 ? 0 : 1);
$indiceHauteur = (($unAngle % 180) === 0 ? 1 : 0);
// Vérifier les dimensions des images
$imageInfo = getimagesize(_PATH_TESTS_OUTPUT_ . 'rotation_original-' . $unAngle . '.' . $uneExtension);
$this->assertEquals(
self::ROTATION_DIM_ORIGINE[$indiceLargeur],
$imageInfo[0],
'Largeur d\'image - Rotation ' . $uneExtension . ' ' . $unAngle
);
$this->assertEquals(
self::ROTATION_DIM_ORIGINE[$indiceHauteur],
$imageInfo[1],
'Hauteur d\'image - Rotation ' . $uneExtension . ' ' . $unAngle
);
// Vérifier les couleurs
$image = new Imagick(_PATH_TESTS_OUTPUT_ . 'rotation_original-' . $unAngle . '.' . $uneExtension);
$this->assertTrue(
$this->compareColor(self::ROTATION_COULEURS[round($unAngle / 90)], $image->getImagePixelColor(0, 0)->getColor()),
'Pixel (0,0) - Couleur ' . $uneExtension . ' - Rotation ' . $unAngle
);
$this->assertEquals(
$this->compareColor(self::ROTATION_COULEURS[(round($unAngle / 90) + 1) % 4], $image->getImagePixelColor(0, self::ROTATION_DIM_ORIGINE[$indiceHauteur])->getColor()),
'Pixel (0,' . self::ROTATION_DIM_ORIGINE[$indiceHauteur] . ') - Couleur ' . $uneExtension . ' - Rotation ' . $unAngle
);
$this->assertEquals(
$this->compareColor(self::ROTATION_COULEURS[(round($unAngle / 90) + 2) % 4], $image->getImagePixelColor(self::ROTATION_DIM_ORIGINE[$indiceLargeur], self::ROTATION_DIM_ORIGINE[$indiceHauteur])->getColor()),
'Pixel (' . self::ROTATION_DIM_ORIGINE[$indiceLargeur] . ',' . self::ROTATION_DIM_ORIGINE[$indiceHauteur] . ') - Couleur ' . $uneExtension . ' - Rotation ' . $unAngle
);
$this->assertEquals(
$this->compareColor(self::ROTATION_COULEURS[(round($unAngle / 90) + 3) % 4], $image->getImagePixelColor(self::ROTATION_DIM_ORIGINE[$indiceLargeur], 0)->getColor()),
'Pixel (' . self::ROTATION_DIM_ORIGINE[$indiceLargeur] . ',0) - Couleur ' . $uneExtension . ' - Rotation ' . $unAngle
);
}
}
}
/**
* Redimensionnement des images
*/
#[RunInSeparateProcess]
public function testRedimensionnementImages(): void
{
require 'config/config.php';
$monImage = new ImageObject();
/*
* Cas incohérents => Ne rien faire
*/
$this->assertFalse(
$monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 600, 800),
'Pas d\'agrandissement'
);
$this->assertFalse(
$monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 601, 800),
'Pas d\'agrandissement'
);
$this->assertFalse(
$monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 600, 801),
'Pas d\'agrandissement'
);
$this->assertFalse(
$monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 599, 800),
'Pas d\'agrandissement'
);
$this->assertFalse(
$monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 600, 799),
'Pas d\'agrandissement'
);
$this->assertFalse(
$monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 0, 799),
'Image de taille zéro'
);
$this->assertFalse(
$monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 0, 0),
'Image de taille zéro'
);
$this->assertFalse(
$monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 10, 0),
'Image de taille zéro'
);
/*
* Format portrait
*/
// Doit être 200x267
$monImage->redimensionner(
_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png',
_PATH_TESTS_OUTPUT_ . 'image_portrait_200x400.png',
200,
400
);
$imageInfo = getimagesize(_PATH_TESTS_OUTPUT_ . 'image_portrait_200x400.png');
$this->assertEquals(
200,
$imageInfo[0],
'Redimensionnement 600x800 -> 200x400'
);
$this->assertEquals(
267,
$imageInfo[1],
'Redimensionnement 600x800 -> 200x400'
);
// Doit être 150x200
$monImage->redimensionner(
_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png',
_PATH_TESTS_OUTPUT_ . 'image_portrait_400x200.png',
400,
200
);
$imageInfo = getimagesize(_PATH_TESTS_OUTPUT_ . 'image_portrait_400x200.png');
$this->assertEquals(
150,
$imageInfo[0],
'Redimensionnement 600x800 -> 400x200'
);
$this->assertEquals(
200,
$imageInfo[1],
'Redimensionnement 600x800 -> 400x200'
);
/*
* Format paysage
*/
// Doit être 267x200
$monImage->redimensionner(
_PATH_TESTS_IMAGES_ . 'image_paysage_800x600.png',
_PATH_TESTS_OUTPUT_ . 'image_paysage_400x200.png',
400,
200
);
$imageInfo = getimagesize(_PATH_TESTS_OUTPUT_ . 'image_paysage_400x200.png');
$this->assertEquals(
267,
$imageInfo[0],
'Redimensionnement 800x600 -> 400x200'
);
$this->assertEquals(
200,
$imageInfo[1],
'Redimensionnement 800x600 -> 400x200'
);
// Doit être 200x150
$monImage->redimensionner(
_PATH_TESTS_IMAGES_ . 'image_paysage_800x600.png',
_PATH_TESTS_OUTPUT_ . 'image_paysage_200x400.png',
200,
400
);
$imageInfo = getimagesize(_PATH_TESTS_OUTPUT_ . 'image_paysage_200x400.png');
$this->assertEquals(
200,
$imageInfo[0],
'Redimensionnement 800x600 -> 200x400'
);
$this->assertEquals(
150,
$imageInfo[1],
'Redimensionnement 800x600 -> 200x400'
);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,40 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHebergTests;
use PHPUnit\Framework\TestCase;
class InstallationTest extends TestCase
{
public function testValidationInstallation(): void
{
/**
* Valeur attendue
*/
$this->expectOutputRegex('#.*L\'installation est OK !$#U');
/**
* Exécution du script...
*/
require 'install.php';
}
}

392
__tests/MembreTest.php Normal file
View file

@ -0,0 +1,392 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHebergTests;
use ImageHeberg\SessionObject;
use ImageHeberg\UtilisateurObject;
use PDO;
use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\TestCase;
class MembreTest extends TestCase
{
/**
* Fonction requise par l'extension Database
* @return mixed
*/
public function getConnection(): mixed
{
$pdo = new PDO('sqlite::memory:');
return $this->createDefaultDBConnection($pdo, ':memory:');
}
/**
* Fonction requise par l'extension Database
* @return PHPUnit_Extensions_Database_DataSet_DefaultDataSet
*/
public function getDataSet(): PHPUnit_Extensions_Database_DataSet_DefaultDataSet
{
return new PHPUnit_Extensions_Database_DataSet_DefaultDataSet();
}
public function testConnexionMembreExistant(): void
{
// Chargement de la configuration
require_once 'config/config.php';
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['valider'] = 1;
$_POST['userName'] = 'admin';
$_POST['userPassword'] = 'password';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Appel de la page
*/
ob_start();
require 'membre/connexionCompte.php';
ob_end_clean();
/**
* Vérification des valeurs
*/
$maSession = new SessionObject();
$this->assertEquals(
UtilisateurObject::LEVEL_ADMIN,
$maSession->getLevel(),
'connexion : doit être OK'
);
}
/**
* Création d'un compte membre avec un nom déjà existant
*/
#[Depends('testConnexionMembreExistant')]
public function testMembreCreerCompteDoublon(): void
{
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['valider'] = 1;
$_POST['userName'] = 'admin';
$_POST['userPassword'] = 'monPassword';
$_POST['userMail'] = 'myMail@example.com';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SESSION['flag'] = true;
/**
* Appel de la page
*/
ob_start();
require 'membre/creerCompte.php';
ob_end_clean();
/**
* Vérification des valeurs
*/
$monMembre = new UtilisateurObject();
$this->assertFalse(
$monMembre->connexion($_POST['userName'], $_POST['userPassword']),
'connexion : le nom d\'utilisateur doit être unique'
);
}
/**
* Création d'un compte membre.
*/
#[Depends('testMembreCreerCompteDoublon')]
public function testMembreCreerCompte(): void
{
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['valider'] = 1;
$_POST['userName'] = 'username';
$_POST['userPassword'] = 'password';
$_POST['userMail'] = 'myMail@example.com';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SESSION['flag'] = true;
/**
* Appel de la page
*/
ob_start();
require 'membre/creerCompte.php';
ob_end_clean();
/**
* Récupération d'un objet
*/
$monMembre = new UtilisateurObject(3);
/**
* Vérification des valeurs
*/
// Email
$this->assertEquals(
'mymail@example.com',
$monMembre->getEmail(),
'Vérification email'
);
// ID
$this->assertEquals(
3,
$monMembre->getId()
);
// @ IP d'inscription
$this->assertEquals(
'127.0.0.1',
$monMembre->getIpInscription()
);
// Niveau de droits
$this->assertEquals(
UtilisateurObject::LEVEL_USER,
$monMembre->getLevel()
);
// Nom
$this->assertEquals(
'username',
$monMembre->getUserName()
);
$this->assertTrue(
$monMembre->connexion($_POST['userName'], $_POST['userPassword'])
);
}
/**
* Modification du mail
*/
#[Depends('testMembreCreerCompte')]
public function testMembreModifierMail(): void
{
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['modifierMail'] = 1;
$_POST['userPasswordMail'] = 'password';
$_POST['userMail'] = 'john.doe@example.com';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Simulation d'une connexion
*/
$unMembre = new UtilisateurObject();
$this->assertTrue(
$unMembre->connexion('username', $_POST['userPasswordMail']),
'connexion avant'
);
/**
* Appel de la page
*/
ob_start();
require 'membre/monCompte.php';
ob_end_clean();
/**
* Récupération de l'utilisateur
*/
$monMembre = new UtilisateurObject(3);
/**
* Vérification des valeurs
*/
// Email
$this->assertEquals(
'john.doe@example.com',
$monMembre->getEmail(),
'getEmail'
);
$this->assertTrue(
$monMembre->connexion('username', $_POST['userPasswordMail']),
'connexion après'
);
}
/**
* Modification du mot de passe
*/
#[Depends('testMembreModifierMail')]
public function testMembreModifierPassword(): void
{
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['modifierPwd'] = 1;
$_POST['oldUserPassword'] = 'password';
$_POST['newUserPassword'] = 'monPassword';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Simulation d'une connexion
*/
$unMembre = new UtilisateurObject();
$this->assertTrue(
$unMembre->connexion('username', $_POST['oldUserPassword']),
'connexion avant'
);
/**
* Appel de la page
*/
ob_start();
require 'membre/monCompte.php';
ob_end_clean();
/**
* Récupération d'un objet
*/
$monMembre = new UtilisateurObject();
/**
* Vérification des valeurs
*/
$this->assertTrue(
$monMembre->connexion('username', $_POST['newUserPassword']),
'connexion'
);
$this->assertFalse(
$monMembre->connexion('username', $_POST['oldUserPassword']),
'connexion'
);
}
/**
* Suppression du compte sans cochage de la checkbox
*/
#[Depends('testMembreModifierPassword')]
public function testMembreSupprimerCompteRequiertCheckbox(): void
{
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['supprimerCompte'] = 1;
$_POST['userPasswordDelete'] = 'monPassword';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Simulation d'une connexion
*/
$unMembre = new UtilisateurObject();
$this->assertTrue(
$unMembre->connexion('username', $_POST['userPasswordDelete']),
'connexion avant'
);
/**
* Appel de la page
*/
ob_start();
require 'membre/monCompte.php';
ob_end_clean();
/**
* Récupération d'un objet
*/
$monMembre = new UtilisateurObject();
/**
* Vérification des valeurs
*/
$this->assertTrue(
$monMembre->connexion('username', $_POST['userPasswordDelete']),
'connexion devrait être possible'
);
}
/**
* Suppression du compte
*/
#[Depends('testMembreSupprimerCompteRequiertCheckbox')]
public function testMembreSupprimerCompte(): void
{
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['supprimerCompte'] = 1;
$_POST['userPasswordDelete'] = 'monPassword';
$_POST['confirmeDelete'] = 1;
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Simulation d'une connexion
*/
$unMembre = new UtilisateurObject();
$this->assertTrue(
$unMembre->connexion('username', $_POST['userPasswordDelete']),
'connexion avant'
);
/**
* Appel de la page
*/
ob_start();
require 'membre/monCompte.php';
ob_end_clean();
/**
* Récupération d'un objet
*/
$monMembre = new UtilisateurObject();
/**
* Vérification des valeurs
*/
$this->assertFalse(
$monMembre->connexion('username', $_POST['userPasswordDelete']),
'connexion ne devrait plus être possible'
);
}
/**
* Connexion au compte créé lors de la création de la BDD
*/
#[Depends('testMembreSupprimerCompte')]
public function testConnexionCompteHistorique(): void
{
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Récupération d'un objet
*/
$monMembre = new UtilisateurObject();
/**
* Vérification des valeurs
*/
$this->assertTrue(
$monMembre->connexion('admin', 'password'),
'connexion au compte créé à l\'import de la BDD devrait être possible'
);
}
}

98
__tests/_bootstrap.php Normal file
View file

@ -0,0 +1,98 @@
<?php
/**
* Préconfiguration de l'environnement de tests
* - Calcul des MD5 des images locales (dépendant de la version de PHP)
* - Mise à jour en BDD des MD5 enregistrés
* - Copie des fichiers requis
*/
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHebergTests;
use ImageHeberg\HelperImage;
use ImageHeberg\MaBDD;
require 'config/config.php';
// Faire la liste des fichiers
$tabFiles = [];
foreach (scandir(_PATH_TESTS_IMAGES_A_IMPORTER_) as $file) {
if (is_file(_PATH_TESTS_IMAGES_A_IMPORTER_ . $file)) {
if (
in_array(HelperImage::getExtension(_PATH_TESTS_IMAGES_A_IMPORTER_ . $file), _ACCEPTED_EXTENSIONS_, true)
&& HelperImage::isModifiableEnMemoire(_PATH_TESTS_IMAGES_A_IMPORTER_ . $file)
) {
$tabFiles[$file] = _PATH_TESTS_IMAGES_A_IMPORTER_ . $file;
}
// Remettre à disposition le fichier pour les tests
copy(_PATH_TESTS_IMAGES_A_IMPORTER_ . $file, _PATH_TESTS_IMAGES_ . $file);
}
}
// Optimiser localement chaque image et en calculer le MD5 résultant
foreach ($tabFiles as $file => $path) {
// Créer un fichier temporaire pour travailler dessus
$fileTmp = tempnam('/tmp/', 'ih');
// PHP ne gère pas les images WebP animée -> ne pas faire de traitements
if (!HelperImage::isAnimatedWebp($path)) {
// Optimiser l'image (permettra de comparer son hash avec celles déjà stockées)
HelperImage::setImage(HelperImage::getImage($path), HelperImage::getType($path), $fileTmp);
} else {
copy($path, $fileTmp);
}
// Calculer le MD5 de l'image
$md5 = md5_file($fileTmp);
// Corriger l'information en BDD
$req = MaBDD::getInstance()->prepare('UPDATE images SET md5 = :md5 WHERE old_name = :oldName');
$req->bindValue(':md5', $md5);
$req->bindValue(':oldName', $file);
$req->execute();
// Copier le fichier dans le bon répertoire
$fileDst = _PATH_IMAGES_ . substr($md5, 0, 1) . '/' . $md5;
copy($fileTmp, $fileDst);
echo $file . ' -> ' . $fileDst . PHP_EOL;
}
// Traitement pour ImageUploadAndDeleteTest::testSuppressionImagePlusieursMiniatures()
$tabThumbs = [
'image_a_supprimerMultiple-100x100.png' => _PATH_TESTS_IMAGES_ . 'image_a_supprimerMultiple-100x100.png',
'image_a_supprimerMultiple-200x200.png' => _PATH_TESTS_IMAGES_ . 'image_a_supprimerMultiple-200x200.png',
];
foreach ($tabThumbs as $file => $path) {
// Calculer le MD5 de l'image
$md5 = md5_file($path);
// Corriger l'information en BDD
$req = MaBDD::getInstance()->prepare('UPDATE thumbnails SET md5 = :md5 WHERE new_name = :newName');
$req->bindValue(':md5', $md5);
$req->bindValue(':newName', $file);
$req->execute();
// Copier le fichier dans le bon répertoire
$fileDst = _PATH_MINIATURES_ . substr($md5, 0, 1) . '/' . $md5;
copy($path, $fileDst);
echo $file . ' -> ' . $fileDst . PHP_EOL;
}

View file

@ -1 +0,0 @@
7

View file

@ -1 +0,0 @@
4

View file

@ -1 +0,0 @@
2

107
__tests/config/config.php Normal file
View file

@ -0,0 +1,107 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
/*
* CHAMPS A CONFIGURER
*/
/* Base de données */
// Serveur de base de données
const _BDD_HOST_ = 'localhost';
// Utilisateur SQL
const _BDD_USER_ = 'root';
// Mot de passe SQL
const _BDD_PASS_ = 'root';
// Nom de la base de données
const _BDD_NAME_ = 'imageheberg';
/* Système de fichiers */
// Emplacement de votre site sur le système de fichiers de votre hébergeur
const _PATH_ = '/home/runner/work/image-heberg.fr/image-heberg.fr/';
/* A propos de l'outil */
// Nom affiché du service
const _SITE_NAME_ = 'monSite';
// URL du site
const _BASE_URL_ = 'www.example.com/';
// Administrateur du site
const _ADMINISTRATEUR_NOM_ = 'John DOE';
// Site web de l'administrateur
const _ADMINISTRATEUR_SITE_ = '//www.example.com/';
// Mail de l'administrateur (non affiché)
const _ADMINISTRATEUR_EMAIL_ = 'john.doe@example.com';
/* Informations légales */
// Hébergeur du site
const _HEBERGEUR_NOM_ = 'OVH';
// Site web de l'hébergeur
const _HEBERGEUR_SITE_ = '//www.ovh.com';
/* Configurations spécifiques de l'outil */
// Poids maximal des fichiers
const _IMAGE_POIDS_MAX_ = 5242880;
// Délai de conservation d'une image jamais affichée (en jours)
const _DELAI_EFFACEMENT_IMAGES_JAMAIS_AFFICHEES_ = 7;
// Délai depuis le dernier affichage d'une image avant de la supprimer (en jours)
const _DELAI_INACTIVITE_AVANT_EFFACEMENT_IMAGES_ = 365;
// Volume maximal de stockage d'images (en Go)
const _QUOTA_MAXIMAL_IMAGES_GO_ = 90;
// Affichage des messages d'erreur
const _DEBUG_ = true;
/* Gestion des abus */
// Nombre d'affichages par jour à partir duquel une image est suspecte
const _ABUSE_NB_AFFICHAGES_PAR_JOUR_WARNING_ = 1500;
// Nombre d'affichages par jour à partir duquel une image est automatiquement bloquée
const _ABUSE_NB_AFFICHAGES_PAR_JOUR_BLOCAGE_AUTO_ = 100000;
// Nombre d'affichages par jour à partir duquel une image est clairement abusive;
const _ABUSE_NB_AFFICHAGES_PAR_JOUR_ABUSIF_ = 10 * _ABUSE_NB_AFFICHAGES_PAR_JOUR_BLOCAGE_AUTO_;
// Division des seuils d'abus si une image est considérée comme suspecte
const _ABUSE_DIVISION_SEUILS_SI_SUSPECT_ = 2;
// Désactiver l'envoi d'images depuis un noeud de sortie Tor
const _TOR_DISABLE_UPLOAD_ = true;
// Désactiver l'envoi d'images au bout de x images bloquées (mettre 0 pour ne pas l'activer)
const _ABUSE_DISABLE_UPLOAD_AFTER_X_IMAGES_ = 5;
// User-Agent pour lesquels bloquer les images
const _ABUSE_DISABLE_PICS_WHEN_USERE_AGENT_ = ['someUserAgentNumberOne', 'AnoterUserAgentNumberTwo'];
/**
* FIN DES CHAMPS A CONFIGURER
*/
/**
* CHAMPS A COMPLETER UNIQUEMENT SI VOUS AVIEZ INSTALLE UNE VERSION ANTERIEURE A v2.0.4
*/
// Salt pour les mots de passe
// Legacy - n'est plus requis !!
const _GRAIN_DE_SEL_ = '';
/**
* FIN DES CHAMPS A COMPLETER UNIQUEMENT SI VOUS AVEZ UNE VERSION ANTERIEURE A v2.0.4
*/
// Activation des tests Tests TRAVIS-CI
const _PHPUNIT_ = true;
require _PATH_ . 'config/image-heberg.php';

View file

@ -1,140 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
/**
* CONFIGURATION FILE FOR TRAVIS
* https://travis-ci.org/AnaelMobilia/image-heberg.fr/
*/
// DEBUG
define('_DEBUG_', TRUE);
if (_DEBUG_) {
error_reporting(E_ALL | E_STRICT);
}
define('_TRAVIS_', TRUE);
if (!_TRAVIS_) {
// Gestion des exceptions de l'application
function exception_handler($exception) {
/* @var $exception Exception */
if (_DEBUG_) {
echo '<pre>';
print_r($exception->getMessage());
echo '<br /><br /><hr /><br />';
print_r($exception->getTraceAsString());
echo '</pre>';
} else {
echo 'Une erreur a été rencontrée';
}
/**
* Envoi d'un mail avec le détail de l'erreur à l'administrateur
*/
// Adresse expediteur
$headers = 'From: ' . _MAIL_ADMIN_ . "\n";
// Adresse de retour
$headers .= 'Reply-To: ' . _MAIL_ADMIN_ . "\n";
// Agent mail
$headers .= 'X-Mailer: Anael Mobilia script at ' . _URL_ . "\n";
// Ip
$headers .= 'User-IP: ' . $_SERVER['REMOTE_ADDR'] . "\n";
// Date
$headers .= 'Date: ' . date('D, j M Y H:i:s +0200') . "\n";
$message = $exception->getMessage() . "\r\n" . $exception->getTraceAsString();
mail(_MAIL_ADMIN_, '[' . _URL_ . '] Erreur rencontrée', $message, $headers);
}
set_exception_handler('exception_handler');
}
// Nom du service
define('_SITE_NAME_', 'Image-Heberg');
// mail admin
define('_MAIL_ADMIN_', 'contrib@anael.eu');
// Répertoires
define('_REPERTOIRE_IMAGE_', 'files/');
define('_REPERTOIRE_MINIATURE_', _REPERTOIRE_IMAGE_ . 'thumbs/');
define('_REPERTOIRE_ADMIN_', 'admin/');
define('_REPERTOIRE_MEMBRE_', 'membre/');
// URL
define('_BASE_URL_', 'www.image-heberg.fr/');
define('_URL_', 'http://' . _BASE_URL_);
define('_URL_HTTPS_', 'https://' . _BASE_URL_);
define('_URL_SANS_SCHEME_', '//' . _BASE_URL_);
define('_URL_ADMIN_', _URL_HTTPS_ . _REPERTOIRE_ADMIN_);
define('_URL_MEMBRE_', _URL_HTTPS_ . _REPERTOIRE_MEMBRE_);
define('_URL_IMAGES_', _URL_ . _REPERTOIRE_IMAGE_);
define('_URL_MINIATURES_', _URL_ . _REPERTOIRE_MINIATURE_);
// Système de fichiers
define('_PATH_', '/home/travis/build/AnaelMobilia/image-heberg.fr/');
define('_PATH_IMAGES_', _PATH_ . _REPERTOIRE_IMAGE_);
define('_PATH_MINIATURES_', _PATH_ . _REPERTOIRE_MINIATURE_);
define('_PATH_ADMIN_', _PATH_ . _REPERTOIRE_ADMIN_);
define('_PATH_TESTS_IMAGES_', _PATH_ . '__tests/images/');
define('_PATH_TESTS_OUTPUT_', _PATH_ . '__tests/output/');
define('_TPL_TOP_', _PATH_ . 'template/templateV2Top.php');
define('_TPL_BOTTOM_', _PATH_ . 'template/templateV2Bottom.php');
// Fonction de chargement des classes en cas de besoin
spl_autoload_register(function ($class) {
// Code pour TRAVIS
$charger = TRUE;
// Code spécifique Travis : pas de chargement des classes de PHPUnit
if (_TRAVIS_ && (strpos($class, "PHPUnit") !== FALSE || strpos($class, "Composer") !== FALSE)) {
$charger = FALSE;
}
if ($charger) {
require _PATH_ . 'classes/' . $class . '.class.php';
}
});
// Images spécifiques
define('_IMAGE_404_', '_image_404.png');
define('_IMAGE_BAN_', '_image_banned.png');
// Salt pour les mots de passe
define('_GRAIN_DE_SEL_', '');
// BDD
define('_BDD_HOST_', 'localhost');
define('_BDD_USER_', 'root');
define('_BDD_PASS_', '');
define('_BDD_NAME_', 'imageheberg');
// Administrateur du site
define('_ADMINISTRATEUR_NOM_', 'Anael MOBILIA');
define('_ADMINISTRATEUR_SITE_', 'http://www.anael.eu/');
// Hébergeur du site
define('_HEBERGEUR_NOM_', 'OVH');
define('_HEBERGEUR_SITE_', 'http://www.ovh.com');
// Spécifications mémoire
define('_FUDGE_FACTOR_', 1.8);
define('_IMAGE_DIMENSION_MAX_', outils::getMaxDimension());
define('_IMAGE_POIDS_MAX_', 5242880);
?>

View file

@ -1,5 +1,5 @@
/*
* Copyright 2008-2018 Anael Mobilia
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
@ -19,35 +19,109 @@
--
-- Image bloquée
--
INSERT INTO `images` (`id`, `ip_envoi`, `date_envoi`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `bloque`) VALUES
(10, '127.0.0.1', '2008-01-01 00:00:00', 'imageBloquee.jpg', 'imageBloquee.jpg', 10, 10, 10, '0000-00-00', 0, 0, '6858ce6ddc171a0fd9640831a5e74dfd', 1);
INSERT INTO `images` (`id`, `remote_addr`, `date_action`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `isBloquee`, `isSignalee`, `isApprouvee`, `abuse_network`) VALUES
(10, '127.0.0.1', '2008-01-01 00:00:00', 'image_a_supprimer.png', 'image_10.png', 10, 10, 10, '0000-00-00', 0, 0, 'to-be-calculatedto-be-calculated', 1, 0, 0, '127.0.2');
--
-- Images à supprimer
--
INSERT INTO `images` (`id`, `ip_envoi`, `date_envoi`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `bloque`) VALUES
(11, '127.0.0.1', '2008-01-01 00:00:00', 'image_a_supprimer.png', '100000019001334055750.png', 4239, 400, 640, '0000-00-00', 0, 0, 'e656d1b6582a15f0f458006898b40e29', 0),
(12, '127.0.0.10', NOW(), 'image_a_supprimer.png', '147834019001334055750.png', 4239, 400, 640, '0000-00-00', 0, 0, 'e656d1b6582a15f0f458006898b40e29', 0),
(13, '127.0.0.1', '2016-01-01 00:00:00', 'image.png', '146734019451334055750.png', 4239, 400, 640, '0000-00-00', 0, 0, 'a876d1b6582a15f0f458006898b40e29', 0),
(14, '127.0.0.1', '2016-01-01 00:00:00', 'image_a_supprimerMultiple.png', '14777777.png', 4239, 400, 640, '0000-00-00', 0, 0, 'aec65c6b4469bb7267d2d55af5fbd87b', 0);
INSERT INTO `images` (`id`, `remote_addr`, `date_action`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `isBloquee`, `isSignalee`, `isApprouvee`, `abuse_network`) VALUES
(11, '127.0.0.1', '2008-01-01 00:00:00', 'image_a_supprimer.png', 'image_11.png', 4239, 400, 640, '0000-00-00', 0, 0, 'to-be-calculatedto-be-calculated', 0, 0, 0, '127.0.0'),
(12, '127.0.0.10', NOW(), 'image_portrait_600x800.png', 'image_12.png', 4239, 400, 640, '0000-00-00', 0, 0, 'to-be-calculatedto-be-calculated', 0, 0, 0, '127.0.0'),
(13, '127.0.0.10', NOW(), 'imageBleue10.png', 'image_13.png', 4239, 400, 640, '0000-00-00', 0, 0, 'to-be-calculatedto-be-calculated', 0, 0, 0, '127.0.0'),
(14, '127.0.0.1', '2016-01-01 00:00:00', 'image_a_supprimerMultiple.png', 'image_14.png', 4239, 400, 640, '0000-00-00', 0, 0, 'to-be-calculatedto-be-calculated', 0, 0, 0, '127.0.0'),
(15, '127.0.0.1', '2016-01-01 00:00:00', 'imageQuiSeraBloquee.png', 'image_15.png', 4239, 400, 640, '0000-00-00', 0, 0, '97a3a88502d6-theSameMd5-97a3a88502d6', 0, 0, 0, '127.0.0'),
(16, '127.0.0.1', '2016-01-01 00:00:00', 'imageAvecMemeMd5QuiDoitEtreBloquee.png', 'image_16.png', 4239, 400, 640, '0000-00-00', 0, 0, '97a3a88502d6-theSameMd5-97a3a88502d6', 0, 0, 0, '127.0.0'),
(17, '127.0.0.1', '2023-01-01 00:00:00', 'imagePeuAfficheeMaisMignatureBeaucoupAffichee.png', 'image_17.png', 4239, 400, 640, '0000-00-00', 1000, 1000, 'not-used--be5e3e8d65ecefdc0dbcca', 0, 0, 0, '127.0.0');
--
-- Image signalée
--
INSERT INTO `images` (`id`, `remote_addr`, `date_action`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `isBloquee`, `isSignalee`, `isApprouvee`, `abuse_network`) VALUES
(18, '127.0.0.1', '2008-01-01 00:00:00', 'test.webp', 'image_18.png', 4239, 400, 640, '0000-00-00', 0, 0, 'to-be-calculatedto-be-calculated', 0, 1, 0, '127.0.1');
--
-- Image bloquée
--
INSERT INTO `images` (`id`, `remote_addr`, `date_action`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `isBloquee`, `isSignalee`, `isApprouvee`, `abuse_network`) VALUES
(19, '10.10.10.10', '2016-01-01 00:00:00', 'imageDejaBloquee.gif', 'image_19.gif', 146, 25, 37, '0000-00-00', 0, 0, 'to-be-calculatedto-be-calculated', 1, 0, 0, '10.10.10');
--
-- Image du même réseau que celle bloquée
--
INSERT INTO `images` (`id`, `remote_addr`, `date_action`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `isBloquee`, `isSignalee`, `isApprouvee`, `abuse_network`) VALUES
(20, '10.10.10.200', '2016-01-01 00:00:00', 'imageMemeReseauQueDejaBloquee.gif', 'image_20.gif', 146, 25, 37, '0000-00-00', 751, 0, 'not-used--dea392173d746c107beda4', 0, 0, 0, '10.10.10');
--
-- Réputation des réseaux
--
INSERT INTO `images` (`id`, `remote_addr`, `date_action`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `isBloquee`, `isSignalee`, `isApprouvee`, `abuse_network`) VALUES
(21, '192.168.0.1', '2024-01-01 00:00:00', 'Capture.jpg', 'image_21.jpg', 1, 1, 1, '0000-00-00', 0, 0, 'not-used--ab4d682db12defa28f09a6', 1, 0, 0, '192.168.0'),
(22, '192.168.0.1', '2024-01-01 00:00:00', 'Capture.jpg', 'image_22.jpg', 1, 1, 1, '0000-00-00', 0, 0, 'not-used--009a3908f941f94f9d9d5a', 1, 0, 0, '192.168.0'),
(23, '192.168.0.1', '2024-01-01 00:00:00', 'Capture.jpg', 'image_23.jpg', 1, 1, 1, '0000-00-00', 0, 0, 'not-used--17dc9dab5ec4aaf13cb5d8', 1, 0, 0, '192.168.0'),
(24, '192.168.0.1', '2024-01-01 00:00:00', 'Capture.jpg', 'image_24.jpg', 1, 1, 1, '0000-00-00', 0, 0, 'not-used--1a18d35e0fed1f2963ac77', 1, 0, 0, '192.168.0'),
(25, '192.168.0.1', '2024-01-01 00:00:00', 'Capture.jpg', 'image_25.jpg', 1, 1, 1, '0000-00-00', 0, 0, 'not-used--4dd6365d4aea4e3bde009f', 1, 0, 0, '192.168.0'),
(26, '192.168.100.1', '2024-01-01 00:00:00', 'Capture.jpg', 'image_26.jpg', 1, 1, 1, '0000-00-00', 0, 0, 'not-used--48c026fca13b23c786ed87', 1, 0, 0, '192.168.100');
--
-- Image qui sera trop affichée EN PROJECTION
--
INSERT INTO `images` (`id`, `remote_addr`, `date_action`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `isBloquee`, `isSignalee`, `isApprouvee`, `abuse_network`) VALUES
(27, '127.0.3.1', (NOW() - INTERVAL 2 HOUR), 'image_trop_affichee_en_projection.png', 'image_27.png', 1, 1, 1, NOW(), 5000, 5000, 'not-used--ab48e8f727e3329aaa6cf4', 0, 0, 0, '127.0.3');
--
-- Images qui seront bloquées
--
INSERT INTO `images` (`id`, `remote_addr`, `date_action`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `isBloquee`, `isSignalee`, `isApprouvee`, `abuse_network`) VALUES
(28, '127.0.1.1', NOW(), 'image_a_bloquer_en_prog.png', 'image_28.png', 1, 1, 1, NOW(), 50, 50, 'ab5fe1f77dfb-theSameMd5-ab5fe1f77dfb', 0, 0, 0, '127.0.1'),
(29, '127.0.1.1', NOW(), 'image_qui_sera_aussi_bloquee_car_md5_identique.png', 'image_29.png', 1, 1, 1, NOW(), 50, 50, 'ab5fe1f77dfb-theSameMd5-ab5fe1f77dfb', 0, 0, 1, '127.0.1');
--
-- Images qui seront validées
--
INSERT INTO `images` (`id`, `remote_addr`, `date_action`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `isBloquee`, `isSignalee`, `isApprouvee`, `abuse_network`) VALUES
(30, '127.0.0.1', NOW(), 'image_a_valider_prog.png', 'image_30.png', 1, 1, 1, NOW(), 50, 50, 'f3a7c514d2-theSameMd5-f3a7c514d2', 0, 0, 0, '127.0.0'),
(31, '127.0.0.1', NOW(), 'image_a_valider_prog.png', 'image_31.png', 1, 1, 1, NOW(), 50, 50, 'f3a7c514d2-theSameMd5-f3a7c514d2', 0, 1, 0, '127.0.0'),
(32, '127.0.0.1', NOW(), 'image_a_valider_prog.png', 'image_32.png', 1, 1, 1, NOW(), 50, 50, 'f3a7c514d2-theSameMd5-f3a7c514d2', 0, 0, 1, '127.0.0');
--
-- Image qui sera bloqué lors de son affichage avec un User-Agent malveillant
--
INSERT INTO `images` (`id`, `remote_addr`, `date_action`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `isBloquee`, `isSignalee`, `isApprouvee`, `abuse_network`) VALUES
(33, '127.0.4.1', NOW(), 'imageQuiSeraSignaleeParUserAgent.png', 'image_33.png', 1, 1, 1, '0000-00-00', 0, 0, 'd0a77eeeff5ef764505fe5b119b913bf', 0, 0, 0, '127.0.4');
--
-- Image beaucoup trop affichée
--
INSERT INTO `images` (`id`, `remote_addr`, `date_action`, `old_name`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`, `isBloquee`, `isSignalee`, `isApprouvee`, `abuse_network`) VALUES
(34, '127.0.0.1', DATE_SUB(NOW(), INTERVAL 3 DAY), 'imageBeaucoupTropAffichee.png', 'image_34.png', 1, 1, 1, NOW(), 99999999, 99999999, 'not-used--fd9cb5a0afba67138bd328', 0, 0, 0, '127.0.0');
--
-- Agrandir la taille du champ pour bien gérer le _bootstrap
--
ALTER TABLE `thumbnails` MODIFY `new_name` VARCHAR(50) ;
--
-- Miniatures à supprimer
--
INSERT INTO `thumbnails` (`id`, `id_image`, `date_creation`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`) VALUES
(1, 14, '2016-01-01', '14777777.png', 10316, 100, 100, '2016-01-01', 19, 0, '031328c1a7ffe7eed0a2cab4eca05a63'),
(2, 14, '2016-01-01', '147777772.png', 10316, 200, 200, '2016-01-01', 19, 0, '278a70a02e036cc85e0d7e605fdc517f');
INSERT INTO `thumbnails` (`id`, `images_id`, `date_action`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`) VALUES
(1, 14, '2016-01-01', 'image_a_supprimerMultiple-100x100.png', 10316, 100, 100, '2016-01-01', 19, 0, 'to-be-calculatedto-be-calculated'),
(2, 14, '2016-01-01', 'image_a_supprimerMultiple-200x200.png', 10316, 200, 200, '2016-01-01', 19, 0, 'to-be-calculatedto-be-calculated');
--
-- Miniature beaucoup affichée
--
INSERT INTO `thumbnails` (`id`, `images_id`, `date_action`, `new_name`, `size`, `height`, `width`, `last_view`, `nb_view_v4`, `nb_view_v6`, `md5`) VALUES
(3, 20, '2023-01-01', '14777777.png', 10316, 100, 100, '2023-01-01', 999999999999, 999999999999, 'not-used--f12d4a42776aba3a16761e');
--
-- Possessions
--
INSERT INTO `possede` (`image_id`, `pk_membres`) VALUES ('11', '2'),
INSERT INTO `possede` (`images_id`, `membres_id`) VALUES ('11', '2'),
('14', '1');
--
-- Second compte utilisateur
--
INSERT INTO `membres` (`id`, `email`, `login`, `password`, `date_inscription`, `ip_inscription`, `lvl`) VALUES
(2, 'john.doe2@example.com', 'user', '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', DATE(NOW()), '127.0.0.1', 1);
INSERT INTO `membres` (`id`, `email`, `login`, `password`, `date_action`, `remote_addr`, `lvl`, `token`) VALUES
(2, 'john.doe2@example.com', 'user', '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', DATE(NOW()), '127.0.0.1', 1, '');

View file

@ -1,81 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
use PHPUnit\Framework\TestCase;
class displayPicsTest extends TestCase {
/**
* Affichage d'une image inexistante
* @runInSeparateProcess
*/
public function testImageInexistante() {
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_URI'] = 'files/fichierInexistant.jpg';
ob_start();
require 'displayPics.php';
ob_end_clean();
/* @var $monObjet ressourceObject */
$this->assertEquals(_IMAGE_404_, $monObjet->getNomNouveau(), "image_404 si inexistante");
}
/**
* Affichage d'une image inexistante
* @runInSeparateProcess
*/
public function testMiniatureInexistante() {
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_URI'] = 'files/thumbs/fichierInexistant.jpg';
ob_start();
require 'displayPics.php';
ob_end_clean();
/* @var $monObjet ressourceObject */
$this->assertEquals(_IMAGE_404_, $monObjet->getNomNouveau(), "image_404 si inexistante");
}
/**
* Affichage d'une image inexistante
* @runInSeparateProcess
*/
public function testRépertoireInexistant() {
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_URI'] = 'files/repertoireInexistant/fichierInexistant.jpg';
ob_start();
require 'displayPics.php';
ob_end_clean();
/* @var $monObjet ressourceObject */
$this->assertEquals(_IMAGE_404_, $monObjet->getNomNouveau(), "image_404 si mauvais sous répertoire");
}
/**
* Affichage d'une image bloquée
* @runInSeparateProcess
*/
public function testImageBloquee() {
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_URI'] = 'files/imageBloquee.jpg';
ob_start();
require 'displayPics.php';
ob_end_clean();
/* @var $monObjet ressourceObject */
$this->assertEquals(_IMAGE_BAN_, $monObjet->getNomNouveau(), "image_ban si image bloquée");
}
}

View file

@ -1,111 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
use PHPUnit\Framework\TestCase;
class imageObjectTest extends TestCase {
/**
* Rotation des images
* @runInSeparateProcess
*/
public function testRotationImages() {
require 'config/configV2.php';
$monImage = new imageObject();
// JPG
$angle = 90;
$monImage->rotation($angle, _PATH_TESTS_IMAGES_ . 'image_banned.jpg', _PATH_TESTS_OUTPUT_ . 'image_banned.jpg-' . $angle);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_banned.jpg-' . $angle, _PATH_TESTS_OUTPUT_ . 'image_banned.jpg-' . $angle, "Rotation JPG " . $angle);
$angle = 180;
$monImage->rotation($angle, _PATH_TESTS_IMAGES_ . 'image_banned.jpg', _PATH_TESTS_OUTPUT_ . 'image_banned.jpg-' . $angle);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_banned.jpg-' . $angle, _PATH_TESTS_OUTPUT_ . 'image_banned.jpg-' . $angle, "Rotation JPG " . $angle);
$angle = 270;
$monImage->rotation($angle, _PATH_TESTS_IMAGES_ . 'image_banned.jpg', _PATH_TESTS_OUTPUT_ . 'image_banned.jpg-' . $angle);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_banned.jpg-' . $angle, _PATH_TESTS_OUTPUT_ . 'image_banned.jpg-' . $angle, "Rotation JPG " . $angle);
// PNG
$angle = 90;
$monImage->rotation($angle, _PATH_TESTS_IMAGES_ . 'image_banned.png', _PATH_TESTS_OUTPUT_ . 'image_banned.png-' . $angle);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_banned.png-' . $angle, _PATH_TESTS_OUTPUT_ . 'image_banned.png-' . $angle, "Rotation PNG " . $angle);
$angle = 180;
$monImage->rotation($angle, _PATH_TESTS_IMAGES_ . 'image_banned.png', _PATH_TESTS_OUTPUT_ . 'image_banned.png-' . $angle);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_banned.png-' . $angle, _PATH_TESTS_OUTPUT_ . 'image_banned.png-' . $angle, "Rotation PNG " . $angle);
$angle = 270;
$monImage->rotation($angle, _PATH_TESTS_IMAGES_ . 'image_banned.png', _PATH_TESTS_OUTPUT_ . 'image_banned.png-' . $angle);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_banned.png-' . $angle, _PATH_TESTS_OUTPUT_ . 'image_banned.png-' . $angle, "Rotation PNG " . $angle);
// GIF
$angle = 90;
$monImage->rotation($angle, _PATH_TESTS_IMAGES_ . 'image_banned.gif', _PATH_TESTS_OUTPUT_ . 'image_banned.gif-' . $angle);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_banned.gif-' . $angle, _PATH_TESTS_OUTPUT_ . 'image_banned.gif-' . $angle, "Rotation GIF " . $angle);
$angle = 180;
$monImage->rotation($angle, _PATH_TESTS_IMAGES_ . 'image_banned.gif', _PATH_TESTS_OUTPUT_ . 'image_banned.gif-' . $angle);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_banned.gif-' . $angle, _PATH_TESTS_OUTPUT_ . 'image_banned.gif-' . $angle, "Rotation GIF " . $angle);
$angle = 270;
$monImage->rotation($angle, _PATH_TESTS_IMAGES_ . 'image_banned.gif', _PATH_TESTS_OUTPUT_ . 'image_banned.gif-' . $angle);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_banned.gif-' . $angle, _PATH_TESTS_OUTPUT_ . 'image_banned.gif-' . $angle, "Rotation GIF " . $angle);
}
/**
* Redimensionnement des images
* @runInSeparateProcess
*/
public function testRedimensionnementImages() {
require 'config/configV2.php';
$monImage = new imageObject();
/**
* Cas NULL
*/
$this->assertEquals(NULL, $monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 600, 800), "Pas d'agrandissement");
$this->assertEquals(NULL, $monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 601, 800), "Pas d'agrandissement");
$this->assertEquals(NULL, $monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 600, 801), "Pas d'agrandissement");
$this->assertEquals(NULL, $monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 599, 800), "Pas d'agrandissement");
$this->assertEquals(NULL, $monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 600, 799), "Pas d'agrandissement");
$this->assertEquals(NULL, $monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 0, 799), "Image de taille zéro");
$this->assertEquals(NULL, $monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 0, 0), "Image de taille zéro");
$this->assertEquals(NULL, $monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', '', 10, 0), "Image de taille zéro");
/**
* Format portrait
*/
// Doit être 200x267
$monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', _PATH_TESTS_OUTPUT_ . 'image_portrait_200x400.png', 200, 400);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_portrait_200x400.png', _PATH_TESTS_OUTPUT_ . 'image_portrait_200x400.png', "Redimensionnement portrait 200x400");
// Doit être 150x200
$monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_portrait_600x800.png', _PATH_TESTS_OUTPUT_ . 'image_portrait_400x200.png', 400, 200);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_portrait_400x200.png', _PATH_TESTS_OUTPUT_ . 'image_portrait_400x200.png', "Redimensionnement portrait 400x200");
/**
* Format paysage
*/
// Doit être 267x200
$monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_paysage_800x600.png', _PATH_TESTS_OUTPUT_ . 'image_paysage_400x200.png', 400, 200);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_paysage_400x200.png', _PATH_TESTS_OUTPUT_ . 'image_paysage_400x200.png', "Redimensionnement paysage 400x200");
// Doit être 200x150
$monImage->redimensionner(_PATH_TESTS_IMAGES_ . 'image_paysage_800x600.png', _PATH_TESTS_OUTPUT_ . 'image_paysage_200x400.png', 200, 400);
$this->assertFileEquals(_PATH_TESTS_IMAGES_ . 'image_paysage_200x400.png', _PATH_TESTS_OUTPUT_ . 'image_paysage_200x400.png', "Redimensionnement paysage 200x400");
}
}

View file

@ -1,905 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
use PHPUnit\Framework\TestCase;
class imageUploadAndDeleteTest extends TestCase {
// Fichiers pour le nombre d'images / possessions attendues
const fichierImage = '../_nbImages';
const fichierMiniature = '../_nbThumbnails';
const fichierPossede = '../_nbPossede';
/**
* Nombre d'images en BDD
* @return int
*/
private static function countImagesEnBdd() {
$maReq = maBDD::getInstance()->query("SELECT COUNT(*) AS nb FROM images");
$result = $maReq->fetch();
return $result->nb;
}
/**
* Nombre de miniatures en BDD
* @return int
*/
private static function countMiniaturesEnBdd() {
$maReq = maBDD::getInstance()->query("SELECT COUNT(*) AS nb FROM thumbnails");
$result = $maReq->fetch();
return $result->nb;
}
/**
* Nombre d'images POSSEDEES en BDD
* @return int
*/
private static function countImagesPossedeesEnBdd() {
$maReq = maBDD::getInstance()->query("SELECT COUNT(*) AS nb FROM possede");
$result = $maReq->fetch();
return $result->nb;
}
/**
* Nombre d'éléments présents dans le fichier
* @param string $nomFichier nom du fichier
* @return int nb éléments
*/
private static function getNb($nomFichier) {
$f = fopen(_PATH_TESTS_IMAGES_ . $nomFichier, 'r');
$val = fread($f, 10);
fclose($f);
return $val;
}
/**
* Ecrit une valeur dans le fichier
* @param string $nomFichier
* @param int $valeur
*/
private static function setNb($nomFichier, $valeur) {
$f = fopen(_PATH_TESTS_IMAGES_ . $nomFichier, 'w');
fwrite($f, $valeur);
fclose($f);
}
/**
* $val--
* @param string $nomFichier
*/
private static function setNbMoins($nomFichier) {
$val = self::getNb($nomFichier);
self::setNb($nomFichier, --$val);
}
/**
* $val++
* @param string $nomFichier
*/
private static function setNbPlus($nomFichier) {
$val = self::getNb($nomFichier);
self::setNb($nomFichier, ++$val);
}
/**
* Test de l'envoi simple : présence BDD et HDD
*/
public function testEnvoi() {
require_once 'config/configV2.php';
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_banned.gif';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), TRUE, "Envoi image ne doit pas être bloqué dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Envoi image ne doit pas être bloqué dans upload.php");
self::setNbPlus(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Envoi image doit créer d'image en BDD");
$this->assertEquals(TRUE, file_exists(_PATH_IMAGES_ . '6/6a9dd81ae12c79d953031bc54c07f900'), "Envoi image doit créer d'image sur HDD");
}
/**
* Test de l'envoi avec miniature : présence BDD et HDD
* @depends testEnvoi
*/
public function testEnvoiMiniature() {
require_once 'config/configV2.php';
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_pour_miniature.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
$_POST['dimMiniature'] = '50x50';
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), TRUE, "Envoi image + miniature ne doit pas être bloqué dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Envoi image + miniature ne doit pas être bloqué dans upload.php");
self::setNbPlus(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Envoi image + miniature doit créer image en BDD");
self::setNbPlus(self::fichierMiniature);
$this->assertEquals(self::countMiniaturesEnBdd(), self::getNb(self::fichierMiniature), "Envoi image + miniature doit créer miniature en BDD");
$this->assertEquals(TRUE, file_exists(_PATH_IMAGES_ . 'f/f653f58431521a201fdc23451c9a8af6'), "Envoi image + miniature doit créer image sur HDD");
$this->assertEquals(TRUE, file_exists(_PATH_MINIATURES_ . 'e/ee5acdecd9894734e685b019662e6959'), "Envoi image + miniature doit créer miniature sur HDD");
}
/**
* Test de l'envoi avec miniature ET rotation : présence BDD et HDD
* @depends testEnvoiMiniature
*/
public function testEnvoiMiniatureRotation() {
require_once 'config/configV2.php';
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_pour_miniature2.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
$_POST['dimMiniature'] = '50x50';
$_POST['angleRotation'] = 90;
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), TRUE, "Envoi image + miniature (rotation) ne doit pas être bloqué dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Envoi image + miniature (rotation) ne doit pas être bloqué dans upload.php");
self::setNbPlus(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Envoi image + miniature (rotation) doit créer image en BDD");
self::setNbPlus(self::fichierMiniature);
$this->assertEquals(self::countMiniaturesEnBdd(), self::getNb(self::fichierMiniature), "Envoi image + miniature (rotation) doit créer miniature en BDD");
$this->assertEquals(TRUE, file_exists(_PATH_IMAGES_ . '4/4a3da533b304629c3ef35ece7fb01308'), "Envoi image + miniature (rotation) doit créer image sur HDD");
$this->assertEquals(TRUE, file_exists(_PATH_MINIATURES_ . '8/8c3b9bd4f7339b9ed4e1aee52cf8b55f'), "Envoi image + miniature (rotation) doit créer miniature sur HDD");
}
/**
* Test du renvoi d'une image mais avec demande de création d'une miniature
* @depends testEnvoiMiniatureRotation
*/
public function testRenvoiImageDemandeMiniature() {
require_once 'config/configV2.php';
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_banned2.gif';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
$_POST['dimMiniature'] = '50x50';
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), TRUE, "Renvoi image - dde miniature - ne doit pas être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Renvoi image - dde miniature - ne doit pas être bloquée dans upload.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Renvoi image - dde miniature - doit être bloquée en BDD");
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Renvoi image - dde miniature (possède) - doit être bloquée en BDD");
self::setNbPlus(self::fichierMiniature);
$this->assertEquals(self::countMiniaturesEnBdd(), self::getNb(self::fichierMiniature), "Renvoi image - dde miniature - doit créer miniature en BDD");
$this->assertEquals(TRUE, file_exists(_PATH_MINIATURES_ . 'b/b8269be7be4e1d804cd5b82d9734bab7'), "Renvoi image - dde miniature - doit créer miniature sur HDD");
}
/**
* Test du renvoi d'une image avec miniature mais demande demande de création d'une autre miniature
* @depends testRenvoiImageDemandeMiniature
*/
public function testRenvoiImageDemandeNouvelleMiniature() {
require_once 'config/configV2.php';
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_banned3.gif';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
$_POST['dimMiniature'] = '40x40';
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), TRUE, "Renvoi image - dde NOUVELLE miniature - ne doit pas être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Renvoi image - dde NOUVELLE miniature - ne doit pas être bloquée dans upload.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Renvoi image - dde NOUVELLE miniature - doit être bloquée en BDD");
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Renvoi image - dde NOUVELLE miniature - doit être bloquée en BDD");
self::setNbPlus(self::fichierMiniature);
$this->assertEquals(self::countMiniaturesEnBdd(), self::getNb(self::fichierMiniature), "Renvoi image - dde NOUVELLE miniature - doit créer miniature en BDD");
$this->assertEquals(TRUE, file_exists(_PATH_MINIATURES_ . '0/0aa6219e66d00bb17a3b3f10da7e3a12'), "Renvoi image - dde NOUVELLE miniature - doit créer miniature sur HDD");
}
/**
* Envoi sans affichage page index.php
* @depends testRenvoiImageDemandeNouvelleMiniature
*/
public function testEnvoiBrut() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), FALSE, "Non affichage du formulaire d'upload devrait être détecté dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Non affichage du formulaire d'upload devrait être détecté dans upload.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Non affichage du formulaire d'upload ne doit pas créer d'image en BDD");
}
/**
* Envoi sans fichierU
* @depends testEnvoiBrut
*/
public function testEnvoiSansFichier() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), FALSE, "Absence de fichier envoyé devrait être détecté dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Absence de fichier envoyé devrait être détecté dans upload.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Absence de fichier envoyé ne doit pas créer d'image en BDD");
}
/**
* Fichier trop lourd
* @depends testEnvoiSansFichier
*/
public function testEnvoiGrosFichier() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['name'] = 'nomFichier';
$_FILES['fichier']['size'] = _IMAGE_POIDS_MAX_ + 1;
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), FALSE, "Fichier trop gros devrait être détecté dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Fichier trop gros devrait être détecté dans upload.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Fichier trop gros ne doit pas créer d'image en BDD");
}
/**
* Type Mime : envoi d'un fichier doc
* @depends testEnvoiGrosFichier
*/
public function testTypeMimePasUneImage() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'fichier_doc.doc';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), FALSE, "Type mime : pas une image doit être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Type mime : pas une image doit être bloquée dans upload.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "type mime : pas une image doit être bloquée en BDD");
}
/**
* Type Mime : mauvais type de fichier (DOC).jpg
* @depends testTypeMimePasUneImage
*/
public function testTypeMimeMauvaisTypeFichier() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'fichier_doc.jpg';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), FALSE, "Type mime : fausse image doit être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Type mime : fausse image doit être bloquée dans upload.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "type mime : fausse image doit être bloquée en BDD");
}
/**
* Type Mime : mauvaise extension (JPG).png
* @depends testTypeMimeMauvaisTypeFichier
*/
public function testTypeMimeMauvaiseExtension() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_jpg.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), TRUE, "Type mime : extension incorrecte ne doit pas poser de soucis dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Type mime : extension incorrecte ne doit pas poser de soucis dans upload.php");
self::setNbPlus(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Type mime : extension incorrecte ne doit pas être bloquée en BDD");
}
/**
* Dimensions de l'image - Très large
* @depends testTypeMimeMauvaiseExtension
*/
public function testTresLarge() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_tres_large.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), TRUE, "Image 10000x1 ne doit pas être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Image 10000x1 ne doit pas être bloquée dans upload.php");
self::setNbPlus(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Image 10000x1 ne doit pas être bloquée en BDD");
}
/**
* Dimensions de l'image - Très haute
* @depends testTresLarge
*/
public function testTresHaute() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_tres_haute.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), TRUE, "Image 1x10000 ne doit pas être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Image 1x10000 ne doit pas être bloquée dans upload.php");
self::setNbPlus(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Image 1x10000 ne doit pas être bloquée en BDD");
}
/**
* Dimensions de l'image - Trop grande
* @depends testTresHaute
*/
public function testTropGrande() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_10000x10000.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), FALSE, "Image 10000x10000 doit être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Image 10000x10000 doit être bloquée dans upload.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Image 10000x10000 doit être bloquée en BDD");
}
/**
* Envoi d'une image authentifié
* @depends testTropGrande
*/
public function testEnvoiImageAuthentifie() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_authentifie.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
/**
* Authentification
*/
$unMembre = new utilisateurObject();
$unMembre->connexion('admin', 'password');
ob_start();
require 'upload.php';
ob_end_clean();
/**
* Désauthentification
*/
$maSession = new sessionObject();
$maSession->deconnexion();
$this->assertEquals(empty($msgErreur), TRUE, "Envoi image authentifié ne doit pas être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Envoi image authentifié ne doit pas être bloquée dans upload.php");
self::setNbPlus(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Envoi image authentifié ne doit pas être bloquée en BDD");
self::setNbPlus(self::fichierPossede);
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Envoi image authentifié ne doit pas être bloquée en BDD");
}
/**
* Renvoi d'une image - Anonyme / Anonyme
* @depends testEnvoiImageAuthentifie
*/
public function testRenvoiImageAnonymeAnonyme() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_tres_haute.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), TRUE, "Renvoi image ne doit pas être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Renvoi image ne doit pas être bloquée dans upload.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Renvoi image doit être bloquée en BDD");
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Renvoi image doit être bloquée en BDD");
}
/**
* Renvoi d'une image - Anonyme / Authentifié
* @depends testRenvoiImageAnonymeAnonyme
*/
public function testRenvoiImageAnonymeAuthentifie() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_tres_haute.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
/**
* Authentification
*/
$unMembre = new utilisateurObject();
$unMembre->connexion('admin', 'password');
ob_start();
require 'upload.php';
ob_end_clean();
/**
* Désauthentification
*/
$maSession = new sessionObject();
$maSession->deconnexion();
$this->assertEquals(empty($msgErreur), TRUE, "Renvoi image ne doit pas être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Renvoi image ne doit pas être bloquée dans upload.php");
self::setNbPlus(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Renvoi image ne doit pas être bloquée en BDD");
self::setNbPlus(self::fichierPossede);
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Renvoi image ne doit pas être bloquée en BDD");
}
/**
* Renvoi d'une image - Authentifié / Anonyme
* @depends testRenvoiImageAnonymeAuthentifie
*/
public function testRenvoiImageAuthentifieAnonyme() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_authentifie.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), TRUE, "Renvoi image ne doit pas être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Renvoi image ne doit pas être bloquée dans upload.php");
self::setNbPlus(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Renvoi image ne doit pas être bloquée en BDD");
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Renvoi image doit être bloquée en BDD");
}
/**
* Renvoi d'une image - Authentifié / Authentifié
* @depends testRenvoiImageAuthentifieAnonyme
*/
public function testRenvoiImageAuthentifieAuthentifie() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_authentifie.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
/**
* Authentification
*/
$unMembre = new utilisateurObject();
$unMembre->connexion('admin', 'password');
ob_start();
require 'upload.php';
ob_end_clean();
/**
* Désauthentification
*/
$maSession = new sessionObject();
$maSession->deconnexion();
$this->assertEquals(empty($msgErreur), TRUE, "Renvoi image ne doit pas être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Renvoi image ne doit pas être bloquée dans upload.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Renvoi image doit être bloquée en BDD");
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Renvoi image doit être bloquée en BDD");
}
/**
* Renvoi d'une image - Authentifié / Authentifié Autrement
* @depends testRenvoiImageAuthentifieAuthentifie
*/
public function testRenvoiImageAuthentifieAuthentifie2() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_authentifie.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
/**
* Authentification
*/
$unMembre = new utilisateurObject();
$unMembre->connexion('user', 'password');
ob_start();
require 'upload.php';
ob_end_clean();
/**
* Désauthentification
*/
$maSession = new sessionObject();
$maSession->deconnexion();
$this->assertEquals(empty($msgErreur), TRUE, "Renvoi image ne doit pas être bloquée dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Renvoi image ne doit pas être bloquée dans upload.php");
self::setNbPlus(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Renvoi image ne doit pas être bloquée en BDD");
self::setNbPlus(self::fichierPossede);
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Renvoi image ne doit pas être bloquée en BDD");
}
/**
* Suppression d'une image inexistante
* @depends testRenvoiImageAuthentifieAuthentifie2
*/
public function testSuppressionImageInexistante() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_GET['id'] = 'fichierInexistant';
$_GET['type'] = ressourceObject::typeImage;
ob_start();
require 'delete.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), FALSE, "Suppression image inexistante doit être bloqué dans delete.php");
$this->assertEquals(empty($msgWarning), TRUE, "Suppression image inexistante doit être bloqué dans delete.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Suppression image inexistante doit être bloqué en BDD");
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Suppression image inexistante doit être bloqué en BDD");
}
/**
* Suppression d'une image - Propriétaire en étant Anonyme
* @depends testSuppressionImageInexistante
*/
public function testSuppressionImageProprietaireAnonyme() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_GET['id'] = '_image_404.png';
$_GET['type'] = ressourceObject::typeImage;
ob_start();
require 'delete.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), FALSE, "Suppression image possédée par autrui doit être bloqué dans delete.php");
$this->assertEquals(empty($msgWarning), TRUE, "Suppression image possédée par autrui doit être bloqué dans delete.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Suppression image possédée par autrui doit être bloqué en BDD");
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Suppression image possédée par autrui doit être bloqué en BDD");
}
/**
* Suppression d'une image - Propriétaire en étant Authentifié mais Autre
* @depends testSuppressionImageProprietaireAnonyme
*/
public function testSuppressionImageProprietaireAuthentifie2() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_GET['id'] = '_image_404.png';
$_GET['type'] = ressourceObject::typeImage;
/**
* Authentification
*/
$unMembre = new utilisateurObject();
$unMembre->connexion('user', 'password');
ob_start();
require 'delete.php';
ob_end_clean();
/**
* Désauthentification
*/
$maSession = new sessionObject();
$maSession->deconnexion();
$this->assertEquals(empty($msgErreur), FALSE, "Suppression image possédée par autrui doit être bloqué dans delete.php");
$this->assertEquals(empty($msgWarning), TRUE, "Suppression image possédée par autrui doit être bloqué dans delete.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Suppression image possédée par autrui doit être bloqué en BDD");
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Suppression image possédée par autrui doit être bloqué en BDD");
}
/**
* Suppression d'une image - Propriétaire en étant Authentifié
* @depends testSuppressionImageProprietaireAuthentifie2
*/
public function testSuppressionImageProprietaireAuthentifie() {
unset($_POST);
unset($_FILES);
unset($_GET);
// Copie du fichier
rename(_PATH_TESTS_IMAGES_ . 'image_a_supprimer.png', _PATH_IMAGES_ . 'e/e656d1b6582a15f0f458006898b40e29');
$_SERVER['REMOTE_ADDR'] = '127.0.0.2';
$_GET['id'] = '100000019001334055750.png';
$_GET['type'] = ressourceObject::typeImage;
/**
* Authentification
*/
$unMembre = new utilisateurObject();
$unMembre->connexion('user', 'password');
ob_start();
require 'delete.php';
ob_end_clean();
/**
* Désauthentification
*/
$maSession = new sessionObject();
$maSession->deconnexion();
$this->assertEquals(empty($msgErreur), TRUE, "Suppression image possédée ne doit pas être bloqué dans delete.php");
$this->assertEquals(empty($msgWarning), TRUE, "Suppression image possédée ne doit pas être bloqué dans delete.php");
self::setNbMoins(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Suppression image possédée ne doit pas être bloqué en BDD");
self::setNbMoins(self::fichierPossede);
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Suppression image possédée ne doit pas être bloqué en BDD");
$this->assertEquals(file_exists(_PATH_IMAGES_ . 'e/e656d1b6582a15f0f458006898b40e29'), TRUE, "Suppression image possédée ne doit pas être effacé du HDD car encore en usage");
}
/**
* Suppression d'une image - Anonyme en étant hors délai
* @depends testSuppressionImageProprietaireAuthentifie
*/
public function testSuppressionImageAnonymeHorsDelai() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_GET['id'] = '146734019451334055750.png';
$_GET['type'] = ressourceObject::typeImage;
ob_start();
require 'delete.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), FALSE, "Suppression image hors délai doit être bloqué dans delete.php");
$this->assertEquals(empty($msgWarning), TRUE, "Suppression image hors délai doit être bloqué dans delete.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Suppression image hors délai doit être bloqué en BDD");
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Suppression image hors délai doit être bloqué en BDD");
}
/**
* Suppression d'une image - Anonyme en étant dans délai mais pas la bonne IP
* @depends testSuppressionImageProprietaireAuthentifie
*/
public function testSuppressionImageAnonymeDansDelaiMauvaiseIP() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.2';
$_GET['id'] = '147834019001334055750.png';
$_GET['type'] = ressourceObject::typeImage;
ob_start();
require 'delete.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), FALSE, "Suppression image dans délai par autre IP doit être bloqué dans delete.php");
$this->assertEquals(empty($msgWarning), TRUE, "Suppression image dans délai par autre IP doit être bloqué dans delete.php");
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Suppression image dans délai par autre IP doit être bloqué en BDD");
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Suppression image dans délai par autre IP doit être bloqué en BDD");
}
/**
* Suppression d'une image - Anonyme en étant dans le délai
* @depends testSuppressionImageAnonymeDansDelaiMauvaiseIP
*/
public function testSuppressionImageAnonymeDansDelai() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.10';
$_GET['id'] = '147834019001334055750.png';
$_GET['type'] = ressourceObject::typeImage;
ob_start();
require 'delete.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), TRUE, "Suppression image dans délai ne doit pas être bloqué dans delete.php");
$this->assertEquals(empty($msgWarning), TRUE, "Suppression image dans délai ne doit pas être bloqué dans delete.php");
self::setNbMoins(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Suppression image dans délai ne doit pas être bloqué en BDD");
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Suppression image dans délai ne doit pas être bloqué en BDD");
$this->assertEquals(file_exists(_PATH_IMAGES_ . 'e/e656d1b6582a15f0f458006898b40e29'), FALSE, "Suppression image dans délai doit être effacé du HDD");
}
/**
* Test de l'envoi simple avec redimensionnement : présence BDD et HDD
* @depends testSuppressionImageAnonymeDansDelai
*/
public function testEnvoiRedim() {
unset($_POST);
unset($_FILES);
unset($_GET);
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_POST['Submit'] = 1;
$_SESSION['_upload'] = 1;
$_FILES['fichier']['size'] = 104857;
$_FILES['fichier']['name'] = 'image_paysage_800x600.png';
$_FILES['fichier']['tmp_name'] = _PATH_TESTS_IMAGES_ . $_FILES['fichier']['name'];
$_POST['redimImage'] = '400x200';
ob_start();
require 'upload.php';
ob_end_clean();
$this->assertEquals(empty($msgErreur), TRUE, "Envoi image avec redim ne doit pas être bloqué dans upload.php");
$this->assertEquals(empty($msgWarning), TRUE, "Envoi image avec redim ne doit pas être bloqué dans upload.php");
self::setNbPlus(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Envoi image avec redim doit créer d'image en BDD");
$this->assertEquals(TRUE, file_exists(_PATH_IMAGES_ . '4/43b604c3a5c18a161bc3a01bdb58ebf7'), "Envoi image avec redim doit créer image redim sur HDD");
$this->assertEquals(FALSE, file_exists(_PATH_IMAGES_ . '4/4db0b6f10d49fb1a8c2e8b8ff47cf3f6'), "Envoi image avec redim ne doit pas créer d'image originale sur HDD");
}
/**
* Test de la suppression d'une image avec plusieurs miniatures
* @depends testEnvoiRedim
*/
public function testSuppressionImagePlusieursMiniatures() {
unset($_POST);
unset($_FILES);
unset($_GET);
// Copie des fichiers
rename(_PATH_TESTS_IMAGES_ . 'image_a_supprimerMultiple.png', _PATH_IMAGES_ . 'a/aec65c6b4469bb7267d2d55af5fbd87b');
rename(_PATH_TESTS_IMAGES_ . 'image_a_supprimerMultiple-100x100.png', _PATH_MINIATURES_ . '0/031328c1a7ffe7eed0a2cab4eca05a63');
rename(_PATH_TESTS_IMAGES_ . 'image_a_supprimerMultiple-200x200.png', _PATH_MINIATURES_ . '2/278a70a02e036cc85e0d7e605fdc517f');
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_GET['id'] = '14777777.png';
$_GET['type'] = ressourceObject::typeImage;
/**
* Authentification
*/
$unMembre = new utilisateurObject();
$unMembre->connexion('admin', 'password');
ob_start();
require 'delete.php';
ob_end_clean();
/**
* Désauthentification
*/
$maSession = new sessionObject();
$maSession->deconnexion();
$this->assertEquals(empty($msgErreur), TRUE, "Suppression image ne doit pas être bloqué dans delete.php");
$this->assertEquals(empty($msgWarning), TRUE, "Suppression image ne doit pas être bloqué dans delete.php");
self::setNbMoins(self::fichierImage);
$this->assertEquals(self::countImagesEnBdd(), self::getNb(self::fichierImage), "Suppression image ne doit pas être bloqué en BDD");
self::setNbMoins(self::fichierPossede);
$this->assertEquals(self::countImagesPossedeesEnBdd(), self::getNb(self::fichierPossede), "Suppression possession ne doit pas être bloqué en BDD");
$this->assertEquals(file_exists(_PATH_IMAGES_ . 'a/aec65c6b4469bb7267d2d55af5fbd87b'), FALSE, "Suppression image doit être effacé du HDD");
self::setNbMoins(self::fichierMiniature);
self::setNbMoins(self::fichierMiniature);
$this->assertEquals(self::countMiniaturesEnBdd(), self::getNb(self::fichierMiniature), "Suppression miniatureS ne doit pas être bloqué en BDD");
$this->assertEquals(file_exists(_PATH_MINIATURES_ . '0/031328c1a7ffe7eed0a2cab4eca05a63'), FALSE, "Suppression image doit effacer toutes les miniatures du HDD");
$this->assertEquals(file_exists(_PATH_MINIATURES_ . '2/278a70a02e036cc85e0d7e605fdc517f'), FALSE, "Suppression image doit effacer toutes les miniatures du HDD");
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

View file

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View file

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View file

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 KiB

BIN
__tests/images/image_33.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

1
__tests/ipv4.txt Normal file

File diff suppressed because one or more lines are too long

1
__tests/ipv6.txt Normal file

File diff suppressed because one or more lines are too long

View file

@ -1,315 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
use PHPUnit\Framework\TestCase;
class membreTest extends TestCase {
/**
* Fonction requise par l'extension Database
* @return type
*/
public function getConnection() {
$pdo = new PDO('sqlite::memory:');
return $this->createDefaultDBConnection($pdo, ':memory:');
}
/**
* Fonction requise par l'extension Database
* @return \PHPUnit_Extensions_Database_DataSet_DefaultDataSet
*/
public function getDataSet() {
return new PHPUnit_Extensions_Database_DataSet_DefaultDataSet();
}
public function testConnexionMembreExistant() {
// Chargement de la configuration
require_once 'config/configV2.php';
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['valider'] = 1;
$_POST['userName'] = 'admin';
$_POST['userPassword'] = 'password';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Appel de la page
*/
ob_start();
require 'membre/connexionCompte.php';
ob_end_clean();
/**
* Vérification des valeurs
*/
$maSession = new sessionObject();
$this->assertEquals(utilisateurObject::levelAdmin, $maSession->getLevel(), "connexion : doit être OK");
}
/**
* Création d'un compte membre avec un nom déjà existant
* @depends testConnexionMembreExistant
*/
public function testMembreCreerCompteDoublon() {
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['valider'] = 1;
$_POST['userName'] = 'admin';
$_POST['userPassword'] = 'monPassword';
$_POST['userMail'] = 'myMail@example.com';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Appel de la page
*/
ob_start();
require 'membre/creerCompte.php';
ob_end_clean();
/**
* Vérification des valeurs
*/
$monMembre = new utilisateurObject();
$this->assertEquals(FALSE, $monMembre->connexion($_POST['userName'], $_POST['userPassword']), "connexion : le nom d'utilisateur doit être unique");
}
/**
* Création d'un compte membre.
* @depends testMembreCreerCompteDoublon
*/
public function testMembreCreerCompte() {
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['valider'] = 1;
$_POST['userName'] = 'username';
$_POST['userPassword'] = 'password';
$_POST['userMail'] = 'myMail@example.com';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Appel de la page
*/
ob_start();
require 'membre/creerCompte.php';
ob_end_clean();
/**
* Récupération d'un objet
*/
$monMembre = new utilisateurObject(3);
/**
* Vérification des valeurs
*/
// Email
$this->assertEquals('myMail@example.com', $monMembre->getEmail(), "Vérification email");
// ID
$this->assertEquals(3, $monMembre->getId());
// @ IP d'inscription
$this->assertEquals('127.0.0.1', $monMembre->getIpInscription());
// Niveau de droits
$this->assertEquals(utilisateurObject::levelUser, $monMembre->getLevel());
// Nom
$this->assertEquals('username', $monMembre->getUserName());
$this->assertEquals(TRUE, $monMembre->connexion($_POST['userName'], $_POST['userPassword']));
}
/**
* Modification du mail
* @depends testMembreCreerCompte
*/
public function testMembreModifierMail() {
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['modifierMail'] = 1;
$_POST['userPasswordMail'] = 'password';
$_POST['userMail'] = 'john.doe@example.com';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Simulation d'une connexion
*/
$unMembre = new utilisateurObject();
$this->assertEquals(TRUE, $unMembre->connexion('username', $_POST['userPasswordMail']), "connexion avant");
/**
* Appel de la page
*/
ob_start();
require 'membre/monCompte.php';
ob_end_clean();
/**
* Récupération de l'utilisateur
*/
$monMembre = new utilisateurObject(3);
/**
* Vérification des valeurs
*/
// Email
$this->assertEquals('john.doe@example.com', $monMembre->getEmail(), "getEmail");
$this->assertEquals(TRUE, $monMembre->connexion('username', $_POST['userPasswordMail']), "connexion après");
}
/**
* Modification du mot de passe
* @depends testMembreModifierMail
*/
public function testMembreModifierPassword() {
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['modifierPwd'] = 1;
$_POST['oldUserPassword'] = 'password';
$_POST['newUserPassword'] = 'monPassword';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Simulation d'une connexion
*/
$unMembre = new utilisateurObject();
$this->assertEquals(TRUE, $unMembre->connexion('username', $_POST['oldUserPassword']), "connexion avant");
/**
* Appel de la page
*/
ob_start();
require 'membre/monCompte.php';
ob_end_clean();
/**
* Récupération d'un objet
*/
$monMembre = new utilisateurObject();
/**
* Vérification des valeurs
*/
$this->assertEquals(TRUE, $monMembre->connexion('username', $_POST['newUserPassword']), "connexion");
$this->assertEquals(false, $monMembre->connexion('username', $_POST['oldUserPassword']), "connexion");
}
/**
* Suppression du compte sans cochage de la checkbox
* @depends testMembreModifierPassword
*/
public function testMembreSupprimerCompteRequiertCheckbox() {
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['supprimerCompte'] = 1;
$_POST['userPasswordDelete'] = 'monPassword';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Simulation d'une connexion
*/
$unMembre = new utilisateurObject();
$this->assertEquals(TRUE, $unMembre->connexion('username', $_POST['userPasswordDelete']), "connexion avant");
/**
* Appel de la page
*/
ob_start();
require 'membre/monCompte.php';
ob_end_clean();
/**
* Récupération d'un objet
*/
$monMembre = new utilisateurObject();
/**
* Vérification des valeurs
*/
$this->assertEquals(TRUE, $monMembre->connexion('username', $_POST['userPasswordDelete']), "connexion devrait être possible");
}
/**
* Suppression du compte
* @depends testMembreSupprimerCompteRequiertCheckbox
*/
public function testMembreSupprimerCompte() {
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_POST['supprimerCompte'] = 1;
$_POST['userPasswordDelete'] = 'monPassword';
$_POST['confirmeDelete'] = 1;
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Simulation d'une connexion
*/
$unMembre = new utilisateurObject();
$this->assertEquals(TRUE, $unMembre->connexion('username', $_POST['userPasswordDelete']), "connexion avant");
/**
* Appel de la page
*/
ob_start();
require 'membre/monCompte.php';
ob_end_clean();
/**
* Récupération d'un objet
*/
$monMembre = new utilisateurObject();
/**
* Vérification des valeurs
*/
$this->assertEquals(FALSE, $monMembre->connexion('username', $_POST['userPasswordDelete']), "connexion ne devrait plus être possible");
}
/**
* Connexion au compte créé lors de la création de la BDD
* @depends testMembreSupprimerCompte
*/
public function testConnexionCompteHistorique() {
unset($_POST);
/**
* Injection des valeurs du formulaire
*/
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
/**
* Récupération d'un objet
*/
$monMembre = new utilisateurObject();
/**
* Vérification des valeurs
*/
$this->assertEquals(TRUE, $monMembre->connexion('admin', 'password'), "connexion au compte créé à l'import de la BDD devrait être possible");
}
}

View file

@ -1,6 +1,7 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
@ -17,96 +18,97 @@
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
require 'config/configV2.php';
namespace ImageHeberg;
require 'config/config.php';
require _TPL_TOP_;
?>
<h1><small>A propos</small></h1>
<h1 class="mb-3"><small>A propos</small></h1>
<div class="panel panel-default">
<div class="panel-body">
Ce site est administré par <a href="<?= _ADMINISTRATEUR_SITE_ ?>"><?= _ADMINISTRATEUR_NOM_ ?></a>
<br />
Pour toute demande ou information concernant ce site, merci d'utiliser <a href="/contact.php">le formulaire de contact</a>.
<div class="card card-default">
<div class="card-body">
Ce site est administré par <a href="<?= _ADMINISTRATEUR_SITE_ ?>"><?= _ADMINISTRATEUR_NOM_ ?></a>
<br/>
Pour toute demande ou information concernant ce site, merci d'utiliser
<a href="/contact.php">le formulaire de contact</a>.
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">Licences</h2>
<div class="card">
<div class="card-header">
Licences
</div>
<div class="card-body">
Auteur de l'outil : <a href="//www.anael.eu">Anael MOBILIA</a>
<br/>
Le <a href="//github.com/AnaelMobilia/image-heberg.fr">code source est disponible</a> sous licence GNU GPLv3.
<br/>
Graphismes : <a href="//getbootstrap.com/">Bootstrap</a>
<br/>
Logos : <a href="//icons.getbootstrap.com/">Bootstrap Icons</a>
<br/>
IA de classification : <a href="//github.com/infinitered/nsfwjs">nsfwjs</a>
<br />
Technologies : PHP, MySQL, HTML5, CSS3
</div>
</div>
<div class="panel-body">
Auteur de l'outil : <a href="http://www.anael.eu">Anael MOBILIA</a>
<br />
Le <a href="https://github.com/AnaelMobilia/image-heberg.fr">code source est disponible</a> sous licence GNU GPL V3.
<br />
Graphismes et images : <a href="http://getbootstrap.com/">Bootstrap</a>
<br />
Technologies : PHP, MySQL, HTML5, CSS, jQuery
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">Hébergeur</h2>
<div class="card">
<div class="card-header">
Hébergeur
</div>
<div class="card-body">
Ce site est hébergé chez <a href="<?= _HEBERGEUR_SITE_ ?> "><?= _HEBERGEUR_NOM_ ?> </a>
<br/>
Vous trouverez leur adresse et téléphone sur <a href="<?= _HEBERGEUR_SITE_ ?>">leur site internet</a>.
</div>
</div>
<div class="panel-body">
Ce site est hébergé chez <a href="<?= _HEBERGEUR_SITE_ ?> "><?= _HEBERGEUR_NOM_ ?> </a>
<br />
Vous trouverez leur adresse et téléphone sur <a href="<?= _HEBERGEUR_SITE_ ?>">leur site internet</a>.
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseCNIL">
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#collapseCNIL">
Conservations de données à caractère privé
&nbsp;<span class="caret"></span>
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</h2>
</div>
<div id="collapseCNIL" class="panel-collapse collapse">
<div class="panel-body">
L'utilisation du service peut conduire à l'enregistrement de cookies sur votre ordinateur.
<br />
Vous pouvez supprimer librement ces cookies via les options de votre navigateur internet.
<br />
A défaut, et sauf action spécifique et explicite de votre part, les cookies seront supprimés lors de la fermeture de votre navigateur.
<br /><br />
Votre adresse IP est enregistrée dans la base de données lors de l'envoi d'une image, de la création et à la connexion à votre espace membre.
<br />
La suppression d'une image envoyée sur le service conduit à la suppression de toutes les informations liées dans la base de données.
<br /><br />
Conformément à la directive 2006/24/CE sur la conservation des données, tous les accès au service seront enregistrés et conservés durant <em>- au moins -</em> 2 années.
<br /><br />
Aucune donnée n'est utilisée à but publicitaire ni est transmise à des tiers, ou réutilisée en dehors du présent service.
</div>
<div id="collapseCNIL" class="collapse">
<div class="card card-body">
L'utilisation du service conduit à l'enregistrement de cookies techniques (gestion des sessions) sur votre ordinateur. Ces cookies seront supprimés lors de la fermeture de votre navigateur.
<br/>
Votre adresse IP est enregistrée dans la base de données lors de l'envoi d'une image, de la création et à la connexion à votre espace membre.
<br/>
La suppression d'une image envoyée sur le service conduit à la suppression de toutes les informations liées dans la base de données. Les images qui ne sont plus affichées depuis plus de
<?= _DELAI_INACTIVITE_AVANT_EFFACEMENT_IMAGES_ ?> jours seront automatiquement effacées.
<br/>
La suppression de votre compte entraine la suppression de toutes les informations liées à ce dernier.
<br/>
Conformément à la directive 2006/24/CE sur la conservation des données, tous les accès au service sont enregistrés et conservés durant une durée d'au moins 12 mois et au plus 24 mois.
<br/>
Aucune donnée n'est utilisée à but publicitaire, ni transmise à des tiers, ou réutilisée en dehors du présent service. L'ensemble des données sont stockées au sein de l'Union Européenne.
</div>
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseCNIL2">
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#collapseCNIL2">
Responsable du traitement : <?= _ADMINISTRATEUR_NOM_ ?>
&nbsp;<span class="caret"></span>
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</h2>
</div>
<div id="collapseCNIL2" class="panel-collapse collapse">
<div class="panel-body">
Les informations recueillies font lobjet dun traitement informatique destiné à personnaliser votre utilisation du service.
<br />
Vous n'&ecirc;tes pas obligé de créer un espace membre pour utiliser le service.
<br />
Le destinataire des données est <?= _ADMINISTRATEUR_NOM_ ?>.
<br />
Conformément à la loi « informatique et libertés » du 6 janvier 1978 modifiée en 2004,
vous bénéficiez d'un droit d'accès et de rectification aux informations qui vous concernent,
que vous pouvez exercer en vous adressant à <a href="/contact.php"><?= _ADMINISTRATEUR_NOM_ ?> via le formulaire de contact</a>.
<br />
Vous pouvez également, pour des motifs légitimes, vous opposer au traitement des données vous concernant.
</div>
<div id="collapseCNIL2" class="collapse">
<div class="card card-body">
Les informations recueillies font lobjet dun traitement informatique destiné à personnaliser votre utilisation du service.
<br/>
Vous n'êtes pas obligé de créer un espace membre pour utiliser le service.
<br/>
Le destinataire des données est <?= _ADMINISTRATEUR_NOM_ ?>.
<br/>
Conformément à la loi « informatique et libertés » du 6 janvier 1978 modifiée en 2004, vous bénéficiez d'un droit d'accès et de rectification aux informations qui vous concernent, que vous pouvez exercer en vous adressant à <?= _ADMINISTRATEUR_NOM_ ?> via le formulaire de contact.
<br/>
Vous pouvez également, pour des motifs légitimes, vous opposer au traitement des données vous concernant.
</div>
</div>
</div>
</div>
<?php require _TPL_BOTTOM_ ?>
<?php require _TPL_BOTTOM_ ?>

133
abuse.php Normal file
View file

@ -0,0 +1,133 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
if (!defined('_PHPUNIT_')) {
require 'config/config.php';
}
// Anti flood
$maSession = new SessionObject();
$msgErreur = '';
require _TPL_TOP_;
// En cas de validation du formulaire
if (
isset($_POST['Submit']) && $maSession->checkFlag()
&& !empty($_POST['userMail']) && !empty($_POST['urlImage'])
) {
// Suivi du traitement
$isTraitee = false;
// Vérification du bon format de l'adresse mail
if (filter_var($_POST['userMail'], FILTER_VALIDATE_EMAIL) !== false) {
// On essaie de matcher l'image - nettoyage des paramètres
$fileName = basename(parse_url(trim($_POST['urlImage']), PHP_URL_PATH));
if (
preg_match('#^[\d]+\.(?:' . implode('|', _ACCEPTED_EXTENSIONS_) . ')$#', $fileName)
|| (_PHPUNIT_ && $fileName === 'image_15.png')
) {
// Suivi du traitement
$isTraitee = true;
// On flaggue l'image en signalée en BDD
$monImage = new ImageObject($fileName);
// Si l'image est approuvée, on ne la bloque pas en automatique
if (!$monImage->isApprouvee()) {
$monImage->setSignalee(true);
$monImage->sauver();
// On cherche les autres images avec le même MD5
$images = HelperAdmin::getImageByMd5($monImage->getMd5());
foreach ($images as $uneImage) {
// On flaggue en signalée...
$monImage = new ImageObject($uneImage);
$monImage->setSignalee(true);
$monImage->sauver();
}
// Les miniatures reprennent automatiquement les informations de l'image parent
} else {
$isTraitee = false;
}
}
// Gestion travis
if (!_PHPUNIT_) {
// Je complète le message avec l'IP de mon émeteur
$message = 'URL : ' . $_POST['urlImage'];
$message .= PHP_EOL . 'Blocage automatique : ' . ($isTraitee ? 'OK' : 'KO');
$message .= PHP_EOL . 'Raison : ' . $_POST['raison'];
$message .= PHP_EOL . 'Message : ' . $_POST['userMessage'];
$message .= PHP_EOL . '---------------------------------------------';
$message .= PHP_EOL . 'IP : ' . $_SERVER['REMOTE_ADDR'];
$message .= PHP_EOL . 'BROWSER : ' . $_SERVER['HTTP_USER_AGENT'];
$message .= PHP_EOL . 'DATE : ' . date('Y-m-d H:i:s');
// Tout va bien, on envoit un mail
$subject = '[' . _SITE_NAME_ . '] - Signalement d\'image';
mail(_ADMINISTRATEUR_EMAIL_, $subject, $message, 'From: ' . $_POST['userMail']);
$maSession->removeFlag();
}
// Retour utilisateur
echo '<div class="alert alert-success">Votre signalement a été envoyé, merci !</div>';
} else {
// Adresse mail invalide
$msgErreur = '<div class="alert alert-danger">Votre adresse mail n\'est pas valide !<br /><pre>' . $_POST['userMail'] . '</pre></div>';
}
} elseif (!isset($_POST['Submit'])) {
// Premier affichage de la page => activation de la protection robot
$maSession->setFlag();
}
?>
<?php if (!isset($_POST['Submit']) || $maSession->checkFlag()) : ?>
<h1 class="mb-3"><small>Signaler une image</small></h1>
<?= $msgErreur ?>
<form method="post">
<div class="mb-3 form-floating">
<input type="text" class="form-control" name="urlImage" id="urlImage" required="required" value="<?= $_POST['urlImage'] ?? '' ?>">
<label for="urlImage">Adresse de l'image</label>
<div class="form-text text-muted">
Indiquer toute l'URL de l'image, telle qu'affichée dans le navigateur (<?= _URL_IMAGES_ . _IMAGE_BAN_ ?>).
</div>
</div>
<div class="mb-3 form-floating">
<select name="raison" id="raison" class="form-select" required="required">
<option value="" selected>-- Sélectionner une raison --</option>
<option value="porno">Pornographie et érotisme</option>
<option value="phishing">Spam et phishing</option>
<option value="legislation">Non respect de la législation française (à préciser)</option>
<option value="autre">Autre (à préciser)</option>
</select>
<label for="raison">Raison du signalement</label>
</div>
<div class="mb-3 form-floating">
<input type="email" class="form-control" name="userMail" id="userMail" required="required" value="<?= $_POST['userMail'] ?? '' ?>">
<label for="userMail">Votre adresse courriel</label>
<div class="form-text text-muted">Sera utilisée uniquement pour vous apporter une réponse.</div>
</div>
<div class="mb-3 form-floating">
<textarea class="form-control" rows="5" name="userMessage" id="userMessage" placeholder="Informations complémentaires sur la raison de votre demande" required="required"><?= $_POST['userMessage'] ?? '' ?></textarea>
<label for="userMessage">Votre message</label>
</div>
<button type="submit" name="Submit" class="btn btn-success">Envoyer</button>
</form>
<?php endif; ?>
<?php require _TPL_BOTTOM_ ?>

59
admin/abuse-network.php Normal file
View file

@ -0,0 +1,59 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
if (!defined('_PHPUNIT_')) {
require '../config/config.php';
}
// Vérification des droits d'accès
UtilisateurObject::checkAccess(UtilisateurObject::LEVEL_ADMIN);
$listeIp = HelperAdmin::getBadNetworks();
require _TPL_TOP_;
?>
<h1 class="mb-3"><small>Réseaux IP suspects</small></h1>
<div class="card">
<div class="card-header">
<?= count($listeIp) ?> réseau<?= (count($listeIp) > 1 ? 'x' : '') ?> d'addresses IP
</div>
<div class="card-body">
<table class="table">
<thead>
<tr>
<th>Réseau</th>
<th>Nombre d'images bloquées</th>
</tr>
</thead>
<tbody id="tbody">
<?php foreach ((array)$listeIp as $key => $value) : ?>
<tr>
<td><?= $key ?></td>
<td><?= $value ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php require _TPL_BOTTOM_; ?>

180
admin/abuse.php Normal file
View file

@ -0,0 +1,180 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
if (!defined('_PHPUNIT_')) {
require '../config/config.php';
}
// Vérification des droits d'accès
UtilisateurObject::checkAccess(UtilisateurObject::LEVEL_ADMIN);
require _TPL_TOP_;
?>
<h1 class="mb-3"><small>Gestion des abus</small></h1>
<?php
$message = '';
$tabTables = [];
// Action à effectuer sur une image
if (isset($_GET['idImage']) && is_numeric($_GET['idImage'])) {
$monImage = new ImageObject($_GET['idImage'], RessourceObject::SEARCH_BY_ID);
if (isset($_GET['bloquer'])) {
// Blocage de l'image
$monImage->bloquer();
$message .= 'Image ' . $monImage->getNomNouveau() . ' bloquée !';
} elseif (isset($_GET['approuver'])) {
// Approbation de l'image
$monImage->approuver();
$message .= 'Image ' . $monImage->getNomNouveau() . ' approuvée !';
}
} else {
/**
* Images à traiter
*/
// Liste des images avec un ratio d'affichage incohérent
$tabTables[] = [
'legende' => 'affichée## > ' . _ABUSE_NB_AFFICHAGES_PAR_JOUR_WARNING_ . ' fois/jour <small>(blocage automatique à ' . _ABUSE_NB_AFFICHAGES_PAR_JOUR_BLOCAGE_AUTO_ . '</small>)',
'values' => HelperAdmin::getImagesTropAffichees(_ABUSE_NB_AFFICHAGES_PAR_JOUR_WARNING_)
];
// Liste des images avec un ratio d'affichage incohérent EN PROJECTION
$tabTables[] = [
'legende' => 'projetée## avec un nombre d\'affichages > ' . _ABUSE_NB_AFFICHAGES_PAR_JOUR_WARNING_ . ' fois/jour <small>(blocage automatique à ' . _ABUSE_NB_AFFICHAGES_PAR_JOUR_BLOCAGE_AUTO_ . '</small>)',
'values' => HelperAdmin::getImagesTropAffichees(_ABUSE_NB_AFFICHAGES_PAR_JOUR_WARNING_, false, true)
];
// Liste des images suspectes avec un ratio d'affichage incohérent
$tabTables[] = [
'legende' => '<b>suspecte##</b> affichée## > ' . (_ABUSE_NB_AFFICHAGES_PAR_JOUR_WARNING_ / _ABUSE_DIVISION_SEUILS_SI_SUSPECT_) . ' fois/jour <small>(blocage automatique à ' . (_ABUSE_NB_AFFICHAGES_PAR_JOUR_BLOCAGE_AUTO_ / _ABUSE_DIVISION_SEUILS_SI_SUSPECT_) . '</small>)',
'values' => HelperAdmin::getImagesTropAffichees((_ABUSE_NB_AFFICHAGES_PAR_JOUR_WARNING_ / _ABUSE_DIVISION_SEUILS_SI_SUSPECT_), true)
];
// Liste des images suspectes avec un ratio d'affichage incohérent EN PROJECTION
$tabTables[] = [
'legende' => '<b>suspecte##</b> projetée## avec un nombre d\'affichages > ' . (_ABUSE_NB_AFFICHAGES_PAR_JOUR_WARNING_ / _ABUSE_DIVISION_SEUILS_SI_SUSPECT_) . ' fois/jour <small>(blocage automatique à ' . (_ABUSE_NB_AFFICHAGES_PAR_JOUR_BLOCAGE_AUTO_ / _ABUSE_DIVISION_SEUILS_SI_SUSPECT_) . '</small>)',
'values' => HelperAdmin::getImagesTropAffichees((_ABUSE_NB_AFFICHAGES_PAR_JOUR_WARNING_ / _ABUSE_DIVISION_SEUILS_SI_SUSPECT_), true, true)
];
// Liste des images signalées
$tabTables[] = [
'legende' => 'signalée##',
'values' => HelperAdmin::getImagesSignalees()
];
// Liste des images suspectes
$tabTables[] = [
'legende' => 'suspecte##',
'values' => HelperAdmin::getImagesPotentiellementIndesirables()
];
// Liste des images approuvables
$tabTables[] = [
'legende' => 'approuvable##',
'values' => HelperAdmin::getImagesPotentiellementApprouvables()
];
// Liste de TOUTES les images avec un ratio d'affichage abusif
$tabTables[] = [
'legende' => 'affichée## > ' . _ABUSE_NB_AFFICHAGES_PAR_JOUR_ABUSIF_ . ' fois/jour',
'values' => HelperAdmin::getImagesTropAffichees(_ABUSE_NB_AFFICHAGES_PAR_JOUR_ABUSIF_, false, true, true)
];
}
/**
* Recherche
*/
$tabSearch = [
'Adresse IP' => 'SELECT new_name FROM images WHERE remote_addr LIKE \'%##value##%\' ORDER BY id DESC',
'Nom originel' => 'SELECT new_name FROM images WHERE old_name LIKE \'%##value##%\' ORDER BY id DESC',
'Nouveau nom' => 'SELECT new_name FROM images WHERE new_name LIKE \'%##value##%\' ORDER BY id DESC',
'Utilisateur' => 'SELECT im.new_name FROM images im LEFT JOIN possede po ON po.images_id = im.id WHERE po.membres_id = \'##value##\' ORDER BY im.id DESC',
'Bloquée' => 'SELECT new_name FROM images WHERE isBloquee = \'1\' ORDER BY id DESC',
'Approuvée' => 'SELECT new_name FROM images WHERE isApprouvee = \'1\' ORDER BY id DESC',
];
if (isset($_POST['Submit']) && !empty($_POST['champ']) && !empty($_POST['valeur'])) {
$reqValue = trim(str_replace('\'', '_', $_POST['valeur']));
$req = str_replace('##value##', $reqValue, $tabSearch[$_POST['champ']]);
array_unshift($tabTables, [
'legende' => 'trouvée## -> recherche sur le champ "' . $_POST['champ'] . '" = "' . $_POST['valeur'] . '"',
'values' => HelperAdmin::queryOnNewName($req)
]);
}
?>
<?php if (!empty($message)) : ?>
<div class="alert alert-success">
<?= $message ?>
</div>
<?php endif; ?>
<div class="alert alert-info">
<form method="post">
<div class="mb-3 form-floating">
<select name="champ" id="champ" class="form-select" required="required">
<option value="" selected>-- Sélectionner un champ --</option>
<?php foreach (array_keys($tabSearch) as $key) : ?>
<option value="<?= $key ?>"><?= $key ?></option>
<?php endforeach; ?>
</select>
<label for="champ">Champ à utiliser</label>
</div>
<div class="mb-3 form-floating">
<input type="text" class="form-control" name="valeur" id="valeur" required="required" value="">
<label for="valeur">Valeur recherchée</label>
</div>
<button type="submit" name="Submit" class="btn btn-success">Rechercher</button>
</form>
</div>
<?php foreach ($tabTables as $uneTable) : ?>
<?php $mesImages = ImageObject::chargerMultiple($uneTable['values'], RessourceObject::SEARCH_BY_NAME);?>
<div class="card">
<div class="card-header">
<?= count($uneTable['values']) ?> image<?= (count($uneTable['values']) > 1 ? 's' : '') . ' ' . str_replace('##', (count($uneTable['values']) > 1 ? 's' : ''), $uneTable['legende']) ?>
</div>
<div class="card-body">
<table class="table">
<thead>
<tr>
<th>Image</th>
<th>Actions</th>
<th class="text-break">Nom originel</th>
<th class="text-break">Date d'envoi</th>
<th class="text-break">IP envoi</th>
<th class="text-break">Nb vues</th>
<th class="text-break">Dernier affichage</th>
<th class="text-break">Utilisateur</th>
</tr>
</thead>
<tbody>
<?php foreach ($mesImages as $uneImage) : ?>
<tr>
<td><a href="<?= $uneImage->getURL(true) ?>?forceDisplay=1" target="_blank" style="<?= ($uneImage->isBloquee() ? 'text-decoration: line-through double red;' : '') . ($uneImage->isApprouvee() ? 'text-decoration: underline double green;' : '') ?>"><?= $uneImage->getNomNouveau() ?></a></td>
<td>
<a href="<?= _URL_ADMIN_ ?>abuse.php?approuver=1&idImage=<?= $uneImage->getId() ?>" title="Approuver"><span class="bi-hand-thumbs-up-fill" style="color: green"></span></a>
<a href="<?= _URL_ADMIN_ ?>abuse.php?bloquer=1&idImage=<?= $uneImage->getId() ?>" title="Bloquer"><span class="bi-hand-thumbs-down-fill" style="color: red"></span></a>
</td>
<td class="text-break"><?= $uneImage->getNomOriginalFormate() ?></td>
<td class="text-break"><?= $uneImage->getDateEnvoiFormatee() ?></td>
<td class="text-break"><?= $uneImage->getIpEnvoi() ?></td>
<td class="text-break"><?= $uneImage->getNbViewTotal() ?><small> (<?= $uneImage->getNbViewPerDay() ?>/jour)</small></td>
<td class="text-break"><?= $uneImage->getLastViewFormate() ?></td>
<td class="text-break"><?= $uneImage->getIdProprietaire() ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<br>
<?php endforeach; ?>
<?php require _TPL_BOTTOM_; ?>

View file

@ -0,0 +1,73 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
require '../config/config.php';
// Vérification des droits d'accès
UtilisateurObject::checkAccess(UtilisateurObject::LEVEL_ADMIN);
require _TPL_TOP_;
?>
<h1 class="mb-3"><small>Nettoyage des comptes jamais utilisés</small></h1>
<?php
$message = '';
// Je récupère la liste des comptes jamais utilisés
$listeComptes = HelperAdmin::getUnusedAccounts();
$isPlural = ($listeComptes->count() > 1 ? 's' : '');
// Si l'effacement est demandé
if (isset($_POST['effacer'])) :
foreach ((array)$listeComptes as $value) {
$message .= '<br />Suppression du compte ' . $value;
// Je crée mon objet et lance la suppression
$monUtilisateur = new UtilisateurObject($value);
$monUtilisateur->supprimer();
}
$message .= '<br />Effacement terminé !';
?>
<div class="alert alert-success">
<?= $message ?>
</div>
<?php else : ?>
<div class="card">
<div class="card-header">
<?= $listeComptes->count() ?> compte<?= $isPlural ?> créé<?= $isPlural ?> il y a au moins <?= _DELAI_EFFACEMENT_COMPTES_JAMAIS_UTILISES_ ?> jour<?= _DELAI_EFFACEMENT_COMPTES_JAMAIS_UTILISES_ > 1 ? 's' : '' ?> et sans images associées
</div>
<div class="card-body">
<ul>
<?php foreach ((array)$listeComptes as $value) : ?>
<li><?= $value ?></li>
<?php endforeach; ?>
</ul>
</div>
<form method="post">
<button class="btn btn-danger" type="submit" name="effacer">
<span class="bi-trash"></span>
&nbsp;Effacer ce<?= $isPlural ?> compte<?= $isPlural ?>
</button>
</form>
</div>
<?php endif; ?>
<?php require _TPL_BOTTOM_; ?>

View file

@ -1,6 +1,7 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
@ -17,147 +18,142 @@
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
require '../config/configV2.php';
namespace ImageHeberg;
use ArrayObject;
require '../config/config.php';
// Vérification des droits d'accès
metaObject::checkUserAccess(utilisateurObject::levelAdmin);
UtilisateurObject::checkAccess(UtilisateurObject::LEVEL_ADMIN);
require _TPL_TOP_;
?>
<h1><small>Nettoyage des incohérences</small></h1>
<h1 class="mb-3"><small>Nettoyage des incohérences</small></h1>
<?php
$message = '';
// Je récupère la liste des images en BDD
$listeImagesBDD = metaObject::getAllImagesNameBDD();
$listeImagesBDD = HelperAdmin::getAllImagesNameBDD();
// Je récupère la liste des images sur le HDD
$listeImagesHDD = metaObject::getAllImagesNameHDD(_PATH_IMAGES_);
$listeImagesHDD = HelperAdmin::getAllImagesNameHDD(_PATH_IMAGES_);
// Je recherche les erreurs sur les images
// Pour chaque images en BDD
$listeErreursImagesBDD = new ArrayObject(array_diff((array) $listeImagesBDD, (array) $listeImagesHDD));
$listeErreursImagesBDD = new ArrayObject(array_diff((array)$listeImagesBDD, (array)$listeImagesHDD));
// Pour chaque images en HDD
$listeErreursImagesHDD = new ArrayObject(array_diff((array) $listeImagesHDD, (array) $listeImagesBDD));
$listeErreursImagesHDD = new ArrayObject(array_diff((array)$listeImagesHDD, (array)$listeImagesBDD));
// Je récupère la liste des miniatures en BDD
$listeMiniaturesBDD = metaObject::getAllMiniaturesNameBDD();
$listeMiniaturesBDD = HelperAdmin::getAllMiniaturesNameBDD();
// Je récupère la liste des miniatures en HDD
$listeMiniaturesHDD = metaObject::getAllImagesNameHDD(_PATH_MINIATURES_);
$listeMiniaturesHDD = HelperAdmin::getAllImagesNameHDD(_PATH_MINIATURES_);
// Je recherche les erreurs sur les miniatures
// Pour chaque miniatures en BDD
$listeErreursMiniaturesBDD = new ArrayObject(array_diff((array) $listeMiniaturesBDD, (array) $listeMiniaturesHDD));
$listeErreursMiniaturesBDD = new ArrayObject(array_diff((array)$listeMiniaturesBDD, (array)$listeMiniaturesHDD));
// Pour chaque miniatures en HDD
$listeErreursMiniaturesHDD = new ArrayObject(array_diff((array) $listeMiniaturesHDD, (array) $listeMiniaturesBDD));
$listeErreursMiniaturesHDD = new ArrayObject(array_diff((array)$listeMiniaturesHDD, (array)$listeMiniaturesBDD));
// Si l'effacement est demandé
if (isset($_POST['effacer'])) :
// Images uniquement en BDD
foreach ((array) $listeErreursImagesBDD as $value) {
$message .= '<br />Suppression de la BDD de l\'image ' . $value;
// Images uniquement en BDD
foreach ((array)$listeErreursImagesBDD as $value) {
$message .= '<br />Suppression de la BDD de l\'image ' . $value;
// Je crée mon objet et lance la suppression
$monImage = new imageObject($value);
$monImage->supprimer();
}
// Images uniquement en HDD
foreach ((array) $listeErreursImagesHDD as $value) {
$message .= '<br />Suppression du disque de l\'image ' . $value;
// Je crée mon objet et lance la suppression
$monImage = new ImageObject($value, RessourceObject::SEARCH_BY_MD5);
$monImage->supprimer();
}
// Images uniquement en HDD
foreach ((array)$listeErreursImagesHDD as $value) {
$message .= '<br />Suppression du disque de l\'image ' . $value;
// Suppression du fichier
$rep = substr($value, 0, 1) . '/';
$pathFinal = _PATH_IMAGES_ . $rep . $value;
unlink($pathFinal);
}
// Miniatures uniquement en BDD
foreach ((array) $listeErreursMiniaturesBDD as $value) {
$message .= '<br />Suppression de la BDD de la miniature ' . $value;
// Suppression du fichier
$rep = substr($value, 0, 1) . '/';
$pathFinal = _PATH_IMAGES_ . $rep . $value;
unlink($pathFinal);
}
// Miniatures uniquement en BDD
foreach ((array)$listeErreursMiniaturesBDD as $value) {
$message .= '<br />Suppression de la BDD de la miniature ' . $value;
// Je crée mon objet et lance la suppression
$maMiniature = new miniatureObject($value);
$maMiniature->supprimer();
}
// Je crée mon objet et lance la suppression
$maMiniature = new MiniatureObject($value, RessourceObject::SEARCH_BY_MD5);
$maMiniature->supprimer();
}
// Miniatures uniquement en HDD
foreach ((array) $listeErreursMiniaturesHDD as $value) {
$message .= '<br />Suppression du disque de la miniature ' . $value;
// Miniatures uniquement en HDD
foreach ((array)$listeErreursMiniaturesHDD as $value) {
$message .= '<br />Suppression du disque de la miniature ' . $value;
// Suppression du fichier
$rep = substr($value, 0, 1) . '/';
$pathFinal = _PATH_MINIATURES_ . $rep . $value;
unlink($pathFinal);
}
$message .= '<br />Effacement terminé !';
?>
// Suppression du fichier
$rep = substr($value, 0, 1) . '/';
$pathFinal = _PATH_MINIATURES_ . $rep . $value;
unlink($pathFinal);
}
$message .= '<br />Effacement terminé !';
?>
<div class="alert alert-success">
<?= $message ?>
</div>
<?php else: ?>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<?= $listeErreursImagesBDD->count() ?> image(s) présente(s) uniquement en BDD
</h2>
</div>
<div class="panel-body">
<ul>
<?php foreach ((array) $listeErreursImagesBDD as $value): ?>
<li><?= $value ?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<?= $listeErreursImagesHDD->count() ?> image(s) présente(s) uniquement sur HDD
</h2>
</div>
<div class="panel-body">
<ul>
<?php foreach ((array) $listeErreursImagesHDD as $value): ?>
<li><?= $value ?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<?= $listeErreursMiniaturesBDD->count() ?> miniature(s) présente(s) uniquement en BDD
</h2>
</div>
<div class="panel-body">
<ul>
<?php foreach ((array) $listeErreursMiniaturesBDD as $value): ?>
<li><?= $value ?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<?= $listeErreursMiniaturesHDD->count() ?> miniature(s) présente(s) uniquement sur HDD
</h2>
</div>
<div class="panel-body">
<ul>
<?php foreach ((array) $listeErreursMiniaturesHDD as $value): ?>
<li><?= $value ?> (<strong>A effacer manuellement</strong>)</li>
<?php endforeach; ?>
</ul>
</div>
</div>
<form method="post">
<button class="btn btn-danger" type="submit" name="effacer">
<span class="glyphicon glyphicon-trash"></span>
&nbsp;
Effacer ces fichiers
</button>
</form>
<?php
endif;
require _TPL_BOTTOM_;
?>
<div class="alert alert-success">
<?= $message ?>
</div>
<?php else : ?>
<div class="card">
<div class="card-header">
<?= $listeErreursImagesBDD->count() ?> image<?= ($listeErreursImagesBDD->count() > 1) ? 's' : '' ?> présente<?= ($listeErreursImagesBDD->count() > 1) ? 's' : '' ?> uniquement en BDD
</div>
<div class="card-body">
<ul>
<?php foreach ((array)$listeErreursImagesBDD as $value) : ?>
<li><?= $value ?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<div class="card">
<div class="card-header">
<?= $listeErreursImagesHDD->count() ?> image<?= ($listeErreursImagesHDD->count() > 1) ? 's' : '' ?> présente<?= ($listeErreursImagesHDD->count() > 1) ? 's' : '' ?> uniquement sur HDD
</div>
<div class="card-body">
<ul>
<?php foreach ((array)$listeErreursImagesHDD as $value) : ?>
<li><?= $value ?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<div class="card">
<div class="card-header">
<?= $listeErreursMiniaturesBDD->count() ?> miniature<?= ($listeErreursMiniaturesBDD->count() > 1) ? 's' : '' ?> présente<?= ($listeErreursMiniaturesBDD->count() > 1) ? 's' : '' ?> uniquement en BDD
</div>
<div class="card-body">
<ul>
<?php foreach ((array)$listeErreursMiniaturesBDD as $value) : ?>
<li><?= $value ?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<div class="card">
<div class="card-header">
<?= $listeErreursMiniaturesHDD->count() ?> miniature<?= ($listeErreursMiniaturesHDD->count() > 1) ? 's' : '' ?> présente<?= ($listeErreursMiniaturesHDD->count() > 1) ? 's' : '' ?> uniquement sur HDD
</div>
<div class="card-body">
<ul>
<?php foreach ((array)$listeErreursMiniaturesHDD as $value) : ?>
<li><?= $value ?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<form method="post">
<button class="btn btn-danger" type="submit" name="effacer">
<span class="bi-trash"></span>
&nbsp;Supprimer les incohérences
</button>
</form>
<?php endif; ?>
<?php require _TPL_BOTTOM_; ?>

View file

@ -0,0 +1,75 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
require '../config/config.php';
// Vérification des droits d'accès
UtilisateurObject::checkAccess(UtilisateurObject::LEVEL_ADMIN);
require _TPL_TOP_;
?>
<h1 class="mb-3"><small>Nettoyage des fichiers jamais utilisés</small></h1>
<?php
$message = '';
// Je récupère la liste des images jamais affichées
$listeImages = HelperAdmin::getNeverUsedFiles();
$isPlural = ($listeImages->count() > 1 ? 's' : '');
// Si l'effacement est demandé
if (isset($_POST['effacer'])) :
$mesImages = ImageObject::chargerMultiple($listeImages, RessourceObject::SEARCH_BY_NAME);
/* @var ImageObject[] $mesImages */
foreach ($mesImages as $monImage) {
$message .= '<br />Suppression de l\'image ' . $monImage->getNomNouveau();
$monImage->supprimer();
}
$message .= '<br />Effacement terminé !';
?>
<div class="alert alert-success">
<?= $message ?>
</div>
<?php else : ?>
<div class="card">
<div class="card-header">
<?= $listeImages->count() ?> image<?= $isPlural ?> envoyée<?= $isPlural ?> il y a au moins <?= _DELAI_EFFACEMENT_IMAGES_JAMAIS_AFFICHEES_ ?> jour<?= _DELAI_EFFACEMENT_IMAGES_JAMAIS_AFFICHEES_ > 1 ? 's' : '' ?> et jamais affichée<?= $isPlural ?>
</div>
<div class="card-body">
<ul>
<?php foreach ((array)$listeImages as $value) : ?>
<li>
<a href="<?= str_replace('http:', 'https:', _URL_IMAGES_) . $value ?>?forceDisplay=1" target="_blank"><?= $value ?></a>
</li>
<?php endforeach; ?>
</ul>
</div>
<form method="post">
<button class="btn btn-danger" type="submit" name="effacer">
<span class="bi-trash"></span>
&nbsp;Effacer ce<?= $isPlural ?> fichier<?= $isPlural ?>
</button>
</form>
</div>
<?php endif; ?>
<?php require _TPL_BOTTOM_; ?>

View file

@ -0,0 +1,75 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
require '../config/config.php';
// Vérification des droits d'accès
UtilisateurObject::checkAccess(UtilisateurObject::LEVEL_ADMIN);
require _TPL_TOP_;
?>
<h1 class="mb-3"><small>Nettoyage des fichiers dormants</small></h1>
<?php
$message = '';
// Je récupère la liste des images non affichées depuis xx jours
$listeImages = HelperAdmin::getUnusedFiles();
$isPlural = ($listeImages->count() > 1 ? 's' : '');
// Si l'effacement est demandé
if (isset($_POST['effacer'])) :
$mesImages = ImageObject::chargerMultiple($listeImages, RessourceObject::SEARCH_BY_NAME);
/* @var ImageObject[] $mesImages */
foreach ($mesImages as $monImage) {
$message .= '<br />Suppression de l\'image ' . $monImage->getNomNouveau();
$monImage->supprimer();
}
$message .= '<br />Effacement terminé !';
?>
<div class="alert alert-success">
<?= $message ?>
</div>
<?php else : ?>
<div class="card">
<div class="card-header">
<?= $listeImages->count() ?> image<?= $isPlural ?> non affichée<?= $isPlural ?> depuis au moins <?= _DELAI_INACTIVITE_AVANT_EFFACEMENT_IMAGES_ ?> jour<?= _DELAI_INACTIVITE_AVANT_EFFACEMENT_IMAGES_ > 1 ? 's' : '' ?>.
</div>
<div class="card-body">
<ul>
<?php foreach ((array)$listeImages as $value) : ?>
<li>
<a href="<?= str_replace('http:', 'https:', _URL_IMAGES_) . $value ?>?forceDisplay=1" target="_blank"><?= $value ?></a>
</li>
<?php endforeach; ?>
</ul>
</div>
<form method="post">
<button class="btn btn-danger" type="submit" name="effacer">
<span class="bi-trash"></span>
&nbsp;Effacer ce<?= $isPlural ?> fichier<?= $isPlural ?>
</button>
</form>
</div>
<?php endif; ?>
<?php require _TPL_BOTTOM_; ?>

View file

@ -1,72 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
require '../config/configV2.php';
// Vérification des droits d'accès
metaObject::checkUserAccess(utilisateurObject::levelAdmin);
require _TPL_TOP_;
?>
<h1><small>Nettoyage des fichiers jamais utilisés depuis 1 année</small></h1>
<?php
$message = '';
// Je récupère la liste des images non affichées depuis un an
$listeImages = metaObject::getNeverUsedOneYear();
// Si l'effacement est demandé
if (isset($_POST['effacer'])) :
foreach ((array) $listeImages as $value) {
$message .= '<br />Suppression de l\'image ' . $value;
// Je crée mon objet et lance la suppression
$monImage = new imageObject($value);
$monImage->supprimer();
}
$message .= '<br />Effacement terminé !';
?>
<div class = "alert alert-success">
<?= $message ?>
</div>
<?php else: ?>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<?= $listeImages->count() ?> image(s) envoyée(s) il y a au moins un an n'ont jamais été affichée(s)
</h2>
</div>
<div class="panel-body">
<ul>
<?php foreach ((array) $listeImages as $value): ?>
<li><?= $value ?></li>
<?php endforeach; ?>
</ul>
</div>
<form method="post">
<button class="btn btn-danger" type="submit" name="effacer">
<span class="glyphicon glyphicon-trash"></span>
&nbsp;
Effacer ces fichiers
</button>
</form>
</div>
<?php
endif;
require _TPL_BOTTOM_;
?>

View file

@ -1,72 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
require '../config/configV2.php';
// Vérification des droits d'accès
metaObject::checkUserAccess(utilisateurObject::levelAdmin);
require _TPL_TOP_;
?>
<h1><small>Nettoyage des fichiers dormants depuis 3 ans</small></h1>
<?php
$message = '';
// Je récupère la liste des images non affichées depuis un an
$listeImages = metaObject::getUnusedThreeYear();
// Si l'effacement est demandé
if (isset($_POST['effacer'])) :
foreach ((array) $listeImages as $value) {
$message .= '<br />Suppression de l\'image ' . $value;
// Je crée mon objet et lance la suppression
$monImage = new imageObject($value);
$monImage->supprimer();
}
$message .= '<br />Effacement terminé !';
?>
<div class="alert alert-success">
<?= $message ?>
</div>
<?php else: ?>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<?= $listeImages->count() ?> image(s) non affichée(s) depuis au moins 3 ans.
</h2>
</div>
<div class="panel-body">
<ul>
<?php foreach ((array) $listeImages as $value): ?>
<li><?= $value ?></li>
<?php endforeach; ?>
</ul>
</div>
<form method="post">
<button class="btn btn-danger" type="submit" name="effacer">
<span class="glyphicon glyphicon-trash"></span>
&nbsp;
Effacer ces fichiers
</button>
</form>
</div>
<?php
endif;
require _TPL_BOTTOM_;
?>

View file

@ -1,6 +1,7 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
@ -17,52 +18,85 @@
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
require '../config/configV2.php';
namespace ImageHeberg;
require '../config/config.php';
// Vérification des droits d'accès
metaObject::checkUserAccess(utilisateurObject::levelAdmin);
UtilisateurObject::checkAccess(UtilisateurObject::LEVEL_ADMIN);
require _TPL_TOP_;
?>
<h1><small>Panneau d'administration</small></h1>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
Outils
</h2>
<h1 class="mb-3"><small>Panneau d'administration</small></h1>
<div class="card">
<div class="card-header">
Gestion du site
</div>
<div class="card-body">
<a href="<?= _URL_ADMIN_ ?>abuse.php" class="btn btn-success">
<span class="bi-radioactive"></span>
&nbsp;Images à vérifier
</a>
<div class="clearfix"></div>
<br/>
<a href="<?= _URL_ADMIN_ ?>lastUpload.php" class="btn btn-success">
<span class="bi-file-earmark-image"></span>
&nbsp;Derniers fichiers envoyés
</a>
<div class="clearfix"></div>
<br/>
<a href="<?= _URL_ADMIN_ ?>nsfwjs.php" class="btn btn-success">
<span class="bi-file-earmark-bar-graph"></span>
&nbsp;IA - Catégorisation nsfwjs
</a>
<div class="clearfix"></div>
<br/>
<a href="<?= _URL_ADMIN_ ?>abuse-network.php" class="btn btn-success">
<span class="bi-cpu"></span>
&nbsp;Réseaux suspects
</a>
<div class="clearfix"></div>
<br/>
<a href="<?= _URL_ADMIN_ ?>validate.php" class="btn btn-success">
<span class="bi-cloud-check"></span>
&nbsp;Vérifier la configuration
</a>
<div class="clearfix"></div>
<br/>
<a href="<?= _URL_ADMIN_ ?>cleanFilesNeverUsed.php" class="btn btn-warning">
<span class="bi-file-earmark-x"></span>
&nbsp;Supprimer les images jamais affichées et envoyées depuis plus de <?= _DELAI_EFFACEMENT_IMAGES_JAMAIS_AFFICHEES_ ?> jour<?= (_DELAI_EFFACEMENT_IMAGES_JAMAIS_AFFICHEES_ > 1) ? 's' : '' ?>
</a>
<div class="clearfix"></div>
<br/>
<a href="<?= _URL_ADMIN_ ?>cleanInactiveFiles.php" class="btn btn-warning">
<span class="bi-file-earmark-x-fill"></span>
&nbsp;Supprimer les images non affichées depuis plus de <?= _DELAI_INACTIVITE_AVANT_EFFACEMENT_IMAGES_ ?> jour<?= (_DELAI_INACTIVITE_AVANT_EFFACEMENT_IMAGES_ > 1) ? 's' : '' ?>
</a>
<div class="clearfix"></div>
<br/>
<a href="<?= _URL_ADMIN_ ?>cleanAccountsNeverUsed.php" class="btn btn-warning">
<span class="bi-person-x"></span>
&nbsp;Supprimer les comptes créés il y a plus de <?= _DELAI_EFFACEMENT_COMPTES_JAMAIS_UTILISES_ ?> jour<?= (_DELAI_EFFACEMENT_COMPTES_JAMAIS_UTILISES_ > 1) ? 's' : '' ?> et sans images associées
</a>
</div>
</div>
<div class="panel-body">
<a href="<?= _URL_ADMIN_ ?>listeFichiers.php" class="btn btn-default">
<span class="glyphicon glyphicon-list-alt"></span>
&nbsp;
Lister les fichiers présents sur le disque
</a>
<div class="clearfix"></div>
<br />
<a href="<?= _URL_ADMIN_ ?>cleanNeverUsedOneYear.php" class="btn btn-danger">
<span class="glyphicon glyphicon-trash"></span>
&nbsp;
Fichiers non affichés et envoi > 1 an
</a>
<div class="clearfix"></div>
<br />
<a href="<?= _URL_ADMIN_ ?>cleanUnusedThreeYears.php" class="btn btn-danger">
<span class="glyphicon glyphicon-flash"></span>
&nbsp;
Fichiers dernier affichage > 3 ans
</a>
<div class="clearfix"></div>
<br />
<a href="<?= _URL_ADMIN_ ?>cleanErrors.php" class="btn btn-warning">
<span class="glyphicon glyphicon-check"></span>
&nbsp;
Vérifier la cohérence disque / BDD
</a>
<div class="clearfix"></div>
<br />
<a href="<?= _URL_ADMIN_ ?>referer.php" class="btn btn-default">
<span class="glyphicon glyphicon-check"></span>
&nbsp;
Afficher les referer
</a>
<div class="card">
<div class="card-header">
Gestion technique
</div>
<div class="card-body">
<a href="<?= _URL_ADMIN_ ?>listeFichiers.php" class="btn btn-default">
<span class="bi-list-check"></span>
&nbsp;
Lister les fichiers présents sur le disque
</a>
<div class="clearfix"></div>
<br/>
<a href="<?= _URL_ADMIN_ ?>cleanErrors.php" class="btn btn-default">
<span class="bi-database-fill-check"></span>
&nbsp;
Vérifier la cohérence disque et BDD
</a>
</div>
</div>
</div>
<?php require _TPL_BOTTOM_ ?>
<?php require _TPL_BOTTOM_ ?>

134
admin/lastUpload.php Normal file
View file

@ -0,0 +1,134 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
use ArrayObject;
if (!defined('_PHPUNIT_')) {
require '../config/config.php';
}
// Vérification des droits d'accès
UtilisateurObject::checkAccess(UtilisateurObject::LEVEL_ADMIN);
require _TPL_TOP_;
?>
<h1 class="mb-3"><small>Derniers fichiers envoyés</small></h1>
<?php
$message = '';
$table = [
'legende' => 'trouvée##',
'values' => new ArrayObject(),
];
// Action à effectuer sur une image
if (isset($_GET['idImage']) && is_numeric($_GET['idImage'])) {
$monImage = new ImageObject($_GET['idImage'], RessourceObject::SEARCH_BY_ID);
if (isset($_GET['bloquer'])) {
// Blocage de l'image
$monImage->bloquer();
$message .= 'Image ' . $monImage->getNomNouveau() . ' bloquée !';
} elseif (isset($_GET['approuver'])) {
// Approbation de l'image
$monImage->approuver();
$message .= 'Image ' . $monImage->getNomNouveau() . ' approuvée !';
}
} else {
/**
* Images à traiter
*/
$idStart = 0;
if (!empty($_GET['nextId']) && preg_match('#^[0-9]+$#', $_GET['nextId'])) {
$idStart = (int)$_GET['nextId'];
}
$req = 'SELECT MAX(new_name) as new_name FROM images' . ($idStart !== 0 ? ' WHERE id < ' . $idStart : '') . ' GROUP BY md5 ORDER BY date_action DESC LIMIT 50';
$table['values'] = HelperAdmin::queryOnNewName($req);
}
$isPlural = false;
if (count($table['values']) > 1) {
$isPlural = true;
}
$lastId = '';
// Charger les objets concernés
$mesImages = ImageObject::chargerMultiple($table['values'], RessourceObject::SEARCH_BY_NAME, false);
?>
<?php if (!empty($message)) : ?>
<div class="alert alert-success">
<?= $message ?>
</div>
<?php endif; ?>
<div class="card">
<div class="card-header">
<?= count($table['values']) ?> image<?= ($isPlural ? 's' : '') . ' ' . str_replace('##', ($isPlural ? 's' : ''), $table['legende']) ?>
</div>
<div class="card-body">
<table class="table">
<thead>
<tr>
<th>Image</th>
<th>Actions</th>
<th class="text-break">Nom originel</th>
<th class="text-break">Date d'envoi</th>
<th class="text-break">IP envoi</th>
<th class="text-break">Nb vues</th>
<th class="text-break">Dernier affichage</th>
<th class="text-break">Utilisateur</th>
</tr>
</thead>
<tbody>
<?php foreach ($mesImages as $uneImage) : ?>
<tr>
<td>
<?= (($uneImage->isSuspecte() || $uneImage->isSignalee()) && !$uneImage->isBloquee() && !$uneImage->isApprouvee() ? '<span class="bi-exclamation-square-fill" style="color:red;"></span>' : '') ?>
<?php if (!$uneImage->isApprouvee()): ?>
<?php if ($uneImage->getNbViewPerDay() >= _ABUSE_NB_AFFICHAGES_PAR_JOUR_BLOCAGE_AUTO_): ?>
<span class="bi-exclamation-diamond" style="color: orange"></span>
<?php elseif ($uneImage->getNbViewPerDay() >= _ABUSE_NB_AFFICHAGES_PAR_JOUR_WARNING_): ?>
<span class="bi-exclamation-circle" style="color: lightblue"></span>
<?php endif; ?>
<?php endif; ?>
<a href="<?= $uneImage->getURL(true) ?>?forceDisplay=1" target="_blank" style="<?= ($uneImage->isBloquee() ? 'text-decoration: line-through double red;' : '') ?><?= ($uneImage->isApprouvee() ? 'text-decoration: underline double green;' : '') ?>"><?= $uneImage->getNomNouveau() ?></a></td>
<td>
<a href="<?= _URL_ADMIN_ ?>lastUpload.php?approuver=1&idImage=<?= $uneImage->getId() . ($idStart !== 0 ? '&nextId=' . $idStart : "") ?>" title="Approuver"><span class="bi-hand-thumbs-up-fill" style="color: green"></span></a>
<a href="<?= _URL_ADMIN_ ?>lastUpload.php?bloquer=1&idImage=<?= $uneImage->getId() . ($idStart !== 0 ? '&nextId=' . $idStart : "") ?>" title="Bloquer"><span class="bi-hand-thumbs-down-fill" style="color: red"></span></a>
</td>
<td class="text-break"><?= $uneImage->getNomOriginalFormate() ?></td>
<td class="text-break"><?= $uneImage->getDateEnvoiFormatee() ?></td>
<td class="text-break"><?= $uneImage->getIpEnvoi() ?></td>
<td><?= $uneImage->getNbViewTotal() ?><small> (<?= $uneImage->getNbViewPerDay() ?>/jour)</small></td>
<td class="text-break"><?= $uneImage->getLastViewFormate() ?></td>
<td class="text-break"><?= $uneImage->getIdProprietaire() ?></td>
</tr>
<?php $lastId = $uneImage->getId() ?>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr>
<th>
<a href="<?= _URL_ADMIN_ ?>lastUpload.php?nextId=<?= $lastId ?>" class="btn btn-primary"><span class="bi-arrow-left"></span> </a>
</th>
</tr>
</tfoot>
</table>
</div>
</div>
<?php require _TPL_BOTTOM_; ?>

View file

@ -1,6 +1,7 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
@ -17,40 +18,44 @@
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
require '../config/configV2.php';
namespace ImageHeberg;
require '../config/config.php';
// Vérification des droits d'accès
metaObject::checkUserAccess(utilisateurObject::levelAdmin);
UtilisateurObject::checkAccess(UtilisateurObject::LEVEL_ADMIN);
require _TPL_TOP_;
?>
<h1><small>Images présentes sur le disque</small></h1>
<ul>
<?php
<h1 class="mb-3"><small>Images présentes sur le disque</small></h1>
<ul>
<?php
/**
* Scan récursif
* @param string $path
* @return string
*/
function getScandirRecursif($path) {
$monRetour = '<ul>';
/**
* Scan récursif
* @param string $path
* @return string
*/
function getScandirRecursif(string $path): string
{
$monRetour = '<ul>';
// Scanne le répertoire fourni
$scan_rep = scandir($path);
// Pour chaque item
foreach ($scan_rep as $item) {
if ($item !== '.' && $item !== '..') {
$monRetour .= '<li>' . $path . $item . '</li>';
if (is_dir($path . $item)) {
// Appel récursif
$monRetour .= getScandirRecursif($path . $item . '/');
}
}
}
$monRetour .= '</ul>';
return $monRetour;
}
// Scanne le répertoire fourni
$scan_rep = scandir($path);
// Pour chaque item
foreach ($scan_rep as $item) {
if ($item !== '.' && $item !== '..') {
$monRetour .= '<li>' . $path . $item . '</li>';
if (is_dir($path . $item)) {
// Appel récursif
$monRetour .= getScandirRecursif($path . $item . '/');
}
}
}
$monRetour .= '</ul>';
return $monRetour;
}
echo getScandirRecursif(_PATH_IMAGES_);
?>
</ul>
<?php require _TPL_BOTTOM_ ?>
echo getScandirRecursif(_PATH_IMAGES_);
?>
</ul>
<?php require _TPL_BOTTOM_ ?>

139
admin/nsfwjs.php Normal file
View file

@ -0,0 +1,139 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
if (!defined('_PHPUNIT_')) {
require '../config/config.php';
}
// Vérification des droits d'accès
UtilisateurObject::checkAccess(UtilisateurObject::LEVEL_ADMIN);
require _TPL_TOP_;
?>
<h1 class="mb-3"><small>NSFWJS</small></h1>
<?php
$message = '';
// Action à effectuer sur une image
if (isset($_GET['idImage']) && is_numeric($_GET['idImage'])) {
$monImage = new ImageObject($_GET['idImage'], RessourceObject::SEARCH_BY_ID);
if (isset($_GET['bloquer'])) {
// Blocage de l'image
$monImage->bloquer();
$message .= 'Image ' . $monImage->getNomNouveau() . ' bloquée !';
} elseif (isset($_GET['approuver'])) {
// Approbation de l'image
$monImage->approuver();
$message .= 'Image ' . $monImage->getNomNouveau() . ' approuvée !';
}
}
/**
* Images à traiter
*/
$idStart = 0;
if (!empty($_GET['nextId']) && is_numeric($_GET['nextId'])) {
$idStart = trim(str_replace('\'', '_', $_GET['nextId']));
}
$req = 'SELECT new_name FROM images' . ($idStart !== 0 ? ' WHERE id < ' . $idStart : '') . ' ORDER BY id DESC LIMIT 50';
$table = [
'legende' => 'trouvée##',
'values' => HelperAdmin::queryOnNewName($req)
];
// Charger les objets concernés
$mesImages = ImageObject::chargerMultiple($table['values'], RessourceObject::SEARCH_BY_NAME);
?>
<?php if (!empty($message)) : ?>
<div class="alert alert-success">
<?= $message ?>
</div>
<?php endif; ?>
<div class="card">
<div class="card-header">
<?= count($table['values']) ?> image<?= (count($table['values']) > 1 ? 's' : '') . ' ' . str_replace('##', (count($table['values']) > 1 ? 's' : ''), $table['legende']) ?>
</div>
<div class="card-body">
<table class="table">
<thead>
<tr>
<th>Image</th>
<th>Actions</th>
<th>Date d'envoi</th>
<th>Catégorisation IA nsfwjs</th>
</tr>
</thead>
<tbody id="tbody">
<?php foreach ($mesImages as $uneImage) : ?>
<tr>
<td><a href="<?= $uneImage->getURL(true) ?>?forceDisplay=1" target="_blank" style="<?= ($uneImage->isBloquee() ? 'text-decoration: line-through double red;' : '') . ($uneImage->isApprouvee() ? 'text-decoration: underline double green;' : '') ?>"><?= $uneImage->getNomNouveau() ?></a></td>
<td>
<a href="<?= _URL_ADMIN_ ?>lastUpload.php?approuver=1&idImage=<?= $uneImage->getId() ?>" title="Approuver"><span class="bi-hand-thumbs-up-fill" style="color: green"></span></a>
<a href="<?= _URL_ADMIN_ ?>lastUpload.php?bloquer=1&idImage=<?= $uneImage->getId() ?>" title="Bloquer"><span class="bi-hand-thumbs-down-fill" style="color: red"></span></a>
</td>
<td><?= $uneImage->getDateEnvoiFormatee() ?></td>
<td></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr>
<th>
<a href="<?= _URL_ADMIN_ ?>nsfwjs.php?nextId=<?= $uneImage->getId() ?>" class="btn btn-primary"><span class="bi-arrow-left"></span> </a>
</th>
</tr>
</tfoot>
</table>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/nsfwjs"></script>
<script type="module">
// Forcer le mode "Production" de tensorflow
tf.enableProdMode();
// Modèle récupéré de https://github.com/infinitered/nsfwjs/tree/master/example/nsfw_demo/public/quant_mid
const model = await nsfwjs.load('<?=_URL_ADMIN_ ?>nsfwjs_model_quant_mid/', {type: 'graph'});
// On itère sur le tableau HTML
let tabTr = Array.from(document.getElementById("tbody").children);
for (const unTr of tabTr) {
let img = new Image();
// Lien vers l'image
img.src = unTr.children[0].children[0].href;
console.log(img.src);
// Attendre que la ressource soit chargée
await img.decode();
// Classify the image -> une seule classification attendue en résultat
const predictions = await model.classify(img, 1);
console.log('Predictions: ', predictions);
// Résultats
let results = '';
for (let unType of predictions) {
results += unType.className + ' -> ' + Math.round(unType.probability * 100) + '%<br />';
}
// Injection de la valeur dans la page
unTr.children[3].innerHTML = results;
}
</script>
<?php require _TPL_BOTTOM_; ?>

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,59 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
require '../config/configV2.php';
// Vérification des droits d'accès
metaObject::checkUserAccess(utilisateurObject::levelAdmin);
require _TPL_TOP_;
?>
<h1><small>Page de provenance des visiteurs</small></h1>
<?php
// Je récupère la liste des referer
$listeReferer = metaObject::getReferers();
?>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<?= $listeReferer->count() ?> page(s) de provenance.
</h2>
</div>
<div class="panel-body">
<table class="table table-striped">
<thead>
<tr>
<td>URL</td>
<td>#</td>
</tr>
</thead>
<tbody>
<?php foreach ($listeReferer as $key => $value): ?>
<tr>
<td><?= $key ?></td>
<td><?= $value ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php
require _TPL_BOTTOM_;
?>

83
admin/validate.php Normal file
View file

@ -0,0 +1,83 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
require '../config/config.php';
// Vérification des droits d'accès
UtilisateurObject::checkAccess(UtilisateurObject::LEVEL_ADMIN);
require _TPL_TOP_;
?>
<h1 class="mb-3"><small>Vérification de la configuration du serveur</small></h1>
<div class="card">
<div class="card-header">
PHP
</div>
<div class="card-body">
<?= HelperSysteme::getPhpVersion() ?>
</div>
</div>
<div class="card">
<div class="card-header">
MySQL
</div>
<div class="card-body">
<?= HelperSysteme::getMysqlVersion() ?>
</div>
</div>
<div class="card">
<div class="card-header">
Imagick
</div>
<div class="card-body">
<?= HelperSysteme::getImagickVersion() ?>
</div>
</div>
<div class="card">
<div class="card-header">
Accès aux répertoires protégés par .htaccess .
</div>
<div class="card-body">
Les valeurs doivent être de type "HTTP/*.* 403 Forbidden".
<ul>
<li>Répertoire config : <?= HelperSysteme::getStatusHTTP(_URL_CONFIG_) ?></li>
<li>Répertoire admin : <?= HelperSysteme::getStatusHTTP(_URL_ADMIN_) ?></li>
<li>Répertoire membre : <?= HelperSysteme::getStatusHTTP(_URL_MEMBRE_) ?></li>
</ul>
</div>
</div>
<div class="card">
<div class="card-header">
Droits sur tous les dossiers dans files/
</div>
<div class="card-body">
<ul>
<?php
$lesDroits = HelperSysteme::isRecursivelyWritable(_PATH_IMAGES_);
foreach ((array)$lesDroits as $unItem) :
?>
<li><?= $unItem ?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<?php require _TPL_BOTTOM_; ?>

117
cgu.php
View file

@ -1,6 +1,7 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
@ -17,52 +18,82 @@
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
require 'config/configV2.php';
namespace ImageHeberg;
require 'config/config.php';
require _TPL_TOP_;
?>
<h1><small>Conditions Générales d'Utilisation</small></h1>
<h1 class="mb-3"><small>Conditions Générales d'Utilisation de <?= _SITE_NAME_ ?></small></h1>
<div class="alert alert-success">Ces CGU sont modifiables, sans pr&eacute;avis, et &agrave; tout moment.</div>
<div class="alert alert-success">Ces CGU sont modifiables sans préavis et à tout moment.</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">
<div class="card">
<div class="card-header">
Contenus autorisés
</h3>
</div>
<div class="panel-body">
<ul>
<li>Toutes images de type JPG, PNG, GIF.</li>
<li>Contenu conforme &agrave; la l&eacute;gislation fran&ccedil;aise.</li>
<li>Pornographie et &eacute;rotisme non autoris&eacute;s.</li>
</ul>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">
Propri&eacute;t&eacute;s de l'h&eacute;bergement
</h3>
</div>
<div class="panel-body">
<ul>
<li>Gratuit.</li>
<li>Traffic illimit&eacute; <em>(hors abus)</em>.</li>
<li><b>Conservation :</b>
<ul>
<li>Trois (3) ans à compter de la dernière utilisation du fichier.</li>
<li>A défaut, Un (1) an après l'envoi <em>(si aucun affichage)</em>.</li>
</ul>
</li>
<li>Nombre d'images par compte : illimit&eacute;.</li>
<li>Les fichiers restent votre propri&eacute;t&eacute;.</li>
<li>Aucune suppression sur demande d'un utilisateur. <em>(utilisez la fonction de suppression à l'envoi ou utilisez l'espace membre)</em></li>
<li>Toutes les donn&eacute;es poss&eacute;d&eacute;es seront fournies en cas de demande judiciaire.</li>
<li>Rappel : l'administrateur peut-avoir acc&egrave;s &agrave; toutes les donn&eacute;es du service.</li>
</ul>
<div class="panel-footer">
<em>Mise &agrave; jour le 24 janvier 2014 : éclaircissement sur les durées de conservation</em>
</div>
<div class="card-body">
<ul>
<li>Toutes images de type <?= strtoupper(implode(', ', _ACCEPTED_EXTENSIONS_)) ?>.</li>
<li>Contenus conformes à la législation française.</li>
<li>L'administrateur du site est seul juge de la conformité d'une image aux présentes CGU. En cas de désaccord, vous pouvez le contacter via <a href="/contact.php">le formulaire de contact</a>.</li>
</ul>
</div>
</div>
</div>
<?php require _TPL_BOTTOM_ ?>
<div class="card">
<div class="card-header">
Contenus non autorisés
</div>
<div class="card-body">
<ul>
<li>Contenus non conformes à la législation française.</li>
<li>Pornographie et érotisme.</li>
<li>Scènes de violence (cadavre, torture, maltraitance, image dégradante, ...) ou d'appel à la violence.</li>
<li>Pour information, les images peuvent être analysées par un composant d'IA dédié au service afin d'aider à leur vérification.</li>
</ul>
</div>
</div>
<div class="card">
<div class="card-header">
Propriétés de l'hébergement
</div>
<div class="card-body">
<ul>
<li>Gratuit.</li>
<li>Traffic illimité <em>(hors abus, auquel cas des limitations peuvent être mises en place)</em>.</li>
<li>
<b>Conservation :</b>
<ul>
<li>
<?= _DELAI_INACTIVITE_AVANT_EFFACEMENT_IMAGES_ ?> jour<?= _DELAI_INACTIVITE_AVANT_EFFACEMENT_IMAGES_ > 1 ? 's' : '' ?> à compter de la dernière utilisation du fichier.
</li>
<li>
A défaut, <?= _DELAI_EFFACEMENT_IMAGES_JAMAIS_AFFICHEES_ ?> jour<?= _DELAI_EFFACEMENT_IMAGES_JAMAIS_AFFICHEES_ > 1 ? 's' : '' ?> après l'envoi <em>(si aucun affichage)</em>.
</li>
</ul>
</li>
<li>
Nombre d'images par compte : illimité.
</li>
<li>
Les fichiers restent votre propriété.
</li>
<li>
Aucune suppression sur demande d'un utilisateur. <em>(utilisez la fonction de suppression à l'envoi ou utilisez <a href="membre/connexionCompte.php">l'espace membre)</a></em>
</li>
<li>
Toutes les données possédées seront fournies en cas de demande judiciaire ou de dépôt de plainte.
</li>
<li>
Suppression des comptes membres qui n'ont jamais été utilisés au bout de <?= _DELAI_EFFACEMENT_COMPTES_JAMAIS_UTILISES_ ?> jour<?= _DELAI_EFFACEMENT_COMPTES_JAMAIS_UTILISES_ > 1 ? 's' : '' ?>.
</li>
<li>
Rappel : <a href="contact.php">l'administrateur (<?= _ADMINISTRATEUR_NOM_ ?>)</a> a accès à toutes les données du service.
</li>
</ul>
<div class="card-footer">
<em>Mises à jour le 02 janvier 2024 : ajout de précisions sur les images non autorisées + module de catégorisation IA.</em>
</div>
</div>
</div>
<?php require _TPL_BOTTOM_ ?>

View file

@ -1,6 +1,7 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
@ -17,213 +18,338 @@
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
require 'config/configV2.php';
namespace ImageHeberg;
require 'config/config.php';
require _TPL_TOP_;
?>
<h1><small>Historique des versions</small></h1>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#v21">
v2.1 - en cours
&nbsp;<span class="caret"></span>
<h1 class="mb-3"><small>Historique des versions</small></h1>
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v2x">
v2.x - A venir
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</h2>
</div>
<div id="v21" class="panel-collapse">
<div class="panel-body">
<ul>
<li>Migration jQuery 2 => 3</li>
<li>Migration bootstrap 3 => 4</li>
<li>Sélection uniquement des images lors du choix du fichier sur l'ordinateur</li>
<li>Envoi de plusieurs images simultanément</li>
<li>Glisser - déposer pour le choix des fichiers</li>
<li>API permettant l'intégration à un site tiers</li>
<li>Membres : Albums photos (création, affichage, partage)</li>
<li>Membres : Permettre la connexion longue durée sur un ordinateur</li>
<li>Membres : Permettre le changement de mot de passe</li>
<li>Membres : Permettre de définir une valeur par défaut pour les paramètres des images à l'envoi</li>
<li>Membres : Afficher les lines de partage dans l'espace membre</li>
<li>Expliquer les avantages pour les personnes inscrites sur le site</li>
<li>Meilleure gestion des statistiques d'affichage (trop d'appels à la base de données)</li>
</ul>
</div>
<div id="v2x" class="card-collapse">
<div class="card-body">
<ul>
<li>Envoi de plusieurs images simultanément.</li>
<li>Glisser - déposer pour le choix des fichiers.</li>
<li>Membres : Albums photos (création, affichage, partage).</li>
<li>Membres : Permettre de définir une valeur par défaut pour les paramètres des images à l'envoi.</li>
<li>Membres : Afficher les liens de partage dans l'espace membre.</li>
</ul>
</div>
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#v201">
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v25">
v2.5 - Janvier 2024
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</div>
<div id="v25" class="card-collapse">
<div class="card-body">
<ul>
<li>Prise en charge du format WEBP.</li>
<li>Blocage d'accès au site pour les personnes ayant envoyé trop d'images qui ont été bloquées.</li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v24">
v2.4 - Décembre 2023
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</div>
<div id="v24" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Espace admin : renforcement des systèmes anti-abus.</li>
<li>Meilleure gestion des GIF animés.</li>
<li>Classification des images via IA avec nsfwjs.</li>
<li>Amélioration des performances des requêtes dans la base de données.</li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v23">
v2.3 - Août 2023
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</div>
<div id="v23" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Espace admin : ajout d'une interface pour gérer les abus.</li>
<li>Renforcement des systèmes anti-abus.</li>
<li>Migration bootstrap 5.1 -> 5.3</li>
<li>Migration fontawesome -> bootstrap icons</li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v22">
v2.2 - Décembre 2021
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</div>
<div id="v22" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Espace membre : ajout des miniatures des images possédées.</li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v21">
v2.1 - Février 2021
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</div>
<div id="v21" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Migration bootstrap 4 -> 5.</li>
<li>Suppression de jQuery.</li>
<li>Sélection uniquement des images lors du choix du fichier sur l'ordinateur.</li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v205">
v2.0.5 - 2020
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</div>
<div id="v205" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Migration bootstrap 3 -> 4.</li>
<li>Utilisation de FontAwesome.</li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v204">
v2.0.4 - Octobre 2019
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</div>
<div id="v204" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Améliorations techniques de l'outil pour les maintenances futures.</li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v203">
v2.0.3 - Octobre 2019
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</div>
<div id="v203" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Améliorations techniques pour MySQL 5.7.</li>
<li>Améliorations techniques pour PHP7.</li>
<li>Ajout d'un outil de validation de l'installation.</li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v202">
v2.0.2 - Janvier 2019
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</div>
<div id="v202" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Correction d'une erreur à l'effacement des images.</li>
<li>Migration jQuery 2 => 3</li>
<li>Suppression de la liste des referer <em>(optimisation des affichages d'images)</em>.</li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v201">
v2.0.1 - Juin 2018
&nbsp;<span class="caret"></span>
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</h2>
</div>
<div id="v201" class="panel-collapse">
<div class="panel-body">
<ul>
<li>Ajout d'une liste des referer</li>
</ul>
</div>
<div id="v201" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Ajout d'une liste des referer</li>
<li>Gestion dynamique des délais avant suppression des fichiers inactifs</li>
</ul>
</div>
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#v20">
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v20">
v2.0 - Novembre 2016
&nbsp;<span class="caret"></span>
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</h2>
</div>
<div id="v20" class="panel-collapse collapse">
<div class="panel-body">
<ul>
<li>Réactivation de l'ensemble des fonctionnalités du site (miniatures, retournement, ...)</li>
<li>Modèle orienté objet pour une meilleure évolutivité sur le long terme</li>
<li>Nouveau thème graphique</li>
<li>Admin : Refonte de l'administration</li>
<li>Admin : création de fonctions pour nettoyer les images oboslètes</li>
<li>Reprise du schéma de la BDD</li>
<li>Mise en place de tests automatisés sur l'ensemble des fonctionnalités du site</li>
</ul>
</div>
<div id="v20" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Réactivation de l'ensemble des fonctionnalités du site (miniatures, retournement, ...)</li>
<li>Modèle orienté objet pour une meilleure évolutivité sur le long terme</li>
<li>Nouveau thème graphique</li>
<li>Admin : Refonte de l'administration</li>
<li>Admin : création de fonctions pour nettoyer les images obsolètes</li>
<li>Reprise du schéma de la BDD</li>
<li>Mise en place de tests automatisés sur l'ensemble des fonctionnalités du site</li>
</ul>
</div>
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#v19">
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v19">
v1.9 - Janvier 2014
&nbsp;<span class="caret"></span>
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</h2>
</div>
<div id="v19" class="panel-collapse collapse">
<div class="panel-body">
<ul>
<li>Passage à la programation objet</li>
<li>Reprise, factorisation et optimisation globale du site</li>
</ul>
</div>
<div id="v19" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Passage à la programation objet</li>
<li>Reprise, factorisation et optimisation globale du site</li>
</ul>
</div>
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#v127">
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v127">
v1.2.7 - 26 avril 2012
&nbsp;<span class="caret"></span>
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</h2>
</div>
<div id="v127" class="panel-collapse collapse">
<div class="panel-body">
<ul>
<li>Remise en place des options miniatures, rotation et redimensionnement</li>
<li>Corrections de charset sur des messages d'erreur</li>
<li>Amélioration de la protection anti-flood</li>
</ul>
</div>
<div id="v127" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Remise en place des options miniatures, rotation et redimensionnement</li>
<li>Corrections de charset sur des messages d'erreur</li>
<li>Amélioration de la protection anti-flood</li>
</ul>
</div>
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#v126">
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v126">
v1.2.6 - 9 janvier 2012
&nbsp;<span class="caret"></span>
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</h2>
</div>
<div id="v126" class="panel-collapse collapse">
<div class="panel-body">
<ul>
<li>Changement de serveur internet (la vitesse d'affichage est meilleure + connectivité IPv6 !)</li>
<li>Changement d'encodage par défaut pour les pages et le code HTML <em>(passage en UTF-8)</em></li>
<li>Gestion de l'IPv6 dans la BDD et les statistiques</li>
<li>Sélection du contenu des champs contenants l'url de l'image au clic</li>
<li>Amélioration du code HTML</li>
<li>Refonte des CSS</li>
<li>Préparation d'un système de templates</li>
<li>Utilisation de jQuery : (box en haut de page, options cachées par défaut à l'envoi d'un fichier)</li>
</ul>
</div>
<div id="v126" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Changement de serveur internet (la vitesse d'affichage est meilleure + connectivité IPv6 !)</li>
<li>Changement d'encodage par défaut pour les pages et le code HTML <em>(passage en UTF-8)</em></li>
<li>Gestion de l'IPv6 dans la BDD et les statistiques</li>
<li>Sélection du contenu des champs contenants l'url de l'image au clic</li>
<li>Amélioration du code HTML</li>
<li>Refonte des CSS</li>
<li>Préparation d'un système de templates</li>
<li>Utilisation de jQuery : box en haut de page, options cachées par défaut à l'envoi d'un fichier</li>
</ul>
</div>
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#v125">
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v125">
v1.2.5 - 30 octobre 2011
&nbsp;<span class="caret"></span>
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</h2>
</div>
<div id="v125" class="panel-collapse collapse">
<div class="panel-body">
<ul>
<li>Suppression de la limite des dimensions d'images pour les utilisateurs enregistrés</li>
<li>Ajout d'une fonction permettant le blocage d'images précises + affichage d'une image d'information sur le blocage</li>
</ul>
</div>
<div id="v125" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Suppression de la limite des dimensions d'images pour les utilisateurs enregistrés</li>
<li>Ajout d'une fonction de blocage d'images + affichage d'une image d'information sur le blocage</li>
</ul>
</div>
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#v124">
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v124">
v1.2.4 - 08 septembre 2011
&nbsp;<span class="caret"></span>
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</h2>
</div>
<div id="v124" class="panel-collapse collapse">
<div class="panel-body">
<ul>
<li>Meilleure gestion des images inexistantes (erreurs 404)</li>
</ul>
</div>
<div id="v124" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Meilleure gestion des images inexistantes (erreurs 404)</li>
</ul>
</div>
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#v123e">
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v123e">
v1.2.3.e - 14 août 2011
&nbsp;<span class="caret"></span>
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</h2>
</div>
<div id="v123e" class="panel-collapse collapse">
<div class="panel-body">
<ul>
<li>Administration : suivi des requêtes SQL amélioré</li>
<li>Finalisation de l'encodage des caractères spéciaux conformément à la norme HTML.</li>
<li>Optimisation de la lisibilité du code source.</li>
<li>Optimisation du temps d'éxecution du code PHP.</li>
</ul>
</div>
<div id="v123e" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Administration : suivi des requêtes SQL amélioré</li>
<li>Finalisation de l'encodage des caractères spéciaux conformément à la norme HTML.</li>
<li>Optimisation de la lisibilité du code source.</li>
<li>Optimisation du temps d'éxecution du code PHP.</li>
</ul>
</div>
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#v123d">
<div class="card">
<div class="card-header">
<a data-bs-toggle="collapse" href="#v123d">
v1.2.3.d - 10 août 2011
&nbsp;<span class="caret"></span>
&nbsp;<span class="bi-caret-down-fill"></span>
</a>
</h2>
</div>
<div id="v123d" class="panel-collapse collapse">
<div class="panel-body">
<ul>
<li>Création du changelog.</li>
<li>Encodage conforme à la norme HTML des caractères spéciaux.</li>
<li>Correction d'une erreur PHP en cas d'envoi 'hack' de fichier.</li>
<li>Amélioration de la portée des variables de language.</li>
</ul>
</div>
<div id="v123d" class="card-collapse collapse">
<div class="card-body">
<ul>
<li>Création du changelog.</li>
<li>Encodage conforme à la norme HTML des caractères spéciaux.</li>
<li>Correction d'une erreur PHP en cas d'envoi 'hack' de fichier.</li>
<li>Amélioration de la portée des variables de language.</li>
</ul>
</div>
</div>
</div>
</div>
<?php require _TPL_BOTTOM_ ?>
<?php require _TPL_BOTTOM_ ?>

54
classes/HelperAbuse.php Normal file
View file

@ -0,0 +1,54 @@
<?php
namespace ImageHeberg;
class HelperAbuse
{
/**
* Retourne le nombre d'images bloquées issues du même réseau IP
* @param string $remote_addr Adresse IP à tester
* @return int
*/
public static function checkIpReputation(string $remote_addr): int
{
$monRetour = 0;
// IPv4 - Filtrer sur un /24 || IPv6 - Filtrer sur un /56
$req = MaBDD::getInstance()->prepare(
'SELECT COUNT(*) AS nb
FROM images
WHERE isBloquee = 1
AND abuse_network = (
IF(LOCATE(\'.\', :remote_addr) != 0,
SUBSTRING(:remote_addr, 1, (LENGTH(:remote_addr) - LOCATE(\'.\', REVERSE(:remote_addr)))),
SUBSTRING(HEX(INET6_ATON(:remote_addr)), 1, 14)
)
)'
);
$req->bindValue(':remote_addr', $remote_addr);
$req->execute();
$resultat = $req->fetch();
if ($resultat !== false) {
$monRetour = (int)$resultat->nb;
}
return $monRetour;
}
/**
* Mettre à jour la réputation des adresses IP en base
* @return void
*/
public static function updateIpReputation(): void
{
// Compléter les données "abuse_network" (normalement déjà fait dans ImageObject::creer())
// IPv4 - Filtrer sur un /24 || IPv6 - Filtrer sur un /56
$req = 'UPDATE images SET abuse_network =
IF(LOCATE(\'.\', remote_addr) != 0,
SUBSTRING(remote_addr, 1, (LENGTH(remote_addr) - LOCATE(\'.\', REVERSE(remote_addr)))),
SUBSTRING(HEX(INET6_ATON(remote_addr)), 1, 14)
)
WHERE abuse_network = \'\'';
MaBDD::getInstance()->query($req);
}
}

404
classes/HelperAdmin.php Normal file
View file

@ -0,0 +1,404 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
use ArrayObject;
/**
* Bibliothèque d'outils pour la gestion du site en tant qu'admin
*/
abstract class HelperAdmin
{
/**
* Liste des images n'ayant jamais été affichées et présentes sur le serveur depuis xx temps
* @return ArrayObject
*/
public static function getNeverUsedFiles(): ArrayObject
{
// Toutes les images jamais affichées & envoyées il y a plus de xx jours
$req = 'SELECT im.new_name
FROM images im
WHERE im.last_view = \'0000-00-00\'
AND im.date_action < DATE_SUB(CURRENT_DATE(), INTERVAL ' . _DELAI_EFFACEMENT_IMAGES_JAMAIS_AFFICHEES_ . ' DAY)
/* Préservation des fichiers des membres */
AND 0 = (
SELECT COUNT(*)
FROM possede po
WHERE po.images_id = im.id
)
/* Préservation si miniature affichée */
AND 0 = (
SELECT COUNT(*)
FROM thumbnails th
WHERE th.images_id = im.id
AND th.last_view <> \'0000-00-00\'
)';
return self::queryOnNewName($req);
}
/**
* Liste des images plus utilisées depuis au moins xx jours
* @return ArrayObject
*/
public static function getUnusedFiles(): ArrayObject
{
// Toutes les images non affichées depuis xx jours
$req = 'SELECT im.new_name
FROM images im
WHERE im.last_view < DATE_SUB(CURRENT_DATE(), INTERVAL ' . _DELAI_INACTIVITE_AVANT_EFFACEMENT_IMAGES_ . ' DAY)
/* Non prise en compte des images jamais affichées */
AND im.last_view <> \'0000-00-00\'
/* Préservation des images membres */
AND 0 = (
SELECT COUNT(*)
FROM possede po
WHERE po.images_id = im.id
)
/* Préservation si miniature affichée */
AND 0 = (
SELECT COUNT(*)
FROM thumbnails th
WHERE th.images_id = im.id
AND th.last_view > DATE_SUB(CURRENT_DATE(), INTERVAL ' . _DELAI_INACTIVITE_AVANT_EFFACEMENT_IMAGES_ . ' DAY)
)';
return self::queryOnNewName($req);
}
/**
* Liste des comptes sans images et créés depuis au moins xx jours
* @return ArrayObject
*/
public static function getUnusedAccounts(): ArrayObject
{
// Effacer les logs de connexion > 1 an
$req = 'DELETE
FROM login
WHERE date_action < (NOW() - INTERVAL 1 YEAR)';
MaBDD::getInstance()->query($req);
// Toutes les comptes créés et jamais utilisés depuis xx jours
$req = 'SELECT m.id
FROM membres m
WHERE m.date_action < DATE_SUB(CURRENT_DATE(), INTERVAL ' . _DELAI_EFFACEMENT_COMPTES_JAMAIS_UTILISES_ . ' DAY)
/* Préservation des comptes possédant des images */
AND 0 = (
SELECT COUNT(*)
FROM possede po
WHERE po.membres_id = m.id
)';
// Exécution de la requête
$resultat = MaBDD::getInstance()->query($req);
$monRetour = new ArrayObject();
// Pour chaque résultat retourné
foreach ($resultat->fetchAll() as $value) {
// J'ajoute l'ID du compte
$monRetour->append($value->id);
}
return $monRetour;
}
/**
* Liste de l'ensemble des images en BDD
* @return ArrayObject
*/
public static function getAllImagesNameBDD(): ArrayObject
{
// Toutes les images (sauf 404 & banned)
$req = 'SELECT md5 FROM images WHERE id > 2';
// Exécution de la requête
$resultat = MaBDD::getInstance()->query($req);
$monRetour = new ArrayObject();
// Pour chaque résultat retourné
foreach ($resultat->fetchAll() as $value) {
// J'ajoute le nom de l'image
$monRetour->append($value->md5);
}
return $monRetour;
}
/**
* Liste de l'ensemble des images en HDD
* @param string $path path à analyser
* @return ArrayObject
*/
public static function getAllImagesNameHDD(string $path): ArrayObject
{
$monRetour = new ArrayObject();
// Scanne le répertoire des images
$scan_rep = scandir($path);
// Pour chaque item
foreach ($scan_rep as $item) {
if (!in_array($item, ['.', '..', '_dummy', 'z_cache'])) {
if (is_dir($path . $item)) {
// Appel récursif
if ($path . $item . '/' !== _PATH_MINIATURES_) {
$monRetourTmp = self::getAllImagesNameHDD($path . $item . '/');
// Parsage et récupération des sous fichiers...
foreach ($monRetourTmp as $fichier) {
$monRetour->append($fichier);
}
}
} elseif ($item !== _IMAGE_404_ && $item !== _IMAGE_BAN_) {
$monRetour->append($item);
}
}
}
return $monRetour;
}
/**
* Liste de l'ensemble des miniatures en BDD
*/
public static function getAllMiniaturesNameBDD(): ArrayObject
{
// Toutes les images
$req = 'SELECT md5 FROM thumbnails';
// Exécution de la requête
$resultat = MaBDD::getInstance()->query($req);
$monRetour = new ArrayObject();
// Pour chaque résultat retourné
foreach ($resultat->fetchAll() as $value) {
// J'ajoute le nom de l'image
$monRetour->append($value->md5);
}
return $monRetour;
}
/**
* Toutes les images avec un même MD5
* @param string $unMd5
* @return ArrayObject
*/
public static function getImageByMd5(string $unMd5): ArrayObject
{
// Images avec le même MD5
$req = MaBDD::getInstance()->prepare('SELECT new_name FROM images WHERE md5 = :md5');
$req->bindValue(':md5', $unMd5);
$req->execute();
$monRetour = new ArrayObject();
// Pour chaque résultat retourné
foreach ($req->fetchAll() as $value) {
// J'ajoute le nom de l'image
$monRetour->append($value->new_name);
}
return $monRetour;
}
/**
* Toutes les images signalées
* @return ArrayObject
*/
public static function getImagesSignalees(): ArrayObject
{
// Images signalées
$req = 'SELECT new_name FROM images WHERE isSignalee = 1 and isBloquee = 0';
return self::queryOnNewName($req);
}
/**
* Images dont les statistiques d'affichage sont incohérentes
* @param int $nbMax Nb affichage / jour à partir duquel on veut les images
* @param bool $onlyOnImagesSuspectes Filtrer sur les images suspectes ?
* @param bool $useProjection Projeter l'utilisation actuelle de l'image (potentialité de dépassement de limite ultérieur)
* @param bool $includeApproved Inclure les images approuvées (ou signalées) ?
* @return ArrayObject
*/
public static function getImagesTropAffichees(int $nbMax, bool $onlyOnImagesSuspectes = false, bool $useProjection = false, bool $includeApproved = false): ArrayObject
{
if ($onlyOnImagesSuspectes) {
$tabNewName = [];
foreach ((array)self::getImagesPotentiellementIndesirables() as $newName) {
$tabNewName[] = '\'' . str_replace('\'', '', $newName) . '\'';
}
if (empty($tabNewName)) {
// Mettre un placeholder vide
$listeImagesForIn = '\'\'';
} else {
$listeImagesForIn = implode(',', $tabNewName);
}
}
// Images avec trop d'affichages
if ($useProjection) {
// Ne prendre que les images qui sont présentes depuis plus d'une heure pour limiter les faux positifs
$req = 'SELECT im.new_name, ( ( im.nb_view_v4 + im.nb_view_v6 + (SELECT IFNULL(SUM(th.nb_view_v4 + th.nb_view_v6), 0) FROM thumbnails th where th.images_id = im.id) ) / IF(im.date_action < (NOW() - INTERVAL 1 HOUR), ( UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(im.date_action) ), -1) ) * (60 * 60 * 24 ) as nbViewPerDay';
} else {
$req = 'SELECT im.new_name, ( im.nb_view_v4 + im.nb_view_v6 + (SELECT IFNULL(SUM(th.nb_view_v4 + th.nb_view_v6), 0) FROM thumbnails th where th.images_id = im.id) ) / IF(DATEDIFF(NOW(), im.date_action) > 0, DATEDIFF(NOW(), im.date_action), 1) as nbViewPerDay';
}
$req .= ' FROM images im
WHERE im.isBloquee = 0';
if (!$includeApproved) {
$req .= ' AND im.isSignalee = 0
AND im.isApprouvee = 0';
}
// Filter sur certaines images
if ($onlyOnImagesSuspectes) {
$req .= ' AND im.new_name IN (' . $listeImagesForIn . ')';
}
$req .= ' HAVING nbViewPerDay > ' . $nbMax . '
ORDER BY nbViewPerDay DESC';
return self::queryOnNewName($req);
}
/**
* Images dont les données sont proches d'images déjà bloquées
* @return ArrayObject
*/
public static function getImagesPotentiellementIndesirables(): ArrayObject
{
// Compléter les données "abuse_network" (normalement déjà fait dans ImageObject::creer())
HelperAbuse::updateIpReputation();
// Images potentiellement indésirables
$req = 'SELECT new_name FROM (
SELECT im.new_name, ((nb_view_v4 + nb_view_v6) / DATEDIFF(NOW(), im.date_action)) AS nbAff
FROM images im
LEFT JOIN possede po ON po.images_id = im.id
WHERE im.isBloquee = 0
AND im.isApprouvee = 0
AND im.isSignalee = 0
AND (
/* Même réseau IP */
im.abuse_network IN (SELECT DISTINCT abuse_network FROM images WHERE isBloquee = 1)
OR (
/* Même propriétaire */
po.membres_id IS NOT NULL
AND
po.membres_id IN (SELECT DISTINCT membres_id FROM possede WHERE images_id IN (SELECT id FROM images WHERE isBloquee = 1))
)
OR (
/* Même MD5 */
im.md5 IN (SELECT DISTINCT md5 FROM images WHERE isBloquee = 1)
)
)
ORDER BY nbAff DESC, im.id DESC
) tableTmp
LIMIT 0, 100';
return self::queryOnNewName($req);
}
/**
* Images dont les données sont proches d'images déjà approuvées
* @return ArrayObject
*/
public static function getImagesPotentiellementApprouvables(): ArrayObject
{
// Compléter les données "abuse_network" (normalement déjà fait dans ImageObject::creer())
HelperAbuse::updateIpReputation();
// Images potentiellement approuvables
$req = 'SELECT new_name FROM (
SELECT im.new_name, ((nb_view_v4 + nb_view_v6) / DATEDIFF(NOW(), im.date_action)) AS nbAff
FROM images im
LEFT JOIN possede po ON po.images_id = im.id
WHERE im.isBloquee = 0
AND im.isApprouvee = 0
AND im.isSignalee = 0
AND (
/* Même réseau IP */
im.abuse_network IN (SELECT DISTINCT abuse_network FROM images WHERE isApprouvee = 1)
OR (
/* Même propriétaire */
po.membres_id IS NOT NULL
AND
po.membres_id IN (SELECT DISTINCT membres_id FROM possede WHERE images_id IN (SELECT id FROM images WHERE isApprouvee = 1))
)
OR (
/* Même MD5 */
im.md5 IN (SELECT DISTINCT md5 FROM images WHERE isApprouvee = 1)
)
/*OR (
/* Même nom originel * /
im.old_name IN (SELECT DISTINCT old_name FROM images WHERE isApprouvee = 1)
)*/
)
HAVING nbAff > ' . (_ABUSE_NB_AFFICHAGES_PAR_JOUR_WARNING_ / 2) . '
ORDER BY nbAff DESC, im.id DESC
) tableTmp
LIMIT 0, 25';
return self::queryOnNewName($req);
}
/**
* Liste des réseaux avec mauvaise réputation
* @return ArrayObject ["IP" => "count()"]
*/
public static function getBadNetworks(): ArrayObject
{
$monRetour = new ArrayObject();
$req = 'SELECT COUNT(*) AS nb, abuse_network FROM images WHERE isBloquee = 1 GROUP BY abuse_network';
// Exécution de la requête
$resultat = MaBDD::getInstance()->query($req);
// Pour chaque résultat retourné
foreach ($resultat->fetchAll() as $value) {
$ip = $value->abuse_network;
// Formatter les IPv6
if (!str_contains($ip, '.')) {
$ip = implode(':', str_split($ip, 4));
$ip .= '::/56';
} else {
$ip .= '.0/24';
}
$monRetour->offsetSet($ip, $value->nb);
}
// Tri "humain"
$monRetour->ksort(SORT_NATURAL);
return $monRetour;
}
/**
* Joue une requête SQL et retourne un tableau "new_name"
* @param string $req
* @return ArrayObject
*/
public static function queryOnNewName(string $req): ArrayObject
{
// Exécution de la requête
$resultat = MaBDD::getInstance()->query($req);
$monRetour = new ArrayObject();
// Pour chaque résultat retourné
foreach ($resultat->fetchAll() as $value) {
// J'ajoute le nom de l'image
$monRetour->append($value->new_name);
}
return $monRetour;
}
}

214
classes/HelperImage.php Normal file
View file

@ -0,0 +1,214 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
use Imagick;
use ImagickException;
/**
* Bibliothèque d'outils pour la gestion des images
*/
abstract class HelperImage
{
/**
* Type de l'image
* @param string $path chemin sur le filesystem
* @return false|int
*/
public static function getType(string $path): bool|int
{
return exif_imagetype($path);
}
/**
* MIME type de l'image
* @param string $path chemin sur le filesystem
* @return string
*/
public static function getMimeType(string $path): string
{
return image_type_to_mime_type(self::getType($path));
}
/**
* Chargement ressource PHP image
* @param string $path
* @return Imagick
* @throws ImagickException
*/
public static function getImage(string $path): Imagick
{
$monImage = new Imagick();
$monImage->readImage($path);
// Pour les images animeés (GIF), générer une image pour chaque frame la composant
if (self::getType($path) === IMAGETYPE_GIF) {
$monImage = $monImage->coalesceImages();
}
return $monImage;
}
/**
* Enregistrement d'une ressource PHP image
* @param Imagick $uneImage Image à enregistrer
* @param int $imageType type PHP de l'image
* @param string $path chemin du fichier
* @return bool Succès ?
* @throws ImagickException
*/
public static function setImage(Imagick $uneImage, int $imageType, string $path): bool
{
$monRetour = false;
// Image animée (GIF)
if ($imageType === IMAGETYPE_GIF) {
$uneImage->setInterlaceScheme(Imagick::INTERLACE_GIF);
// Pour la génération du GIF, on ne veut que les différences entre les images
$uneImage = $uneImage->deconstructImages();
// Suppression des commentaires & co
$uneImage->stripImage();
// Enregistrement de l'ensemble des images
$monRetour = $uneImage->writeImages($path, true);
} else {
// Image non animée
if ($imageType === IMAGETYPE_JPEG) {
$uneImage->setInterlaceScheme(Imagick::INTERLACE_JPEG);
// Pas de destruction de l'image
$uneImage->setImageCompression(Imagick::COMPRESSION_JPEG);
$uneImage->setImageCompressionQuality(100);
} elseif ($imageType === IMAGETYPE_PNG) {
$uneImage->setInterlaceScheme(Imagick::INTERLACE_PNG);
$uneImage->setImageCompression(Imagick::COMPRESSION_LZW);
$uneImage->setImageCompressionQuality(9);
} elseif ($imageType === IMAGETYPE_WEBP) {
$uneImage->setImageFormat('webp');
$uneImage->setImageCompression(Imagick::COMPRESSION_LZW);
$uneImage->setImageCompressionQuality(100);
}
// Suppression des commentaires & co
$uneImage->stripImage();
$monRetour = $uneImage->writeImage($path);
}
return $monRetour;
}
/**
* Fourni l'extension officielle d'une ressource
* @param string $path chemin sur le filesystem
* @return string
*/
public static function getExtension(string $path): string
{
$ext = strtolower(image_type_to_extension(self::getType($path), false));
if ($ext === 'jpeg') {
// Préférence pour .jpg [filename.ext]
$ext = 'jpg';
}
return $ext;
}
/**
* Est-il possible de modifier l'image (mémoire suffisante ?)
* @param string $path
* @return bool Possible ?
* @see http://www.dotsamazing.com/en/labs/phpmemorylimit
*/
public static function isModifiableEnMemoire(string $path): bool
{
$monRetour = false;
// Nombre de canaux d'information de l'image
$nbCanaux = 4;
/**
* Information sur les canaux ?
*/
$imageinfo = getimagesize($path);
// Si information sur les canaux de l'image...
if (isset($imageinfo['channels']) && is_int($imageinfo['channels'])) {
$nbCanaux = $imageinfo['channels'];
}
/**
* Mémoire requise :
* (hauteur x largeur x profondeur)
* => x 2 [imageSource + imageDest]
* => x 1.8 [fudge factor]
*/
$memReq = $imageinfo[1] * $imageinfo[0] * $nbCanaux;
$memReq *= 2;
$memReq *= _FUDGE_FACTOR_;
// Est-ce possible ?
if ($memReq < HelperSysteme::getMemoireAllouee()) {
$monRetour = true;
}
return $monRetour;
}
/**
* Dimension maximale acceptable en mémoire pour les images
* <br />Suppose que l'image est carrée (donc indicatif !)
* <br /> Suppose 4 canaux dans l'image
* @return int
* @see isModifiableEnMemoire
*/
public static function getMaxDimension(): int
{
$memDispo = HelperSysteme::getMemoireAllouee();
/**
* Mémoire requise :
* (hauteur x largeur x profondeur)
* => x 2 [imageSource + imageDest]
* => x 1.8 [fudge factor]
*/
$dimMax = round(sqrt($memDispo / 4 / 2 / _FUDGE_FACTOR_));
return (int)$dimMax;
}
/**
* Est-ce une image WEBP animée ?
* @param string $path fichier à tester
* @return bool
*/
public static function isAnimatedWebp(string $path): bool
{
$monRetour = false;
// "Note that animated WebP files cannot be read."
// https://www.php.net/manual/en/function.imagecreatefromwebp.php
if (self::getType($path) === IMAGETYPE_WEBP) {
// "An animation is controlled by 'ANIM' and 'ANMF' Chunks."
// https://developers.google.com/speed/webp/docs/riff_container?hl=en
$headerFile = file_get_contents($path, false, null, 0, 100);
if (stripos($headerFile, 'ANIM') !== false || stripos($headerFile, 'ANMF') !== false) {
$monRetour = true;
}
}
return $monRetour;
}
}

170
classes/HelperSysteme.php Normal file
View file

@ -0,0 +1,170 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
use ArrayObject;
use Imagick;
use PDO;
/**
* Bibliothèque d'outils pour la gestion du système
*/
abstract class HelperSysteme
{
/**
* Taille mémoire maximale autorisée
* @see http://php.net/manual/fr/function.ini-get.php
* @return int
*/
public static function getMemoireAllouee(): int
{
// Récupération de la valeur du php.ini
$valBrute = trim(ini_get('memory_limit'));
// memory_limit=0 / -1 est possible
if ($valBrute <= 0) {
// Arbitrairement limite à 2Go
$valBrute = '2G';
}
// Gestion de l'unité multiplicatrice...
$unite = strtolower(substr($valBrute, -1));
$monRetour = (int)substr($valBrute, 0, -1);
switch ($unite) {
case 'g':
$monRetour *= 1024;
// no break
case 'm':
$monRetour *= 1024;
// no break
case 'k':
$monRetour *= 1024;
// no break
}
return $monRetour;
}
/**
* Version de PHP
* @return string
*/
public static function getPhpVersion(): string
{
return PHP_VERSION . ' - ' . PHP_OS;
}
/**
* Version de Imagick
* @return string
*/
public static function getImagickVersion(): string
{
return Imagick::getVersion()['versionString'];
}
/**
* Version de MySQL
* @return string
*/
public static function getMysqlVersion(): string
{
// Exécution de la requête
return MaBDD::getInstance()->getAttribute(PDO::ATTR_SERVER_VERSION);
}
/**
* Headers HTTP status code
* @param string $url URL à tester
* @return string retour HTTP
*/
public static function getStatusHTTP(string $url): string
{
$classe = 'danger';
$fa = 'exclamation-circle';
// On regarde ce que ça donne
$resultat = get_headers($url);
// Est-ce le résultat attendu ?
if (stripos($resultat[0], 'Forbidden')) {
$classe = 'success';
$fa = 'check';
}
// Mise en forme du résultat
return '<span class="bi-' . $fa . ' text-' . $classe . '">&nbsp;' . $resultat[0] . '</span>';
}
/**
* Vérifie de manière récursive l'écriture dans un dossier
* @param string $folder Path du dossier parent
* @return ArrayObject
*/
public static function isRecursivelyWritable(string $folder): ArrayObject
{
// On évite le // dans le path... (estéthique)
if (str_ends_with($folder, '/')) {
$folder = substr($folder, 0, -1);
}
$monRetour = new ArrayObject();
if (is_writable($folder)) {
$monRetour->append('<span class="bi-check text-success">&nbsp;' . $folder . '</span>');
} else {
$monRetour->append('<span class="bi-exclamation-circle text-danger">&nbsp;' . $folder . '</span>');
}
// Dossiers enfants
$objects = glob($folder . '/*', GLOB_ONLYDIR);
foreach ($objects as $object) {
// Je vérifie si les dossiers enfants sont écrivables
$sousRetour = self::isRecursivelyWritable($object);
// Gestion de l'itération...
foreach ($sousRetour as $unRetour) {
$monRetour->append($unRetour);
}
}
return $monRetour;
}
/**
* Volume des images
* @return float
*/
public static function getHDDUsage(): float
{
// Poids de l'ensemble des images
$req = 'SELECT SUM(im.size) AS images, (
SELECT SUM(th.size)
FROM thumbnails th
) AS miniatures
FROM images im';
// Exécution de la requête
$resultat = MaBDD::getInstance()->query($req);
// Récupération de la valeur
$value = $resultat->fetch();
return round(($value->images + $value->miniatures) / (1024 * 1024 * 1024));
}
}

View file

@ -0,0 +1,47 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
use Exception;
/**
* Exception custom à l'application
*/
class ImageHebergException extends Exception
{
/**
* Définir les champs custom de l'exception
*
* @param string $message Message d'erreur
* @param int $code Code de l'exception
* @param string $file Fichier l'erreur à eu lieu
* @param int $line Line concernée
* @return void
*/
public function define(string $message, int $code, string $file, int $line): void
{
$this->message = $message;
$this->code = $code;
$this->file = $file;
$this->line = $line;
}
}

View file

@ -0,0 +1,375 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
use ArrayObject;
use Exception;
use ImagickException;
use PDO;
/**
* Les images
*/
class ImageObject extends RessourceObject implements RessourceInterface
{
/**
* Constructeur
* @param string $value Identifiant image-heberg
* @param string $fromField Champ à utiliser en BDD
* @throws ImageHebergException
*/
public function __construct(string $value = '', string $fromField = RessourceObject::SEARCH_BY_NAME)
{
// Définition du type pour le RessourceObject
$this->setType(RessourceObject::TYPE_IMAGE);
// Faut-il charger l'objet ?
if ($value !== '' && !$this->charger($value, $fromField)) {
// Envoi d'une exception si l'image n'existe pas
throw new ImageHebergException('Image ' . $value . ' inexistante (' . $fromField . ')');
}
}
public function charger(string $value, string $fromField = RessourceObject::SEARCH_BY_NAME): bool
{
// Charger les informations depuis la BDD
$this->chargerFromBdd([$value], $fromField);
// Gestion du retour
return ($this->getId() !== 0);
}
/**
* Charger des images en masse
* @param ArrayObject $values Valeur du champ $fromField
* @param string $fromField Nom du champ à utiliser en BDD pour identifier les images
* @param bool $orderByIdAsc Trier les résultats par ID ASC ?
* @return array
*/
public static function chargerMultiple(ArrayObject $values, string $fromField, bool $orderByIdAsc = true): array
{
$monRetour = [];
if (count($values) > 0) {
$monRetour = (new ImageObject())->chargerFromBdd((array)$values, $fromField, false, $orderByIdAsc);
}
return $monRetour;
}
/**
* Charger des images depuis la BDD
* @param array $values Valeurs du champ $fromField
* @param string $fromField Nom du champ à utiliser en BDD pour identifier les images
* @param bool $saveOnCurrentObject Enregistrer les résultats dans l'objet courant ou dans un tableau ?
* @param bool $orderByIdAsc Trier les résultats par ID ASC ?
* @return array
*/
private function chargerFromBdd(array $values, string $fromField, bool $saveOnCurrentObject = true, bool $orderByIdAsc = true): array
{
$monRetour = [];
// Génération des placeholders
$placeHolders = str_repeat('?,', count($values) - 1) . '?';
// Je vais chercher les infos en BDD
$req = MaBDD::getInstance()->prepare('SELECT *, (SELECT COUNT(*) FROM images im2 WHERE im2.isBloquee = 1 AND im2.abuse_network = images.abuse_network) AS reputation FROM images LEFT JOIN possede on images.id = possede.images_id WHERE ' . $fromField . ' IN (' . $placeHolders . ') ORDER BY images.id ' . ($orderByIdAsc ? 'ASC' : 'DESC'));
$req->execute($values);
// Traitement des résultats
foreach ($req->fetchAll() as $resultat) {
if ($saveOnCurrentObject) {
$varName = 'this';
} else {
$varName = 'uneImage';
unset(${$varName});
${$varName} = new ImageObject();
}
${$varName}->setId($resultat->id);
${$varName}->setIpEnvoi($resultat->remote_addr);
${$varName}->setDateEnvoi($resultat->date_action);
${$varName}->setNomOriginal($resultat->old_name);
${$varName}->setNomNouveau($resultat->new_name);
${$varName}->setPoids($resultat->size);
${$varName}->setHauteur($resultat->height);
${$varName}->setLargeur($resultat->width);
${$varName}->setLastView($resultat->last_view);
${$varName}->setNbViewIPv4($resultat->nb_view_v4);
${$varName}->setNbViewIPv6($resultat->nb_view_v6);
${$varName}->setMd5($resultat->md5);
${$varName}->setBloquee($resultat->isBloquee);
${$varName}->setSignalee($resultat->isSignalee);
${$varName}->setApprouvee($resultat->isApprouvee);
${$varName}->setIdProprietaire($resultat->membres_id);
${$varName}->setSuspecte(($resultat->reputation > 0));
if (!$saveOnCurrentObject) {
// Gestion du retour
$monRetour[] = ${$varName};
}
}
return $monRetour;
}
public function sauver(): void
{
// J'enregistre les infos en BDD
$req = MaBDD::getInstance()->prepare('UPDATE images SET remote_addr = :ipEnvoi, date_action = :dateEnvoi, old_name = :oldName, new_name = :newName, size = :size, height = :height, width = :width, last_view = :lastView, nb_view_v4 = :nbViewV4, nb_view_v6 = :nbViewV6, md5 = :md5, isBloquee = :isBloquee, isSignalee = :isSignalee, isApprouvee = :isApprouvee WHERE id = :id');
$req->bindValue(':ipEnvoi', $this->getIpEnvoi());
$req->bindValue(':dateEnvoi', $this->getDateEnvoiBrute());
$req->bindValue(':oldName', $this->getNomOriginal());
$req->bindValue(':newName', $this->getNomNouveau());
$req->bindValue(':size', $this->getPoids(), PDO::PARAM_INT);
$req->bindValue(':height', $this->getHauteur(), PDO::PARAM_INT);
$req->bindValue(':width', $this->getLargeur(), PDO::PARAM_INT);
$req->bindValue(':lastView', $this->getLastView());
$req->bindValue(':nbViewV4', $this->getNbViewIPv4(), PDO::PARAM_INT);
$req->bindValue(':nbViewV6', $this->getNbViewIPv6(), PDO::PARAM_INT);
$req->bindValue(':md5', $this->getMd5());
$req->bindValue(':isBloquee', $this->isBloquee(), PDO::PARAM_INT);
$req->bindValue(':isSignalee', $this->isSignalee(), PDO::PARAM_INT);
$req->bindValue(':isApprouvee', $this->isApprouvee(), PDO::PARAM_INT);
$req->bindValue(':id', $this->getId(), PDO::PARAM_INT);
$req->execute();
}
/**
* Récupérer les ID des images des miniatures associées
* @param bool $onlyPreview Uniquement les miniatures d'aperçu dans l'espace membre ?
* @return ArrayObject new_name en BDD des miniatures
*/
public function getMiniatures(bool $onlyPreview = false): ArrayObject
{
$monRetour = new ArrayObject();
// Chargement des miniatures
$query = 'SELECT new_name FROM thumbnails WHERE images_id = :imagesId';
if ($onlyPreview) {
$query .= ' AND is_preview = 1';
}
$req = MaBDD::getInstance()->prepare($query);
$req->bindValue(':imagesId', $this->getId(), PDO::PARAM_INT);
$req->execute();
// Je passe toutes les lignes de résultat
foreach ($req->fetchAll() as $value) {
// Nom du fichier
$monRetour->append($value->new_name);
}
return $monRetour;
}
/**
* @throws ImageHebergException
*/
public function supprimer(): void
{
/**
* Suppression de la ou les miniatures
*/
// Je passe toutes les lignes de résultat
foreach ($this->getMiniatures() as $new_name) {
// Chargement de la miniature
$maMiniature = new MiniatureObject($new_name);
// Suppression
$maMiniature->supprimer();
}
// Suppresion de l'affectation en BDD
$req = MaBDD::getInstance()->prepare('DELETE FROM possede WHERE images_id = :imagesId');
$req->bindValue(':imagesId', $this->getId(), PDO::PARAM_INT);
if ($req->execute()) {
// Suppresion de l'image en BDD
$req = MaBDD::getInstance()->prepare('DELETE FROM images WHERE id = :id');
$req->bindValue(':id', $this->getId(), PDO::PARAM_INT);
// Si plus aucune image n'utilise le fichier => supprimer l'image sur le HDD
if (
$req->execute()
&& $this->getNbUsages() === 0
&& is_file($this->getPathMd5())
) {
unlink($this->getPathMd5());
}
}
}
/**
* @throws ImagickException
* @throws Exception
*/
public function creer(): bool
{
// Retour
$monRetour = true;
/**
* Détermination du nom &&
* Vérification de sa disponibilité
*/
$tmpImage = new ImageObject();
$nb = 0;
do {
// Récupération d'un nouveau nom
$new_name = $this->genererNom($nb);
// Incrémentation compteur entropie sur le nom
$nb++;
} while ($tmpImage->charger($new_name) !== false);
// Effacement de l'objet temporaire
unset($tmpImage);
// On enregistre le nom
$this->setNomNouveau($new_name);
// PHP ne gère pas les images WebP animée -> ne pas faire de traitements
if (!HelperImage::isAnimatedWebp($this->getPathTemp())) {
// Optimiser l'image (permettra de comparer son hash avec celles déjà stockées)
HelperImage::setImage(HelperImage::getImage($this->getPathTemp()), HelperImage::getType($this->getPathTemp()), $this->getPathTemp());
}
/**
* Déplacement du fichier
*/
// Vérification de la non existence du fichier
if ($this->getNbUsages() === 0) {
// Copie du fichier vers l'emplacement de stockage
// Ne peut pas être fait avant car le MD5 n'est pas encore connu
$monRetour = copy($this->getPathTemp(), $this->getPathMd5());
} else {
// Ce MD5 est-il déjà bloqué pour une autre image ?
$req = MaBDD::getInstance()->prepare('SELECT MAX(isBloquee) AS isBloquee FROM images WHERE md5 = :md5');
$req->bindValue(':md5', $this->getMd5());
$req->execute();
$values = $req->fetch();
if ($values !== false) {
$this->setBloquee((bool)$values->isBloquee);
}
}
// Ssi copie du fichier réussie
if ($monRetour) {
/**
* Informations sur l'image
*/
// Dimensions
$imageInfo = getimagesize($this->getPathMd5());
$this->setLargeur($imageInfo[0]);
$this->setHauteur($imageInfo[1]);
// Poids
$this->setPoids(filesize($this->getPathMd5()));
// Nom originel (non récupérable sur le fichier)
$this->setNomOriginal($this->getNomTemp());
// @ IP d'envoi
$this->setIpEnvoi($_SERVER['REMOTE_ADDR']);
/**
* Création en BDD
*/
$req = MaBDD::getInstance()->prepare('INSERT INTO images (remote_addr, date_action, old_name, new_name, size, height, width, md5, isBloquee) VALUES (:ipEnvoi, NOW(), :oldName, :newName, :size, :height, :width, :md5, :isBloquee)');
$req->bindValue(':ipEnvoi', $this->getIpEnvoi());
// Date : NOW()
$req->bindValue(':oldName', $this->getNomOriginal());
$req->bindValue(':newName', $this->getNomNouveau());
$req->bindValue(':size', $this->getPoids(), PDO::PARAM_INT);
$req->bindValue(':height', $this->getHauteur(), PDO::PARAM_INT);
$req->bindValue(':width', $this->getLargeur(), PDO::PARAM_INT);
$req->bindValue(':md5', $this->getMd5());
$req->bindValue(':isBloquee', $this->isBloquee());
if (!$req->execute()) {
// Gestion de l'erreur d'insertion en BDD
$monRetour = false;
} else {
/**
* Récupération de l'ID de l'image
*/
$idEnregistrement = MaBDD::getInstance()->lastInsertId();
$this->setId($idEnregistrement);
// Définir les informations relatives au réseau utilisé (anti abus)
HelperAbuse::updateIpReputation();
}
}
return $monRetour;
}
/**
* Bloquer une image en BDD
* Effet contaminant sur les autres images partagant le même MD5
*/
public function bloquer(): void
{
// J'enregistre les infos en BDD
$req = MaBDD::getInstance()->prepare('UPDATE images SET isBloquee = 1, isApprouvee = 0 WHERE md5 = :md5');
$req->bindValue(':md5', $this->getMd5());
$req->execute();
}
/**
* Approuver une image en BDD
* Effet contaminant sur les autres images partagant le même MD5
*/
public function approuver(): void
{
// J'enregistre les infos en BDD
$req = MaBDD::getInstance()->prepare('UPDATE images SET isBloquee = 0, isSignalee = 0, isApprouvee = 1 WHERE md5 = :md5');
$req->bindValue(':md5', $this->getMd5());
$req->execute();
}
/**
* Nombre d'appels IPv4 & IPv6
* @return int
*/
public function getNbViewTotal(): int
{
return parent::getNbViewTotal() + $this->getNbViewMiniatures();
}
/**
* Récupérer le total d'affichage des miniatures
* @return int
*/
public function getNbViewMiniatures(): int
{
$monRetour = 0;
// Chargement des miniatures
$query = 'SELECT SUM(nb_view_v4 + nb_view_v6) as total FROM thumbnails WHERE images_id = :imagesId';
$req = MaBDD::getInstance()->prepare($query);
$req->bindValue(':imagesId', $this->getId(), PDO::PARAM_INT);
$req->execute();
// Je passe toutes les lignes de résultat
foreach ($req->fetchAll() as $value) {
if (!is_null($value->total)) {
$monRetour = $value->total;
}
}
return $monRetour;
}
}

108
classes/MaBDD.class.php Normal file
View file

@ -0,0 +1,108 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
use PDO;
use PDOStatement;
/**
* Lien vers la BDD
*
* @author anael
*/
class MaBDD
{
// PDO
private PDO $maBDD;
// Instance de la classe
private static ?MaBDD $monInstance = null;
/**
* Constructeur
*/
private function __construct()
{
$this->maBDD = new PDO('mysql:host=' . _BDD_HOST_ . ';dbname=' . _BDD_NAME_, _BDD_USER_, _BDD_PASS_);
$this->maBDD->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->maBDD->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
}
/**
* Crée & renvoi l'objet d'instance
* @return MaBDD
*/
public static function getInstance(): MaBDD
{
// Si pas de connexion active, en crée une
if (is_null(self::$monInstance)) {
self::$monInstance = new MaBDD();
}
return self::$monInstance;
}
/**
* PDO::query
* @param string $query
* @return false|PDOStatement
*/
public function query(string $query): bool|PDOStatement
{
return $this->maBDD->query($query);
}
/**
* PDO::prepare
* @param string $query
* @return false|PDOStatement
*/
public function prepare(string $query): bool|PDOStatement
{
return $this->maBDD->prepare($query);
}
/**
* PDO::lastInsertId
* @return string
*/
public function lastInsertId(): string
{
return $this->maBDD->lastInsertId();
}
/**
* Fermeture du PDO
*/
public static function close(): void
{
self::$monInstance = null;
}
/**
* PDO::getAttribute
* @param int $attribute
* @return mixed
*/
public function getAttribute(int $attribute): mixed
{
return $this->maBDD->getAttribute($attribute);
}
}

View file

@ -0,0 +1,243 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
use Exception;
use PDO;
/**
* Les miniatures
*/
class MiniatureObject extends RessourceObject implements RessourceInterface
{
private int $idImage;
private bool $isPreview = false;
/**
* Constructeur
* @param string $value Identifiant image-heberg
* @param string $fromField Champ à utiliser en BDD
* @throws ImageHebergException
*/
public function __construct(string $value = '', string $fromField = RessourceObject::SEARCH_BY_NAME)
{
// Définition du type pour le RessourceObject
$this->setType(RessourceObject::TYPE_MINIATURE);
// Faut-il charger l'objet ?
if ($value !== '' && !$this->charger($value, $fromField)) {
// Envoi d'une exception si l'image n'existe pas
throw new ImageHebergException('Miniature ' . $value . ' inexistante - ' . $fromField);
}
}
public function charger(string $value, string $fromField = RessourceObject::SEARCH_BY_NAME): bool
{
$monRetour = false;
// Je vais chercher les infos en BDD
$req = MaBDD::getInstance()->prepare('SELECT * FROM thumbnails WHERE ' . $fromField . ' = :value');
$req->bindValue(':value', $value);
$req->execute();
// J'éclate les informations
$resultat = $req->fetch();
if ($resultat !== false) {
$this->setPoids($resultat->size);
$this->setHauteur($resultat->height);
$this->setLargeur($resultat->width);
$this->setLastView($resultat->last_view);
$this->setNbViewIPv4($resultat->nb_view_v4);
$this->setNbViewIPv6($resultat->nb_view_v6);
$this->setMd5($resultat->md5);
$this->setId($resultat->id);
$this->setDateEnvoi($resultat->date_action);
$this->setNomNouveau($resultat->new_name);
$this->setIdImage($resultat->images_id);
$this->setIsPreview($resultat->is_preview);
// Reprise des informations de l'image maitresse
$imageParente = new ImageObject();
$imageParente->charger($this->getIdImage(), RessourceObject::SEARCH_BY_ID);
$this->setBloquee($imageParente->isBloquee());
$this->setSignalee($imageParente->isSignalee());
$this->setApprouvee($imageParente->isApprouvee());
$this->setNomOriginal($imageParente->getNomOriginal());
$this->setIpEnvoi($imageParente->getIpEnvoi());
$this->setIdProprietaire($imageParente->getIdProprietaire());
$this->setSuspecte($imageParente->isSuspecte());
// Notification du chargement réussi
$monRetour = true;
}
return $monRetour;
}
public function sauver(): void
{
// J'enregistre les infos en BDD
$req = MaBDD::getInstance()->prepare('UPDATE thumbnails SET images_id = :imagesId, is_preview = :isPreview, date_action = :dateCreation, new_name = :newName, size = :size, height = :height, width = :width, last_view = :lastView, nb_view_v4 = :nbViewV4, nb_view_v6 = :nbViewV6, md5 = :md5 WHERE id = :id');
$req->bindValue(':imagesId', $this->getIdImage(), PDO::PARAM_INT);
$req->bindValue(':isPreview', $this->getIsPreview(), PDO::PARAM_INT);
$req->bindValue(':dateCreation', $this->getDateEnvoiBrute());
$req->bindValue(':newName', $this->getNomNouveau(), PDO::PARAM_STMT);
$req->bindValue(':size', $this->getPoids(), PDO::PARAM_INT);
$req->bindValue(':height', $this->getHauteur(), PDO::PARAM_INT);
$req->bindValue(':width', $this->getLargeur(), PDO::PARAM_INT);
$req->bindValue(':lastView', $this->getLastView());
$req->bindValue(':nbViewV4', $this->getNbViewIPv4(), PDO::PARAM_INT);
$req->bindValue(':nbViewV6', $this->getNbViewIPv6(), PDO::PARAM_INT);
$req->bindValue(':md5', $this->getMd5());
$req->bindValue(':id', $this->getId(), PDO::PARAM_INT);
$req->execute();
}
public function supprimer(): void
{
/**
* Suppression de l'image en BDD
*/
// Suppresion de l'image en BDD
$req = MaBDD::getInstance()->prepare('DELETE FROM thumbnails WHERE id = :id');
$req->bindValue(':id', $this->getId(), PDO::PARAM_INT);
// Si plus aucune image n'utilise le fichier => supprimer l'image sur le HDD
if (
$req->execute()
&& $this->getNbUsages() === 0
&& file_exists($this->getPathMd5())
) {
unlink($this->getPathMd5());
}
}
/**
* @throws Exception
*/
public function creer(): bool
{
// Retour
$monRetour = true;
/**
* Détermination du nom &&
* Vérification de sa disponibilité
*/
$tmpMiniature = new MiniatureObject();
$nb = 0;
do {
// Récupération d'un nouveau nom
$new_name = $this->genererNom($nb);
// Incrémentation compteur entropie sur le nom
$nb++;
} while ($tmpMiniature->charger($new_name) !== false);
// Effacement de l'objet temporaire
unset($tmpMiniature);
// On enregistre le nom
$this->setNomNouveau($new_name);
/**
* Déplacement du fichier
*/
// Vérification de la non existence du fichier
if ($this->getNbUsages() === 0) {
$monRetour = rename($this->getPathTemp(), $this->getPathMd5());
}
// Ssi copie du fichier réussie
if ($monRetour) {
/**
* Informations sur l'image
*/
// Dimensions
$imageInfo = getimagesize($this->getPathMd5());
$this->setLargeur($imageInfo[0]);
$this->setHauteur($imageInfo[1]);
// Poids
$this->setPoids(filesize($this->getPathMd5()));
/**
* Création en BDD
*/
$req = MaBDD::getInstance()->prepare('INSERT INTO thumbnails (images_id, date_action, new_name, size, height, width, md5) VALUES (:imagesId, NOW(), :newName, :size, :height, :width, :md5)');
$req->bindValue(':imagesId', $this->getIdImage(), PDO::PARAM_INT);
// Date : NOW()
$req->bindValue(':newName', $this->getNomNouveau());
$req->bindValue(':size', $this->getPoids(), PDO::PARAM_INT);
$req->bindValue(':height', $this->getHauteur(), PDO::PARAM_INT);
$req->bindValue(':width', $this->getLargeur(), PDO::PARAM_INT);
$req->bindValue(':md5', $this->getMd5());
if (!$req->execute()) {
// Gestion de l'erreur d'insertion en BDD
$monRetour = false;
} else {
/**
* Récupération de l'ID de l'image
*/
$idEnregistrement = MaBDD::getInstance()->lastInsertId();
$this->setId($idEnregistrement);
}
}
return $monRetour;
}
/**
* GETTERS & SETTERS
*/
/**
* ID image parente
* @return int
*/
public function getIdImage(): int
{
return $this->idImage;
}
/**
* ID image parente
* @param int $idImage
*/
public function setIdImage(int $idImage): void
{
$this->idImage = $idImage;
}
/**
* @return bool
*/
public function getIsPreview(): bool
{
return $this->isPreview;
}
/**
* @param bool $isPreview
*/
public function setIsPreview(bool $isPreview): void
{
$this->isPreview = $isPreview;
}
}

View file

@ -1,6 +1,7 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
@ -18,33 +19,34 @@
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
/**
* Fonctions devant êtres implémentées spécifiquement par les images et miniatures
*/
interface ressourceInterface {
interface RessourceInterface
{
/**
* Crée sur le HDD et dans la BDD la ressource
* @return bool Résultat ?
*/
public function creer(): bool;
/**
* Crée sur le HDD et dans la BDD la ressource
* @return boolean Résultat ?
*/
function creer();
/**
* Charge un objet ressource depuis la BDD
* @param string $value Identifiant image-heberg
* @param string $fromField Champ à utiliser en BDD
* @return bool Résultat ?
*/
public function charger(string $value, string $fromField = RessourceObject::SEARCH_BY_NAME): bool;
/**
* Charge unn objet ressource depuis la BDD
* @param string $nom Identifiant image-heberg
* @return boolean Résultat ?
*/
function charger($nom);
/**
* Enregistre en BDD un objet ressource
*/
public function sauver(): void;
/**
* Enregistre en BDD un objet ressource
* @return boolean Résultat ?
*/
function sauver();
/**
* Supprime sur le HDD et dans la BDD la ressource
* @return boolean Résultat ?
*/
function supprimer();
}
/**
* Supprime sur le HDD et dans la BDD la ressource
*/
public function supprimer(): void;
}

View file

@ -0,0 +1,735 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
use Exception;
use ImagickException;
use PDO;
/**
* Fonctions génériques aux images et miniatures
*/
abstract class RessourceObject
{
// Types de ressources
final public const int TYPE_IMAGE = 1;
final public const int TYPE_MINIATURE = 2;
// Champ à utiliser en BDD pour charger la ressource
final public const string SEARCH_BY_MD5 = 'md5';
final public const string SEARCH_BY_NAME = 'new_name';
final public const string SEARCH_BY_ID = 'id';
// Attributs de la classe
private int $id = 0;
private string $nomOriginal = '';
private string $nomNouveau = '';
private int $largeur = 0;
private int $hauteur = 0;
private int $poids = 0;
private string $lastView = '0000-00-00';
private int $nbViewIPv4 = 0;
private int $nbViewIPv6 = 0;
private string $dateEnvoi = '';
private ?string $md5 = null;
private string $ipEnvoi = '';
private bool $isBloquee = false;
private bool $isSignalee = false;
private bool $isApprouvee = false;
private bool $isSuspecte = false;
private string $pathTemp = '';
private int $type = self::TYPE_IMAGE;
private string $nomTemp = '';
private ?int $idProprietaire = null;
/**
* Génère le nom d'une nouvelle image
* @param int $nb nombre de chiffres à rajouter à la fin du nom
* @return string nom de l'image
* @throws Exception
*/
protected function genererNom(int $nb = 0): string
{
// Random pour unicité + cassage lien nom <-> @IP
$random = random_int(100, 999);
// @IP expéditeur
$adresseIP = abs(crc32($_SERVER['REMOTE_ADDR'] . $random));
// Timestamp d'envoi
$timestamp = $_SERVER['REQUEST_TIME'];
// Taille max : 28 chr
// - Timestamp : 1699048241 : 10 caractères jusqu'en 2286...
// - $adresseIP -> CRC32 : 8 bits en hexa, soit 16^8 valeurs => 4 294 967 296 : 10 caractères
// - Suffixe anti-doublon : hypothèse très haute 10k doublons : 4 caractères
// - Extension : 1+3 caractères
// Calcul du nom de l'image
return $timestamp . $adresseIP . substr($random, 0, $nb) . '.' . HelperImage::getExtension($this->getPathTemp());
}
/**
* MD5 de la ressource
* @return string
*/
public function getMd5(): string
{
// Création d'une image => Utilisation du fichier temporaire
if (is_null($this->md5) && $this->getPathTemp()) {
// Fichier temporaire...
$this->md5 = md5_file($this->getPathTemp());
}
return $this->md5;
}
/**
* Path sur le HDD
* @return string
*/
public function getPathMd5(): string
{
// Path du type d'image
if ($this->getType() === self::TYPE_IMAGE) {
// Image
$pathDuType = _PATH_IMAGES_;
} else {
// Miniature
$pathDuType = _PATH_MINIATURES_;
}
// Path final
if ($this->getType() === self::TYPE_IMAGE && ($this->getId() === 1 || $this->getId() === 2)) {
// Gestion des images spécifiques 404 / ban
$pathFinal = $pathDuType . $this->getNomNouveau();
} else {
// Cas par défaut
$rep = substr($this->getMd5(), 0, 1) . '/';
$pathFinal = $pathDuType . $rep . $this->getMd5();
}
return $pathFinal;
}
/**
* Nombre d'images ayant le même MD5 (Normalement 1 à minima, l'image courante...)
* @return int nombre d'images ayant ce MD5 (0 par défaut)
*/
public function getNbUsages(): int
{
$monRetour = 0;
// Si l'image n'existe pas et qu'on est pas en train de l'envoyer, ne pas tenter de la charger
if (!is_null($this->md5) || $this->getPathTemp()) {
// Existe-t-il d'autres occurences de cette image ?
if ($this->getType() === self::TYPE_IMAGE) {
// Image
$req = MaBDD::getInstance()->prepare('SELECT COUNT(*) AS nb FROM images WHERE md5 = :md5');
} else {
// Miniature
$req = MaBDD::getInstance()->prepare('SELECT COUNT(*) AS nb FROM thumbnails WHERE md5 = :md5');
}
$req->bindValue(':md5', $this->getMd5());
$req->execute();
$resultat = $req->fetch();
if ($resultat !== false) {
$monRetour = (int)$resultat->nb;
}
}
return $monRetour;
}
/**
* URL de la ressource
* @param bool $forceHttps Forcer le HTTPS ?
* @return string
*/
public function getURL(bool $forceHttps = false): string
{
// Path du type d'image
if ($this->getType() === self::TYPE_IMAGE) {
// Image
$urlDuType = _URL_IMAGES_;
} else {
// Miniature
$urlDuType = _URL_MINIATURES_;
}
// Forcer le HTTPS ?
if ($forceHttps) {
$urlDuType = str_replace('http:/', 'https:/', $urlDuType);
}
return $urlDuType . $this->getNomNouveau();
}
/**
* Rotation d'une ressource <br />
* Inclus mise à jour largeur / hauteur / poids de l'image
* @param int $angle xxx° de rotation horaire
* @param string $pathSrc chemin de la ressource d'origine
* @param string $pathDst chemin de la ressource de destination
* @return bool succès ?
* @throws ImagickException
*/
public function rotation(int $angle, string $pathSrc, string $pathDst): bool
{
// Je charge l'image en mémoire
$resImg = HelperImage::getImage($pathSrc);
// Rotation (Imagick est dans le sens horaire, imagerotate dans le sens anti-horaire)
if (HelperImage::getType($pathSrc) === IMAGETYPE_GIF) {
// Image animée (GIF) : c'est une succession d'images !
foreach ($resImg as $frame) {
$frame->rotateImage('rgb(0,0,0)', $angle);
}
} else {
// Cas standard (image non animée)
$resImg->rotateImage('rgb(0,0,0)', $angle);
}
// J'enregistre l'image
return HelperImage::setImage($resImg, HelperImage::getType($pathSrc), $pathDst);
}
/**
* Redimensionne une image en respectant le ratio de l'image original
* @param string $pathSrc chemin de la ressource d'origine
* @param string $pathDst chemin de la ressource de destination
* @param int $largeurDemandee largeur souhaitée
* @param int $hauteurDemandee hauteur souhaitée
* @return bool réussi ?
* @throws ImagickException
*/
public function redimensionner(string $pathSrc, string $pathDst, int $largeurDemandee, int $hauteurDemandee): bool
{
// Chargement de l'image
$monImage = HelperImage::getImage($pathSrc);
// Récupération de ses dimensions
$largeurImage = $monImage->getImageWidth();
$hauteurImage = $monImage->getImageHeight();
// Dimensions incohérentes : on arrête
if ($hauteurImage <= 0 || $hauteurDemandee <= 0 || $largeurImage <= 0 || $largeurDemandee <= 0 || $largeurImage <= $largeurDemandee || $hauteurImage <= $hauteurDemandee) {
return false;
}
// Redimensionnement par Imagick
if (HelperImage::getType($pathSrc) === IMAGETYPE_GIF) {
// Cas image animée (GIF) : c'est une succession d'images !
foreach ($monImage as $frame) {
$frame->thumbnailImage($largeurDemandee, $hauteurDemandee, true);
}
} else {
// Cas standard (image non animée)
$monImage->thumbnailImage($largeurDemandee, $hauteurDemandee, true);
}
// Ecriture de l'image
return HelperImage::setImage($monImage, HelperImage::getType($pathSrc), $pathDst);
}
/**
* Cet utilisateur est-il propriétaire de l'image ?
* @return bool
*/
public function isProprietaire(): bool
{
$monRetour = false;
// Si l'image à un propriétaire...
if ($this->getIdProprietaire() !== null) {
// Le propriétaire est-il connecté ?
$uneSession = new SessionObject();
// Est-ce le propriétaire de l'image ?
if ($this->getIdProprietaire() === $uneSession->getId()) {
// Si oui... on confirme !
$monRetour = true;
}
}
return $monRetour;
}
/**
* Date d'envoi formatée
* @return string
*/
public function getDateEnvoiFormatee(): string
{
$phpdate = strtotime($this->getDateEnvoiBrute());
return date('d/m/Y H:i:s', $phpdate);
}
/**
* Date de dernier affichage formaté
* @return string
*/
public function getLastViewFormate(): string
{
$monRetour = '?';
if ($this->getLastView() !== '0000-00-00') {
$phpdate = strtotime($this->getLastView());
// Gestion du cas de non affichage
if ($phpdate !== 0 && $phpdate !== false) {
$monRetour = date('d/m/Y', $phpdate);
}
}
return $monRetour;
}
/**
* Nombre d'appels IPv4 & IPv6
* @return int
*/
public function getNbViewTotal(): int
{
return $this->getNbViewIPv4() + $this->getNbViewIPv6();
}
/**
* Nombre d'affichage par jour
* @return int
*/
public function getNbViewPerDay(): int
{
// date_diff ne comptabilise que les journées entières, alors qu'en SQL, on compare des dates
// date_diff('2023-09-03 23:38:42', '2023-09-05 22:53:03') => 1
// date_diff('2023-09-03', '2023-09-05 22:53:03') => 2
// => substr() de la date d'envoi pour aligner sur les valeurs du SQL
$nbJours = (int)date_diff(date_create(substr($this->getDateEnvoiBrute(), 0, 10)), date_create())->format('%r%a');
// Le premier jour, autoriser les xxx vues de la journée
if ($nbJours === 0) {
$nbJours = 1;
}
return (int)($this->getNbViewTotal() / $nbJours);
}
/**
* Nom original de la ressource
* @return string
*/
public function getNomOriginalFormate(): string
{
return htmlentities($this->nomOriginal, ENT_SUBSTITUTE);
}
/**
* Met à jour les statistiques (nb d'affichage et date) en BDD
*/
public function updateStatsAffichage(string $remoteAddr): void
{
// Prendre la bonne table
if ($this->getType() === self::TYPE_IMAGE) {
// Image
$table = 'images';
} else {
// Miniature
$table = 'thumbnails';
}
// Prendre le bon type d'@ IP
if (filter_var($remoteAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
// IPv4
$typeAcces = 'nb_view_v4';
} else {
// IPv6
$typeAcces = 'nb_view_v6';
}
$req = MaBDD::getInstance()->prepare('UPDATE ' . $table . ' SET last_view = NOW(), ' . $typeAcces . ' = ' . $typeAcces . ' + 1 WHERE id = :id');
$req->bindValue(':id', $this->getId(), PDO::PARAM_INT);
$req->execute();
}
/**
* GETTERS ET SETTERS
*/
/**
* ID de la ressource
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* Nom original de la ressource
* @return string
*/
protected function getNomOriginal(): string
{
return $this->nomOriginal;
}
/**
* Nom image-heberg
* @return string
*/
public function getNomNouveau(): string
{
return $this->nomNouveau;
}
/**
* Largeur en px
* @return int
*/
public function getLargeur(): int
{
return $this->largeur;
}
/**
* Hauteur en px
* @return int
*/
public function getHauteur(): int
{
return $this->hauteur;
}
/**
* Poids de la ressource
* @return int
*/
public function getPoids(): int
{
return $this->poids;
}
/**
* Poids de la ressource en Mo
* @return float
*/
public function getPoidsMo(): float
{
return round($this->getPoids() / 1024 / 1024, 1);
}
/**
* Date de dernier affichage
* @return string
*/
protected function getLastView(): string
{
return $this->lastView;
}
/**
* Nb d'affichage en IPv4
* @return int
*/
protected function getNbViewIPv4(): int
{
return $this->nbViewIPv4;
}
/**
* Nb d'affichage en IPv6
* @return int
*/
protected function getNbViewIPv6(): int
{
return $this->nbViewIPv6;
}
/**
* Date d'envoi du fichier
* @return string
*/
public function getDateEnvoiBrute(): string
{
return $this->dateEnvoi;
}
/**
* @ IP d'envoi
* @return string
*/
public function getIpEnvoi(): string
{
return $this->ipEnvoi;
}
/**
* Image bloquée ?
* @return bool
*/
public function isBloquee(): bool
{
return $this->isBloquee;
}
/**
* Image signalée ?
* @return bool
*/
public function isSignalee(): bool
{
return $this->isSignalee;
}
/**
* Image approuvée (marquée comme valide)
* @return bool
*/
public function isApprouvee(): bool
{
return $this->isApprouvee;
}
/**
* Image envoyée depuis un réseau suspect
* @return bool
*/
public function isSuspecte(): bool
{
return $this->isSuspecte;
}
/**
* Path temporaire (upload d'image)
* @return string
*/
public function getPathTemp(): string
{
return $this->pathTemp;
}
/**
* Type d'image
* @return int ressourceObject const
*/
public function getType(): int
{
return $this->type;
}
/**
* Nom temporaire (PC utilisateur - upload d'image)
* @return string
*/
public function getNomTemp(): string
{
return $this->nomTemp;
}
/**
* Nom temporaire (PC utilisateur - upload d'image)
* @param string $nomTemp
*/
public function setNomTemp(string $nomTemp): void
{
$this->nomTemp = $nomTemp;
}
/**
* Type d'image
* @param int $type RessourceObject const
*/
public function setType(int $type): void
{
$this->type = $type;
}
/**
* Path temporaire (upload d'image)
* @param string $pathTemp
*/
public function setPathTemp(string $pathTemp): void
{
$this->pathTemp = $pathTemp;
}
/**
* Image bloquée ?
* @param bool $bloquee
*/
public function setBloquee(bool $bloquee): void
{
$this->isBloquee = $bloquee;
}
/**
* Image signalée ?
* @param bool $isSignalee
*/
public function setSignalee(bool $isSignalee): void
{
$this->isSignalee = $isSignalee;
}
/**
* Image approuvée (marquée comme valide) ?
* @param bool $isApprouvee
*/
public function setApprouvee(bool $isApprouvee): void
{
$this->isApprouvee = $isApprouvee;
}
/**
* Image envoyée depuis un réseau suspect
* @param bool $isSuspecte
*/
public function setSuspecte(bool $isSuspecte): void
{
$this->isSuspecte = $isSuspecte;
}
/**
* ID de l'image
* @param int $id
*/
protected function setId(int $id): void
{
$this->id = $id;
}
/**
* Nom original de la ressource
* @param string $nomOriginal
*/
protected function setNomOriginal(string $nomOriginal): void
{
$this->nomOriginal = $nomOriginal;
}
/**
* Nom image-heberg
* @param string $nomNouveau
*/
protected function setNomNouveau(string $nomNouveau): void
{
$this->nomNouveau = $nomNouveau;
}
/**
* Largeur en px
* @param int $largeur
*/
protected function setLargeur(int $largeur): void
{
$this->largeur = $largeur;
}
/**
* Hauteur en px
* @param int $hauteur
*/
protected function setHauteur(int $hauteur): void
{
$this->hauteur = $hauteur;
}
/**
* Poids de la ressource
* @param int $poids
*/
protected function setPoids(int $poids): void
{
$this->poids = $poids;
}
/**
* Date de dernier affichage
* @param ?string $lastView
*/
protected function setLastView(?string $lastView): void
{
if (is_null($lastView)) {
// Si l'image n'a jamais été affichée, elle est à NULL en BDD
$lastView = '';
}
$this->lastView = $lastView;
}
/**
* Nb d'affichage en IPv4
* @param int $nbViewIPv4
*/
protected function setNbViewIPv4(int $nbViewIPv4): void
{
$this->nbViewIPv4 = $nbViewIPv4;
}
/**
* Nb d'affichage en IPv6
* @param int $nbViewIPv6
*/
protected function setNbViewIPv6(int $nbViewIPv6): void
{
$this->nbViewIPv6 = $nbViewIPv6;
}
/**
* Date d'envoi du fichier
* @param string $dateEnvoi
*/
protected function setDateEnvoi(string $dateEnvoi): void
{
$this->dateEnvoi = $dateEnvoi;
}
/**
* MD5 de la ressource
* @param string $md5
*/
protected function setMd5(string $md5): void
{
$this->md5 = $md5;
}
/**
* @ IP d'envoi
* @param string $ipEnvoi
*/
protected function setIpEnvoi(string $ipEnvoi): void
{
$this->ipEnvoi = $ipEnvoi;
}
/**
* ID du compte propriétaire de l'image
* @return ?int
*/
public function getIdProprietaire(): ?int
{
return $this->idProprietaire;
}
/**
* @param ?int $idProprietaire ID du compte propriétaire de l'image
* @return void
*/
protected function setIdProprietaire(?int $idProprietaire): void
{
$this->idProprietaire = $idProprietaire;
}
}

View file

@ -0,0 +1,173 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
/**
* Gestion des sessions
*/
class SessionObject
{
// @ IP de l'utilisateur
private string $IP = '';
// Objet utilisateur
private UtilisateurObject $userObject;
public function __construct()
{
// Je vérifie qu'une session n'est pas déjà lancée & que pas tests travis (session_start déjà effectué)
if (!_PHPUNIT_ && session_status() === PHP_SESSION_NONE) {
// Je lance la session côté PHP
session_start();
}
// Si j'ai déjà une session existante && que l'@ IP correspond
if (isset($_SESSION['userObject']) && $_SESSION['IP'] === $_SERVER['REMOTE_ADDR']) {
// On recharge les informations
$this->setIP($_SESSION['IP']);
$this->setUserObject($_SESSION['userObject']);
}
}
/**
* Mon utilisateur
* @return UtilisateurObject
*/
private function getUserObject(): UtilisateurObject
{
return $this->userObject ?? new UtilisateurObject();
}
/**
* Mon utilisateur
* @param UtilisateurObject $userObject Objet utilisateur
*/
public function setUserObject(UtilisateurObject $userObject): void
{
$this->userObject = $userObject;
$_SESSION['userObject'] = $userObject;
}
/**
* Nom d'utilisateur
* @return string
*/
public function getUserName(): string
{
return $this->getUserObject()->getUserName();
}
/**
* @ IP
* @return string
*/
public function getIP(): string
{
return $this->IP;
}
/**
* Niveau de droits
* @return int
*/
public function getLevel(): int
{
return $this->getUserObject()->getLevel();
}
/**
* ID en BDD
* @return int
*/
public function getId(): int
{
return $this->getUserObject()->getId();
}
/**
* IP
* @param string $IP
*/
public function setIP(string $IP): void
{
$this->IP = $IP;
// On enregistre dans la session
$_SESSION['IP'] = $this->getIP();
}
/**
* Vérification des droits de l'utilisateur pour la page
* @param int $levelRequis
* @return bool
*/
public function verifierDroits(int $levelRequis): bool
{
$monRetour = false;
if ($this->getLevel() >= $levelRequis) {
$monRetour = true;
}
return $monRetour;
}
/**
* Déconnexion d'un utilisateur
*/
public function deconnexion(): void
{
// Destruction de l'objet utilisateur
unset($_SESSION['userObject']);
if (!_PHPUNIT_) {
// Je détruis la session
session_destroy();
}
}
/**
* Active le flag de suivi (vérification d'affichage de page avant envoi)
*/
public function setFlag(): void
{
$_SESSION['flag'] = time();
}
/**
* Supprime le flag de suivi
*/
public function removeFlag(): void
{
unset($_SESSION['flag']);
}
/**
* Vérifie le flag de suivi (a été activé il y a plus d'une seconde)
* @return bool Suivi OK ?
*/
public function checkFlag(): bool
{
$monRetour = false;
// Au moins une seconde pour remplir le formulaire
if (isset($_SESSION['flag']) && (time() - $_SESSION['flag']) > 1) {
$monRetour = true;
}
return $monRetour;
}
}

182
classes/Tor.class.php Normal file
View file

@ -0,0 +1,182 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
use JsonException;
/**
* Fonctions relative à Tor
*/
class Tor
{
private const string IPV4 = 'IPv4';
private const string IPV6 = 'IPv6';
/**
* Mettre à jour la liste des adresses IP des noeuds de sortie Tor
* @throws JsonException
*/
public function updateListeExitNodes(): void
{
$torNodeList = file_get_contents(_TOR_EXIT_NODE_LIST_URL_);
// Ne mettre à jour que si on a des données
if (!empty($torNodeList)) {
// Récupération du dernier fichier
$objJson = json_decode($torNodeList, false, 512, JSON_THROW_ON_ERROR);
$tabIP = [];
$tabIP[self::IPV4] = [];
$tabIP[self::IPV6] = [];
foreach ($objJson->relays as $unRelay) {
// Adresse IP de sortie (IPv4 uniquement)
// https://metrics.torproject.org/onionoo.html#details_relay_exit_addresses
if (isset($unRelay->exit_addresses)) {
foreach ($unRelay->exit_addresses as $uneIp) {
$this->addToTab($uneIp, $tabIP);
}
}
// Adresse IP sur lequel le noeud écoute (IPv4 + IPv6)
// Lorsque exit_addresses incluera les IPv6, plus besoin de cette partie qui surbloque...
if (isset($unRelay->or_addresses)) {
foreach ($unRelay->or_addresses as $uneIp) {
$this->addToTab($uneIp, $tabIP, true);
}
}
}
// Enregister le résultat sur le disque
$retour = file_put_contents(_TOR_LISTE_IPV4_, json_encode($tabIP[self::IPV4], JSON_THROW_ON_ERROR));
echo 'IPv4 : ' . $retour;
$retour = file_put_contents(_TOR_LISTE_IPV6_, json_encode($tabIP[self::IPV6], JSON_THROW_ON_ERROR));
echo '<br />IPv6 : ' . $retour;
} else {
// Envoyer un mail d'avertissement
mail(_ADMINISTRATEUR_EMAIL_, '[' . _SITE_NAME_ . '] - Actualisation des noeuds Tor en erreur', 'Liste de noeuds récupérée : ' . var_export($torNodeList, true), 'From: ' . _ADMINISTRATEUR_EMAIL_);
die();
}
}
/**
* Nettoyer et ajouter une IP dans le tableau des adresses connues
* @param string $ip @ IP à ajouter
* @param string[] $tabIp Liste des addresses IP déjà connues
* @param bool $withPort Le port est précisé (1.2.3.4:1234)
*/
private function addToTab(string $ip, array &$tabIp, bool $withPort = false): void
{
if (substr_count($ip, ':') > 1) {
// C'est une IPv6
// Supprimer le port
if ($withPort) {
$ip = substr($ip, 0, strrpos($ip, ':'));
}
// Supprimer les crochets de la notation [1234:5678::]
$ip = str_replace(['[', ']'], '', $ip);
// Forcer la réécriture de l'IP
$ip = inet_ntop(inet_pton($ip));
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$this->saveInTab($ip, $tabIp, self::IPV6);
}
} else {
// C'est une IPv4
// Supprimer le port
if ($withPort) {
$ip = substr($ip, 0, strrpos($ip, ':'));
}
// Valider l'IP et l'enregistrer si inconnue
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$this->saveInTab($ip, $tabIp, self::IPV4);
}
}
}
/**
* Insérer dans le tableau une adresse sans faire de doublon
* @param string $ip @ IP à ajouter
* @param array $tabIp Liste des addresses IP déjà connues
* @param string $typeIp IPv4 ou IPv6
*/
private function saveInTab(string $ip, array &$tabIp, string $typeIp): void
{
if (!in_array($ip, $tabIp[$typeIp], true)) {
$tabIp[$typeIp][] = self::formatIp($ip);
}
}
/**
* Formatter une adresse IP
* @param string $ip adresse IP à formatter
* @return string adresse IP formattée
*/
private static function formatIp(string $ip): string
{
return inet_ntop(inet_pton($ip));
}
/**
* Vérifie si une IP correspond à un noeud de sortie Tor
* @param string $ip
* @return bool
*/
public static function checkIp(string $ip): bool
{
$monRetour = true;
$ip = self::formatIp($ip);
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
if (file_exists(_TOR_LISTE_IPV6_) && filesize(_TOR_LISTE_IPV6_) > 0) {
try {
$tabIp = json_decode(file_get_contents(_TOR_LISTE_IPV6_), true, 512, JSON_THROW_ON_ERROR);
if (!in_array($ip, $tabIp, true)) {
$monRetour = false;
}
} catch (JsonException $e) {
// En cas d'erreur, par défaut, faire confiance à l'IP
$monRetour = false;
}
}
} elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
if (file_exists(_TOR_LISTE_IPV4_) && filesize(_TOR_LISTE_IPV4_) > 0) {
try {
$tabIp = json_decode(file_get_contents(_TOR_LISTE_IPV4_), true, 512, JSON_THROW_ON_ERROR);
if (!in_array($ip, $tabIp, true)) {
$monRetour = false;
}
} catch (JsonException $e) {
// En cas d'erreur, par défaut, faire confiance à l'IP
$monRetour = false;
}
}
}
return $monRetour;
}
}

View file

@ -0,0 +1,550 @@
<?php
/*
* Copyright 2008-2024 Anael MOBILIA
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
namespace ImageHeberg;
use PDO;
use ArrayObject;
/**
* Gestion (BDD) des utilisateurs
*/
class UtilisateurObject
{
private string $userName = '';
private string $password = '';
private string $email = '';
private string $dateInscription = '';
private string $ipInscription = '';
private int $level = self::LEVEL_GUEST;
private int $id = 0;
private bool $isActif = true;
private string $token = '';
// Niveaux de droits
final public const int LEVEL_GUEST = 0;
final public const int LEVEL_USER = 1;
final public const int LEVEL_ADMIN = 2;
/**
* @throws ImageHebergException
*/
public function __construct($userID = false)
{
// Utilisateur à charger
if ($userID && !$this->charger($userID)) {
// Envoi d'une exception si l'utilisateur n'existe pas
throw new ImageHebergException('Utilisateur ' . $userID . ' inexistant.');
}
}
/**
* Nom d'utilisateur avec htmlentities
* @return string
*/
public function getUserName(): string
{
return htmlentities($this->userName);
}
/**
* BDD - Nom d'utilisateur non htmlentities
* @return string
*/
private function getUserNameBDD(): string
{
return $this->userName;
}
/**
* Mot de passe
* @return string
*/
private function getPassword(): string
{
return $this->password;
}
/**
* Email
* @return string
*/
public function getEmail(): string
{
return $this->email;
}
/**
* Date d'inscription
* @return string
*/
private function getDateInscription(): string
{
return $this->dateInscription;
}
/**
* Date d'inscription formatée
* @return string
*/
public function getDateInscriptionFormate(): string
{
$phpdate = strtotime($this->getDateInscription());
return date('d/m/Y', $phpdate);
}
/**
* @ IP d'inscription
* @return string
*/
public function getIpInscription(): string
{
return $this->ipInscription;
}
/**
* Niveau de droits
* @return int
*/
public function getLevel(): int
{
return $this->level;
}
/**
* ID en BDD
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* Utilisateur est actif ?
* @return bool
*/
public function getIsActif(): bool
{
return $this->isActif;
}
/**
* Token associé au compte utilisateur
* @return string
*/
public function getToken(): string
{
return $this->token;
}
/**
* Utilisateur est actif ?
* @param bool $isActif
*/
public function setIsActif(bool $isActif): void
{
$this->isActif = $isActif;
}
/**
* Token lié à l'utilisateur
* @param string $token
*/
public function setToken(string $token): void
{
$this->token = $token;
}
/**
* Nom d'utilisateur
* @param string $userName
*/
public function setUserName(string $userName): void
{
$this->userName = $userName;
}
/**
* Mot de passe
* @param string $password
*/
private function setPassword(string $password): void
{
$this->password = $password;
}
/**
* Mot de passe à crypter
* @param string $password
*/
public function setPasswordToCrypt(string $password): void
{
$this->password = password_hash($password, PASSWORD_DEFAULT);
}
/**
* Email
* @param string $email
*/
public function setEmail(string $email): void
{
$this->email = $email;
}
/**
* Date d'inscription
* @param string $dateInscription
*/
private function setDateInscription(string $dateInscription): void
{
$this->dateInscription = $dateInscription;
}
/**
* @ IP d'inscription
* @param string $ipInscription
*/
private function setIpInscription(string $ipInscription): void
{
$this->ipInscription = $ipInscription;
}
/**
* Niveau de droits
* @param int $level
*/
public function setLevel(int $level): void
{
$this->level = $level;
}
/**
* ID en BDD
* @param int $id
*/
private function setId(int $id): void
{
$this->id = $id;
}
/**
* Connexion d'un utilisateur : vérification & création de la session
* @param string $user Nom de l'utilisateur
* @param string $pwd Mot de passe associé
* @return int ID de l'utilisateur (0 si identifiants invalides)
*/
private function verifierIdentifiants(string $user, string $pwd): int
{
// Identifiants KO par défaut
$monRetour = 0;
// Vérification de l'existance du login
$req = MaBDD::getInstance()->prepare('SELECT * FROM membres WHERE login = :login');
$req->bindValue(':login', $user);
$req->execute();
// Je récupère les potentielles valeurs
$resultat = $req->fetch();
// Si l'utilisateur existe
if ($resultat !== false) {
// Faut-il mettre à jour le hash du mot de passe ?
$updateHash = false;
// Est-ce un cas de compatibilité avec les anciens mots de passe ?
if (!str_starts_with($resultat->password, '$')) {
// Les hash générés par crypt possédent un schème spécifique avec $ en premier chr
// https://en.wikipedia.org/wiki/Crypt_(C)#Key_derivation_functions_supported_by_crypt
if (hash_equals($resultat->password, hash('sha256', _GRAIN_DE_SEL_ . $pwd))) {
// Ancien mot de passe => update hash du password ;-)
$updateHash = true;
// Identifiants matchent !
$monRetour = $resultat->id;
}
} elseif (password_verify($pwd, $resultat->password)) {
// Cas standard : comparaison du hash du mot de passe fourni avec celui stocké en base
// => Faut-il mettre à jour le chiffrement utilisé ?
if (password_needs_rehash($resultat->password, PASSWORD_DEFAULT)) {
$updateHash = true;
}
// Identifiants matchent !
$monRetour = $resultat->id;
}
// Mise à jour du hash si requis
if ($updateHash) {
$monUtilisateur = new UtilisateurObject();
$monUtilisateur->charger($resultat->id);
$monUtilisateur->setPasswordToCrypt($pwd);
$monUtilisateur->modifier();
}
}
return $monRetour;
}
/**
* Connexion d'un utilisateur : vérification & création de la session
* @param string $user Utilisateur
* @param string $pwd Mot de passe
* @return bool
*/
public function connexion(string $user, string $pwd): bool
{
// Protection contre une attaque : on délaie un peu l'action
usleep(500000);
// Ma session
$maSession = new SessionObject();
// Mon retour
$monRetour = false;
// Vérification des identifiants
$userID = $this->verifierIdentifiants($user, $pwd);
if ($userID) {
$monRetour = true;
// Chargement de mon utilisateur
$this->charger($userID);
// Je complète les variables de la session
$maSession->setIP($_SERVER['REMOTE_ADDR']);
$maSession->setUserObject($this);
// J'enregistre en BDD la connexion réussie
$req = MaBDD::getInstance()->prepare('INSERT INTO login (remote_addr, date_action, membres_id) VALUES (:ipLogin, NOW(), :membresId)');
$req->bindValue(':ipLogin', $_SERVER['REMOTE_ADDR']);
$req->bindValue(':membresId', $userID, PDO::PARAM_INT);
$req->execute();
}
// Retour...
return $monRetour;
}
/**
* Charge un utilisateur depuis la BDD
* @param int $userID ID en BDD
* @return bool Utilisateur existant ?
*/
private function charger(int $userID): bool
{
$monRetour = false;
// Je récupère les données en BDD
$req = MaBDD::getInstance()->prepare('SELECT * FROM membres WHERE id = :id');
$req->bindValue(':id', $userID, PDO::PARAM_INT);
$req->execute();
// Je récupère les potentielles valeurs
$resultat = $req->fetch();
// Si l'utilisateur n'existe pas... on retourne un UtilisateurObject vide
if ($resultat !== false) {
// Je charge les informations de l'utilisateur (sauf password)
$this->setId($userID);
$this->setEmail($resultat->email);
$this->setUserName($resultat->login);
$this->setDateInscription($resultat->date_action);
$this->setIpInscription($resultat->remote_addr);
$this->setLevel($resultat->lvl);
$this->setPassword($resultat->password);
$this->setIsActif($resultat->isActif);
$this->setToken($resultat->token);
// Gestion du retour
$monRetour = true;
}
return $monRetour;
}
/**
* Enregistrement (BDD) d'un utilisateur
*/
public function enregistrer(): void
{
$req = MaBDD::getInstance()->prepare('INSERT INTO membres (email, login, password, date_action, remote_addr, lvl, isActif, token) VALUES (:email, :login, :password, NOW(), :ipInscription, :lvl, :isActif, :token)');
$req->bindValue(':email', $this->getEmail());
$req->bindValue(':login', $this->getUserNameBDD());
$req->bindValue(':password', $this->getPassword());
// Date est définie par NOW()
$req->bindValue(':ipInscription', $_SERVER['REMOTE_ADDR']);
$req->bindValue(':lvl', $this->getLevel(), PDO::PARAM_INT);
$req->bindValue(':isActif', $this->getIsActif(), PDO::PARAM_BOOL);
$req->bindValue(':token', $this->getToken());
$req->execute();
}
/**
* Modifier (BDD) un utilisateur déjà existant
*/
public function modifier(): void
{
$req = MaBDD::getInstance()->prepare('UPDATE membres SET email = :email, login = :login, password = :password, lvl = :lvl, isActif = :isActif, token = :token WHERE id = :id');
$req->bindValue(':email', $this->getEmail());
$req->bindValue(':login', $this->getUserNameBDD());
$req->bindValue(':password', $this->getPassword());
$req->bindValue(':lvl', $this->getLevel(), PDO::PARAM_INT);
$req->bindValue(':isActif', $this->getIsActif(), PDO::PARAM_BOOL);
$req->bindValue(':token', $this->getToken());
$req->bindValue(':id', $this->getId(), PDO::PARAM_INT);
$req->execute();
}
/**
* Suppression (BDD) d'un utilisateur
*/
public function supprimer(): void
{
// Les images possédées
$req = MaBDD::getInstance()->prepare('DELETE FROM possede WHERE membres_id = :membresId');
$req->bindValue(':membresId', $this->getId(), PDO::PARAM_INT);
$req->execute();
// Historique des logins
$req = MaBDD::getInstance()->prepare('DELETE FROM login WHERE membres_id = :membresId');
$req->bindValue(':membresId', $this->getId(), PDO::PARAM_INT);
$req->execute();
// Paramètres du compte
$req = MaBDD::getInstance()->prepare('DELETE FROM membres WHERE id = :id');
$req->bindValue(':id', $this->getId(), PDO::PARAM_INT);
$req->execute();
}
/**
* Assigne une image à un utilisateur en BDD
* @param ImageObject $imageObject
* @throws ImageHebergException
*/
public function assignerImage(ImageObject $imageObject): void
{
if ($this->getId() === 0) {
throw new ImageHebergException('Aucun utilisateur n\'est défini !');
}
// Les images possédées
$req = MaBDD::getInstance()->prepare('INSERT INTO possede (images_id, membres_id) VALUES (:imagesId, :membresId)');
$req->bindValue(':imagesId', $imageObject->getId(), PDO::PARAM_INT);
$req->bindValue(':membresId', $this->getId(), PDO::PARAM_INT);
$req->execute();
}
/**
* Vérifier si un login est disponible pour enregistrement
* @param string $login
* @return bool
*/
public static function verifierLoginDisponible(string $login): bool
{
$req = MaBDD::getInstance()->prepare('SELECT * FROM membres WHERE login = :login');
$req->bindValue(':login', $login);
$req->execute();
// Par défaut le login est disponible
$monRetour = true;
// Si j'ai un résultat...
if ($req->fetch()) {
// Le retour est négatif
$monRetour = false;
}
return $monRetour;
}
/**
* Vérifier si un email est disponible pour enregistrement
* @param string $email
* @return bool
*/
public static function verifierEmailDisponible(string $email): bool
{
$req = MaBDD::getInstance()->prepare('SELECT * FROM membres WHERE email = :email');
$req->bindValue(':email', strtolower($email));
$req->execute();
// Par défaut l'email est disponible
$monRetour = true;
// Si j'ai un résultat...
if ($req->fetch()) {
// Le retour est négatif
$monRetour = false;
}
return $monRetour;
}
/**
* Vérifie que l'utilisateur à le droit d'afficher la page et affiche un EM au cas
* @param int $levelRequis Niveau de droit minimum requis
* @param bool $dieIfNotGranted Arrêter le script si le niveau de droit n'est pas atteint
* @return void|bool
*/
public static function checkAccess(int $levelRequis, bool $dieIfNotGranted = true)
{
$monRetour = false;
$monUser = new SessionObject();
if ($monUser->verifierDroits($levelRequis) === false) {
// Arrêter le script...
if ($dieIfNotGranted) {
header('HTTP/2 403 Forbidden');
require _TPL_TOP_;
echo '<h1 class="mb-3">Accès refusé</h1>';
echo '<p>Désolé, vous n\'avez pas le droit d\'accèder à cette page.</p>';
require _TPL_BOTTOM_;
die();
}
} else {
$monRetour = true;
}
return $monRetour;
}
/**
* Toutes les images appartenant à un utilisateur
* @return ArrayObject new_name image
*/
public function getImages(): ArrayObject
{
// Toutes les images
$req = MaBDD::getInstance()->prepare('SELECT new_name FROM possede, images WHERE id = images_id AND membres_id = :membresId ');
$req->bindValue(':membresId', $this->getId(), PDO::PARAM_INT);
// Exécution de la requête
$req->execute();
$monRetour = new ArrayObject();
// Pour chaque résultat retourné
foreach ($req->fetchAll() as $value) {
// J'ajoute le nom de l'image
$monRetour->append($value->new_name);
}
return $monRetour;
}
}

View file

@ -1,240 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Les images
*/
class imageObject extends ressourceObject implements ressourceInterface {
/**
* Constructeur
* @param string $newName nom de l'image
*/
function __construct($newName = FALSE) {
// Définition du type pour le ressourceObject
$this->setType(ressourceObject::typeImage);
// Si on me donne un ID d'image, je charge l'objet
if ($newName) {
if (!$this->charger($newName)) {
// Envoi d'une exception si l'image n'existe pas
throw new Exception('Image ' . $newName . ' inexistante');
}
}
}
/**
* {@inheritdoc}
*/
public function charger($newName) {
// Retour
$monRetour = FALSE;
// Je vais chercher les infos en BDD
$req = maBDD::getInstance()->prepare("SELECT * FROM images WHERE new_name = :newName");
$req->bindValue(':newName', $newName, PDO::PARAM_STR);
$req->execute();
// J'éclate les informations
$resultat = $req->fetch();
if ($resultat !== FALSE) {
$this->setId($resultat->id);
$this->setIpEnvoi($resultat->ip_envoi);
$this->setDateEnvoi($resultat->date_envoi);
$this->setNomOriginal($resultat->old_name);
// Permet l'effacement des fichiers non enregistrés en BDD
$this->setNomNouveau($newName);
$this->setPoids($resultat->size);
$this->setHauteur($resultat->height);
$this->setLargeur($resultat->width);
$this->setLastView($resultat->last_view);
$this->setNbViewIPv4($resultat->nb_view_v4);
$this->setNbViewIPv6($resultat->nb_view_v6);
$this->setMd5($resultat->md5);
$this->setBloque($resultat->bloque);
// Gestion du retour
$monRetour = TRUE;
}
return $monRetour;
}
/**
* {@inheritdoc}
*/
public function sauver() {
// J'enregistre les infos en BDD
$req = maBDD::getInstance()->prepare("UPDATE images SET ip_envoi = :ipEnvoi, date_envoi = :dateEnvoi, old_name = :oldName, new_name = :newName, size = :size, height = :height, width = :width, last_view = :lastView, nb_view_v4 = :nbViewV4, nb_view_v6 = :nbViewV6, md5 = :md5, bloque = :bloque WHERE id = :id");
$req->bindValue(':ipEnvoi', $this->getIpEnvoi(), PDO::PARAM_STR);
$req->bindValue(':dateEnvoi', $this->getDateEnvoiBrute());
$req->bindValue(':oldName', $this->getNomOriginal(), PDO::PARAM_STR);
$req->bindValue(':newName', $this->getNomNouveau(), PDO::PARAM_STR);
$req->bindValue(':size', $this->getPoids(), PDO::PARAM_INT);
$req->bindValue(':height', $this->getHauteur(), PDO::PARAM_INT);
$req->bindValue(':width', $this->getLargeur(), PDO::PARAM_INT);
$req->bindValue(':lastView', $this->getLastView());
$req->bindValue(':nbViewV4', $this->getNbViewIPv4(), PDO::PARAM_INT);
$req->bindValue(':nbViewV6', $this->getNbViewIPv6(), PDO::PARAM_INT);
$req->bindValue(':md5', $this->getMd5(), PDO::PARAM_STR);
$req->bindValue(':bloque', $this->isBloque(), PDO::PARAM_INT);
$req->bindValue(':id', $this->getId(), PDO::PARAM_INT);
$req->execute();
}
/**
* {@inheritdoc}
*/
public function supprimer() {
$monRetour = TRUE;
/**
* Suppression de la ou les miniatures
*/
// Chargement des miniatures
$req = maBDD::getInstance()->prepare("SELECT new_name FROM thumbnails where id_image = :idImage");
$req->bindValue(':idImage', $this->getId(), PDO::PARAM_INT);
$req->execute();
// Je passe toutes les lignes de résultat
foreach ($req->fetchAll() as $value) {
// Chargement de la miniature
$maMiniature = new miniatureObject($value->new_name);
// Suppression
$maMiniature->supprimer();
}
/**
* Suppression de l'affectation
*/
if ($monRetour) {
$req = maBDD::getInstance()->prepare("DELETE FROM possede WHERE image_id = :imageId");
/* @var $req PDOStatement */
$req->bindValue(':imageId', $this->getId(), PDO::PARAM_INT);
$monRetour = $req->execute();
}
/**
* Suppression de l'image en BDD
*/
if ($monRetour) {
$req = maBDD::getInstance()->prepare("DELETE FROM images WHERE id = :id");
/* @var $req PDOStatement */
$req->bindValue(':id', $this->getId(), PDO::PARAM_INT);
$monRetour = $req->execute();
}
/**
* Suppression du HDD
*/
if ($monRetour) {
// Existe-t-il d'autres occurences de cette image ?
$req = maBDD::getInstance()->prepare("SELECT COUNT(*) AS nb FROM images WHERE md5 = :md5");
/* @var $req PDOStatement */
$req->bindValue(':md5', $this->getMd5(), PDO::PARAM_STR);
$req->execute();
$values = $req->fetch();
// Il n'y a plus d'image identique...
if ($values !== FALSE && (int) $values->nb === 0) {
// Je supprime l'image sur le HDD
$monRetour = unlink($this->getPathMd5());
} elseif ($values === FALSE) {
$monRetour = FALSE;
}
}
return $monRetour;
}
/**
* {@inheritdoc}
*/
public function creer() {
/**
* Détermination du nom &&
* Vérification de sa disponibilité
*/
$tmpImage = new imageObject();
$nb = 0;
do {
// Récupération d'un nouveau nom
$new_name = $this->genererNom($nb);
// Incrémentation compteur entropie sur le nom
$nb++;
} while ($tmpImage->charger($new_name) !== FALSE);
// Effacement de l'objet temporaire
unset($tmpImage);
// On enregistre le nom
$this->setNomNouveau($new_name);
/**
* Déplacement du fichier
*/
// Chargement de l'image + enregistrement : permet de réduire la taille
$monRetour = outils::setImage(outils::getImage($this->getPathTemp()), outils::getType($this->getPathTemp()), $this->getPathMd5());
// Ssi copie du fichier réussie
if ($monRetour) {
/**
* Informations sur l'image
*/
// Dimensions
$imageInfo = getimagesize($this->getPathMd5());
$this->setLargeur($imageInfo[0]);
$this->setHauteur($imageInfo[1]);
// Poids
$this->setPoids(filesize($this->getPathMd5()));
// Nom originel (non récupérable sur le fichier)
$this->setNomOriginal($this->getNomTemp());
// @ IP d'envoi
$this->setIpEnvoi($_SERVER['REMOTE_ADDR']);
/**
* Création en BDD
*/
$req = maBDD::getInstance()->prepare("INSERT INTO images (ip_envoi, date_envoi, old_name, new_name, size, height, width, md5) VALUES (:ipEnvoi, NOW(), :oldName, :newName, :size, :height, :width, :md5)");
$req->bindValue(':ipEnvoi', $this->getIpEnvoi(), PDO::PARAM_STR);
// Date : NOW()
$req->bindValue(':oldName', $this->getNomOriginal(), PDO::PARAM_STR);
$req->bindValue(':newName', $this->getNomNouveau(), PDO::PARAM_STR);
$req->bindValue(':size', $this->getPoids(), PDO::PARAM_INT);
$req->bindValue(':height', $this->getHauteur(), PDO::PARAM_INT);
$req->bindValue(':width', $this->getLargeur(), PDO::PARAM_INT);
$req->bindValue(':md5', $this->getMd5(), PDO::PARAM_STR);
if (!$req->execute()) {
// Gestion de l'erreur d'insertion en BDD
$monRetour = FALSE;
} else {
/**
* Récupération de l'ID de l'image
*/
$idEnregistrement = maBDD::getInstance()->lastInsertId();
$this->setId($idEnregistrement);
}
}
return $monRetour;
}
}

View file

@ -1,86 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Lien vers la BDD
*
* @author anael
*/
class maBDD {
// PDO
private $maBDD = null;
// Instance de la classe
private static $monInstance = null;
/**
* Constructeur
*/
private function __construct() {
$this->maBDD = new PDO('mysql:host=' . _BDD_HOST_ . ';dbname=' . _BDD_NAME_, _BDD_USER_, _BDD_PASS_);
$this->maBDD->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->maBDD->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
}
/**
* Crée & renvoi l'objet d'instance
* @return PDO
*/
public static function getInstance() {
// Si pas de connexion active, en crée une
if (is_null(self::$monInstance)) {
self::$monInstance = new maBDD();
}
return self::$monInstance;
}
/**
* PDO::query
* @param type $query
* @return type
*/
public function query($query) {
return $this->maBDD->query($query);
}
/**
* PDO::prepare
* @param type $query
* @return type
*/
public function prepare($query) {
return $this->maBDD->prepare($query);
}
/**
* PDO::lastInsertId
* @return type
*/
public function lastInsertId() {
return $this->maBDD->lastInsertId();
}
/**
* Fermeture du PDO
*/
public static function close() {
self::$monInstance = null;
}
}

View file

@ -1,235 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Les méthodes "génériques"
*
* @author anael
*/
class metaObject {
/**
* Liste des images n'ayant jamais été affichées et présentes sur le serveur depuis une année
* @return \ArrayObject
*/
public static function getNeverUsedOneYear() {
// Toutes les images jamais affichées & envoyées il y a plus d'un an
$req = "SELECT new_name FROM images where last_view = '0000-00-00'
AND date_envoi < DATE_SUB(CURRENT_DATE(), INTERVAL 1 YEAR)
AND id NOT IN (SELECT image_id FROM possede)";
// Exécution de la requête
$resultat = maBDD::getInstance()->query($req);
$retour = new ArrayObject();
// Pour chaque résultat retourné
foreach ($resultat->fetchAll() as $value) {
// J'ajoute le nom de l'image
$retour->append($value->new_name);
}
return $retour;
}
/**
* Liste des images n'ayant pas été affichées les trois dernières années
* @return \ArrayObject
*/
public static function getUnusedThreeYear() {
// Toutes les images non affichées depuis 3 ans
$req = "SELECT new_name FROM images where last_view < DATE_SUB(CURRENT_DATE(), INTERVAL 3 YEAR)
AND date_envoi < DATE_SUB(CURRENT_DATE(), INTERVAL 3 YEAR)
AND id NOT IN (SELECT image_id FROM possede)";
// Exécution de la requête
$resultat = maBDD::getInstance()->query($req);
$retour = new ArrayObject();
// Pour chaque résultat retourné
foreach ($resultat->fetchAll() as $value) {
// J'ajoute le nom de l'image
$retour->append($value->new_name);
}
return $retour;
}
/**
* Liste de l'ensemble des images en BDD
* @return \ArrayObject
*/
public static function getAllImagesNameBDD() {
// Toutes les images (sauf 404 & banned)
$req = "SELECT md5 FROM images WHERE id > 2";
// Exécution de la requête
$resultat = maBDD::getInstance()->query($req);
$retour = new ArrayObject();
// Pour chaque résultat retourné
foreach ($resultat->fetchAll() as $value) {
// J'ajoute le nom de l'image
$retour->append($value->md5);
}
return $retour;
}
/**
* Liste de l'ensemble des images en HDD
* @param type $path path à analyser
* @return \ArrayObject
*/
public static function getAllImagesNameHDD($path) {
$monRetour = new ArrayObject();
// Scanne le répertoire des images
$scan_rep = scandir($path);
// Pour chaque item
foreach ($scan_rep as $item) {
if ($item !== '.' && $item !== '..' && $item !== '_dummy') {
if (is_dir($path . $item)) {
// Appel récursif
if ($path . $item . '/' !== _PATH_MINIATURES_) {
$monRetourTmp = self::getAllImagesNameHDD($path . $item . '/');
// Parsage et récupération des sous fichiers...
foreach ($monRetourTmp as $fichier) {
$monRetour->append($fichier);
}
}
} elseif ($item !== _IMAGE_404_ && $item !== _IMAGE_BAN_) {
$monRetour->append($item);
}
}
}
return $monRetour;
}
/**
* Liste de l'ensemble des miniatures en BDD
*/
public static function getAllMiniaturesNameBDD() {
// Toutes les images
$req = "SELECT thumbnails.md5 FROM images, thumbnails WHERE images.id = thumbnails.id";
// Exécution de la requête
$resultat = maBDD::getInstance()->query($req);
$retour = new ArrayObject();
// Pour chaque résultat retourné
foreach ($resultat->fetchAll() as $value) {
// J'ajoute le nom de l'image
$retour->append($value->md5);
}
return $retour;
}
/**
* Toutes les images appartenant à un utilisateur
* @param type $userId ID de l'user en question
* @return \ArrayObject new_name image
*/
public static function getAllPicsOffOneUser($userId) {
// Toutes les images
$req = maBDD::getInstance()->prepare("SELECT new_name FROM possede, images WHERE id = image_id AND pk_membres = :pkMembres ");
/* @var $req PDOStatement */
$req->bindValue(':pkMembres', $userId, PDO::PARAM_INT);
// Exécution de la requête
$req->execute();
$retour = new ArrayObject();
// Pour chaque résultat retourné
foreach ($req->fetchAll() as $value) {
// J'ajoute le nom de l'image
$retour->append($value->new_name);
}
return $retour;
}
/**
* Vérifie que l'utilisateur à le droit d'afficher la page et affiche un EM au cas
* @param type $levelRequis
*/
public static function checkUserAccess($levelRequis) {
$monUser = new sessionObject();
if ($monUser->verifierDroits($levelRequis) === FALSE) {
require _TPL_TOP_;
?>
<h1>Accès refusé</h1>
<p>Désolé, vous n'avez pas le droit d'accèder à cette page.</p>
<?php
require _TPL_BOTTOM_;
die();
}
}
/**
* Vérifier si un login est disponible pour enregistrement
* @param type $login
* @return boolean
*/
public static function verifierLoginDisponible($login) {
$req = maBDD::getInstance()->prepare("SELECT * FROM membres WHERE login = :login");
/* @var $req PDOStatement */
$req->bindValue(':login', $login, PDO::PARAM_STR);
$req->execute();
// Par défaut le login est disponible
$retour = TRUE;
// Si j'ai un résultat...
if ($req->fetch()) {
// Le retour est négatif
$retour = FALSE;
}
return $retour;
}
/**
* Page de provenance des visiteurs
* @return \ArrayObject
*/
public static function getReferers() {
// Toutes les images
$req = "SELECT urlExt, count(*) AS nb FROM referer
GROUP BY urlExt";
// Exécution de la requête
$resultat = maBDD::getInstance()->query($req);
$retour = new ArrayObject();
// Pour chaque résultat retourné
foreach ($resultat->fetchAll() as $value) {
// J'ajoute le nom de l'image
$retour->offsetSet($value->urlExt, $value->nb);
}
return $retour;
}
}

View file

@ -1,228 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Les miniatures
*/
class miniatureObject extends ressourceObject implements ressourceInterface {
private $idImage;
/**
* Constructeur
* @param string $newName newName de l'image maître
*/
function __construct($newName = FALSE) {
// Définition du type pour le ressourceObject
$this->setType(ressourceObject::typeMiniature);
// Si on me donne un newName d'image, je charge l'objet
if ($newName) {
if (!$this->charger($newName)) {
// Envoi d'une exception si l'image n'existe pas
throw new Exception('Miniature ' . $newName . ' inexistante');
}
}
}
/**
* {@inheritdoc}
*/
public function charger($newName) {
$monRetour = FALSE;
// Je vais chercher les infos en BDD
$req = maBDD::getInstance()->prepare("SELECT * FROM thumbnails WHERE new_name = :newName");
/* @var $req PDOStatement */
$req->bindValue(':newName', $newName, PDO::PARAM_INT);
$req->execute();
// J'éclate les informations
$resultat = $req->fetch();
if ($resultat !== FALSE) {
$this->setPoids($resultat->size);
$this->setHauteur($resultat->height);
$this->setLargeur($resultat->width);
$this->setLastView($resultat->last_view);
$this->setNbViewIPv4($resultat->nb_view_v4);
$this->setNbViewIPv6($resultat->nb_view_v6);
$this->setMd5($resultat->md5);
$this->setId($resultat->id);
$this->setDateEnvoi($resultat->date_creation);
$this->setNomNouveau($newName);
$this->setIdImage($resultat->id_image);
// Reprise des informations de l'image maitresse
$imageMaitre = new imageObject();
$imageMaitre->charger($newName);
$this->setBloque($imageMaitre->isBloque());
$this->setNomOriginal($imageMaitre->getNomOriginal());
$this->setIpEnvoi($imageMaitre->getIpEnvoi());
// Notification du chargement réussi
$monRetour = TRUE;
}
return $monRetour;
}
/**
* {@inheritdoc}
*/
public function sauver() {
// J'enregistre les infos en BDD
$req = maBDD::getInstance()->prepare("UPDATE thumbnails SET id_image = :idImage, date_creation = :dateCreation, new_name = :newName, size = :size, height = :height, width = :width, last_view = :lastView, nb_view_v4 = :nbViewV4, nb_view_v6 = :nbViewV6, md5 = :md5 WHERE id = :id");
$req->bindValue(':idImage', $this->getIdImage(), PDO::PARAM_INT);
$req->bindValue(':dateCreation', $this->getDateEnvoiBrute());
$req->bindValue(':newName', $this->getNomNouveau(), PDO::PARAM_STMT);
$req->bindValue(':size', $this->getPoids(), PDO::PARAM_INT);
$req->bindValue(':height', $this->getHauteur(), PDO::PARAM_INT);
$req->bindValue(':width', $this->getLargeur(), PDO::PARAM_INT);
$req->bindValue(':lastView', $this->getLastView());
$req->bindValue(':nbViewV4', $this->getNbViewIPv4(), PDO::PARAM_INT);
$req->bindValue(':nbViewV6', $this->getNbViewIPv6(), PDO::PARAM_INT);
$req->bindValue(':md5', $this->getMd5(), PDO::PARAM_STR);
$req->bindValue(':id', $this->getId(), PDO::PARAM_INT);
$req->execute();
}
/**
* {@inheritdoc}
*/
public function supprimer() {
$monRetour = TRUE;
/**
* Suppression de l'image en BDD
*/
$req = maBDD::getInstance()->prepare("DELETE FROM thumbnails WHERE id = :id");
/* @var $req PDOStatement */
$req->bindValue(':id', $this->getId(), PDO::PARAM_INT);
$monRetour = $req->execute();
/**
* Suppression du HDD
*/
if ($monRetour) {
// Existe-t-il d'autres occurences de cette image ?
$req = maBDD::getInstance()->prepare("SELECT COUNT(*) AS nb FROM thumbnails WHERE md5 = :md5");
/* @var $req PDOStatement */
$req->bindValue(':md5', $this->getMd5(), PDO::PARAM_STR);
$req->execute();
$values = $req->fetch();
// Il n'y a plus d'image identique...
if ($values !== FALSE && (int) $values->nb === 0) {
// Je supprime l'image sur le HDD
$monRetour = unlink($this->getPathMd5());
} elseif ($values === FALSE) {
$monRetour = FALSE;
}
}
return $monRetour;
}
/**
* {@inheritdoc}
*/
public function creer() {
/**
* Détermination du nom &&
* Vérification de sa disponibilité
*/
$tmpMiniature = new miniatureObject();
$nb = 0;
do {
// Récupération d'un nouveau nom
$new_name = $this->genererNom($nb);
// Incrémentation compteur entropie sur le nom
$nb++;
} while ($tmpMiniature->charger($new_name) !== FALSE);
// Effacement de l'objet temporaire
unset($tmpMiniature);
// On enregistre le nom
$this->setNomNouveau($new_name);
/**
* Déplacement du fichier
*/
$monRetour = rename($this->getPathTemp(), $this->getPathMd5());
// Ssi copie du fichier réussie
if ($monRetour) {
/**
* Informations sur l'image
*/
// Dimensions
$imageInfo = getimagesize($this->getPathMd5());
$this->setLargeur($imageInfo[0]);
$this->setHauteur($imageInfo[1]);
// Poids
$this->setPoids(filesize($this->getPathMd5()));
/**
* Création en BDD
*/
$req = maBDD::getInstance()->prepare("INSERT INTO thumbnails (id_image, date_creation, new_name, size, height, width, md5) VALUES (:idImage, NOW(), :newName, :size, :height, :width, :md5)");
$req->bindValue(':idImage', $this->getIdImage(), PDO::PARAM_INT);
// Date : NOW()
$req->bindValue(':newName', $this->getNomNouveau(), PDO::PARAM_STR);
$req->bindValue(':size', $this->getPoids(), PDO::PARAM_INT);
$req->bindValue(':height', $this->getHauteur(), PDO::PARAM_INT);
$req->bindValue(':width', $this->getLargeur(), PDO::PARAM_INT);
$req->bindValue(':md5', $this->getMd5(), PDO::PARAM_STR);
if (!$req->execute()) {
// Gestion de l'erreur d'insertion en BDD
$monRetour = FALSE;
} else {
/**
* Récupération de l'ID de l'image
*/
$idEnregistrement = maBDD::getInstance()->lastInsertId();
$this->setId($idEnregistrement);
}
}
return $monRetour;
}
/**
* GETTERS & SETTERS
*/
/**
* ID image parente
* @return int
*/
public function getIdImage() {
return $this->idImage;
}
/**
* ID image parente
* @param int $idImage
*/
public function setIdImage($idImage) {
$this->idImage = $idImage;
}
}

View file

@ -1,268 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Bibliothèque d'outils pour la gestion des images
*/
class outils {
/**
* Type de l'image
* @param string $path chemin sur le filesystem
* @return string
*/
public static function getType($path) {
return exif_imagetype($path);
}
/**
* MIME type de l'image
* @param string $path chemin sur le filesystem
* @return string
*/
public static function getMimeType($path) {
return image_type_to_mime_type(self::getType($path));
}
/**
* Chargement ressource PHP image
* @return resource
*/
public static function getImage($path) {
$monImage = NULL;
// Je charge l'image en mémoire en fonction de son type
switch (self::getType($path)) {
case IMAGETYPE_GIF:
$monImage = imagecreatefromgif($path);
break;
case IMAGETYPE_JPEG:
$monImage = imagecreatefromjpeg($path);
break;
case IMAGETYPE_PNG:
$monImage = imagecreatefrompng($path);
break;
}
return $monImage;
}
/**
* Enregistrement d'une ressource PHP image
* @param ressource $uneImage Image a enregistrer
* @param int $imageType type PHP de l'image
* @param string $path chemin du fichier
* @return boolean Succès ?
*/
public static function setImage($uneImage, $imageType, $path) {
$monRetour = FALSE;
// Je charge l'image en mémoire en fonction de son type
switch ($imageType) {
case IMAGETYPE_GIF:
$monRetour = imagegif($uneImage, $path);
break;
case IMAGETYPE_JPEG:
$monRetour = imagejpeg($uneImage, $path, 100);
break;
case IMAGETYPE_PNG:
$monRetour = imagepng($uneImage, $path, 9);
break;
}
return $monRetour;
}
/**
* Fourni l'extension officielle d'une ressource
* @param string $path chemin sur le filesystem
* @return string
*/
public static function getExtension($path) {
$ext = image_type_to_extension(self::getType($path), FALSE);
if ($ext === 'jpeg') {
// Préférence pour .jpg [filenmae.ext]
$ext = 'jpg';
}
return $ext;
}
/**
* Taille mémoire maximale autorisée
* @see http://php.net/manual/fr/function.ini-get.php
* @return int
*/
public static function getMemoireAllouee() {
// Récupération de la valeur du php.ini
$valBrute = trim(ini_get('memory_limit'));
// Gestion de l'unité multiplicatrice...
$unite = strtolower(substr($valBrute, -1));
$val = (int) substr($valBrute, 0, -1);
switch ($unite) {
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $val;
}
/**
* Est-il possible de modifier l'image (mémoire suffisante ?)
* @param string $path
* @return boolean Possible ?
* @see http://www.dotsamazing.com/en/labs/phpmemorylimit
*/
public static function isModifiableEnMemoire($path) {
$monRetour = FALSE;
// Nombre de canaux d'information de l'image
$nbCanaux = 4;
/**
* Information sur les canaux ?
*/
$imageinfo = getimagesize($path);
// Si information sur les canaux de l'image...
if (isset($imageinfo['channels']) && is_int($imageinfo['channels'])) {
$nbCanaux = $imageinfo['channels'];
}
/**
* Mémoire requise :
* (hauteur x largeur x profondeur)
* => x 2 [imageSource + imageDest]
* => x 1.8 [fudge factor]
*/
$memReq = $imageinfo[1] * $imageinfo[0] * $nbCanaux;
$memReq *= 2;
$memReq *= _FUDGE_FACTOR_;
// Est-ce possible ?
if ($memReq < self::getMemoireAllouee()) {
$monRetour = TRUE;
}
return $monRetour;
}
/**
* Dimension maximale acceptable en mémoire pour les images
* <br />Suppose que l'image est carrée (donc indicatif !)
* <br /> Suppose 4 canaux dans l'image
* @return int
* @see isModifiableEnMemoire
*/
public static function getMaxDimension() {
$memDispo = self::getMemoireAllouee();
/**
* Mémoire requise :
* (hauteur x largeur x profondeur)
* => x 2 [imageSource + imageDest]
* => x 1.8 [fudge factor]
*/
$dimMax = round(sqrt($memDispo / 4 / 2 / _FUDGE_FACTOR_), 0);
return (int) $dimMax;
}
/**
* Vérifie l'existence de l'image pour :
* @param string $unMD5 le md5 du fichier
* @param string $uneIp l'adresse IP d'envoi
* @param int $typeImage ressourceObject::const Type de l'image
* @return string|NULL Nom de l'image si déjà présente
*/
public static function verifierRenvoiImage($unMD5, $uneIp, $typeImage) {
$monRetour = NULL;
// Info de l'utilisateur
$maSession = new sessionObject();
if (_TRAVIS_) {
var_dump($maSession);
}
/**
* IMAGE
*/
if ($typeImage === ressourceObject::typeImage) {
if ($maSession->getLevel() === utilisateurObject::levelGuest) {
/**
* Utilisateur anonyme
* Recherche sur MD5, @IP (sauf images possédées) sur les 15 derniers jours !
*/
$req = maBDD::getInstance()->prepare("SELECT new_name FROM images WHERE md5 = :md5 AND ip_envoi = :ipEnvoi AND date_envoi > DATE_SUB(NOW(), INTERVAL 15 DAY) AND id NOT IN (SELECT image_id from possede) ORDER BY date_envoi DESC");
/* @var $req PDOStatement */
$req->bindValue(':md5', $unMD5, PDO::PARAM_STR);
$req->bindValue(':ipEnvoi', $uneIp, PDO::PARAM_STR);
} else {
/**
* Utilisateur authentifié
* Recherche sur MD5, possede (sur ses images)
*/
$req = maBDD::getInstance()->prepare("SELECT new_name FROM images, possede, membres WHERE md5 = :md5 AND images.id = possede.image_id AND possede.pk_membres = membres.id AND membres.id = :id ORDER BY date_envoi DESC");
/* @var $req PDOStatement */
$req->bindValue(':md5', $unMD5, PDO::PARAM_STR);
$req->bindValue(':id', $maSession->getId(), PDO::PARAM_INT);
}
}
/**
* MINIATURE
*/ else {
if ($maSession->getLevel() === utilisateurObject::levelGuest) {
/**
* Utilisateur anonyme
* Recherche sur MD5, @IP (sauf images possédées)
*/
$req = maBDD::getInstance()->prepare("SELECT thumbnails.new_name FROM thumbnails, images WHERE thumbnails.md5 = :md5 AND images.ip_envoi = :ipEnvoi AND thumbnails.date_creation > DATE_SUB(NOW(), INTERVAL 15 DAY) AND id_image NOT IN (SELECT image_id from possede) AND thumbnails.id_image = images.id ORDER BY date_envoi DESC");
/* @var $req PDOStatement */
$req->bindValue(':md5', $unMD5, PDO::PARAM_STR);
$req->bindValue(':ipEnvoi', $uneIp, PDO::PARAM_STR);
} else {
/**
* Utilisateur authentifié
* Recherche sur MD5, possede (sur ses images)
*/
$req = maBDD::getInstance()->prepare("SELECT thumbnails.new_name FROM thumbnails, images, possede, membres WHERE thumbnails.md5 = :md5 AND images.id = possede.image_id AND possede.pk_membres = membres.id AND membres.id = :id AND thumbnails.id_image = images.id ORDER BY date_envoi DESC");
/* @var $req PDOStatement */
$req->bindValue(':md5', $unMD5, PDO::PARAM_STR);
$req->bindValue(':id', $maSession->getId(), PDO::PARAM_INT);
}
}
// Exécution de la requête
$req->execute();
// Je récupère les potentielles valeurs
$values = $req->fetch();
if ($values !== FALSE) {
// Données éventuelles
$monRetour = $values->new_name;
}
if (_TRAVIS_) {
var_dump($monRetour);
}
return $monRetour;
}
}

View file

@ -1,566 +0,0 @@
<?php
/*
* Copyright 2008-2018 Anael Mobilia
*
* This file is part of image-heberg.fr.
*
* image-heberg.fr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* image-heberg.fr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with image-heberg.fr. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Fonctions génériques aux images et miniatures
*/
abstract class ressourceObject {
const typeImage = 1;
const typeMiniature = 2;
private $id;
private $nomOriginal;
private $nomNouveau;
private $largeur;
private $hauteur;
private $poids;
private $lastView;
private $nbViewIPv4;
private $nbViewIPv6;
private $dateEnvoi;
private $md5;
private $ipEnvoi;
private $bloque;
private $pathTemp;
private $type;
private $nomTemp;
/**
* Génère le nom d'une nouvelle image
* @param int $nb nombre de chiffres à rajouter à la fin du nom
* @return string nom de l'image
*/
protected function genererNom($nb = 0) {
// Random pour unicité + cassage lien nom <-> @IP
$random = rand(100, 999);
// @IP expéditeur
$adresseIP = abs(crc32($_SERVER['REMOTE_ADDR'] . $random));
// Timestamp d'envoi
$timestamp = $_SERVER['REQUEST_TIME'];
// Calcul du nom de l'image
$new_name = $timestamp . $adresseIP . substr($random, 0, $nb) . '.' . outils::getExtension($this->getPathTemp());
return $new_name;
}
/**
* MD5 de la ressource
* @return string
*/
public function getMd5() {
// Création d'une image
if (is_null($this->md5)) {
// Fichier temporaire...
$this->md5 = md5_file($this->getPathTemp());
}
return $this->md5;
}
/**
* Path sur le HDD
* @return string
*/
public function getPathMd5() {
// Path final
$pathFinal = '';
// Path du type d'image
$pathDuType = '';
if ($this->getType() === self::typeImage) {
// Image
$pathDuType = _PATH_IMAGES_;
} else {
// Miniature
$pathDuType = _PATH_MINIATURES_;
}
if ($this->getType() === self::typeImage && ($this->getId() === 1 || $this->getId() === 2)) {
// Gestion des images spécificques 404 / ban
$pathFinal = $pathDuType . $this->getNomNouveau();
} else {
// Cas par défaut
$rep = substr($this->getMd5(), 0, 1) . '/';
$pathFinal = $pathDuType . $rep . $this->getMd5();
}
return $pathFinal;
}
/**
* URL de la ressource
* @return string
*/
public function getURL() {
// Path du type d'image
$urlDuType = '';
if ($this->getType() === self::typeImage) {
// Image
$urlDuType = _URL_IMAGES_;
} else {
// Miniature
$urlDuType = _URL_MINIATURES_;
}
return $urlDuType . $this->getNomNouveau();
}
/**
* Rotation d'une ressource <br />
* Inclus mise à jour largeur / hauteur / poids de l'image
* @param int $angle xxx° de rotation GAUCHE
* @param string $pathSrc chemin de la ressource d'origine
* @param string $pathDst chemin de la ressource de destination
* @return boolean succès ?
*/
function rotation($angle, $pathSrc, $pathDst) {
// Je charge l'image en mémoire
$resImg = outils::getImage($pathSrc);
// Je vérifie que tout va bien
if ($resImg === FALSE) {
return FALSE;
}
// J'effectue la rotation
$imgRotate = imagerotate($resImg, $angle, 0);
// Je vérifie que tout va bien
if ($imgRotate === FALSE) {
return FALSE;
}
// Nettoyage mémoire (image d'origine)
imagedestroy($resImg);
// J'enregistre l'image
$retour = outils::setImage($imgRotate, outils::getType($pathSrc), $pathDst);
// La création du fichier s'est bien passé ?
if ($retour === FALSE) {
return FALSE;
}
// Mise à jour des propriétés de l'image
// Dimensions
$this->setLargeur(imagesx($imgRotate));
$this->setHauteur(imagesy($imgRotate));
// Poids de l'image
$this->setPoids(filesize($pathDst));
return $retour;
}
/**
* Redimensionne une image en respectant le ratio de l'image original
* @param string $pathSrc chemin de la ressource d'origine
* @param string $pathDst chemin de la ressource de destination
* @param int $largeurDemandee largeur souhaitée
* @param int $hauteurDemandee hauteur souhaitée
* @return boolean réussi ?
*/
public function redimensionner($pathSrc, $pathDst, $largeurDemandee, $hauteurDemandee) {
// Chargement de l'image
$monImage = outils::getImage($pathSrc);
// Récupération de ses dimensions
$largeurImage = imagesx($monImage);
$hauteurImage = imagesy($monImage);
// Dimension nulle : on arrête
if ($hauteurImage <= 0 || $hauteurDemandee <= 0 || $largeurImage <= 0 || $largeurDemandee <= 0 || $largeurImage <= $largeurDemandee || $hauteurImage <= $hauteurDemandee) {
return false;
}
/**
* @author Nicolas
*/
if ($largeurImage > $hauteurImage) {
// Format paysage
$largeurMax = max(array($largeurDemandee, $hauteurDemandee));
$hauteurMax = min(array($largeurDemandee, $hauteurDemandee));
} else {
// Format portrait ou carré
$largeurMax = min(array($largeurDemandee, $hauteurDemandee));
$hauteurMax = max(array($largeurDemandee, $hauteurDemandee));
}
// Calcul du ratio
$monRatio = min(array($largeurMax / $largeurImage, $hauteurMax / $hauteurImage));
// Dimensions finales
$largeurFinale = round($largeurImage * $monRatio);
$hauteurFinale = round($hauteurImage * $monRatio);
// Debug
if (_TRAVIS_) {
echo "Initial : " . $largeurImage . " x " . $hauteurImage . "\r\n";
echo "Demandé : " . $largeurDemandee . " x " . $hauteurDemandee . "\r\n";
echo "Fourni : " . $largeurFinale . " x " . $hauteurFinale . "\r\n";
}
// Redimensionnement (en mémoire)
$newImage = imagescale($monImage, $largeurFinale, $hauteurFinale);
// Ecriture de l'image
$monRetour = outils::setImage($newImage, outils::getType($pathSrc), $pathDst);
return $monRetour;
}
/**
* Cet utilisateur est-il propriétaire de l'image ?
* @return boolean
*/
public function isProprietaire() {
$monRetour = FALSE;
// Je vais chercher les infos en BDD
$req = maBDD::getInstance()->prepare("SELECT * FROM possede WHERE image_id = :imageId");
/* @var $req PDOStatement */
$req->bindValue(':imageId', $this->getId(), PDO::PARAM_INT);
$req->execute();
// Je récupère les potentielles valeurs
$values = $req->fetch();
// Si l'image à un propriétaire...
if ($values !== FALSE) {
// Le propriétaire est-il connecté ?
$uneSession = new sessionObject();
// Est-ce le propriétaire de l'image ?
if ((int) $values->pk_membres === $uneSession->getId()) {
// Si oui... on confirme !
$monRetour = TRUE;
}
}
return $monRetour;
}
/**
* Date d'envoi formatée
* @return string
*/
public function getDateEnvoiFormatee() {
$phpdate = strtotime($this->getDateEnvoiBrute());
return date("d/m/Y H:i:s", $phpdate);
}
/**
* Date de dernier affichage formaté
* @return string
*/
public function getLastViewFormate() {
$phpdate = strtotime($this->getLastView());
// Gestion du cas de non affichage
if ($phpdate === 0) {
return "-";
}
return date("d/m/Y", $phpdate);
}
/**
* Nombre d'appels IPv4 & IPv6
* @return int
*/
public function getNbViewTotal() {
return (int) $this->getNbViewIPv4() + $this->getNbViewIPv6();
}
/**
* Nom original de la ressource
* @return string
*/
public function getNomOriginalFormate() {
return htmlentities($this->nomOriginal);
}
/**
* Incrémente le nombre d'affichage IPv4
*/
public function setNbViewIpv4PlusUn() {
$this->nbViewIPv4 = $this->getNbViewIPv4() + 1;
$this->setLastView(date("Y-m-d"));
}
/**
* Incrémente le nombre d'affichage IPv6
*/
public function setNbViewIpv6PlusUn() {
$this->nbViewIPv6 = $this->getNbViewIPv6() + 1;
$this->setLastView(date("Y-m-d"));
}
/**
* GETTERS ET SETTERS
*/
/**
* ID de la ressource
* @return int
*/
public function getId() {
return (int) $this->id;
}
/**
* Nom original de la ressource
* @return string
*/
protected function getNomOriginal() {
return $this->nomOriginal;
}
/**
* Nom image-heberg
* @return string
*/
public function getNomNouveau() {
return $this->nomNouveau;
}
/**
* Largeur en px
* @return int
*/
public function getLargeur() {
return (int) $this->largeur;
}
/**
* Hauteur en px
* @return int
*/
public function getHauteur() {
return (int) $this->hauteur;
}
/**
* Poids de la ressource
* @return int
*/
public function getPoids() {
return (int) $this->poids;
}
/**
* Date de dernier affichage
* @return type
*/
protected function getLastView() {
return $this->lastView;
}
/**
* Nb d'affichage en IPv4
* @return int
*/
protected function getNbViewIPv4() {
return (int) $this->nbViewIPv4;
}
/**
* Nb d'affichage en IPv6
* @return int
*/
protected function getNbViewIPv6() {
return (int) $this->nbViewIPv6;
}
/**
* Date d'envoi du fichier
* @return type
*/
public function getDateEnvoiBrute() {
return $this->dateEnvoi;
}
/**
* @ IP d'envoi
* @return string
*/
public function getIpEnvoi() {
return $this->ipEnvoi;
}
/**
* Fichier bloqué ?
* @return boolean
*/
public function isBloque() {
return $this->bloque;
}
/**
* Path temporaire (upload d'image)
* @return string
*/
public function getPathTemp() {
return $this->pathTemp;
}
/**
* Type d'image
* @return int ressoruceObject const
*/
public function getType() {
return $this->type;
}
/**
* Nom temporaire (PC utilisateur - upload d'image)
* @return string
*/
public function getNomTemp() {
return $this->nomTemp;
}
/**
* Nom temporaire (PC utilisateur - upload d'image)
* @param string $nomTemp
*/
public function setNomTemp($nomTemp) {
$this->nomTemp = $nomTemp;
}
/**
* Type d'image
* @param int $type ressourceObject const
*/
public function setType($type) {
$this->type = $type;
}
/**
* Path temporaire (upload d'image)
* @param string $pathTemp
*/
public function setPathTemp($pathTemp) {
$this->pathTemp = $pathTemp;
}
/**
* Fichier bloqué ?
* @param boolean $bloque
*/
public function setBloque($bloque) {
$this->bloque = $bloque;
}
/**
* ID de l'image
* @param int $id
*/
protected function setId($id) {
$this->id = $id;
}
/**
* Nom original de la ressource
* @param string $nomOriginal
*/
protected function setNomOriginal($nomOriginal) {
$this->nomOriginal = $nomOriginal;
}
/**
* Nom image-heberg
* @param string $nomNouveau
*/
protected function setNomNouveau($nomNouveau) {
$this->nomNouveau = $nomNouveau;
}
/**
* Largeur en px
* @param int $largeur
*/
protected function setLargeur($largeur) {
$this->largeur = $largeur;
}
/**
* Hauteur en px
* @param int $hauteur
*/
protected function setHauteur($hauteur) {
$this->hauteur = $hauteur;
}
/**
* Poids de la ressource
* @param int $poids
*/
protected function setPoids($poids) {
$this->poids = $poids;
}
/**
* Date de dernier affichage
* @param type $lastView
*/
protected function setLastView($lastView) {
$this->lastView = $lastView;
}
/**
* Nb d'affichage en IPv4
* @param int $nbViewIPv4
*/
protected function setNbViewIPv4($nbViewIPv4) {
$this->nbViewIPv4 = $nbViewIPv4;
}
/**
* Nb d'affichage en IPv6
* @param int $nbViewIPv6
*/
protected function setNbViewIPv6($nbViewIPv6) {
$this->nbViewIPv6 = $nbViewIPv6;
}
/**
* Date d'envoi du fichier
* @param type $dateEnvoi
*/
protected function setDateEnvoi($dateEnvoi) {
$this->dateEnvoi = $dateEnvoi;
}
/**
* MD5 de la ressource
* @param string $md5
*/
protected function setMd5($md5) {
$this->md5 = $md5;
}
/**
* @ IP d'envoi
* @param string $ipEnvoi
*/
protected function setIpEnvoi($ipEnvoi) {
$this->ipEnvoi = $ipEnvoi;
}
}

Some files were not shown because too many files have changed in this diff Show more