d04d4b062d129086b0a2d55f9798584c3a9113ce
[racktables] / wwwroot / index.php
1 <?php
2
3 # This file is a part of RackTables, a datacenter and server room management
4 # framework. See accompanying file "COPYING" for the full copyright and
5 # licensing information.
6
7 ob_start();
8 require_once 'inc/pre-init.php';
9 try {
10 // Code block below is a module request dispatcher. Turning it into a
11 // function will break things because of the way require() works.
12 switch (TRUE)
13 {
14 case ! array_key_exists ('module', $_REQUEST):
15 case 'interface' == $_REQUEST['module']:
16 require_once 'inc/interface.php';
17 // init.php has to be included after interface.php, otherwise the bits
18 // set by local.php get lost
19 require_once 'inc/init.php';
20 prepareNavigation();
21 // Security context is built on the requested page/tab/bypass data,
22 // do not override.
23 fixContext();
24 redirectIfNecessary();
25 assertPermission();
26 header ('Content-Type: text/html; charset=UTF-8');
27 // call the main handler - page or tab handler.
28 if (isset ($tabhandler[$pageno][$tabno]))
29 {
30 if (! function_exists ($tabhandler[$pageno][$tabno]))
31 throw new RackTablesError ("Missing handler function for node '${pageno}-${tabno}'", RackTablesError::INTERNAL);
32 call_user_func ($tabhandler[$pageno][$tabno], getBypassValue());
33 }
34 elseif (isset ($page[$pageno]['handler']))
35 {
36 if (! function_exists ($page[$pageno]['handler']))
37 throw new RackTablesError ("Missing handler function for node '${pageno}'", RackTablesError::INTERNAL);
38 $page[$pageno]['handler'] ($tabno);
39 }
40 else
41 throw new RackTablesError ("Failed to find handler for page '${pageno}', tab '${tabno}'", RackTablesError::INTERNAL);
42 // Embed the current text in OB into interface layout (the latter also
43 // empties color message buffer).
44 $contents = ob_get_contents();
45 ob_clean();
46 renderInterfaceHTML ($pageno, $tabno, $contents);
47 break;
48 case 'chrome' == $_REQUEST['module']:
49 require_once 'inc/init.php';
50 require_once 'inc/solutions.php';
51 genericAssertion ('uri', 'string');
52 proxyStaticURI ($_REQUEST['uri']);
53 break;
54 case 'download' == $_REQUEST['module']:
55 require_once 'inc/init.php';
56 $pageno = 'file';
57 $tabno = 'download';
58 fixContext();
59 assertPermission();
60 $file = getFile (getBypassValue());
61 header("Content-Type: {$file['type']}");
62 header("Content-Length: {$file['size']}");
63 if (! array_key_exists ('asattach', $_REQUEST) or $_REQUEST['asattach'] != 'no')
64 header("Content-Disposition: attachment; filename={$file['name']}");
65 echo $file['contents'];
66 break;
67 case 'image' == $_REQUEST['module']:
68 # The difference between "image" and "download" ways to serve the same
69 # picture file is that the former is used in <IMG SRC=...> construct,
70 # and the latter is accessed as a standalone URL and can reply with any
71 # Content-type. Hence "image" module indicates failures with internally
72 # built images, and "download" can return a full-fledged "permission
73 # denied" or "exception" HTML page instead of the file requested.
74 require_once 'inc/init.php'; // for authentication check
75 require_once 'inc/solutions.php';
76 try
77 {
78 dispatchImageRequest();
79 }
80 catch (RTPermissionDenied $e)
81 {
82 ob_clean();
83 renderAccessDeniedImage();
84 }
85 catch (Exception $e)
86 {
87 ob_clean();
88 renderErrorImage();
89 }
90 break;
91 case 'svg' == $_REQUEST['module']:
92 require_once 'inc/init.php';
93 require_once 'inc/solutions.php';
94 header ('Content-Type: image/svg+xml');
95 echo '<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>' . "\n";
96 echo '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' . "\n";
97 try
98 {
99 genericAssertion ('view', 'string');
100 if (! array_key_exists ($_REQUEST['view'], $svghandler))
101 throw new InvalidRequestArgException ('view', $_REQUEST['view'], 'undefined view');
102 if (! function_exists ($svghandler[$_REQUEST['view']]))
103 throw new RackTablesError ('missing handler function', RackTablesError::INTERNAL);
104 call_user_func ($svghandler[$_REQUEST['view']]);
105 }
106 catch (RTPermissionDenied $e)
107 {
108 ob_clean();
109 printSVGMessageBar ('permission denied', array ('fill' => 'white'), array ('fill' => 'black', 'stroke' => 'gray'));
110 }
111 catch (InvalidRequestArgException $e)
112 {
113 ob_clean();
114 printSVGMessageBar ('malformed HTTP request', array(), array ('fill' => 'yellow', 'stroke' => 'black'));
115 }
116 catch (EntityNotFoundException $e)
117 {
118 ob_clean();
119 printSVGMessageBar ('no such record', array(), array ('fill' => 'yellow', 'stroke' => 'black'));
120 }
121 catch (RackTablesError $e)
122 {
123 ob_clean();
124 printSVGMessageBar ('RT error: ' . $e->getMessage(), array(), array ('fill' => 'red', 'stroke' => 'black'));
125 }
126 catch (Exception $e)
127 {
128 ob_clean();
129 printSVGMessageBar ('unknown error', array(), array ('fill' => 'red', 'stroke' => 'black'));
130 }
131 break;
132 case 'progressbar' == $_REQUEST['module']:
133 # Unlike images (and like static content), progress bars are processed
134 # without a permission check, but only for authenticated users.
135 require_once 'inc/init.php';
136 require_once 'inc/solutions.php';
137 try
138 {
139 genericAssertion ('done', 'uint0');
140 // 'progressbar's never change, make browser cache the result
141 if (checkCachedResponse (0, CACHE_DURATION))
142 break;
143 renderProgressBarImage ($_REQUEST['done']);
144 }
145 catch (Exception $e)
146 {
147 ob_clean();
148 renderProgressBarError();
149 }
150 break;
151 case 'progressbar4' == $_REQUEST['module']:
152 # Unlike images (and like static content), progress bars are processed
153 # without a permission check, but only for authenticated users.
154 require_once 'inc/init.php';
155 require_once 'inc/solutions.php';
156 try
157 {
158 renderProgressBar4Image ($_REQUEST['px1'], $_REQUEST['px2'], $_REQUEST['px3']);
159 }
160 catch (Exception $e)
161 {
162 ob_clean();
163 renderProgressBarError();
164 }
165 break;
166 case 'ajax' == $_REQUEST['module']:
167 require_once 'inc/ajax-interface.php';
168 require_once 'inc/solutions.php';
169 require_once 'inc/init.php';
170 try
171 {
172 dispatchAJAXRequest();
173 }
174 catch (InvalidRequestArgException $e)
175 {
176 ob_clean();
177 echo "NAK\nMalformed request";
178 }
179 catch (RTPermissionDenied $e)
180 {
181 ob_clean();
182 # FIXME: the remote client could be expecting JSON data instead
183 echo "NAK\nPermission denied";
184 }
185 catch (Exception $e)
186 {
187 ob_clean();
188 echo "NAK\nRuntime exception: ". $e->getMessage();
189 }
190 break;
191 case 'redirect' == $_REQUEST['module']:
192 // Include init after ophandlers/snmp, not before, so local.php can redefine things.
193 require_once 'inc/ophandlers.php';
194 // snmp.php is an exception, it is treated by a special hack
195 if (isset ($_REQUEST['op']) and $_REQUEST['op'] == 'querySNMPData')
196 require_once 'inc/snmp.php';
197 require_once 'inc/init.php';
198 try
199 {
200 genericAssertion ('op', 'string');
201 $op = $_REQUEST['op'];
202 prepareNavigation();
203 $location = buildRedirectURL();
204 // FIXME: find a better way to handle this error
205 if ($op == 'addFile' && !isset($_FILES['file']['error']))
206 throw new RackTablesError ('File upload error, check upload_max_filesize in php.ini', RackTablesError::MISCONFIGURED);
207 fixContext();
208 if
209 (
210 !isset ($ophandler[$pageno][$tabno][$op]) or
211 !function_exists ($ophandler[$pageno][$tabno][$op])
212 )
213 throw new RackTablesError ("Invalid navigation data for '${pageno}-${tabno}-${op}'", RackTablesError::INTERNAL);
214 // We have a chance to handle an error before starting HTTP header.
215 if (!isset ($delayauth["${pageno}-${tabno}-${op}"]))
216 assertPermission();
217 # Call below does the job of bypass argument assertion, if such is required,
218 # so the ophandler function doesn't have to re-assert this portion of its
219 # arguments. And it would be even better to pass returned value to ophandler,
220 # so it is not necessary to remember the name of bypass in it.
221 getBypassValue();
222 if (strlen ($redirect_to = call_user_func ($ophandler[$pageno][$tabno][$op])))
223 $location = $redirect_to;
224 }
225 // known "soft" failures require a short error message
226 catch (InvalidRequestArgException $e)
227 {
228 ob_clean();
229 showError ($e->getMessage());
230 }
231 catch (RTDatabaseError $e)
232 {
233 ob_clean();
234 showError ('Database error: ' . $e->getMessage());
235 }
236 catch (RTPermissionDenied $e)
237 {
238 ob_clean();
239 showError ('Operation not permitted');
240 }
241 redirectUser ($location);
242 // any other error requires no special handling and will be caught outside
243 break;
244 case 'popup' == $_REQUEST['module']:
245 require_once 'inc/popup.php';
246 require_once 'inc/init.php';
247 renderPopupHTML();
248 break;
249 case 'upgrade' == $_REQUEST['module']:
250 require_once 'inc/config.php'; // for CODE_VERSION
251 require_once 'inc/dictionary.php';
252 require_once 'inc/upgrade.php';
253 renderUpgraderHTML();
254 break;
255 case 'installer' == $_REQUEST['module']:
256 require_once 'inc/dictionary.php';
257 require_once 'inc/config.php';
258 require_once 'inc/install.php';
259 renderInstallerHTML();
260 break;
261 default:
262 throw new InvalidRequestArgException ('module', $_REQUEST['module']);
263 }
264 ob_end_flush();
265 }
266 catch (Exception $e)
267 {
268 ob_end_clean();
269 printException ($e);
270 }
271 ?>