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