r4277 getFile(): simplify
[racktables] / wwwroot / render_image.php
CommitLineData
b325120a 1<?php
e673ee24 2
21d40daa
DO
3define ('CACHE_DURATION', 604800); // 7 * 24 * 3600
4if ( // 'progressbar's never change, force cache hit before loading init.php
5 isset ($_SERVER['HTTP_IF_MODIFIED_SINCE'])
6 && $_REQUEST['img'] == 'progressbar'
7)
8{
b6993903 9 $client_time = HTTPDateToUnixTime ($_SERVER['HTTP_IF_MODIFIED_SINCE']);
21d40daa
DO
10 if ($client_time !== FALSE && $client_time !== -1) // readable
11 {
12 $server_time = time();
13 // not in future and not yet expired
14 if ($client_time <= $server_time && $client_time + CACHE_DURATION >= $server_time)
15 {
16 header ('Last-Modified: ' . $_SERVER['HTTP_IF_MODIFIED_SINCE'], TRUE, 304);
17 exit;
18 }
19 }
20}
90a3d6d8
DY
21
22ob_start();
23try {
e673ee24
DO
24require 'inc/init.php';
25
0cc24e9a 26assertStringArg ('img');
d15b2330
DO
27switch ($_REQUEST['img'])
28{
da958e52 29 case 'minirack': // rack security context
0cc24e9a 30 assertUIntArg ('rack_id');
da958e52 31 $pageno = 'rack';
d15b2330 32 $tabno = 'default';
da958e52
DO
33 fixContext();
34 if (!permitted())
35 renderAccessDeniedImage();
36 else
37 renderRackThumb ($_REQUEST['rack_id']);
d15b2330 38 break;
da958e52 39 case 'progressbar': // no security context
0cc24e9a 40 assertUIntArg ('done', TRUE);
21d40daa
DO
41 // 'progressbar's never change, make browser cache the result
42 header ('Cache-Control: private, max-age=' . CACHE_DURATION . ', pre-check=' . CACHE_DURATION);
4bbc4560 43 header ('Last-Modified: ' . gmdate (DATE_RFC1123));
d15b2330
DO
44 renderProgressBarImage ($_REQUEST['done']);
45 break;
0df8c52b 46 case 'preview': // file security context
0cc24e9a 47 assertUIntArg ('file_id');
37e59768 48 $pageno = 'file';
0df8c52b 49 $tabno = 'download';
37e59768
DO
50 fixContext();
51 if (!permitted())
52 renderAccessDeniedImage();
53 else
43d0585d 54 renderFilePreview ($_REQUEST['file_id'], $_REQUEST['img']);
37e59768 55 break;
d15b2330
DO
56 default:
57 renderError();
58}
e673ee24 59
90a3d6d8
DY
60ob_end_flush();
61}
62catch (Exception $e)
63{
64 ob_end_clean();
3a089a44 65 renderError();
90a3d6d8
DY
66}
67
e673ee24 68//------------------------------------------------------------------------
b6993903
DO
69function HTTPDateToUnixTime ($string)
70{
71 //Written per RFC 2616 3.3.1 - Full Date
72 //http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
73 $month_number = array
74 (
75 'Jan' => 1,
76 'Feb' => 2,
77 'Mar' => 3,
78 'Apr' => 4,
79 'May' => 5,
80 'Jun' => 6,
81 'Jul' => 7,
82 'Aug' => 8,
83 'Sep' => 9,
84 'Oct' => 10,
85 'Nov' => 11,
86 'Dec' => 12,
87 );
88
89 $formats = array();
7a660125
DO
90 # RFC2616 dictates exchanged timestamps to be in GMT TZ, and RFC822
91 # (which RFC1123 relies on) explicitly defines, that "GMT" is equivalent
92 # to "-0000" and "+0000".
c3eb96dd
AA
93 $formats['rfc1123'] = '/^(Sun|Mon|Tue|Wed|Thu|Fri|Sat), (\d{2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d{2}):(\d{2}):(\d{2}) (?:GMT|[-+]0000)$/';
94 $formats['rfc850'] = '/^(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday), (\d{2})-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d{2}) (\d{2}):(\d{2}):(\d{2}) (?:GMT|[-+]0000)$/';
b6993903
DO
95 $formats['asctime'] = '/^(Sun|Mon|Tue|Wed|Thu|Fri|Sat) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{2}|\d{1}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/';
96
97 $matches = array();
98 if (preg_match ($formats['rfc1123'], $string, $matches)) {
99 $hours = $matches[5];
100 $minutes = $matches[6];
101 $seconds = $matches[7];
102 $month = $month_number[$matches[3]];
103 $day = $matches[2];
104 $year = $matches[4];
105 } elseif (preg_match ($formats['rfc850'], $string, $matches)) {
106 $hours = $matches[5];
107 $minutes = $matches[6];
108 $seconds = $matches[7];
109 $month = $month_number[substr($matches[3],0,3)];
110 $day = $matches[2];
111 $year = $matches[4];
112 } elseif (preg_match ($formats['asctime'], $string, $matches)) {
113 $hours = $matches[4];
114 $minutes = $matches[5];
115 $seconds = $matches[6];
116 $month = $month_number[$matches[2]];
117 $day = $matches[3];
118 $year = $matches[7];
119 } else
120 return false;
121 return gmmktime ($hours, $minutes, $seconds, $month, $day, $year);
122}
123
e673ee24
DO
124function renderError ()
125{
e673ee24 126 header("Content-type: image/png");
d5f8fa19
DO
127 // "ERROR", 76x17, red on white
128 echo base64_decode
129 (
130 'iVBORw0KGgoAAAANSUhEUgAAAEwAAAARCAYAAAB3h0oCAAAAAXNSR0IArs4c6QAAALBJREFUWMPt' .
131 'WFsOwCAIG4v3vzL7WEyWxQdVwM1A4l/F2iHVETPzESGOMyTAInURRP0suUhb2FIho/jWXO38w4KN' .
132 'LPDGEt2jlgPBZxFKc2o8UT7Lj6SkAmfw1nx+28MkVWQlcjT9EOwjLqnpaNImi+I1j/YSl5RY/gx+' .
133 'VCCF/MnkCz4JZQtvEUXx1nyW9jCUlPVLbTJ/3MO2dsnWRq2Nwl2wTarM51rhsVEnDhT/w7C4APaJ' .
134 'ZhkIGYaUAAAAAElFTkSuQmCC'
135 );
da958e52
DO
136}
137
9c0b0016 138// Having a local caching array speeds things up. A little.
e673ee24
DO
139function colorFromHex ($image, $hex)
140{
9c0b0016
DO
141 static $colorcache = array ();
142 if (isset ($colorcache[$hex]))
143 return $colorcache[$hex];
e673ee24
DO
144 $r = hexdec ('0x' . substr ($hex, 0, 2));
145 $g = hexdec ('0x' . substr ($hex, 2, 2));
146 $b = hexdec ('0x' . substr ($hex, 4, 2));
9c0b0016
DO
147 $c = imagecolorallocate ($image, $r, $g, $b);
148 $colorcache[$hex] = $c;
149 return $c;
e673ee24
DO
150}
151
152function renderRackThumb ($rack_id = 0)
35ee7bd0
DO
153{
154 // Don't call DB extra times, hence we are most probably not the
6b06a019 155 // only script wishing to access the same data now.
61a1d996
DO
156 if (NULL !== ($thumbcache = loadThumbCache ($rack_id)))
157 {
158 header("Content-type: image/png");
35ee7bd0 159 echo $thumbcache;
61a1d996
DO
160 return;
161 }
162 ob_start();
163 if (FALSE !== generateMiniRack ($rack_id))
35ee7bd0 164 {
61a1d996
DO
165 $capture = ob_get_clean();
166 header("Content-type: image/png");
167 echo $capture;
68a0bd8a 168 usePreparedUpdateBlade ('Rack', array ('thumb_data' => base64_encode ($capture)), array ('id' => $rack_id));
61a1d996 169 return;
35ee7bd0 170 }
61a1d996
DO
171 // error text in the buffer
172 ob_end_flush();
35ee7bd0
DO
173}
174
61a1d996
DO
175// Output a binary string containing the PNG minirack. Indicate error with return code.
176function generateMiniRack ($rack_id)
e673ee24 177{
61a1d996
DO
178 if (NULL === ($rackData = spotEntity ('rack', $rack_id)))
179 return FALSE;
180 amplifyCell ($rackData);
e673ee24 181 markupObjectProblems ($rackData);
529eac25 182 global $rtwidth;
d5157018 183 $rtdepth = 9;
e673ee24
DO
184 $offset[0] = 3;
185 $offset[1] = 3 + $rtwidth[0];
186 $offset[2] = 3 + $rtwidth[0] + $rtwidth[1];
187 $totalheight = 3 + 3 + $rackData['height'] * 2;
188 $totalwidth = $offset[2] + $rtwidth[2] + 3;
aa0e4c55
DO
189 $img = @imagecreatetruecolor ($totalwidth, $totalheight)
190 or die("Cannot Initialize new GD image stream");
9c0b0016
DO
191 // cache our palette as well
192 $color = array();
193 foreach (array ('F', 'A', 'U', 'T', 'Th', 'Tw', 'Thw') as $statecode)
d1adb55a 194 $color[$statecode] = colorFromHex ($img, getConfigVar ('color_' . $statecode));
d5157018
DO
195 $color['black'] = colorFromHex ($img, '000000');
196 $color['gray'] = colorFromHex ($img, 'c0c0c0');
197 imagerectangle ($img, 0, 0, $totalwidth - 1, $totalheight - 1, $color['black']);
198 imagerectangle ($img, 1, 1, $totalwidth - 2, $totalheight - 2, $color['gray']);
199 imagerectangle ($img, 2, 2, $totalwidth - 3, $totalheight - 3, $color['black']);
200 for ($unit_no = 1; $unit_no <= $rackData['height']; $unit_no++)
e673ee24
DO
201 {
202 for ($locidx = 0; $locidx < 3; $locidx++)
203 {
204 $colorcode = $rackData[$unit_no][$locidx]['state'];
205 if (isset ($rackData[$unit_no][$locidx]['hl']))
206 $colorcode = $colorcode . $rackData[$unit_no][$locidx]['hl'];
207 imagerectangle
208 (
209 $img,
210 $offset[$locidx],
211 3 + ($rackData['height'] - $unit_no) * 2,
212 $offset[$locidx] + $rtwidth[$locidx] - 1,
213 3 + ($rackData['height'] - $unit_no) * 2 + 1,
d1adb55a 214 $color[$colorcode]
e673ee24
DO
215 );
216 }
217 }
e673ee24
DO
218 imagepng ($img);
219 imagedestroy ($img);
61a1d996 220 return TRUE;
e673ee24
DO
221}
222
d15b2330
DO
223function renderProgressBarImage ($done)
224{
d1adb55a 225 $img = @imagecreatetruecolor (100, 10);
fec0c8da
DO
226 switch (isset ($_REQUEST['theme']) ? $_REQUEST['theme'] : 'rackspace')
227 {
228 case 'sparenetwork':
229 $color['T'] = colorFromHex ($img, '808080');
230 $color['F'] = colorFromHex ($img, 'c0c0c0');
231 break;
232 case 'rackspace': // teal
233 default:
234 $color['T'] = colorFromHex ($img, getConfigVar ('color_T'));
235 $color['F'] = colorFromHex ($img, getConfigVar ('color_F'));
236 }
d1adb55a
DO
237 imagefilledrectangle ($img, 0, 0, $done, 10, $color['T']);
238 imagefilledrectangle ($img, $done, 0, 100, 10, $color['F']);
074106cf
DO
239 for ($x = 20; $x <= 80; $x += 20)
240 {
241 $cc = $x > $done ? $color['T'] : $color['F'];
242 imagesetpixel ($img, $x, 0, $cc);
243 imagesetpixel ($img, $x, 1, $cc);
244 imagesetpixel ($img, $x, 4, $cc);
245 imagesetpixel ($img, $x, 5, $cc);
246 imagesetpixel ($img, $x, 8, $cc);
247 imagesetpixel ($img, $x, 9, $cc);
248 }
d15b2330
DO
249 header("Content-type: image/png");
250 imagepng ($img);
251 imagedestroy ($img);
d15b2330
DO
252}
253
2d75c30b
DO
254function renderAccessDeniedImage ()
255{
256 $img = @imagecreatetruecolor (1, 1);
257 imagefilledrectangle ($img, 0, 0, 1, 1, colorFromHex ($img, '000000'));
258 header("Content-type: image/png");
259 imagepng ($img);
260 imagedestroy ($img);
0df8c52b 261 die;
2d75c30b
DO
262}
263
43d0585d 264function renderFilePreview ($file_id = 0, $mode = 'view')
37e59768 265{
43d0585d 266 switch ($mode)
37e59768 267 {
43d0585d
DO
268 case 'view':
269 // GFX files can become really big, if we uncompress them in memory just to
270 // provide a PNG version of a file. To keep things working, just send the
271 // contents as is for known MIME types.
272 $file = getFile ($file_id);
273 if (!in_array ($file['type'], array ('image/jpeg', 'image/png', 'image/gif')))
274 {
6b06a019 275 renderError();
43d0585d
DO
276 break;
277 }
278 header("Content-type: ${file['type']}");
279 echo $file['contents'];
280 break;
281 case 'preview':
6b06a019
DO
282 if ($image = getFileCache ($file_id)) //Cache Hit
283 {
d3346ce2
DO
284 header("Content-type: image/jpeg");
285 echo $image;
286 break;
287 }
d3346ce2 288 //Cache Miss
43d0585d
DO
289 $file = getFile ($file_id);
290 $image = imagecreatefromstring ($file['contents']);
d3346ce2 291 unset ($file['contents']);
43d0585d
DO
292 $width = imagesx ($image);
293 $height = imagesy ($image);
d3346ce2 294 header ('Content-type: image/jpeg');
43d0585d
DO
295 if ($width > getConfigVar ('PREVIEW_IMAGE_MAXPXS') or $height > getConfigVar ('PREVIEW_IMAGE_MAXPXS'))
296 {
43d0585d
DO
297 $ratio = getConfigVar ('PREVIEW_IMAGE_MAXPXS') / max ($width, $height);
298 $newwidth = $width * $ratio;
299 $newheight = $height * $ratio;
300 $resampled = imagecreatetruecolor ($newwidth, $newheight);
301 imagecopyresampled ($resampled, $image, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
302 imagedestroy ($image);
303 $image = $resampled;
d3346ce2
DO
304
305 //TODO: Find a better way to save the stream of the image... Output buffer seems silly.
306 ob_start();
307 imagejpeg ($image);
308 commitAddFileCache ($file_id, ob_get_flush());
309 imagedestroy ($image);
310 unset ($file);
43d0585d
DO
311 unset ($resampled);
312 }
43d0585d
DO
313 break;
314 default:
6b06a019 315 renderError();
43d0585d 316 break;
37e59768 317 }
37e59768 318}
f537da2f 319
e673ee24 320?>