Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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

file.php

Zuletzt modifiziert: 09.10.2024, 12:54 - Dateigröße: 11.41 KiB


001  <?php
002  /**
003  *
004  * This file is part of the phpBB Forum Software package.
005  *
006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
007  * @license GNU General Public License, version 2 (GPL-2.0)
008  *
009  * For full copyright and license information, please see
010  * the docs/CREDITS.txt file.
011  *
012  */
013   
014  namespace phpbb\cache\driver;
015   
016  /**
017  * ACM File Based Caching
018  */
019  class file extends \phpbb\cache\driver\base
020  {
021      var $var_expires = array();
022   
023      /**
024       * @var    \phpbb\filesystem\filesystem_interface
025       */
026      protected $filesystem;
027   
028      /**
029      * Set cache path
030      *
031      * @param string $cache_dir Define the path to the cache directory (default: $phpbb_root_path . 'cache/')
032      */
033      function __construct($cache_dir = null)
034      {
035          global $phpbb_container;
036   
037          $this->cache_dir = !is_null($cache_dir) ? $cache_dir : $phpbb_container->getParameter('core.cache_dir');
038          $this->filesystem = new \phpbb\filesystem\filesystem();
039   
040          if (!is_dir($this->cache_dir))
041          {
042              @mkdir($this->cache_dir, 0777, true);
043          }
044      }
045   
046      /**
047      * {@inheritDoc}
048      */
049      function load()
050      {
051          return $this->_read('data_global');
052      }
053   
054      /**
055      * {@inheritDoc}
056      */
057      function unload()
058      {
059          parent::unload();
060          unset($this->var_expires);
061          $this->var_expires = array();
062      }
063   
064      /**
065      * {@inheritDoc}
066      */
067      function save()
068      {
069          if (!$this->is_modified)
070          {
071              return;
072          }
073   
074          global $phpEx;
075   
076          if (!$this->_write('data_global'))
077          {
078              // Now, this occurred how often? ... phew, just tell the user then...
079              if (!$this->filesystem->is_writable($this->cache_dir))
080              {
081                  // We need to use die() here, because else we may encounter an infinite loop (the message handler calls $cache->unload())
082                  die('Fatal: ' . $this->cache_dir . ' is NOT writable.');
083                  exit;
084              }
085   
086              die('Fatal: Not able to open ' . $this->cache_dir . 'data_global.' . $phpEx);
087              exit;
088          }
089   
090          $this->is_modified = false;
091      }
092   
093      /**
094      * {@inheritDoc}
095      */
096      function tidy()
097      {
098          global $config, $phpEx;
099   
100          $dir = @opendir($this->cache_dir);
101   
102          if (!$dir)
103          {
104              return;
105          }
106   
107          $time = time();
108   
109          while (($entry = readdir($dir)) !== false)
110          {
111              if (!preg_match('/^(sql_|data_(?!global))/', $entry))
112              {
113                  continue;
114              }
115   
116              if (!($handle = @fopen($this->cache_dir . $entry, 'rb')))
117              {
118                  continue;
119              }
120   
121              // Skip the PHP header
122              fgets($handle);
123   
124              // Skip expiration
125              $expires = (int) fgets($handle);
126   
127              fclose($handle);
128   
129              if ($time >= $expires)
130              {
131                  $this->remove_file($this->cache_dir . $entry);
132              }
133          }
134          closedir($dir);
135   
136          if (file_exists($this->cache_dir . 'data_global.' . $phpEx))
137          {
138              if (!sizeof($this->vars))
139              {
140                  $this->load();
141              }
142   
143              foreach ($this->var_expires as $var_name => $expires)
144              {
145                  if ($time >= $expires)
146                  {
147                      $this->destroy($var_name);
148                  }
149              }
150          }
151   
152          $config->set('cache_last_gc', time(), false);
153      }
154   
155      /**
156      * {@inheritDoc}
157      */
158      function get($var_name)
159      {
160          if ($var_name[0] == '_')
161          {
162              if (!$this->_exists($var_name))
163              {
164                  return false;
165              }
166   
167              return $this->_read('data' . $var_name);
168          }
169          else
170          {
171              return ($this->_exists($var_name)) ? $this->vars[$var_name] : false;
172          }
173      }
174   
175      /**
176      * {@inheritDoc}
177      */
178      function put($var_name, $var, $ttl = 31536000)
179      {
180          if ($var_name[0] == '_')
181          {
182              $this->_write('data' . $var_name, $var, time() + $ttl);
183          }
184          else
185          {
186              $this->vars[$var_name] = $var;
187              $this->var_expires[$var_name] = time() + $ttl;
188              $this->is_modified = true;
189          }
190      }
191   
192      /**
193      * {@inheritDoc}
194      */
195      function purge()
196      {
197          parent::purge();
198          $this->var_expires = array();
199      }
200   
201      /**
202      * {@inheritDoc}
203      */
204      function destroy($var_name, $table = '')
205      {
206          global $phpEx;
207   
208          if ($var_name == 'sql' && !empty($table))
209          {
210              if (!is_array($table))
211              {
212                  $table = array($table);
213              }
214   
215              $dir = @opendir($this->cache_dir);
216   
217              if (!$dir)
218              {
219                  return;
220              }
221   
222              while (($entry = readdir($dir)) !== false)
223              {
224                  if (strpos($entry, 'sql_') !== 0)
225                  {
226                      continue;
227                  }
228   
229                  if (!($handle = @fopen($this->cache_dir . $entry, 'rb')))
230                  {
231                      continue;
232                  }
233   
234                  // Skip the PHP header
235                  fgets($handle);
236   
237                  // Skip expiration
238                  fgets($handle);
239   
240                  // Grab the query, remove the LF
241                  $query = substr(fgets($handle), 0, -1);
242   
243                  fclose($handle);
244   
245                  foreach ($table as $check_table)
246                  {
247                      // Better catch partial table names than no table names. ;)
248                      if (strpos($query, $check_table) !== false)
249                      {
250                          $this->remove_file($this->cache_dir . $entry);
251                          break;
252                      }
253                  }
254              }
255              closedir($dir);
256   
257              return;
258          }
259   
260          if (!$this->_exists($var_name))
261          {
262              return;
263          }
264   
265          if ($var_name[0] == '_')
266          {
267              $this->remove_file($this->cache_dir . 'data' . $var_name . ".$phpEx", true);
268          }
269          else if (isset($this->vars[$var_name]))
270          {
271              $this->is_modified = true;
272              unset($this->vars[$var_name]);
273              unset($this->var_expires[$var_name]);
274   
275              // We save here to let the following cache hits succeed
276              $this->save();
277          }
278      }
279   
280      /**
281      * {@inheritDoc}
282      */
283      function _exists($var_name)
284      {
285          if ($var_name[0] == '_')
286          {
287              global $phpEx;
288              $var_name = $this->clean_varname($var_name);
289              return file_exists($this->cache_dir . 'data' . $var_name . ".$phpEx");
290          }
291          else
292          {
293              if (!sizeof($this->vars))
294              {
295                  $this->load();
296              }
297   
298              if (!isset($this->var_expires[$var_name]))
299              {
300                  return false;
301              }
302   
303              return (time() > $this->var_expires[$var_name]) ? false : isset($this->vars[$var_name]);
304          }
305      }
306   
307      /**
308      * {@inheritDoc}
309      */
310      function sql_save(\phpbb\db\driver\driver_interface $db, $query, $query_result, $ttl)
311      {
312          // Remove extra spaces and tabs
313          $query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
314   
315          $query_id = md5($query);
316          $this->sql_rowset[$query_id] = array();
317          $this->sql_row_pointer[$query_id] = 0;
318   
319          while ($row = $db->sql_fetchrow($query_result))
320          {
321              $this->sql_rowset[$query_id][] = $row;
322          }
323          $db->sql_freeresult($query_result);
324   
325          if ($this->_write('sql_' . $query_id, $this->sql_rowset[$query_id], $ttl + time(), $query))
326          {
327              return $query_id;
328          }
329   
330          return $query_result;
331      }
332   
333      /**
334      * Read cached data from a specified file
335      *
336      * @access private
337      * @param string $filename Filename to write
338      * @return mixed False if an error was encountered, otherwise the data type of the cached data
339      */
340      function _read($filename)
341      {
342          global $phpEx;
343   
344          $filename = $this->clean_varname($filename);
345          $file = "{$this->cache_dir}$filename.$phpEx";
346   
347          $type = substr($filename, 0, strpos($filename, '_'));
348   
349          if (!file_exists($file))
350          {
351              return false;
352          }
353   
354          if (!($handle = @fopen($file, 'rb')))
355          {
356              return false;
357          }
358   
359          // Skip the PHP header
360          fgets($handle);
361   
362          if ($filename == 'data_global')
363          {
364              $this->vars = $this->var_expires = array();
365   
366              $time = time();
367   
368              while (($expires = (int) fgets($handle)) && !feof($handle))
369              {
370                  // Number of bytes of data
371                  $bytes = substr(fgets($handle), 0, -1);
372   
373                  if (!is_numeric($bytes) || ($bytes = (int) $bytes) === 0)
374                  {
375                      // We cannot process the file without a valid number of bytes
376                      // so we discard it
377                      fclose($handle);
378   
379                      $this->vars = $this->var_expires = array();
380                      $this->is_modified = false;
381   
382                      $this->remove_file($file);
383   
384                      return false;
385                  }
386   
387                  if ($time >= $expires)
388                  {
389                      fseek($handle, $bytes, SEEK_CUR);
390   
391                      continue;
392                  }
393   
394                  $var_name = substr(fgets($handle), 0, -1);
395   
396                  // Read the length of bytes that consists of data.
397                  $data = fread($handle, $bytes - strlen($var_name));
398                  $data = @unserialize($data);
399   
400                  // Don't use the data if it was invalid
401                  if ($data !== false)
402                  {
403                      $this->vars[$var_name] = $data;
404                      $this->var_expires[$var_name] = $expires;
405                  }
406   
407                  // Absorb the LF
408                  fgets($handle);
409              }
410   
411              fclose($handle);
412   
413              $this->is_modified = false;
414   
415              return true;
416          }
417          else
418          {
419              $data = false;
420              $line = 0;
421   
422              while (($buffer = fgets($handle)) && !feof($handle))
423              {
424                  $buffer = substr($buffer, 0, -1); // Remove the LF
425   
426                  // $buffer is only used to read integers
427                  // if it is non numeric we have an invalid
428                  // cache file, which we will now remove.
429                  if (!is_numeric($buffer))
430                  {
431                      break;
432                  }
433   
434                  if ($line == 0)
435                  {
436                      $expires = (int) $buffer;
437   
438                      if (time() >= $expires)
439                      {
440                          break;
441                      }
442   
443                      if ($type == 'sql')
444                      {
445                          // Skip the query
446                          fgets($handle);
447                      }
448                  }
449                  else if ($line == 1)
450                  {
451                      $bytes = (int) $buffer;
452   
453                      // Never should have 0 bytes
454                      if (!$bytes)
455                      {
456                          break;
457                      }
458   
459                      // Grab the serialized data
460                      $data = fread($handle, $bytes);
461   
462                      // Read 1 byte, to trigger EOF
463                      fread($handle, 1);
464   
465                      if (!feof($handle))
466                      {
467                          // Somebody tampered with our data
468                          $data = false;
469                      }
470                      break;
471                  }
472                  else
473                  {
474                      // Something went wrong
475                      break;
476                  }
477                  $line++;
478              }
479              fclose($handle);
480   
481              // unserialize if we got some data
482              $data = ($data !== false) ? @unserialize($data) : $data;
483   
484              if ($data === false)
485              {
486                  $this->remove_file($file);
487                  return false;
488              }
489   
490              return $data;
491          }
492      }
493   
494      /**
495      * Write cache data to a specified file
496      *
497      * 'data_global' is a special case and the generated format is different for this file:
498      * <code>
499      * <?php exit; ?>
500      * (expiration)
501      * (length of var and serialised data)
502      * (var)
503      * (serialised data)
504      * ... (repeat)
505      * </code>
506      *
507      * The other files have a similar format:
508      * <code>
509      * <?php exit; ?>
510      * (expiration)
511      * (query) [SQL files only]
512      * (length of serialised data)
513      * (serialised data)
514      * </code>
515      *
516      * @access private
517      * @param string $filename Filename to write
518      * @param mixed $data Data to store
519      * @param int $expires Timestamp when the data expires
520      * @param string $query Query when caching SQL queries
521      * @return bool True if the file was successfully created, otherwise false
522      */
523      function _write($filename, $data = null, $expires = 0, $query = '')
524      {
525          global $phpEx;
526   
527          $filename = $this->clean_varname($filename);
528          $file = "{$this->cache_dir}$filename.$phpEx";
529   
530          $lock = new \phpbb\lock\flock($file);
531          $lock->acquire();
532   
533          if ($handle = @fopen($file, 'wb'))
534          {
535              // File header
536              fwrite($handle, '<' . '?php exit; ?' . '>');
537   
538              if ($filename == 'data_global')
539              {
540                  // Global data is a different format
541                  foreach ($this->vars as $var => $data)
542                  {
543                      if (strpos($var, "\r") !== false || strpos($var, "\n") !== false)
544                      {
545                          // CR/LF would cause fgets() to read the cache file incorrectly
546                          // do not cache test entries, they probably won't be read back
547                          // the cache keys should really be alphanumeric with a few symbols.
548                          continue;
549                      }
550                      $data = serialize($data);
551   
552                      // Write out the expiration time
553                      fwrite($handle, "\n" . $this->var_expires[$var] . "\n");
554   
555                      // Length of the remaining data for this var (ignoring two LF's)
556                      fwrite($handle, strlen($data . $var) . "\n");
557                      fwrite($handle, $var . "\n");
558                      fwrite($handle, $data);
559                  }
560              }
561              else
562              {
563                  fwrite($handle, "\n" . $expires . "\n");
564   
565                  if (strpos($filename, 'sql_') === 0)
566                  {
567                      fwrite($handle, $query . "\n");
568                  }
569                  $data = serialize($data);
570   
571                  fwrite($handle, strlen($data) . "\n");
572                  fwrite($handle, $data);
573              }
574   
575              fclose($handle);
576   
577              if (function_exists('opcache_invalidate'))
578              {
579                  @opcache_invalidate($this->cache_file);
580              }
581   
582              try
583              {
584                  $this->filesystem->phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE);
585              }
586              catch (\phpbb\filesystem\exception\filesystem_exception $e)
587              {
588                  // Do nothing
589              }
590   
591              $return_value = true;
592          }
593          else
594          {
595              $return_value = false;
596          }
597   
598          $lock->release();
599   
600          return $return_value;
601      }
602   
603      /**
604      * Replace slashes in the file name
605      *
606      * @param string $varname name of a cache variable
607      * @return string $varname name that is safe to use as a filename
608      */
609      protected function clean_varname($varname)
610      {
611          return str_replace('/', '-', $varname);
612      }
613  }
614