root/fast_file_responder.php

Revision c58f974886cb3bf0c7cf751690e100c386847c54, 4.5 KB (checked in by Xemle <xemle@phtagr.org>, 3 weeks ago)

Remove tailing whitespaces

  • Property mode set to 100644
Line 
1<?php
2/**
3 * PHP versions 5
4 *
5 * phTagr : Tag, Browse, and Share Your Photos.
6 * Copyright 2006-2012, Sebastian Felis (sebastian@phtagr.org)
7 *
8 * Licensed under The GPL-2.0 License
9 * Redistributions of files must retain the above copyright notice.
10 *
11 * @copyright     Copyright 2006-2012, Sebastian Felis (sebastian@phtagr.org)
12 * @link          http://www.phtagr.org phTagr
13 * @package       Phtagr
14 * @since         phTagr 2.2b3
15 * @license       GPL-2.0 (http://www.opensource.org/licenses/GPL-2.0)
16 */
17
18/** This class enables a fast file response without the framework stack of
19 * CakePHP. It checks the session and the URL and returns a valid file */
20class FastFileResponder {
21  /** Should be same as in app/config/core.php Session.cookie */
22  var $sessionCookie = 'CAKEPHP';
23  var $sessionKey = 'fastFile';
24  var $items = array();
25
26  function __construct() {
27    $this->startSession();
28  }
29
30  /** Starts the session if the session sessionCookie is set */
31  function startSession() {
32    if (!isset($_COOKIE[$this->sessionCookie])) {
33      return;
34    }
35    session_id($_COOKIE[$this->sessionCookie]);
36    session_start();
37    if (isset($_SESSION[$this->sessionKey])) {
38      $this->items = (array) $_SESSION[$this->sessionKey]['items'];
39      $this->deleteExpiredItems();
40    }
41  }
42
43  /** Deletes expired itemes from the session list */
44  function deleteExpiredItems() {
45    if (!count($this->items)) {
46      return;
47    }
48    $now = time();
49    foreach ($this->items as $key => $item) {
50      if ($item['expires'] < $now) {
51        unset($_SESSION[$this->sessionKey][$key]);
52      }
53    }
54  }
55
56  /** Simple log function for debug purpos */
57  function log($msg) {
58    $h = @fopen(dirname(__FILE__) . DS . 'fast_file_responder.log', 'a');
59    @fwrite($h, sprintf("%s %s\n", date('Y-M-d h:i:s', time()), $msg));
60    @fclose($h);
61  }
62
63  /** Extracts the item key from the url and returns it. Returns false if no
64   * key could be found */
65  function getItemKey($url) {
66    if (!preg_match('/media\/(\w+)\/(\d+)/', $url, $matches)) {
67      return false;
68    }
69    return $matches[1] . '-' . $matches[2];
70  }
71
72  /** Returns the file of the media request */
73  function getFilename($url) {
74    $key = $this->getItemKey($url);
75    if (!$key || !isset($this->items[$key])) {
76      return false;
77    }
78    $item = $this->items[$key];
79    if ($item['expires'] < time() || !is_readable($item['file'])) {
80      return false;
81    }
82    return $item['file'];
83  }
84
85  /** Returns an array of request headers */
86  function getRequestHeaders() {
87    $headers = array();
88    if (function_exists('apache_request_headers')) {
89      $headers = apache_request_headers();
90      foreach($headers as $h => $v) {
91        $headers[strtolower($h)] = $v;
92      }
93    } else {
94      $headers = array();
95      foreach($_SERVER as $h => $v) {
96        if(ereg('HTTP_(.+)', $h, $hp)) {
97          $headers[strtolower($hp[1])] = $v;
98        }
99      }
100    }
101    return $headers;
102  }
103
104  /** Evaluates the client file cache and response if the client has still a
105   * valid file
106   * @param filename Current cache file */
107  function checkClientCache($filename) {
108    $cacheTime = filemtime($filename);
109    $headers = $this->getRequestHeaders();
110    if (isset($headers['if-modified-since']) &&
111        (strtotime($headers['if-modified-since']) == $cacheTime)) {
112      header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $cacheTime).' GMT', true, 304);
113      // Allow further caching for 30 days
114      header('Cache-Control: max-age=2592000, must-revalidate');
115      exit;
116    }
117  }
118
119  function sendResponseHeaders($file) {
120    $fileSize = @filesize($file);
121    header('Content-Type: image/jpg');
122    header('Content-Length: ' . $fileSize);
123    header('Cache-Control: max-age=2592000, must-revalidate');
124    header('Pragma: cache');
125    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($file)));
126  }
127
128  /** Evaluates if a valid cache file exists */
129  function exists($url) {
130    return $this->getFilename($url) != false;
131  }
132
133  /** Sends the cache file if it exists and exit. If it returns an error
134    * occured */
135  function send($url) {
136    $filename = $this->getFilename($url);
137    if (!$filename) {
138      return false;
139    }
140    $this->checkClientCache($filename);
141    $this->sendResponseHeaders($filename);
142
143    $chunkSize = 1024;
144    $buffer = '';
145    $handle = fopen($filename, 'rb');
146    while (!feof($handle)) {
147      $buffer = fread($handle, $chunkSize);
148      echo $buffer;
149    }
150    fclose($handle);
151    //$this->log("File send: $filename");
152    exit(0);
153  }
154
155  /** Closes the session */
156  function close() {
157    session_write_close();
158  }
159}
160?>
Note: See TracBrowser for help on using the browser.