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