serverLog.class.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <?php
  2. /**
  3. * Classe serverLog
  4. *
  5. * Cette classe gère les journaux du serveur, y compris l'affichage des logs,
  6. * la détection des types de logs, et le filtrage des informations sensibles.
  7. */
  8. class serverLog {
  9. /**
  10. * Affiche un log avec un style approprié en fonction de son contenu.
  11. *
  12. * @param string $_log Le message de log à afficher.
  13. */
  14. public static function printLog(string $_log){
  15. if (serverLog::detectLogsAttempts($_log)) {
  16. self::printLogAttempts($_log);
  17. } elseif (serverLog::detectApacheLog($_log)) {
  18. self::printColoredApacheLog($_log );
  19. } elseif (stripos($_log, 'error') !== false) {
  20. echo '<div style="color: salmon;">' . $_log . '</div>';
  21. } elseif (stripos($_log, 'fatal') !== false) {
  22. echo '<div style="color: #FF5252;">' . $_log . '</div>';
  23. } elseif (stripos($_log, 'warn') !== false OR stripos($_log, 'alert') !== false) {
  24. echo '<div style="color: orange;">' . $_log . '</div>';
  25. } elseif (stripos($_log, 'notice') !== false) {
  26. echo '<div style="color: white;">' . $_log . '</div>';
  27. } else {
  28. echo '<div style="color: grey;">' . $_log . '</div>';
  29. }
  30. }
  31. /**
  32. * Filtre un log pour masquer les informations sensibles avant de l'afficher.
  33. *
  34. * @param string $_log Le message de log à filtrer.
  35. */
  36. public static function filtreLog(string $_log){
  37. $log = self::hidePassword($_log);
  38. $log = self::hideEmail($log);
  39. self::printLog($log);
  40. }
  41. /**
  42. * Détecte si une chaîne correspond au format des tentatives de connexion.
  43. *
  44. * @param string $str La chaîne à analyser.
  45. * @return bool Vrai si la chaîne correspond, faux sinon.
  46. */
  47. private static function detectLogsAttempts(string $str): bool {
  48. return preg_match(
  49. '/^\d{1,3}(\.\d{1,3}){3},\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},/',
  50. $str
  51. ) === 1;
  52. }
  53. /**
  54. * Affiche un log formaté pour les tentatives de connexion.
  55. *
  56. * @param string $_log Le message de log à afficher.
  57. */
  58. public static function printLogAttempts(string $_log){
  59. $parts = explode(',', $_log, 4);
  60. if (count($parts) === 4) {
  61. echo '<div class="notice">'
  62. . '<span style="color:#4FC3F7;">' . htmlspecialchars($parts[0]) . '</span>, '
  63. . '<span style="color:#81C784;">' . htmlspecialchars($parts[1]) . '</span>, '
  64. . '<span style="color:#FFD54F;">' . htmlspecialchars($parts[2]) . '</span>, '
  65. . '<span style="color:#FF8A65;">' . htmlspecialchars($parts[3]) . '</span>'
  66. . '</div>';
  67. return;
  68. }
  69. }
  70. /**
  71. * Détecte si une chaîne correspond au format des logs Apache.
  72. *
  73. * @param string $str La chaîne à analyser.
  74. * @return bool Vrai si la chaîne correspond, faux sinon.
  75. */
  76. private static function detectApacheLog(string $str): bool {
  77. return preg_match(
  78. '/^\[(?<date>[A-Za-z]{3} [A-Za-z]{3} \d{2} [\d:.]+ \d{4})\] \[(?<type>[^\]]+)\] \[pid (?<pid>\d+):tid (?<tid>\d+)\] \[client (?<client>[^\]]+)\] (?<msg>.*?)(?:, referer: (?<referer>.+))?$/',
  79. $str
  80. ) === 1;
  81. }
  82. /**
  83. * Affiche un log Apache avec des couleurs pour chaque partie.
  84. *
  85. * @param string $line La ligne de log Apache à afficher.
  86. */
  87. public static function printColoredApacheLog(string $line) {
  88. $regex = '/^\[(?<date>[A-Za-z]{3} [A-Za-z]{3} \d{2} [\d:.]+ \d{4})\] \[(?<type>[^\]]+)\] \[pid (?<pid>\d+):tid (?<tid>\d+)\] \[client (?<client>[^\]]+)\] (?<msg>.*?)(?:, referer: (?<referer>.+))?$/';
  89. if (preg_match($regex, $line, $matches)) {
  90. echo '<div class="notice">'
  91. . '<span style="color:#4FC3F7;">[' . htmlspecialchars($matches['date']) . ']</span> '
  92. . '<span style="color:#FFD54F;">[' . htmlspecialchars($matches['type']) . ']</span> '
  93. . '<span style="color:#BDBDBD;">[pid ' . htmlspecialchars($matches['pid']) . ':tid ' . htmlspecialchars($matches['tid']) . ']</span> '
  94. . '<span style="color:#81C784;">[client ' . htmlspecialchars($matches['client']) . ']</span> '
  95. . '<span style="color:#FF8A65;">' . htmlspecialchars($matches['msg']) . '</span>';
  96. if (!empty($matches['referer'])) {
  97. echo ' <span style="color:#90CAF9;">referer: ' . htmlspecialchars($matches['referer']) . '</span>';
  98. }
  99. echo '</div>';
  100. } else {
  101. echo '<div style="color:grey;">' . htmlspecialchars($line) . '</div>';
  102. }
  103. }
  104. /**
  105. * Vérifie si un log contient le chemin du dossier www.
  106. *
  107. * @param string $_log Le message de log à analyser.
  108. * @return bool Vrai si le chemin est trouvé, faux sinon.
  109. */
  110. private static function ifFolderWww(string $_log){
  111. return (stripos($_log, DOCUMENT_ROOT) !== false) ? TRUE : FALSE;
  112. }
  113. /**
  114. * Vérifie si un log contient le domaine CMS.
  115. *
  116. * @param string $_log Le message de log à analyser.
  117. * @return bool Vrai si le domaine est trouvé, faux sinon.
  118. */
  119. private static function ifFolderDomain(string $_log){
  120. return (stripos($_log, DOMAIN_CMS) !== false) ? TRUE : FALSE;
  121. }
  122. /**
  123. * Vérifie si un log est général (ni dossier www, ni domaine CMS).
  124. *
  125. * @param string $_log Le message de log à analyser.
  126. * @return bool Vrai si le log est général, faux sinon.
  127. */
  128. private static function ifGeneral(string $_log){
  129. return (stripos($_log, "/var/www/") == FALSE AND stripos($_log, "https://") == FALSE) ? TRUE : FALSE;
  130. }
  131. /**
  132. * Masque les mots de passe dans une chaîne de log.
  133. *
  134. * @param string $input La chaîne à traiter.
  135. * @return string La chaîne avec les mots de passe masqués.
  136. */
  137. private static function hidePassword($input) {
  138. return preg_replace("/('password'\s*=>\s*)'[^']*'/", "$1'##PASSWORD##'", $input);
  139. }
  140. /**
  141. * Masque les adresses e-mail dans une chaîne de log.
  142. *
  143. * @param string $input La chaîne à traiter.
  144. * @return string La chaîne avec les adresses e-mail masquées.
  145. */
  146. private static function hideEmail($input) {
  147. return preg_replace("/('email'\s*=>\s*)'[^']*'/", "$1'##EMAIL##'", $input);
  148. }
  149. /**
  150. * Affiche les logs d'un fichier dans la console, avec des options de recherche et de limite.
  151. *
  152. * @param string $_logFile Le chemin du fichier de log à lire.
  153. */
  154. public static function consoleLog(string $_logFile){
  155. if (!is_readable($_logFile)) {
  156. echo "Le fichier n'est pas accessible en lecture.";
  157. exit();
  158. }
  159. $lines = file($_logFile);
  160. $search = strtolower($_GET['search'] ?? '');
  161. $limit = strtolower($_GET['limit'] ?? 50); // A défaut les 50 derniers logs
  162. if ($search) {
  163. $lines = array_filter($lines, fn($line) => stripos($line, $search) !== false);
  164. }
  165. $lines = array_reverse($lines);
  166. foreach (array_slice($lines, 0, $limit) as $line) {
  167. serverLog::filtreLog($line);
  168. }
  169. }
  170. }