xss patient name vulnerability fix contributed by Andrew Moore
[openemr.git] / interface / main / finder / patient_select.php
blob63492644514b9f4e3474a6bfba37ad1adc150ce1
1 <?php
2 // This program is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU General Public License
4 // as published by the Free Software Foundation; either version 2
5 // of the License, or (at your option) any later version.
7 include_once("../../globals.php");
8 include_once("$srcdir/patient.inc");
9 include_once("$srcdir/formdata.inc.php");
11 $fstart = $_REQUEST['fstart'] + 0;
12 $popup = empty($_REQUEST['popup']) ? 0 : 1;
13 $message = strip_escape_custom($_GET['message']);
16 <html>
17 <head>
18 <?php html_header_show();?>
20 <link rel=stylesheet href="<?php echo $css_header;?>" type="text/css">
21 <style>
22 form {
23 padding: 0px;
24 margin: 0px;
26 #searchCriteria {
27 text-align: center;
28 width: 100%;
29 font-size: 0.8em;
30 background-color: #ddddff;
31 font-weight: bold;
32 padding: 3px;
34 #searchResultsHeader {
35 width: 100%;
36 background-color: lightgrey;
38 #searchResultsHeader table {
39 width: 96%; /* not 100% because the 'searchResults' table has a scrollbar */
40 border-collapse: collapse;
42 #searchResultsHeader th {
43 font-size: 0.7em;
45 #searchResults {
46 width: 100%;
47 height: 80%;
48 overflow: auto;
51 .srName { width: 12%; }
52 .srPhone { width: 11%; }
53 .srSS { width: 11%; }
54 .srDOB { width: 8%; }
55 .srID { width: 7%; }
56 .srPID { width: 7%; }
57 .srNumEnc { width: 11%; }
58 .srNumDays { width: 11%; }
59 .srDateLast { width: 11%; }
60 .srDateNext { width: 11%; }
61 .srMisc { width: 10%; }
63 #searchResults table {
64 width: 100%;
65 border-collapse: collapse;
66 background-color: white;
68 #searchResults tr {
69 cursor: hand;
70 cursor: pointer;
72 #searchResults td {
73 font-size: 0.7em;
74 border-bottom: 1px solid #eee;
76 .oneResult { }
77 .billing { color: red; font-weight: bold; }
78 .highlight {
79 background-color: #336699;
80 color: white;
82 </style>
84 <script type="text/javascript" src="<?php echo $GLOBALS['webroot'] ?>/library/js/jquery-1.2.2.min.js"></script>
86 <script language="JavaScript">
88 // This is called when forward or backward paging is done.
90 function submitList(offset) {
91 var f = document.forms[0];
92 var i = parseInt(f.fstart.value) + offset;
93 if (i < 0) i = 0;
94 f.fstart.value = i;
95 f.submit();
98 </script>
100 </head>
101 <body class="body_top">
103 <form method='post' action='patient_select.php' name='theform'>
104 <input type='hidden' name='fstart' value='<?php echo $fstart ?>' />
106 <?php
107 $MAXSHOW = 100; // maximum number of results to display at once
109 //the maximum number of patient records to display:
110 $sqllimit = $MAXSHOW;
111 $given = "*, DATE_FORMAT(DOB,'%m/%d/%Y') as DOB_TS";
112 $orderby = "lname ASC, fname ASC";
114 if ($popup) {
115 echo "<input type='hidden' name='popup' value='1' />\n";
117 // Construct WHERE clause and save search parameters as form fields.
118 $where = "1 = 1";
119 $fres = sqlStatement("SELECT * FROM layout_options " .
120 "WHERE form_id = 'DEM' AND uor > 0 AND field_id != '' " .
121 "ORDER BY group_name, seq");
122 while ($frow = sqlFetchArray($fres)) {
123 $field_id = $frow['field_id'];
124 if (strpos($field_id, 'em_') === 0) continue;
125 $data_type = $frow['data_type'];
126 if (!empty($_REQUEST[$field_id])) {
127 $value = formData($field_id,"R",true);
128 if ($field_id == 'pid') {
129 $where .= " AND $field_id = '$value'";
131 else if ($field_id == 'pubpid') {
132 $where .= " AND $field_id LIKE '$value'";
134 else {
135 $where .= " AND $field_id LIKE '$value%'";
137 echo "<input type='hidden' name='$field_id' value='$value' />\n";
141 $sql = "SELECT $given FROM patient_data " .
142 "WHERE $where ORDER BY $orderby LIMIT $fstart, $sqllimit";
143 $rez = sqlStatement($sql);
144 $result = array();
145 while ($row = sqlFetchArray($rez)) $result[] = $row;
146 _set_patient_inc_count($sqllimit, count($result), $where);
148 else {
149 $patient = formData("patient","R");
150 $findBy = $_REQUEST['findBy'];
151 $searchFields = $_REQUEST['searchFields'];
153 echo "<input type='hidden' name='patient' value='$patient' />\n";
154 echo "<input type='hidden' name='findBy' value='$findBy' />\n";
156 if ($findBy == "Last")
157 $result = getPatientLnames("$patient", $given, $orderby, $sqllimit, $fstart);
158 else if ($findBy == "ID")
159 $result = getPatientId("$patient", $given, "id ASC, ".$orderby, $sqllimit, $fstart);
160 else if ($findBy == "DOB")
161 $result = getPatientDOB("$patient", $given, "DOB ASC, ".$orderby, $sqllimit, $fstart);
162 else if ($findBy == "SSN")
163 $result = getPatientSSN("$patient", $given, "ss ASC, ".$orderby, $sqllimit, $fstart);
164 elseif ($findBy == "Phone") //(CHEMED) Search by phone number
165 $result = getPatientPhone("$patient", $given, $orderby, $sqllimit, $fstart);
166 else if ($findBy == "Any")
167 $result = getByPatientDemographics("$patient", $given, $orderby, $sqllimit, $fstart);
168 else if ($findBy == "Filter") {
169 $result = getByPatientDemographicsFilter($searchFields, "$patient", $given, $orderby, $sqllimit, $fstart);
174 </form>
176 <table border='0' cellpadding='5' cellspacing='0' width='100%'>
177 <tr>
178 <td class='text'>
179 <a href="./patient_select_help.php" target=_new>[<?php xl('Help','e'); ?>]&nbsp</a>
180 </td>
181 <td class='text' align='center'>
182 <?php if ($message) echo "<font color='red'><b>$message</b></font>\n"; ?>
183 </td>
184 <td class='text' align='right'>
185 <?php
186 // Show start and end row number, and number of rows, with paging links.
188 // $count = $fstart + $GLOBALS['PATIENT_INC_COUNT']; // Why did I do that???
189 $count = $GLOBALS['PATIENT_INC_COUNT'];
190 $fend = $fstart + $MAXSHOW;
191 if ($fend > $count) $fend = $count;
193 <?php if ($fstart) { ?>
194 <a href="javascript:submitList(-<?php echo $MAXSHOW ?>)">
195 &lt;&lt;
196 </a>
197 &nbsp;&nbsp;
198 <?php } ?>
199 <?php echo ($fstart + 1) . " - $fend of $count" ?>
200 <?php if ($count > $fend) { ?>
201 &nbsp;&nbsp;
202 <a href="javascript:submitList(<?php echo $MAXSHOW ?>)">
203 &gt;&gt;
204 </a>
205 <?php } ?>
206 </td>
207 </tr>
208 </table>
210 <div id="searchResultsHeader">
211 <table>
212 <tr>
213 <th class="srName"><?php xl('Name','e');?></th>
214 <th class="srPhone"><?php xl('Phone','e');?></th>
215 <th class="srSS"><?php xl('SS','e');?></th>
216 <th class="srDOB"><?php xl('DOB','e');?></th>
217 <th class="srID"><?php xl('ID','e');?></th>
219 <?php if (empty($GLOBALS['patient_search_results_style'])) { ?>
220 <th class="srPID"><?php xl('PID','e');?></th>
221 <th class="srNumEnc"><?php xl('[Number Of Encounters]','e');?></th>
222 <th class="srNumDays"><?php xl('[Days Since Last Encounter]','e');?></th>
223 <th class="srDateLast"><?php xl('[Date of Last Encounter]','e');?></th>
224 <th class="srDateNext">
225 <?php
226 $add_days = 90;
227 if (!$popup && preg_match('/^(\d+)\s*(.*)/',$patient,$matches) > 0) {
228 $add_days = $matches[1];
229 $patient = $matches[2];
232 [<?php echo $add_days?> <?php xl('Days From Last Encounter','e'); ?>]
233 </th>
235 <?php
237 else {
238 // Alternate patient search results style; this gets address plus other
239 // fields that are mandatory, up to a limit of 5.
240 $extracols = array();
241 $tres = sqlStatement("SELECT field_id, title FROM layout_options " .
242 "WHERE form_id = 'DEM' AND ( uor > 1 AND field_id != '' " .
243 "OR uor > 0 AND field_id = 'street' ) AND " .
244 "field_id NOT LIKE '_name' AND " .
245 "field_id NOT LIKE 'phone%' AND " .
246 "field_id NOT LIKE 'title' AND " .
247 "field_id NOT LIKE 'ss' AND " .
248 "field_id NOT LIKE 'DOB' AND " .
249 "field_id NOT LIKE 'pubpid' " .
250 "ORDER BY group_name, seq LIMIT 5");
251 while ($trow = sqlFetchArray($tres)) {
252 $extracols[$trow['field_id']] = $trow['title'];
253 echo "<th class='srMisc'>" . $trow['title'] . "</th>\n";
258 </tr>
259 </table>
260 </div>
262 <div id="searchResults">
264 <table>
265 <tr>
266 <?php
267 if ($result) {
268 foreach ($result as $iter) {
269 echo "<tr class='oneresult' id='".$iter['pid']."'>";
270 echo "<td class='srName'>" . htmlspecialchars($iter['lname'] . ", " . $iter['fname']) . "</td>\n";
271 //other phone number display setup for tooltip
272 $phone_biz = '';
273 if ($iter{"phone_biz"} != "") {
274 $phone_biz = " [business phone ".$iter{"phone_biz"}."] ";
276 $phone_contact = '';
277 if ($iter{"phone_contact"} != "") {
278 $phone_contact = " [contact phone ".$iter{"phone_contact"}."] ";
280 $phone_cell = '';
281 if ($iter{"phone_cell"} != "") {
282 $phone_cell = " [cell phone ".$iter{"phone_cell"}."] ";
284 $all_other_phones = $phone_biz.$phone_contact.$phone_cell;
285 if ($all_other_phones == '') {$all_other_phones = 'No other phone numbers listed';}
286 //end of phone number display setup, now display the phone number(s)
287 echo "<td class='srPhone' title='$all_other_phones'>" . $iter['phone_home']. "</td>\n";
289 echo "<td class='srSS'>" . $iter['ss'] . "</td>";
290 if ($iter{"DOB"} != "0000-00-00 00:00:00") {
291 echo "<td class='srDOB'>" . $iter['DOB_TS'] . "</td>";
292 } else {
293 echo "<td class='srDOB'>&nbsp;</td>";
296 echo "<td class='srID'>" . $iter['pubpid'] . "</td>";
298 if (empty($GLOBALS['patient_search_results_style'])) {
300 echo "<td class='srPID'>" . $iter['pid'] . "</td>";
302 //setup for display of encounter date info
303 $encounter_count = 0;
304 $day_diff = '';
305 $last_date_seen = '';
306 $next_appt_date= '';
307 $pid = '';
309 // calculate date differences based on date of last encounter with billing entries
310 $query = "select DATE_FORMAT(max(form_encounter.date),'%m/%d/%y') as mydate," .
311 " (to_days(current_date())-to_days(max(form_encounter.date))) as day_diff," .
312 " DATE_FORMAT(max(form_encounter.date) + interval " . $add_days .
313 " day,'%m/%d/%y') as next_appt, dayname(max(form_encounter.date) + interval " .
314 $add_days." day) as next_appt_day from form_encounter " .
315 "join billing on billing.encounter = form_encounter.encounter and " .
316 "billing.pid = form_encounter.pid and billing.activity = 1 and " .
317 "billing.code_type not like 'COPAY' where ".
318 "form_encounter.pid = " . $iter{"pid"};
319 $statement= sqlStatement($query);
320 if ($results = mysql_fetch_array($statement, MYSQL_ASSOC)) {
321 $last_date_seen = $results['mydate'];
322 $day_diff = $results['day_diff'];
323 $next_appt_date= $results['next_appt_day'].', '.$results['next_appt'];
325 // calculate date differences based on date of last encounter regardless of billing
326 $query = "select DATE_FORMAT(max(form_encounter.date),'%m/%d/%y') as mydate," .
327 " (to_days(current_date())-to_days(max(form_encounter.date))) as day_diff," .
328 " DATE_FORMAT(max(form_encounter.date) + interval " . $add_days .
329 " day,'%m/%d/%y') as next_appt, dayname(max(form_encounter.date) + interval " .
330 $add_days." day) as next_appt_day from form_encounter " .
331 " where form_encounter.pid = " . $iter{"pid"};
332 $statement= sqlStatement($query);
333 if ($results = mysql_fetch_array($statement, MYSQL_ASSOC)) {
334 $last_date_seen = $results['mydate'];
335 $day_diff = $results['day_diff'];
336 $next_appt_date= $results['next_appt_day'].', '.$results['next_appt'];
339 //calculate count of encounters by distinct billing dates with cpt4
340 //entries
341 $query = "select count(distinct date) as encounter_count " .
342 " from billing ".
343 " where code_type not like 'COPAY' and activity = 1 " .
344 " and pid = ".$iter{"pid"};
345 $statement= sqlStatement($query);
346 if ($results = mysql_fetch_array($statement, MYSQL_ASSOC)) {
347 $encounter_count_billed = $results['encounter_count'];
349 // calculate count of encounters, regardless of billing
350 $query = "select count(date) as encounter_count ".
351 " from form_encounter where ".
352 " pid = ".$iter{"pid"};
353 $statement= sqlStatement($query);
354 if ($results = mysql_fetch_array($statement, MYSQL_ASSOC)) {
355 $encounter_count = $results['encounter_count'];
357 echo "<td class='srNumEnc'>" . $encounter_count . "</td>\n";
358 echo "<td class='srNumDay'>" . $day_diff . "</td>\n";
359 echo "<td class='srDateLast'>" . $last_date_seen . "</td>\n";
360 echo "<td class='srDateNext'>" . $next_appt_date . "</td>\n";
363 else { // alternate search results style
364 foreach ($extracols as $field_id => $title) {
365 echo "<td class='srMisc'>" . $iter[$field_id] . "</td>\n";
371 </table>
372 </div> <!-- end searchResults DIV -->
374 <script language="javascript">
376 // jQuery stuff to make the page a little easier to use
378 $(document).ready(function(){
379 // $("#searchparm").focus();
380 $(".oneresult").mouseover(function() { $(this).addClass("highlight"); });
381 $(".oneresult").mouseout(function() { $(this).removeClass("highlight"); });
382 $(".oneresult").click(function() { SelectPatient(this); });
383 // $(".event").dblclick(function() { EditEvent(this); });
386 var SelectPatient = function (eObj) {
387 <?php
388 // For the old layout we load a frameset that also sets up the new pid.
389 // The new layout loads just the demographics frame here, which in turn
390 // will set the pid and load all the other frames.
391 if ($GLOBALS['concurrent_layout']) {
392 $newPage = "../../patient_file/summary/demographics.php?set_pid=";
393 $target = "document";
395 else {
396 $newPage = "../../patient_file/patient_file.php?set_pid=";
397 $target = "top";
400 objID = eObj.id;
401 var parts = objID.split("~");
402 <?php if ($popup) echo "opener."; echo $target; ?>.location.href = '<?php echo $newPage; ?>' + parts[0];
403 <?php if ($popup) echo "window.close();\n"; ?>
404 return true;
407 </script>
409 </body>
410 </html>