Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

FileProfilerStorage.php

Zuletzt modifiziert: 02.04.2025, 15:03 - Dateigröße: 8.39 KiB


001  <?php
002   
003  /*
004   * This file is part of the Symfony package.
005   *
006   * (c) Fabien Potencier <fabien@symfony.com>
007   *
008   * For the full copyright and license information, please view the LICENSE
009   * file that was distributed with this source code.
010   */
011   
012  namespace Symfony\Component\HttpKernel\Profiler;
013   
014  /**
015   * Storage for profiler using files.
016   *
017   * @author Alexandre Salomé <alexandre.salome@gmail.com>
018   */
019  class FileProfilerStorage implements ProfilerStorageInterface
020  {
021      /**
022       * Folder where profiler data are stored.
023       *
024       * @var string
025       */
026      private $folder;
027   
028      /**
029       * Constructs the file storage using a "dsn-like" path.
030       *
031       * Example : "file:/path/to/the/storage/folder"
032       *
033       * @param string $dsn The DSN
034       *
035       * @throws \RuntimeException
036       */
037      public function __construct($dsn)
038      {
039          if (0 !== strpos($dsn, 'file:')) {
040              throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use FileStorage with an invalid dsn "%s". The expected format is "file:/path/to/the/storage/folder".', $dsn));
041          }
042          $this->folder = substr($dsn, 5);
043   
044          if (!is_dir($this->folder) && false === @mkdir($this->folder, 0777, true) && !is_dir($this->folder)) {
045              throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $this->folder));
046          }
047      }
048   
049      /**
050       * {@inheritdoc}
051       */
052      public function find($ip, $url, $limit, $method, $start = null, $end = null, $statusCode = null)
053      {
054          $file = $this->getIndexFilename();
055   
056          if (!file_exists($file)) {
057              return [];
058          }
059   
060          $file = fopen($file, 'r');
061          fseek($file, 0, \SEEK_END);
062   
063          $result = [];
064          while (\count($result) < $limit && $line = $this->readLineFromFile($file)) {
065              $values = str_getcsv($line);
066              list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode) = $values;
067              $csvTime = (int) $csvTime;
068   
069              if ($ip && false === strpos($csvIp, $ip) || $url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method) || $statusCode && false === strpos($csvStatusCode, $statusCode)) {
070                  continue;
071              }
072   
073              if (!empty($start) && $csvTime < $start) {
074                  continue;
075              }
076   
077              if (!empty($end) && $csvTime > $end) {
078                  continue;
079              }
080   
081              $result[$csvToken] = [
082                  'token' => $csvToken,
083                  'ip' => $csvIp,
084                  'method' => $csvMethod,
085                  'url' => $csvUrl,
086                  'time' => $csvTime,
087                  'parent' => $csvParent,
088                  'status_code' => $csvStatusCode,
089              ];
090          }
091   
092          fclose($file);
093   
094          return array_values($result);
095      }
096   
097      /**
098       * {@inheritdoc}
099       */
100      public function purge()
101      {
102          $flags = \FilesystemIterator::SKIP_DOTS;
103          $iterator = new \RecursiveDirectoryIterator($this->folder, $flags);
104          $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);
105   
106          foreach ($iterator as $file) {
107              if (is_file($file)) {
108                  unlink($file);
109              } else {
110                  rmdir($file);
111              }
112          }
113      }
114   
115      /**
116       * {@inheritdoc}
117       */
118      public function read($token)
119      {
120          if (!$token || !file_exists($file = $this->getFilename($token))) {
121              return null;
122          }
123   
124          return $this->createProfileFromData($token, unserialize(file_get_contents($file)));
125      }
126   
127      /**
128       * {@inheritdoc}
129       *
130       * @throws \RuntimeException
131       */
132      public function write(Profile $profile)
133      {
134          $file = $this->getFilename($profile->getToken());
135   
136          $profileIndexed = is_file($file);
137          if (!$profileIndexed) {
138              // Create directory
139              $dir = \dirname($file);
140              if (!is_dir($dir) && false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
141                  throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $dir));
142              }
143          }
144   
145          $profileToken = $profile->getToken();
146          // when there are errors in sub-requests, the parent and/or children tokens
147          // may equal the profile token, resulting in infinite loops
148          $parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null;
149          $childrenToken = array_filter(array_map(function ($p) use ($profileToken) {
150              return $profileToken !== $p->getToken() ? $p->getToken() : null;
151          }, $profile->getChildren()));
152   
153          // Store profile
154          $data = [
155              'token' => $profileToken,
156              'parent' => $parentToken,
157              'children' => $childrenToken,
158              'data' => $profile->getCollectors(),
159              'ip' => $profile->getIp(),
160              'method' => $profile->getMethod(),
161              'url' => $profile->getUrl(),
162              'time' => $profile->getTime(),
163              'status_code' => $profile->getStatusCode(),
164          ];
165   
166          if (false === file_put_contents($file, serialize($data))) {
167              return false;
168          }
169   
170          if (!$profileIndexed) {
171              // Add to index
172              if (false === $file = fopen($this->getIndexFilename(), 'a')) {
173                  return false;
174              }
175   
176              fputcsv($file, [
177                  $profile->getToken(),
178                  $profile->getIp(),
179                  $profile->getMethod(),
180                  $profile->getUrl(),
181                  $profile->getTime(),
182                  $profile->getParentToken(),
183                  $profile->getStatusCode(),
184              ]);
185              fclose($file);
186          }
187   
188          return true;
189      }
190   
191      /**
192       * Gets filename to store data, associated to the token.
193       *
194       * @param string $token
195       *
196       * @return string The profile filename
197       */
198      protected function getFilename($token)
199      {
200          // Uses 4 last characters, because first are mostly the same.
201          $folderA = substr($token, -2, 2);
202          $folderB = substr($token, -4, 2);
203   
204          return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token;
205      }
206   
207      /**
208       * Gets the index filename.
209       *
210       * @return string The index filename
211       */
212      protected function getIndexFilename()
213      {
214          return $this->folder.'/index.csv';
215      }
216   
217      /**
218       * Reads a line in the file, backward.
219       *
220       * This function automatically skips the empty lines and do not include the line return in result value.
221       *
222       * @param resource $file The file resource, with the pointer placed at the end of the line to read
223       *
224       * @return mixed A string representing the line or null if beginning of file is reached
225       */
226      protected function readLineFromFile($file)
227      {
228          $line = '';
229          $position = ftell($file);
230   
231          if (0 === $position) {
232              return null;
233          }
234   
235          while (true) {
236              $chunkSize = min($position, 1024);
237              $position -= $chunkSize;
238              fseek($file, $position);
239   
240              if (0 === $chunkSize) {
241                  // bof reached
242                  break;
243              }
244   
245              $buffer = fread($file, $chunkSize);
246   
247              if (false === ($upTo = strrpos($buffer, "\n"))) {
248                  $line = $buffer.$line;
249                  continue;
250              }
251   
252              $position += $upTo;
253              $line = substr($buffer, $upTo + 1).$line;
254              fseek($file, max(0, $position), \SEEK_SET);
255   
256              if ('' !== $line) {
257                  break;
258              }
259          }
260   
261          return '' === $line ? null : $line;
262      }
263   
264      protected function createProfileFromData($token, $data, $parent = null)
265      {
266          $profile = new Profile($token);
267          $profile->setIp($data['ip']);
268          $profile->setMethod($data['method']);
269          $profile->setUrl($data['url']);
270          $profile->setTime($data['time']);
271          $profile->setStatusCode($data['status_code']);
272          $profile->setCollectors($data['data']);
273   
274          if (!$parent && $data['parent']) {
275              $parent = $this->read($data['parent']);
276          }
277   
278          if ($parent) {
279              $profile->setParent($parent);
280          }
281   
282          foreach ($data['children'] as $token) {
283              if (!$token || !file_exists($file = $this->getFilename($token))) {
284                  continue;
285              }
286   
287              $profile->addChild($this->createProfileFromData($token, unserialize(file_get_contents($file)), $profile));
288          }
289   
290          return $profile;
291      }
292  }
293