r4366 findAutoTagWarnings(): update for spotEntity() throwing an exception
[racktables] / wwwroot / index.php
1 <?php
2 ob_start();
3 # Neither "throw/catch" for custom exceptions nor printException() will
4 # work without first loading exceptions.php.
5 require_once 'inc/exceptions.php';
6 try {
7 // Code block below is a module request dispatcher. Turning it into a
8 // function will break things because of the way require() works.
9 switch (TRUE)
10 {
11 case ! array_key_exists ('module', $_REQUEST):
12 case 'interface' == $_REQUEST['module']:
13 require_once 'inc/interface.php';
14 // init.php has to be included after interface.php, otherwise the bits
15 // set by local.php get lost
16 require_once 'inc/init.php';
17 prepareNavigation();
18 // Security context is built on the requested page/tab/bypass data,
19 // do not override.
20 fixContext();
21 redirectIfNecessary();
22 assertPermission();
23 header ('Content-Type: text/html; charset=UTF-8');
24 // Only store the tab name after clearance is got. Any failure is unhandleable.
25 if (isset ($_REQUEST['tab']) and ! isset ($_SESSION['RTLT'][$pageno]['dont_remember']))
26 $_SESSION['RTLT'][$pageno] = array ('tabname' => $tabno, 'time' => time());
27 // call the main handler - page or tab handler.
28 if (isset ($tabhandler[$pageno][$tabno]))
29 call_user_func ($tabhandler[$pageno][$tabno], getBypassValue());
30 elseif (isset ($page[$pageno]['handler']))
31 $page[$pageno]['handler'] ($tabno);
32 else
33 throw new RackTablesError ("Failed to find handler for page '${pageno}', tab '${tabno}'", RackTablesError::INTERNAL);
34 // Embed the current text in OB into interface layout (the latter also
35 // empties color message buffer).
36 $contents = ob_get_contents();
37 ob_clean();
38 renderInterfaceHTML ($pageno, $tabno, $contents);
39 break;
40 case 'chrome' == $_REQUEST['module']:
41 require_once 'inc/init.php';
42 require_once 'inc/solutions.php';
43 genericAssertion ('uri', 'string');
44 proxyStaticURI ($_REQUEST['uri']);
45 break;
46 case 'download' == $_REQUEST['module']:
47 require_once 'inc/init.php';
48 $pageno = 'file';
49 $tabno = 'download';
50 fixContext();
51 assertPermission();
52 $file = getFile (getBypassValue());
53 header("Content-Type: {$file['type']}");
54 header("Content-Length: {$file['size']}");
55 if (! array_key_exists ('asattach', $_REQUEST) or $_REQUEST['asattach'] != 'no')
56 header("Content-Disposition: attachment; filename={$file['name']}");
57 echo $file['contents'];
58 break;
59 case 'image' == $_REQUEST['module']:
60 # The difference between "image" and "download" ways to serve the same
61 # picture file is that the former is used in <IMG SRC=...> construct,
62 # and the latter is accessed as a standalone URL and can reply with any
63 # Content-type. Hence "image" module indicates failures with internally
64 # built images, and "download" can return a full-fledged "permission
65 # denied" or "exception" HTML page instead of the file requested.
66 require_once 'inc/init.php'; // for authentication check
67 require_once 'inc/solutions.php';
68 try
69 {
70 dispatchImageRequest();
71 }
72 catch (RTPermissionDenied $e)
73 {
74 ob_clean();
75 renderAccessDeniedImage();
76 }
77 catch (Exception $e)
78 {
79 ob_clean();
80 renderErrorImage();
81 }
82 break;
83 case 'progressbar' == $_REQUEST['module']:
84 # Unlike images (and like static content), progress bars are processed
85 # without a permission check, but only for authenticated users.
86 require_once 'inc/init.php';
87 require_once 'inc/solutions.php';
88 try
89 {
90 genericAssertion ('done', 'uint0');
91 // 'progressbar's never change, make browser cache the result
92 if (checkCachedResponse (0, CACHE_DURATION))
93 break;
94 renderProgressBarImage ($_REQUEST['done']);
95 }
96 catch (Exception $e)
97 {
98 ob_clean();
99 renderProgressBarError();
100 }
101 break;
102 case 'ajax' == $_REQUEST['module']:
103 require_once 'inc/ajax-interface.php';
104 require_once 'inc/init.php';
105 try
106 {
107 dispatchAJAXRequest();
108 }
109 catch (InvalidRequestArgException $e)
110 {
111 ob_clean();
112 echo "NAK\nMalformed request";
113 }
114 catch (RTPermissionDenied $e)
115 {
116 ob_clean();
117 # FIXME: the remote client could be expecting JSON data instead
118 echo "NAK\nPermission denied";
119 }
120 catch (Exception $e)
121 {
122 ob_clean();
123 echo "NAK\nRuntime exception: ". $e->getMessage();
124 }
125 break;
126 case 'redirect' == $_REQUEST['module']:
127 // Include init after ophandlers/snmp, not before, so local.php can redefine things.
128 require_once 'inc/ophandlers.php';
129 // snmp.php is an exception, it is treated by a special hack
130 if (isset ($_REQUEST['op']) and $_REQUEST['op'] == 'querySNMPData')
131 require_once 'inc/snmp.php';
132 require_once 'inc/init.php';
133 try
134 {
135 genericAssertion ('op', 'string');
136 $op = $_REQUEST['op'];
137 prepareNavigation();
138 $location = buildWideRedirectURL();
139 // FIXME: find a better way to handle this error
140 if ($op == 'addFile' && !isset($_FILES['file']['error']))
141 throw new RackTablesError ('File upload error, check upload_max_filesize in php.ini', RackTablesError::MISCONFIGURED);
142 fixContext();
143 if
144 (
145 !isset ($ophandler[$pageno][$tabno][$op]) or
146 !function_exists ($ophandler[$pageno][$tabno][$op])
147 )
148 throw new RackTablesError ("Invalid navigation data for '${pageno}-${tabno}-${op}'", RackTablesError::INTERNAL);
149 // We have a chance to handle an error before starting HTTP header.
150 if (!isset ($delayauth[$pageno][$tabno][$op]))
151 assertPermission();
152 # Call below does the job of bypass argument assertion, if such is required,
153 # so the ophandler function doesn't have to re-assert this portion of its
154 # arguments. And it would be even better to pass returned value to ophandler,
155 # so it is not necessary to remember the name of bypass in it.
156 getBypassValue();
157 if (strlen ($redirect_to = call_user_func ($ophandler[$pageno][$tabno][$op])))
158 $location = $redirect_to;
159 }
160 // known "soft" failures require a short error message
161 catch (InvalidRequestArgException $e)
162 {
163 ob_clean();
164 showError ($e->getMessage());
165 }
166 catch (RTDatabaseError $e)
167 {
168 ob_clean();
169 showError ('Database error: ' . $e->getMessage());
170 }
171 catch (RTPermissionDenied $e)
172 {
173 ob_clean();
174 showError ('Operation not permitted');
175 }
176 header ('Location: ' . $location);
177 // any other error requires no special handling and will be caught outside
178 break;
179 case 'popup' == $_REQUEST['module']:
180 require_once 'inc/popup.php';
181 require_once 'inc/init.php';
182 renderPopupHTML();
183 break;
184 case 'upgrade' == $_REQUEST['module']:
185 require_once 'inc/config.php'; // for CODE_VERSION
186 require_once 'inc/dictionary.php';
187 require_once 'inc/upgrade.php';
188 // Enforce default value for now, releases prior to 0.17.0 didn't support 'httpd' auth source.
189 $user_auth_src = 'database';
190 if (FALSE === @include_once 'inc/secret.php')
191 die ('<center>There is no working RackTables instance here, <a href="?module=installer">install</a>?</center>');
192 try
193 {
194 $dbxlink = new PDO ($pdo_dsn, $db_username, $db_password);
195 }
196 catch (PDOException $e)
197 {
198 die ("Database connection failed:\n\n" . $e->getMessage());
199 }
200 renderUpgraderHTML();
201 break;
202 case 'installer' == $_REQUEST['module']:
203 require_once 'inc/dictionary.php';
204 require_once 'inc/install.php';
205 renderInstallerHTML();
206 break;
207 default:
208 throw new InvalidRequestArgException ('module', $_REQUEST['module']);
209 }
210 ob_end_flush();
211 }
212 catch (Exception $e)
213 {
214 ob_end_clean();
215 # prevent message appearing in foreign tab
216 if (isset ($_SESSION['log']))
217 unset ($_SESSION['log']);
218 printException ($e);
219 }
220 ?>