Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
// Note that REAL cache should check for Last-Modified HTTP header at least;
4
// As I don't like idea of implementing the full-scaled HTTP protocol library
5
// and curl extension is very rare, this implementation of cache is very simple.
6
// Cache is cleared after the script finishes it work!
7
 
8
// Also, it can have problems with simultaneous access to the images.
9
 
10
// The class responsible for downloading and caching images
11
// as PHP does not support the static variables, we'll use a global variable
12
// containing all cached objects; note that cache consumes memory!
13
//
14
$GLOBALS['g_image_cache'] = array();
15
 
16
class Image {
17
  var $_handle;
18
  var $_filename;
19
  var $_type;
20
 
21
  function Image($handle, $filename, $type) {
22
    $this->_handle = $handle;
23
    $this->_filename = $filename;
24
    $this->_type = $type;
25
  }
26
 
27
  function get_filename() {
28
    return $this->_filename;
29
  }
30
 
31
  function get_handle() {
32
    return $this->_handle;
33
  }
34
 
35
  function get_type() {
36
    return $this->_type;
37
  }
38
 
39
  function sx() {
40
    if (!$this->_handle) {
41
      return 0;
42
    };
43
 
44
    return imagesx($this->_handle);
45
  }
46
 
47
  function sy() {
48
    if (!$this->_handle) {
49
      return 0;
50
    };
51
 
52
    return imagesy($this->_handle);
53
  }
54
}
55
 
56
class ImageFactory {
57
  // Static funcion; checks if given URL is already cached and either returns
58
  // cached object or downloads the requested image
59
  //
60
  function get($url, &$pipeline) {
61
    global $g_config;
62
    if (!$g_config['renderimages']) { return null; };
63
 
64
    global $g_image_cache;
65
 
66
    // Check if this URL have been cached
67
    //
68
    if (isset($g_image_cache[$url])) {
69
      //      return do_image_open($g_image_cache[$url]);
70
      return $g_image_cache[$url];
71
    };
72
 
73
    // Download image; we should do it before we call do_image_open,
74
    // as it tries to open image file twice: first to determine image type
75
    // and second to actually create the image - PHP url wrappers do no caching
76
    // at all
77
    //
78
    $filename = ImageFactory::make_cache_filename($url);
79
 
80
    // REQUIRES: PHP 4.3.0+
81
    // we suppress warning messages, as missing image files will cause 'copy' to print
82
    // several warnings
83
    //
84
    // @TODO: change to fetcher class call
85
    //
86
 
87
    $data = $pipeline->fetch($url);
88
 
89
    if (is_null($data)) {
90
      error_log("Cannot fetch image: ".$url);
91
      return null;
92
    };
93
 
94
    $file = fopen($filename, 'wb');
95
    fwrite($file, $data->content);
96
    fclose($file);
97
    $pipeline->pop_base_url();
98
 
99
    // register it in the cached objects array
100
    //
101
    $handle = do_image_open($filename, $type);
102
    if ($handle) {
103
      $g_image_cache[$url] =& new Image($handle,
104
                                        $filename,
105
                                        $type);
106
    } else {
107
      $g_image_cache[$url] = null;
108
    };
109
    // return image
110
    //
111
    // return do_image_open($filename);
112
    return $g_image_cache[$url];
113
  }
114
 
115
  // Makes the filename to contain the cached version of URL
116
  //
117
  function make_cache_filename($url) {
118
    // We cannot use the $url as an cache image name as it could be longer than
119
    // allowed file name length (especially after escaping specialy symbols)
120
    // thus, we generate long almost random 32-character name using the md5 hash function
121
    //
122
    return CACHE_DIR.md5(time() + $url + rand());
123
  }
124
 
125
  // Checks if cache directory is available
126
  //
127
  function check_cache_dir() {
128
    // TODO: some cool easily understandable error message for the case
129
    // image cache directory cannot be created or accessed
130
 
131
    // Check if CACHE_DIR exists
132
    //
133
    if (!is_dir(CACHE_DIR)) {
134
      // Cache directory does not exists; try to create it (with read/write rightss for the owner only)
135
      //
136
      if (!mkdir(CACHE_DIR, 0700)) { die("Cache directory cannot be created"); }
137
    };
138
 
139
    // Check if we can read and write to the CACHE_DIR
140
    //
141
    // Note that directory should have 'rwx' (7) permission, so the script will
142
    // be able to list directory contents; under Windows is_executable always returns false
143
    // for directories, so we need to drop this check in this case.
144
    //
145
    // A user's note for 'is_executable' function on PHP5:
146
    // "The change doesn't appear to be documented, so I thought I would mention it.
147
    // In php5, as opposed to php4, you can no longer rely on is_executable to check the executable bit
148
    // on a directory in 'nix. You can still use the first note's method to check if a directory is traversable:
149
    // @file_exists("adirectory/.");"
150
    //
151
    if (!is_readable(CACHE_DIR) ||
152
        !is_writeable(CACHE_DIR) ||
153
        (!@file_exists(CACHE_DIR.'.'))) {
154
      // omg. Cache directory exists, but useless
155
      //
156
      die("Check cache directory permissions; cannot either read or write to directory cache");
157
    };
158
 
159
    return;
160
  }
161
 
162
  // Clears the image cache (as we're neither implemented checking of Last-Modified HTTP header nor
163
  // provided the means of limiting the cache size
164
  //
165
  // TODO: Will cause problems with simultaneous access to the same images
166
  //
167
  function clear_cache() {
168
    foreach ($GLOBALS['g_image_cache'] as $key => $value) {
169
      if (!is_null($value)) {
170
        unlink($value->get_filename());
171
      };
172
    };
173
    $g_image_cache = array();
174
  }
175
}
176
?>