quick minor path updates (#1968)
[openemr.git] / interface / main / main_screen.php
blobc80439152b8460f8a4a5222ccf1491648c651d9e
1 <?php
2 /**
3 * The outside frame that holds all of the OpenEMR User Interface.
5 * @package OpenEMR
6 * @link http://www.open-emr.org
7 * @author Rod Roark <rod@sunsetsystems.com>
8 * @author Brady Miller <brady.g.miller@gmail.com>
9 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
10 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
13 /* Include our required headers */
14 require_once('../globals.php');
16 use OpenEMR\Core\Header;
17 use u2flib_server\U2F;
19 ///////////////////////////////////////////////////////////////////////
20 // Functions to support MFA.
21 ///////////////////////////////////////////////////////////////////////
23 function posted_to_hidden($name)
25 if (isset($_POST[$name])) {
26 echo "<input type='hidden' name='" . attr($name) . "' value='" . attr($_POST[$name]) . "' />\n";
30 function generate_html_start($title)
32 global $appId;
34 <html>
35 <head>
36 <?php Header::setupHeader(); ?>
37 <title><?php echo text($title); ?></title>
38 <script src="<?php echo $GLOBALS['webroot'] ?>/library/js/u2f-api.js"></script>
39 <script>
40 function doAuth() {
41 var f = document.forms[0];
42 var requests = JSON.parse(f.form_requests.value);
43 // The server's getAuthenticateData() repeats the same challenge in all requests.
44 var challenge = requests[0].challenge;
45 var registeredKeys = new Array();
46 for (var i = 0; i < requests.length; ++i) {
47 registeredKeys[i] = {"version": requests[i].version, "keyHandle": requests[i].keyHandle};
49 u2f.sign(
50 '<?php echo addslashes($appId); ?>',
51 challenge,
52 registeredKeys,
53 function(data) {
54 if(data.errorCode && data.errorCode != 0) {
55 alert('<?php echo xls("Key access failed with error"); ?> ' + data.errorCode);
56 return;
58 f.form_response.value = JSON.stringify(data);
59 f.submit();
64 </script>
65 </head>
66 <body class='body_top'>
67 <center>
68 <h2><?php echo text($title); ?></h2>
69 <form method="post"
70 action="main_screen.php?auth=login&site=<?php echo attr(urlencode($_GET['site'])); ?>"
71 target="_top" name="challenge_form">
72 <?php
73 posted_to_hidden('new_login_session_management');
74 posted_to_hidden('authProvider');
75 posted_to_hidden('languageChoice');
76 posted_to_hidden('authUser');
77 posted_to_hidden('clearPass');
80 function generate_html_end()
82 echo "</form></center></body></html>\n";
83 session_unset();
84 session_destroy();
85 unset($_COOKIE[session_name()]);
86 return 0;
89 $errormsg = '';
91 ///////////////////////////////////////////////////////////////////////
92 // Begin code to support U2F.
93 ///////////////////////////////////////////////////////////////////////
95 $regs = array(); // for mapping device handles to their names
96 $registrations = array(); // the array of stored registration objects
97 $res1 = sqlStatement(
98 "SELECT a.name, a.var1 FROM login_mfa_registrations AS a " .
99 "WHERE a.user_id = ? AND a.method = 'U2F' ORDER BY a.name",
100 array($_SESSION['authId'])
102 while ($row1 = sqlFetchArray($res1)) {
103 $regobj = json_decode($row1['var1']);
104 $regs[json_encode($regobj->keyHandle)] = $row1['name'];
105 $registrations[] = $regobj;
107 if (!empty($registrations)) {
108 // There is at least one U2F key registered so we have to request or verify key data.
109 // https is required, and with a proxy the server might not see it.
110 $scheme = "https://"; // isset($_SERVER['HTTPS']) ? "https://" : "http://";
111 $appId = $scheme . $_SERVER['HTTP_HOST'];
112 $u2f = new u2flib_server\U2F($appId);
113 $userid = $_SESSION['authId'];
114 $form_response = empty($_POST['form_response']) ? '' : $_POST['form_response'];
115 if ($form_response) {
116 // We have key data, check if it matches what was registered.
117 $tmprow = sqlQuery("SELECT login_work_area FROM users_secure WHERE id = ?", array($userid));
118 try {
119 $registration = $u2f->doAuthenticate(
120 json_decode($tmprow['login_work_area']), // these are the original challenge requests
121 $registrations,
122 json_decode($_POST['form_response'])
124 // Stored registration data needs to be updated because the usage count has changed.
125 // We have to use the matching registered key.
126 $strhandle = json_encode($registration->keyHandle);
127 if (isset($regs[$strhandle])) {
128 sqlStatement(
129 "UPDATE login_mfa_registrations SET `var1` = ? WHERE " .
130 "`user_id` = ? AND `method` = 'U2F' AND `name` = ?",
131 array(json_encode($registration), $userid, $regs[$strhandle])
133 } else {
134 error_log("Unexpected keyHandle returned from doAuthenticate(): '$strhandle'");
136 // Keep track of when challenges were last answered correctly.
137 sqlStatement(
138 "UPDATE users_secure SET last_challenge_response = NOW() WHERE id = ?",
139 array($_SESSION['authId'])
141 } catch (u2flib_server\Error $e) {
142 // Authentication failed so we will build the U2F form again.
143 $form_response = '';
144 $errormsg = xl('Authentication error') . ": " . $e->getMessage();
147 if (!$form_response) {
148 // There is no key data yet or authentication failed, so we need to solicit it.
149 $requests = json_encode($u2f->getAuthenticateData($registrations));
150 // Persist the challenge also in the database because the browser is untrusted.
151 sqlStatement(
152 "UPDATE users_secure SET login_work_area = ? WHERE id = ?",
153 array($requests, $userid)
155 generate_html_start(xl('U2F Key Verification'));
156 echo "<p>\n";
157 echo xlt('Insert your key into a USB port and click the Authenticate button below.');
158 echo " " . xlt('Then press the flashing button on your key within 1 minute.') . "</p>\n";
159 echo "<table><tr><td>\n";
160 echo "<input type='button' value='" . xla('Authenticate') . "' onclick='doAuth()' />\n";
161 echo "<input type='hidden' name='form_requests' value='" . attr($requests) . "' />\n";
162 echo "<input type='hidden' name='form_response' value='' />\n";
163 echo "</td></tr></table>\n";
164 if ($errormsg) {
165 echo "<p style='color:red;font-weight:bold'>" . text($errormsg) . "</p>\n";
167 exit(generate_html_end());
171 ///////////////////////////////////////////////////////////////////////
172 // End of U2F logic.
173 ///////////////////////////////////////////////////////////////////////
175 // Creates a new session id when load this outer frame
176 // (allows creations of separate OpenEMR frames to view patients concurrently
177 // on different browser frame/windows)
178 // This session id is used below in the restoreSession.php include to create a
179 // session cookie for this specific OpenEMR instance that is then maintained
180 // within the OpenEMR instance by calling top.restoreSession() whenever
181 // refreshing or starting a new script.
182 if (isset($_POST['new_login_session_management'])) {
183 // This is a new login, so create a new session id and remove the old session
184 session_regenerate_id(true);
185 } else {
186 // This is not a new login, so check csrf and then create a new session id and do NOT remove the old session
187 if (!verifyCsrfToken($_POST["csrf_token_form"])) {
188 csrfNotVerified();
190 session_regenerate_id(false);
192 // Create the csrf_token
193 $_SESSION['csrf_token'] = createCsrfToken();
195 $_SESSION["encounter"] = '';
197 // Fetch the password expiration date
198 $is_expired=false;
199 if ($GLOBALS['password_expiration_days'] != 0) {
200 $is_expired=false;
201 $q= (isset($_POST['authUser'])) ? $_POST['authUser'] : '';
202 $result = sqlStatement("select pwd_expiration_date from users where username = ?", array($q));
203 $current_date = date('Y-m-d');
204 $pwd_expires_date = $current_date;
205 if ($row = sqlFetchArray($result)) {
206 $pwd_expires_date = $row['pwd_expiration_date'];
209 // Display the password expiration message (starting from 7 days before the password gets expired)
210 $pwd_alert_date = date('Y-m-d', strtotime($pwd_expires_date . '-7 days'));
212 if (strtotime($pwd_alert_date) != '' &&
213 strtotime($current_date) >= strtotime($pwd_alert_date) &&
214 (!isset($_SESSION['expiration_msg'])
215 or $_SESSION['expiration_msg'] == 0)) {
216 $is_expired = true;
217 $_SESSION['expiration_msg'] = 1; // only show the expired message once
221 if ($is_expired) {
222 //display the php file containing the password expiration message.
223 $frame1url = "pwd_expires_alert.php?csrf_token_form=" . attr(urlencode(collectCsrfToken()));
224 $frame1target = "adm";
225 } else if (!empty($_POST['patientID'])) {
226 $patientID = 0 + $_POST['patientID'];
227 if (empty($_POST['encounterID'])) {
228 // Open patient summary screen (without a specific encounter)
229 $frame1url = "../patient_file/summary/demographics.php?set_pid=" . attr(urlencode($patientID));
230 $frame1target = "pat";
231 } else {
232 // Open patient summary screen with a specific encounter
233 $encounterID = 0 + $_POST['encounterID'];
234 $frame1url = "../patient_file/summary/demographics.php?set_pid=" . attr(urlencode($patientID)) . "&set_encounterid=" . attr(urlencode($encounterID));
235 $frame1target = "pat";
237 } else if (isset($_GET['mode']) && $_GET['mode'] == "loadcalendar") {
238 $frame1url = "calendar/index.php?pid=" . attr(urlencode($_GET['pid']));
239 if (isset($_GET['date'])) {
240 $frame1url .= "&date=" . attr(urlencode($_GET['date']));
243 $frame1target = "cal";
244 } else {
245 // standard layout
246 $map_paths_to_targets = array(
247 'main_info.php' => ('cal'),
248 '../new/new.php' => ('pat'),
249 '../../interface/main/finder/dynamic_finder.php' => ('fin'),
250 '../../interface/patient_tracker/patient_tracker.php?skip_timeout_reset=1' => ('flb'),
251 '../../interface/main/messages/messages.php?form_active=1' => ('msg')
253 if ($GLOBALS['default_top_pane']) {
254 $frame1url=attr($GLOBALS['default_top_pane']);
255 $frame1target = $map_paths_to_targets[$GLOBALS['default_top_pane']];
256 if (empty($frame1target)) {
257 $frame1target = "msc";
259 } else {
260 $frame1url = "main_info.php";
261 $frame1target = "cal";
263 if ($GLOBALS['default_second_tab']) {
264 $frame2url=attr($GLOBALS['default_second_tab']);
265 $frame2target = $map_paths_to_targets[$GLOBALS['default_second_tab']];
266 if (empty($frame2target)) {
267 $frame2target = "msc";
269 } else {
270 $frame2url = "../../interface/main/messages/messages.php?form_active=1";
271 $frame2target = "msg";
275 $nav_area_width = '130';
276 if (!empty($GLOBALS['gbl_nav_area_width'])) {
277 $nav_area_width = $GLOBALS['gbl_nav_area_width'];
280 // This is where will decide whether to use tabs layout or non-tabs layout
281 // Will also set Session variables to communicate settings to tab layout
282 if ($GLOBALS['new_tabs_layout']) {
283 $_SESSION['frame1url'] = $frame1url;
284 $_SESSION['frame1target'] = $frame1target;
285 $_SESSION['frame2url'] = $frame2url;
286 $_SESSION['frame2target'] = $frame2target;
287 // mdsupport - Apps processing invoked for valid app selections from list
288 if ((isset($_POST['appChoice'])) && ($_POST['appChoice'] !== '*OpenEMR')) {
289 $_SESSION['app1'] = $_POST['appChoice'];
292 // Pass a unique token, so main.php script can not be run on its own
293 $_SESSION['token_main_php'] = createUniqueToken();
294 header('Location: ' . $web_root . "/interface/main/tabs/main.php?token_main=" . urlencode($_SESSION['token_main_php']));
295 exit();
299 <html>
300 <head>
301 <title>
302 <?php echo text($openemr_name) ?>
303 </title>
304 <script type="text/javascript" src="<?php echo $GLOBALS['assets_static_relative']; ?>/jquery-1-9-1/jquery.min.js"></script>
305 <script type="text/javascript" src="../../library/topdialog.js"></script>
306 <script type="text/javascript" src="tabs/js/dialog_utils.js?v=<?php echo $v_js_includes; ?>"></script>
308 <link rel="shortcut icon" href="<?php echo $GLOBALS['images_static_relative']; ?>/favicon.ico" />
310 <script language='JavaScript'>
312 // Flag that tab mode is off
313 var tab_mode=false;
315 var webroot_url = '<?php echo $GLOBALS['web_root']; ?>';
316 var jsLanguageDirection = "<?php echo $_SESSION["language_direction"]; ?>";
318 <?php require($GLOBALS['srcdir'] . "/restoreSession.php"); ?>
320 // Since this should be the parent window, this is to prevent calls to the
321 // window that opened this window. For example when a new window is opened
322 // from the Patient Flow Board or the Patient Finder.
323 window.opener = null;
325 // This flag indicates if another window or frame is trying to reload the login
326 // page to this top-level window. It is set by javascript returned by auth.inc
327 // and is checked by handlers of beforeunload events.
328 var timed_out = false;
330 // This counts the number of frames that have reported themselves as loaded.
331 // Currently only left_nav and Title do this, so the maximum will be 2.
332 // This is used to determine when those frames are all loaded.
333 var loadedFrameCount = 0;
335 function allFramesLoaded() {
336 // Change this number if more frames participate in reporting.
337 return loadedFrameCount >= 2;
339 </script>
341 </head>
343 <?php
345 * for RTL layout we need to change order of frames in framesets
347 $lang_dir = $_SESSION['language_direction'];
349 $sidebar_tpl = "<frameset rows='*,0' frameborder='0' border='0' framespacing='0'>
350 <frame src='left_nav.php' name='left_nav' />
351 <frame src='daemon_frame.php' name='Daemon' scrolling='no' frameborder='0'
352 border='0' framespacing='0' />
353 </frameset>";
355 $main_tpl = "<frameset rows='60%,*' id='fsright' bordercolor='#999999' frameborder='1'>" ;
356 $main_tpl .= "<frame src='". $frame1url ."' name='RTop' scrolling='auto' />
357 <frame src='messages/messages.php?form_active=1' name='RBot' scrolling='auto' /></frameset>";
359 // Please keep in mind that border (mozilla) and framespacing (ie) are the
360 // same thing. use both.
361 // frameborder specifies a 3d look, not whether there are borders.
363 if (empty($GLOBALS['gbl_tall_nav_area'])) {
364 // not tall nav area ?>
365 <frameset rows='<?php echo attr($GLOBALS['titleBarHeight']) + 5 ?>,*' frameborder='1' border='1' framespacing='1' onunload='imclosing()'>
366 <frame src='main_title.php' name='Title' scrolling='no' frameborder='1' noresize />
367 <?php if ($lang_dir != 'rtl') { ?>
368 <frameset cols='<?php echo attr($nav_area_width) . ',*'; ?>' id='fsbody' frameborder='1' border='4' framespacing='4'>
369 <?php echo $sidebar_tpl ?>
370 <?php echo $main_tpl ?>
371 </frameset>
373 <?php } else { ?>
374 <frameset cols='<?php echo '*,' . attr($nav_area_width); ?>' id='fsbody' frameborder='1' border='4' framespacing='4'>
375 <?php echo $main_tpl ?>
376 <?php echo $sidebar_tpl ?>
377 </frameset>
379 <?php } ?>
381 </frameset>
382 </frameset>
384 <?php } else { // use tall nav area ?>
385 <frameset cols='<?php echo attr($nav_area_width); ?>,*' id='fsbody' frameborder='1' border='4' framespacing='4' onunload='imclosing()'>
386 <frameset rows='*,0' frameborder='0' border='0' framespacing='0'>
387 <frame src='left_nav.php' name='left_nav' />
388 <frame src='daemon_frame.php' name='Daemon' scrolling='no' frameborder='0'
389 border='0' framespacing='0' />
390 </frameset>
391 <frameset rows='<?php echo attr($GLOBALS['titleBarHeight']) + 5 ?>,*' frameborder='1' border='1' framespacing='1'>
392 <frame src='main_title.php' name='Title' scrolling='no' frameborder='1' />
393 <frameset rows='60%,*' id='fsright' bordercolor='#999999' frameborder='1' border='4' framespacing='4'>
394 <frame src='<?php echo $frame1url ?>' name='RTop' scrolling='auto' />
395 <frame src='messages/messages.php?form_active=1' name='RBot' scrolling='auto' />
396 </frameset>
397 </frameset>
398 </frameset>
400 <?php } // end tall nav area ?>
402 </html>