r4359 dispatchImageRequest(): add missing semicolon
[racktables] / wwwroot / inc / solutions.php
1 <?php
2 /*
3
4 The purpose of this file is to contain functions, which generate a complete
5 HTTP response body and are either "dead ends" or depend on just a small
6 amount of other code (which should eventually be placed in a sort of
7 "first order" library file).
8
9 */
10
11 define ('RE_STATIC_URI', '#^([[:alpha:]]+)/(?:[[:alpha:]]+/)*[[:alnum:]\._-]+\.([[:alpha:]]+)$#');
12
13 function dispatchImageRequest()
14 {
15 genericAssertion ('img', 'string');
16 global $pageno, $tabno;
17 switch ($_REQUEST['img'])
18 {
19 case 'minirack': // rack security context
20 $pageno = 'rack';
21 $tabno = 'default';
22 fixContext();
23 assertPermission();
24 renderRackThumb (getBypassValue());
25 break;
26 case 'progressbar': // no security context
27 assertUIntArg ('done', TRUE);
28 // 'progressbar's never change, make browser cache the result
29 renderProgressBarImage ($_REQUEST['done']);
30 break;
31 case 'preview': // file security context
32 $pageno = 'file';
33 $tabno = 'download';
34 fixContext();
35 assertPermission();
36 renderFilePreview (getBypassValue());
37 break;
38 default:
39 renderErrorImage();
40 }
41 }
42
43 function renderErrorImage ()
44 {
45 header("Content-type: image/png");
46 // "ERROR", 76x17, red on white
47 echo base64_decode
48 (
49 'iVBORw0KGgoAAAANSUhEUgAAAEwAAAARCAYAAAB3h0oCAAAAAXNSR0IArs4c6QAAALBJREFUWMPt' .
50 'WFsOwCAIG4v3vzL7WEyWxQdVwM1A4l/F2iHVETPzESGOMyTAInURRP0suUhb2FIho/jWXO38w4KN' .
51 'LPDGEt2jlgPBZxFKc2o8UT7Lj6SkAmfw1nx+28MkVWQlcjT9EOwjLqnpaNImi+I1j/YSl5RY/gx+' .
52 'VCCF/MnkCz4JZQtvEUXx1nyW9jCUlPVLbTJ/3MO2dsnWRq2Nwl2wTarM51rhsVEnDhT/w7C4APaJ' .
53 'ZhkIGYaUAAAAAElFTkSuQmCC'
54 );
55 }
56
57 function renderAccessDeniedImage()
58 {
59 header ('Content-type: image/png');
60 // 1x1, single black pixel
61 echo base64_decode
62 (
63 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAAxJREFUCNdj' .
64 'YGBgAAAABAABJzQnCgAAAABJRU5ErkJggg=='
65 );
66 }
67
68 // Having a local caching array speeds things up. A little.
69 function colorFromHex ($image, $hex)
70 {
71 static $colorcache = array ();
72 if (isset ($colorcache[$hex]))
73 return $colorcache[$hex];
74 $r = hexdec ('0x' . substr ($hex, 0, 2));
75 $g = hexdec ('0x' . substr ($hex, 2, 2));
76 $b = hexdec ('0x' . substr ($hex, 4, 2));
77 $c = imagecolorallocate ($image, $r, $g, $b);
78 $colorcache[$hex] = $c;
79 return $c;
80 }
81
82 function renderRackThumb ($rack_id = 0)
83 {
84 // Don't call DB extra times, hence we are most probably not the
85 // only script wishing to access the same data now.
86 if (NULL !== ($thumbcache = loadThumbCache ($rack_id)))
87 {
88 header("Content-type: image/png");
89 echo $thumbcache;
90 return;
91 }
92 ob_start();
93 if (FALSE !== generateMiniRack ($rack_id))
94 {
95 $capture = ob_get_clean();
96 header("Content-type: image/png");
97 echo $capture;
98 usePreparedUpdateBlade ('Rack', array ('thumb_data' => base64_encode ($capture)), array ('id' => $rack_id));
99 return;
100 }
101 // error text in the buffer
102 ob_end_flush();
103 }
104
105 // Output a binary string containing the PNG minirack. Indicate error with return code.
106 function generateMiniRack ($rack_id)
107 {
108 if (NULL === ($rackData = spotEntity ('rack', $rack_id)))
109 return FALSE;
110 amplifyCell ($rackData);
111 markupObjectProblems ($rackData);
112 global $rtwidth;
113 $rtdepth = 9;
114 $offset[0] = 3;
115 $offset[1] = 3 + $rtwidth[0];
116 $offset[2] = 3 + $rtwidth[0] + $rtwidth[1];
117 $totalheight = 3 + 3 + $rackData['height'] * 2;
118 $totalwidth = $offset[2] + $rtwidth[2] + 3;
119 $img = @imagecreatetruecolor ($totalwidth, $totalheight)
120 or die("Cannot Initialize new GD image stream");
121 // cache our palette as well
122 $color = array();
123 foreach (array ('F', 'A', 'U', 'T', 'Th', 'Tw', 'Thw') as $statecode)
124 $color[$statecode] = colorFromHex ($img, getConfigVar ('color_' . $statecode));
125 $color['black'] = colorFromHex ($img, '000000');
126 $color['gray'] = colorFromHex ($img, 'c0c0c0');
127 imagerectangle ($img, 0, 0, $totalwidth - 1, $totalheight - 1, $color['black']);
128 imagerectangle ($img, 1, 1, $totalwidth - 2, $totalheight - 2, $color['gray']);
129 imagerectangle ($img, 2, 2, $totalwidth - 3, $totalheight - 3, $color['black']);
130 for ($unit_no = 1; $unit_no <= $rackData['height']; $unit_no++)
131 {
132 for ($locidx = 0; $locidx < 3; $locidx++)
133 {
134 $colorcode = $rackData[$unit_no][$locidx]['state'];
135 if (isset ($rackData[$unit_no][$locidx]['hl']))
136 $colorcode = $colorcode . $rackData[$unit_no][$locidx]['hl'];
137 imagerectangle
138 (
139 $img,
140 $offset[$locidx],
141 3 + ($rackData['height'] - $unit_no) * 2,
142 $offset[$locidx] + $rtwidth[$locidx] - 1,
143 3 + ($rackData['height'] - $unit_no) * 2 + 1,
144 $color[$colorcode]
145 );
146 }
147 }
148 imagepng ($img);
149 imagedestroy ($img);
150 return TRUE;
151 }
152
153 function renderProgressBarImage ($done)
154 {
155 $img = @imagecreatetruecolor (100, 10);
156 switch (isset ($_REQUEST['theme']) ? $_REQUEST['theme'] : 'rackspace')
157 {
158 case 'sparenetwork':
159 $color['T'] = colorFromHex ($img, '808080');
160 $color['F'] = colorFromHex ($img, 'c0c0c0');
161 break;
162 case 'rackspace': // teal
163 default:
164 $color['T'] = colorFromHex ($img, getConfigVar ('color_T'));
165 $color['F'] = colorFromHex ($img, getConfigVar ('color_F'));
166 }
167 imagefilledrectangle ($img, 0, 0, $done, 10, $color['T']);
168 imagefilledrectangle ($img, $done, 0, 100, 10, $color['F']);
169 for ($x = 20; $x <= 80; $x += 20)
170 {
171 $cc = $x > $done ? $color['T'] : $color['F'];
172 imagesetpixel ($img, $x, 0, $cc);
173 imagesetpixel ($img, $x, 1, $cc);
174 imagesetpixel ($img, $x, 4, $cc);
175 imagesetpixel ($img, $x, 5, $cc);
176 imagesetpixel ($img, $x, 8, $cc);
177 imagesetpixel ($img, $x, 9, $cc);
178 }
179 header("Content-type: image/png");
180 imagepng ($img);
181 imagedestroy ($img);
182 }
183
184 function renderFilePreview ($file_id)
185 {
186 if ($image = getFileCache ($file_id)) //Cache Hit
187 {
188 header("Content-type: image/jpeg");
189 echo $image;
190 return;
191 }
192 //Cache Miss
193 $file = getFile ($file_id);
194 $image = imagecreatefromstring ($file['contents']);
195 unset ($file);
196 $width = imagesx ($image);
197 $height = imagesy ($image);
198 if ($width > getConfigVar ('PREVIEW_IMAGE_MAXPXS') or $height > getConfigVar ('PREVIEW_IMAGE_MAXPXS'))
199 {
200 $ratio = getConfigVar ('PREVIEW_IMAGE_MAXPXS') / max ($width, $height);
201 $newwidth = $width * $ratio;
202 $newheight = $height * $ratio;
203 $resampled = imagecreatetruecolor ($newwidth, $newheight);
204 imagecopyresampled ($resampled, $image, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
205 imagedestroy ($image);
206 $image = $resampled;
207 unset ($resampled);
208 }
209 header ('Content-type: image/jpeg');
210 ob_start();
211 imagejpeg ($image);
212 imagedestroy ($image);
213 commitAddFileCache ($file_id, ob_get_flush());
214 }
215
216 function printStatic404()
217 {
218 header ('404 Not Found');
219 ?><!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
220 <html><head>
221 <title>404 Not Found</title>
222 </head><body>
223 <h1>Not Found</h1>
224 <p>The requested file was not found in this instance.</p>
225 <hr>
226 <address>RackTables static content proxy</address>
227 </body></html><?php
228 exit;
229 }
230
231 function proxyStaticURI ($URI)
232 {
233 $content_type = array
234 (
235 'css' => 'text/css',
236 'js' => 'text/javascript',
237 'html' => 'text/html',
238 'png' => 'image/png',
239 'gif' => 'image/gif',
240 'jpg' => 'image/jpeg',
241 'jpeg' => 'image/jpeg',
242 'ico' => 'image/x-icon',
243 );
244 $matches = array();
245 if
246 (
247 ! preg_match (RE_STATIC_URI, $URI, $matches)
248 or ! in_array ($matches[1], array ('pix', 'css', 'js'))
249 or ! array_key_exists (strtolower ($matches[2]), $content_type)
250 )
251 printStatic404();
252 global $racktables_staticdir;
253 if (FALSE === $fh = fopen ("${racktables_staticdir}/${URI}", 'r'))
254 printStatic404();
255 if (FALSE !== $stat = fstat ($fh))
256 if (checkCachedResponse (max ($stat['mtime'], $stat['ctime']), 0))
257 exit;
258 header ('Content-type: ' . $content_type[$matches[2]]);
259 fpassthru ($fh);
260 fclose ($fh);
261 }
262
263 ?>