Refactor Fee Sheet Printing to support an array of patient IDs from the appointment...
[openemr.git] / library / log.inc
blob34b3ce6ff9424bd6dbc7e8eebbc269b37f9802ca
1 <?php
2 #require_once("{$GLOBALS['srcdir']}/sql.inc");
3 require_once(dirname(__FILE__). "/sql.inc");
5 function newEvent($event, $user, $groupname, $success, $comments="") {
6     $adodb = $GLOBALS['adodb']['db'];
7     $crt_user=isset($_SERVER['SSL_CLIENT_S_DN_CN']) ?  $_SERVER['SSL_CLIENT_S_DN_CN'] : null;
8     /* More details added to the log */
9     $sql = "insert into log ( date, event, user, groupname, success, comments, crt_user) " .
10             "values ( NOW(), " . $adodb->qstr($event) . "," . $adodb->qstr($user) .
11             "," . $adodb->qstr($groupname) . "," . $adodb->qstr($success) . "," .
12             $adodb->qstr($comments) ."," .
13             $adodb->qstr($crt_user) .  ")";
15     $ret = sqlInsertClean_audit($sql);
16     send_atna_audit_msg($user, $groupname, $event, 0, $success, $comments);
19 function getEventByDate($date, $user="", $cols="DISTINCT date, event, user, groupname, patient_id, success, comments, checksum")
21     $sql = "SELECT $cols FROM log WHERE date >= '$date 00:00:00' AND date <= '$date 23:59:59'";
22     if ($user) $sql .= " AND user LIKE '$user'";
23     $sql .= " ORDER BY date DESC LIMIT 5000";
24     $res = sqlStatement($sql);
25     for($iter=0; $row=sqlFetchArray($res); $iter++) {
26         $all[$iter] = $row;
27     }
28     return $all;
31 /******************
32  * Get records from the LOG and Extended_Log table
33  * using the optional parameters:
34  *   date : a specific date  (defaults to today)
35  *   user : a specific user  (defaults to none)
36  *   cols : gather specific columns  (defaults to date,event,user,groupname,comments)
37  *   sortby : sort the results by  (defaults to none)
38  * RETURNS:
39  *   array of results
40  ******************/
41 function getEvents($params) 
43     // parse the parameters
44     $cols = "DISTINCT date, event, user, groupname, patient_id, success, comments,checksum,crt_user";
45     if (isset($params['cols']) && $params['cols'] != "") $cols = $params['cols'];
47     $date1 = date("Y-m-d", time());
48     if (isset($params['sdate']) && $params['sdate'] != "") $date1= $params['sdate'];
49     
50     $date2 = date("Y-m-d", time());
51     if (isset($params['edate']) && $params['edate'] != "") $date2= $params['edate'];
52     
53     $user = "";
54     if (isset($params['user']) && $params['user'] != "") $user= $params['user'];
56     //VicarePlus :: For Generating log with patient id.
57     $patient = "";
58     if (isset($params['patient']) && $params['patient'] != "") $patient= $params['patient'];
59     
60     $sortby = "";
61     if (isset($params['sortby']) && $params['sortby'] != "") $sortby = $params['sortby'];
62     
63     $levent = "";
64     if (isset($params['levent']) && $params['levent'] != "") $levent = $params['levent'];
65     
66      $tevent = "";
67     if (isset($params['tevent']) && $params['tevent'] != "") $tevent = $params['tevent'];
68     
69      $event = "";
70     if (isset($params['event']) && $params['event'] != "") $event = $params['event'];
71     if ($event!=""){
72     if ($sortby == "comments") $sortby = "description";
73     if ($sortby == "groupname") $sortby = ""; //VicarePlus :: since there is no groupname in extended_log
74     if ($sortby == "success") $sortby = "";   //VicarePlus :: since there is no success field in extended_log
75     if ($sortby == "checksum") $sortby = "";  //VicarePlus :: since there is no checksum field in extended_log
76     $columns = "DISTINCT date, event, user, recipient,patient_id,description";
77     $sql = "SELECT $columns FROM extended_log WHERE date >= '$date1 00:00:00' AND date <= '$date2 23:59:59'";
78     if ($user != "") $sql .= " AND user LIKE '$user'";
79     if ($patient != "") $sql .= " AND patient_id LIKE '$patient'";
80     if ($levent != "") $sql .= " AND event LIKE '$levent%'";
81     if ($sortby != "") $sql .= " ORDER BY ".$sortby." DESC "; // descending order
82     $sql .= " LIMIT 5000";
83     }
84     else
85     {
86     // do the query
87     $sql = "SELECT $cols FROM log WHERE date >= '$date1 00:00:00' AND date <= '$date2 23:59:59'";
88     if ($user != "") $sql .= " AND user LIKE '$user'";
89     if ($patient != "") $sql .= " AND patient_id LIKE '$patient'";
90     if ($levent != "") $sql .= " AND event LIKE '$levent%'";
91     if ($tevent != "") $sql .= " AND event LIKE '%$tevent'";
92     if ($sortby != "") $sql .= " ORDER BY ".$sortby." DESC "; // descending order
93     $sql .= " LIMIT 5000";
94     }
95     $res = sqlStatement($sql);
96     for($iter=0; $row=sqlFetchArray($res); $iter++) {
97         $all[$iter] = $row;
98     }
99     return $all;
102 /* Given an SQL insert/update that was just performeds:
103  * - Find the table and primary id of the row that was created/modified
104  * - Calculate the SHA1 checksum of that row (with all the
105  *   column values concatenated together).
106  * - Return the SHA1 checksum as a 40 char hex string.
107  * If this is not an insert/update query, return "".
108  * If multiple rows were modified, return "".
109  * If we're unable to determine the row modified, return "".
110  */
111 function sql_checksum_of_modified_row($statement)
113     $table = "";
114     $rid = "";
116     $tokens = preg_split("/[\s,(\'\"]+/", $statement);
117     /* Identifying the id for insert/replace statements for calculating the checksum */
118         if((strcasecmp($tokens[0],"INSERT")==0) || (strcasecmp($tokens[0],"REPLACE")==0)){
119         $table = $tokens[2];
120         $rid = mysql_insert_id($GLOBALS['dbh']);
121         /* For handling the table that doesn't have auto-increment column */
122         if ($rid === 0 || $rid === FALSE) {
123           if($table == "gacl_aco_map" || $table == "gacl_aro_groups_map" || $table == "gacl_aro_map" || $table == "gacl_axo_groups_map" || $table == "gacl_axo_map")
124            $id="acl_id";
125           else if($table == "gacl_groups_aro_map" || $table == "gacl_groups_axo_map")
126           $id="group_id";
127           else
128            $id="id";
129           /* To handle insert statements */
130           if($tokens[3] == $id){
131              for($i=4;$i<count($tokens);$i++){
132                  if(strcasecmp($tokens[$i],"VALUES")==0){
133                   $rid=$tokens[$i+1];
134                      break;
135                 }// if close
136               }//for close
137             }//if close
138         /* To handle replace statements */
139           else if(strcasecmp($tokens[3],"SET")==0){
140                  if((strcasecmp($tokens[4],"ID")==0) || (strcasecmp($tokens[4],"`ID`")==0)){
141                   $rid=$tokens[6];
142            }// if close
143         }
145         else {          
146             return "";
147           }
148         }
149     }
150      /* Identifying the id for update statements for calculating the checksum */
151        else if(strcasecmp($tokens[0],"UPDATE")==0){
152         $table = $tokens[1];
154         $offset = 3;
155         $total = count($tokens);
157         /* Identifying the primary key column for the updated record */ 
158         if ($table == "form_physical_exam") {
159             $id = "forms_id";
160         }
161         else if ($table == "claims"){
162             $id = "patient_id";
163         }
164         else if ($table == "openemr_postcalendar_events") {
165             $id = "pc_eid";
166         }
167          else if ($table == "lang_languages"){
168             $id = "lang_id";
169          }
170          else if ($table == "openemr_postcalendar_categories" || $table == "openemr_postcalendar_topics"){
171             $id = "pc_catid";
172          }
173          else if ($table == "openemr_postcalendar_limits"){
174             $id = "pc_limitid";
175          }
176          else if($table == "gacl_aco_map" || $table == "gacl_aro_groups_map" || $table == "gacl_aro_map" || $table == "gacl_axo_groups_map" || $table == "gacl_axo_map"){
177            $id="acl_id";
178           }
179           else if($table == "gacl_groups_aro_map" || $table == "gacl_groups_axo_map"){
180           $id="group_id";
181           }
182            else {
183             $id = "id";
184            }
185         
186          /* Identifying the primary key value for the updated record */
187         while ($offset < $total) {
188             /* There are 4 possible ways that the id=123 can be parsed:
189              * ('id', '=', '123')
190              * ('id=', '123')
191              * ('id=123')
192              * ('id', '=123')
193              */
194             $rid = "";
195            /*id=', '123'*/
196             if (($tokens[$offset] == "$id=") && ($offset + 1 < $total)) {
197                 $rid = $tokens[$offset+1];
198                 break;
199             }
200            /* 'id', '=', '123' */
201             else if ($tokens[$offset] == "$id" && $tokens[$offset+1] == "=" && ($offset+2 < $total)) {
202                 $rid = $tokens[$offset+2];
203                 break;
204              }
205             /*id=123*/
206             else if (strpos($tokens[$offset], "$id=") === 0) {
207                 $tid = substr($tokens[$offset], strlen($id)+1);
208                 if(is_numeric($tid))
209                  $rid=$tid;
210                  break;
211              }
212            /*'id', '=123' */
213              else if($tokens[$offset] == "$id") {
214                 $tid = substr($tokens[$offset+1],1);
215                 if(is_numeric($tid))
216                  $rid=$tid;
217                 break;
218               } 
219             $offset += 1;
220         }//while ($offset < $total)
221     }// else if ($tokens[0] == 'update' || $tokens[0] == 'UPDATE' )
223     if ($table == "" || $rid == "") {
224         return "";
225     }
226    /* Framing sql statements for calculating checksum */ 
227    if ($table == "form_physical_exam") {
228         $sql = "select * from $table where forms_id = $rid";
229     }
230    else if ($table == "claims"){
231                 $sql = "select * from $table where patient_id = $rid";
232         }
233    else if ($table == "openemr_postcalendar_events") {
234             $sql = "select * from $table where pc_eid = $rid";
235         }
236     else if ($table == "lang_languages") {
237             $sql = "select * from $table where lang_id = $rid";
238     }
239     else if ($table == "openemr_postcalendar_categories" || $table == "openemr_postcalendar_topics"){
240             $sql = "select * from $table where pc_catid = $rid";
241          }
242     else if ($table == "openemr_postcalendar_limits"){
243            $sql = "select * from $table where pc_limitid = $rid";
244          }
245     else if ($table ==  "gacl_aco_map" || $table == "gacl_aro_groups_map" || $table == "gacl_aro_map" || $table == "gacl_axo_groups_map" || $table == "gacl_axo_map"){
246            $sql = "select * from $table where acl_id = $rid";
247          }
248      else if($table == "gacl_groups_aro_map" || $table == "gacl_groups_axo_map"){
249            $sql = "select * from $table where group_id = $rid";
250       }
251      else {
252         $sql = "select * from $table where id = $rid";
253     }
254     $results = sqlQuery($sql,'true');    
255     $column_values = "";
256    /* Concatenating the column values for the row inserted/updated */
257     if (is_array($results)) {
258         foreach ($results as $field_name => $field) {
259             $column_values .= $field;
260         }
261     }
262     // ViCarePlus: As per NIST standard, the encryption algorithm SHA1 is used
263     return sha1($column_values);
266 /* Create an XML audit record corresponding to RFC 3881.
267  * The parameters passed are the column values (from table 'log')
268  * for a single audit record.
269  */
270 function create_rfc3881_msg($user, $group, $event, $patient_id, $outcome, $comments)
273     /* Event action codes indicate whether the event is read/write.
274      * C = create, R = read, U = update, D = delete, E = execute
275      */
276     $eventActionCode = 'E';
277     if (substr($event, -7) == "-create") {
278         $eventActionCode = 'C';
279     }
280     else if (substr($event, -7) == "-insert") {
281         $eventActionCode = 'C';
282     }
283     else if (substr($event, -7) == "-select") {
284         $eventActionCode = 'R';
285     }
286     else if (substr($event, -7) == "-update") {
287         $eventActionCode = 'U';
288     }
289     else if (substr($event, -7) == "-delete") {
290         $eventActionCode = 'D';
291     }
293     $date_obj = new DateTime();
294     $eventDateTime = $date_obj->format(DATE_ATOM);
296     /* For EventOutcomeIndicator, 0 = success and 4 = minor error */
297     $eventOutcome = ($outcome === 1) ? 0 : 4;
299     /* The choice of event codes is up to OpenEMR.
300      * We're using the same event codes as
301      * https://iheprofiles.projects.openhealthtools.org/
302      */
303     $eventIDcodeSystemName = "DCM";
304     $eventIDcode = 0;
305     $eventIDdisplayName = $event;
307     if (strpos($event, 'patient-record') !== FALSE) {
308         $eventIDcode = 110110;
309         $eventIDdisplayName = 'Patient Record';
310     }
311     else if (strpos($event, 'view') !== FALSE) {
312         $eventIDCode = 110110;
313         $eventIDdisplayName = 'Patient Record';
314     }
315     else if (strpos($event, 'login') !== FALSE) {
316         $eventIDcode = 110122;
317         $eventIDdisplayName = 'Login';
318     }
319     else if (strpos($event, 'logout') !== FALSE) {
320         $eventIDcode = 110123;
321         $eventIDdisplayName = 'Logout';
322     }
323     else if (strpos($event, 'scheduling') !== FALSE) {
324         $eventIDcode = 110111;
325         $eventIDdisplayName = 'Patient Care Assignment';
326     }
327     else if (strpos($event, 'security-administration') !== FALSE) {
328         $eventIDcode = 110129;
329         $eventIDdisplayName = 'Security Administration';
330     }
333    
335     /* Variables used in ActiveParticipant section, which identifies
336      * the IP address and application of the source and destination.
337      */
338     $srcUserID = $_SERVER['SERVER_NAME'] . '|OpenEMR';
339     $srcNetwork = $_SERVER['SERVER_ADDR'];
340     $destUserID = $GLOBALS['atna_audit_host'];
341     $destNetwork = $GLOBALS['atna_audit_host'];
343     $userID = $user;
344     $userTypeCode = 1;
345     $userRole = 6;
346     $userCode = 11;
347     $userDisplayName = 'User Identifier';
349     $patientID = "";
350     $patientTypeCode = "";
351     $patientRole = "";
352     $patientCode = "";
353     $patientDisplayName = "";
355     if ($eventIdDisplayName == 'Patient Record') {
356         $patientID = $patient_id;
357         $pattientTypeCode = 1;
358         $patientRole = 1;
359         $patientCode = 2;
360         $patientDisplayName = 'Patient Number';
361     }
363     /* Construct the XML audit message, and save to $msg */
364     $msg =  '<?xml version="1.0" encoding="ASCII"?>';
365     $msg .= '<AuditMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ';
366     $msg .= 'xsi:noNamespaceSchemaLocation="healthcare-security-audit.xsd">';
368     /* Indicate the event code, text name, read/write type, and date/time */
369     $msg .= "<EventIdentification EventActionCode=\"$eventActionCode\" ";
370     $msg .= "EventDateTime=\"$eventDateTime\" ";
371     $msg .= "EventOutcomeIndicator=\"$eventOutcome\">";
372     $msg .= "<EventID code=\"eventIDcode\" displayName=\"$eventIDdisplayName\" ";
373     $msg .= "codeSystemName=\"DCM\" />";
374     $msg .= "</EventIdentification>";
376     /* Indicate the IP address and application of the source and destination */
377     $msg .= "<ActiveParticipant UserID=\"$srcUserID\" UserIsRequestor=\"true\" ";
378     $msg .= "NetworkAccessPointID=\"$srcNetwork\" NetworkAccessPointTypeCode=\"2\" >";
379     $msg .= "<RoleIDCode code=\"110153\" displayName=\"Source\" codeSystemName=\"DCM\" />";
380     $msg .= "</ActiveParticipant>";
381     $msg .= "<ActiveParticipant UserID=\"$destUserID\" UserIsRequestor=\"false\" ";
382     $msg .= "NetworkAccessPointID=\"$destNetwork\" NetworkAccessPointTypeCode=\"2\" >";
383     $msg .= "<RoleIDCode code=\"110152\" displayName=\"Destination\" codeSystemName=\"DCM\" />";
384     $msg .= "</ActiveParticipant>";
386     $msg .= "<AuditSourceIdentification AuditSourceID=\"$srcUserID\" />";
388     /* Indicate the username who generated this audit record */
389     $msg .= "<ParticipantObjectIdentification ParticipantObjectID=\"$user\" ";
390     $msg .= "ParticipantObjectTypeCode=\"1\" ";
391     $msg .= "ParticipantObjectTypeCodeRole=\"6\" >";
392     $msg .= "<ParticipantObjectIDTypeCode code=\"11\" ";
393     $msg .= "displayName=\"User Identifier\" ";
394     $msg .= "codeSystemName=\"RFC-3881\" /></ParticipantObjectIdentification>";
396     if ($eventIDdisplayName == 'Patient Record' && $patient_id != 0) {
397         $msg .= "<ParticipantObjectIdentification ParticipantObjectID=\"$patient_id\" ";
398         $msg .= "ParticipantObjectTypeCode=\"1\" ";
399         $msg .= "ParticipantObjectTypeCodeRole=\"1\" >";
400         $msg .= "<ParticipantObjectIDTypeCode code=\"2\" ";
401         $msg .= "displayName=\"Patient Number\" ";
402         $msg .= "codeSystemName=\"RFC-3881\" /></ParticipantObjectIdentification>";
403     }
404     $msg .= "</AuditMessage>";
406     /* Add the syslog header */
407     $date_obj = new DateTime($date);
408     $datestr= $date_obj->format(DATE_ATOM);
409     $msg = "<13> " . $datestr . " " . $_SERVER['SERVER_NAME'] . " " . $msg;
410     return $msg;
414 /* Create a TLS (SSLv3) connection to the given host/port.
415  * $localcert is the path to a PEM file with a client certificate and private key.
416  * $cafile is the path to the CA certificate file, for
417  *  authenticating the remote machine's certificate.
418  * If $cafile is "", the remote machine's certificate is not verified.
419  * If $localcert is "", we don't pass a client certificate in the connection.
421  * Return a stream resource that can be used with fwrite(), fread(), etc.
422  * Returns FALSE on error.
423  */
424 function create_tls_conn($host, $port, $localcert, $cafile) {
425     $sslopts = array();
426     if ($cafile !== null && $cafile != "") {
427         $sslopts['cafile'] = $cafile;
428         $sslopts['verify_peer'] = TRUE;
429         $sslopts['verify_depth'] = 10;
430     }
431     if ($localcert !== null && $localcert != "") {
432         $sslopts['local_cert'] = $localcert;
433     }
434     $opts = array('tls' => $sslopts, 'ssl' => $sslopts);
435     $ctx = stream_context_create($opts);
436     $timeout = 60;
437     $flags = STREAM_CLIENT_CONNECT;
439     $olderr = error_reporting(0);
440     $conn = stream_socket_client('tls://' . $host . ":" . $port, $errno, $errstr,
441                                  $timeout, $flags, $ctx);
442     error_reporting($olderr);
443     return $conn;
447 /* This function is used to send audit records to an Audit Repository Server,
448  * as described in the Audit Trail and Node Authentication (ATNA) standard.
449  * Given the fields in a single audit record:
450  * - Create an XML audit message according to RFC 3881, including the RFC5425 syslog header.
451  * - Create a TLS connection that performs bi-directions certificate authentication,
452  *   according to RFC 5425.
453  * - Send the XML message on the TLS connection.
454  */
455 function send_atna_audit_msg($user, $group, $event, $patient_id, $outcome, $comments)
457     /* If no ATNA repository server is configured, return */
458     if ($GLOBALS['atna_audit_host'] === null || $GLOBALS['atna_audit_host'] == "" || !($GLOBALS['enable_atna_audit'])) {
459         return;
460     }
461     $host = $GLOBALS['atna_audit_host'];
462     $port = $GLOBALS['atna_audit_port'];
463     $localcert = $GLOBALS['atna_audit_localcert'];
464     $cacert = $GLOBALS['atna_audit_cacert'];
465     $conn = create_tls_conn($host, $port, $localcert, $cacert);
466     if ($conn !== FALSE) {
467         $msg = create_rfc3881_msg($user, $group, $event, $patient_id, $outcome, $comments);
468         $len = strlen($msg);
469         fwrite($conn, $msg);
470         fclose($conn);
471     }
475 /* Add an entry into the audit log table, indicating that an
476  * SQL query was performed. $outcome is true if the statement
477  * successfully completed.  Determine the event type based on
478  * the tables present in the SQL query.
479  */
480 function auditSQLEvent($statement, $outcome)
482     $user =  isset($_SESSION['authUser']) ? $_SESSION['authUser'] : "";
483         /* Don't log anything if the audit logging is not enabled. Exception for "emergency" users */
484    if (!isset($GLOBALS['enable_auditlog']) || !($GLOBALS['enable_auditlog']))
485    {
486             if ((soundex($user) != soundex("emergency")) && (soundex($user) != soundex("breakglass")))
487             return;
488    }
491    $statement = trim($statement);
493     /* Don't audit SQL statements done to the audit log,
494      * or we'll have an infinite loop.
495      */
496     if ((stripos($statement, "insert into log") !== FALSE) ||
497         (stripos($statement, "FROM log ") !== FALSE) ) {
498         return;
499     }
501     $group = isset($_SESSION['authGroup']) ?  $_SESSION['authGroup'] : "";
502     $comments = $statement;
503     $success = 1;
504     $checksum = "";
505     if ($outcome === FALSE) {
506         $success = 0;
507     }
508     if ($outcome !== FALSE) {
509         $checksum = sql_checksum_of_modified_row($statement);
510     }
511     /* Determine the query type (select, update, insert, delete) */
512     $querytype = "select";
513     $querytypes = array("select", "update", "insert", "delete","replace");
514     foreach ($querytypes as $qtype) {
515         if (stripos($statement, $qtype) === 0) {
516             $querytype = $qtype;
517         }
518     }
520     /* Determine the audit event based on the database tables */
521     $event = "other";
522     $tables = array("billing" => "patient-record",
523                     "claims" => "patient-record",
524                     "employer_data" => "patient-record",
525                     "forms" => "patient-record",
526                     "form_encounter" => "patient-record",
527                     "form_dictation" => "patient-record",
528                     "form_misc_billing_options" => "patient-record",
529                     "form_reviewofs" => "patient-record",
530                     "form_ros" => "patient-record",
531                     "form_soap" => "patient-record",
532                     "form_vitals" => "patient-record",
533                     "history_data" => "patient-record",
534                     "immunizations" => "patient-record",
535                     "insurance_data" => "patient-record",
536                     "issue_encounter" => "patient-record",
537                     "lists" => "patient-record",
538                     "patient_data" => "patient-record",
539                     "payments" => "patient-record",
540                     "pnotes" => "patient-record",
541                     "onotes" => "patient-record",
542                     "prescriptions" => "order",
543                     "transactions" => "patient-record",
544                     "facility" => "security-administration",
545                     "pharmacies" => "security-administration",
546                     "addresses" => "security-administration",
547                     "phone_numbers" => "security-administration",
548                     "x12_partners" => "security-administration",
549                     "insurance_companies" => "security-administration",
550                     "codes" => "security-administration",
551                     "registry" => "security-administration", 
552                     "users" => "security-administration",
553                     "groups" => "security-administration",
554                     "openemr_postcalendar_events" => "scheduling",
555                                 "openemr_postcalendar_categories" => "security-administration",
556                                 "openemr_postcalendar_limits" => "security-administration",
557                                 "openemr_postcalendar_topics" => "security-administration",
558                                 "gacl_acl" => "security-administration",
559                                 "gacl_acl_sections" => "security-administration",
560                                 "gacl_acl_seq" => "security-administration",
561                                 "gacl_aco" => "security-administration",
562                                 "gacl_aco_map" => "security-administration",
563                                 "gacl_aco_sections" => "security-administration",
564                                 "gacl_aco_sections_seq" => "security-administration",
565                                 "gacl_aco_seq" => "security-administration",
566                                 "gacl_aro" => "security-administration",
567                                 "gacl_aro_groups" => "security-administration",                                 
568                                 "gacl_aro_groups_id_seq" => "security-administration",
569                                 "gacl_aro_groups_map" => "security-administration",
570                                 "gacl_aro_map" => "security-administration",
571                                 "gacl_aro_sections" => "security-administration",
572                                 "gacl_aro_sections_seq" => "security-administration",
573                                 "gacl_aro_seq" => "security-administration",
574                                 "gacl_axo" => "security-administration",
575                                 "gacl_axo_groups" => "security-administration",
576                                 "gacl_axo_groups_map" => "security-administration",
577                                 "gacl_axo_map" => "security-administration",
578                                 "gacl_axo_sections" => "security-administration",
579                                 "gacl_groups_aro_map" => "security-administration",
580                                 "gacl_groups_axo_map" => "security-administration",
581                                 "gacl_phpgacl" => "security-administration"                             
582                   );
584     /* When searching for table names, truncate the SQL statement,
585      * removing any WHERE, SET, or VALUE clauses.
586      */
587         $truncated_sql = $statement;
588         $truncated_sql = str_replace("\n", " ", $truncated_sql);
589         if ($querytype == "select") {
590         $startwhere = stripos($truncated_sql, " where ");
591         if ($startwhere > 0) {
592         $truncated_sql = substr($truncated_sql, 0, $startwhere);
593     }
595         else {
596      $startparen = stripos($truncated_sql, "(" );
597      $startset = stripos($truncated_sql, " set ");
598      $startvalues = stripos($truncated_sql, " values ");
600         if ($startparen > 0) {
601             $truncated_sql = substr($truncated_sql, 0, $startparen);
602         }
603         if ($startvalues > 0) {
604             $truncated_sql = substr($truncated_sql, 0, $startvalues);
605         }
606         if ($startset > 0) {
607             $truncated_sql = substr($truncated_sql, 0, $startset);
608         }
609     }
610     foreach ($tables as $table => $value) {
611         if (strpos($truncated_sql, $table) !== FALSE) {
612             $event = $value;
613              break;
614         }
615       else if (strpos($truncated_sql, "form_") !== FALSE) {
616             $event = "patient-record";
617              break;
618         }
619     }
621     /* Avoid filling the audit log with trivial SELECT statements.
622      * Skip SELECTs from unknown tables.  
623      * Skip SELECT count() statements.
624      * Skip the SELECT made by the authCheckSession() function.
625      */
626     if ($querytype == "select") {
627         if ($event == "other")
628             return;
629         if (stripos($statement, "SELECT count(" ) === 0)
630             return;
631         if (stripos($statement, "select username, password from users") === 0)
632             return;
633     }
636     /* If the event is a patient-record, then note the patient id */
637     $pid = 0;
638     if ($event == "patient-record") {
639         if (array_key_exists('pid', $_SESSION) && $_SESSION['pid'] != '') {
640             $pid = $_SESSION['pid'];
641         }
642     }
644     /* If query events are not enabled, don't log them */
645     if (($querytype == "select") && !($GLOBALS['audit_events_query']))
646     { 
647        if ((soundex($user) != soundex("emergency")) && (soundex($user) != soundex("breakglass")))
648        return;
649     }
651     if (!($GLOBALS["audit_events_${event}"])) 
652     {
653         if ((soundex($user) != soundex("emergency")) && (soundex($user) != soundex("breakglass")))
654         return;
655     }
656            
658     $event = $event . "-" . $querytype;
660     $adodb = $GLOBALS['adodb']['db'];
661    
662     // ViSolve : Don't log sequences - to avoid the affect due to GenID calls
663     if (strpos($comments, "sequences") !== FALSE) return;
665     $sql = "insert into log (date, event, user, groupname, comments, patient_id, success, checksum,crt_user) " .
666          "values ( NOW(), " . 
667          $adodb->qstr($event) . ", " .
668          $adodb->qstr($user) . "," . 
669          $adodb->qstr($group) . "," .
670          $adodb->qstr($comments) . "," .
671          $adodb->qstr($pid) . "," .
672          $adodb->qstr($success) . "," . 
673          $adodb->qstr($checksum) . "," .
674          $adodb->qstr($_SERVER['SSL_CLIENT_S_DN_CN']) .")";
677     sqlInsertClean_audit($sql);
678     send_atna_audit_msg($user, $group, $event, $pid, $success, $comments);
679     //return $ret;
682  * Record the patient disclosures.
683  * @param $dates    - The date when the disclosures are sent to the thrid party.
684  * @param $event    - The type of the disclosure.
685  * @param $pid      - The id of the patient for whom the disclosures are recorded.
686  * @param $comment  - The recipient name and description of the disclosure.
687  * @uname           - The username who is recording the disclosure.
688  */
689 function recordDisclosure($dates,$event,$pid,$recipient,$description,$user)
691         $adodb = $GLOBALS['adodb']['db'];
692         $crt_user= $_SERVER['SSL_CLIENT_S_DN_CN'];
693         $groupname=$_SESSION['authProvider'];
694         $success=1;
695         $sql = "insert into extended_log ( date, event, user, recipient, patient_id, description) " .
696             "values (" . $adodb->qstr($dates) . "," . $adodb->qstr($event) . "," . $adodb->qstr($user) .
697             "," . $adodb->qstr($recipient) . ",".
698             $adodb->qstr($pid) ."," .
699             $adodb->qstr($description) .")";
700         $ret = sqlInsertClean_audit($sql);
703  * Edit the disclosures that is recorded.
704  * @param $dates  - The date when the disclosures are sent to the thrid party.
705  * @param $event  - The type of the disclosure.
706  * param $comment - The recipient and the description of the disclosure are appended.
707  * $logeventid    - The id of the record which is to be edited.
708  */
709 function updateRecordedDisclosure($dates,$event,$recipient,$description,$disclosure_id)
711          $adodb = $GLOBALS['adodb']['db'];
712          $sql="update extended_log set
713                 event=" . $adodb->qstr($event) . ",
714                 date=" .  $adodb->qstr($dates) . ",
715                 recipient=" . $adodb->qstr($recipient) . ",
716                 description=" . $adodb->qstr($description) . "
717                 where id=" . $adodb->qstr($disclosure_id) . "";
718           $ret = sqlInsertClean_audit($sql);
721  * Delete the disclosures that is recorded.
722  * $deleteid - The id of the record which is to be deleted.
723  */
724 function deleteDisclosure($deletelid)
726         $sql="delete from extended_log where id='$deletelid'";
727         $ret = sqlInsertClean_audit($sql);