<?php /* Question2Answer by Gideon Greenspan and contributors http://www.question2answer.org/ File: qa-plugin/event-logger/qa-event-logger.php Description: Event module class for event logger plugin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. More about this license: http://www.question2answer.org/license.php */ class qa_event_logger { public function init_queries($table_list) { if (qa_opt('event_logger_to_database')) { $tablename = qa_db_add_table_prefix('eventlog'); if (!in_array($tablename, $table_list)) { // table does not exist, so create it require_once QA_INCLUDE_DIR . 'app/users.php'; require_once QA_INCLUDE_DIR . 'db/maxima.php'; return 'CREATE TABLE ^eventlog (' . 'datetime DATETIME NOT NULL,' . 'ipaddress VARCHAR (45) CHARACTER SET ascii,' . 'userid ' . qa_get_mysql_user_column_type() . ',' . 'handle VARCHAR(' . QA_DB_MAX_HANDLE_LENGTH . '),' . 'cookieid BIGINT UNSIGNED,' . 'event VARCHAR (20) CHARACTER SET ascii NOT NULL,' . 'params VARCHAR (800) NOT NULL,' . 'KEY datetime (datetime),' . 'KEY ipaddress (ipaddress),' . 'KEY userid (userid),' . 'KEY event (event)' . ') ENGINE=MyISAM DEFAULT CHARSET=utf8'; } else { // table exists: check it has the correct schema $column = qa_db_read_one_assoc(qa_db_query_sub('SHOW COLUMNS FROM ^eventlog WHERE Field="ipaddress"')); if (strtolower($column['Type']) !== 'varchar(45)') { // upgrade to handle IPv6 return 'ALTER TABLE ^eventlog MODIFY ipaddress VARCHAR(45) CHARACTER SET ascii'; } } } return array(); } public function admin_form(&$qa_content) { // Process form input $saved = false; if (qa_clicked('event_logger_save_button')) { qa_opt('event_logger_to_database', (int)qa_post_text('event_logger_to_database_field')); qa_opt('event_logger_to_files', qa_post_text('event_logger_to_files_field')); qa_opt('event_logger_directory', qa_post_text('event_logger_directory_field')); qa_opt('event_logger_hide_header', !qa_post_text('event_logger_hide_header_field')); $saved = true; } // Check the validity of the currently entered directory (if any) $directory = qa_opt('event_logger_directory'); $note = null; $error = null; if (!strlen($directory)) $note = 'Please specify a directory that is writable by the web server.'; elseif (!file_exists($directory)) $error = 'This directory cannot be found. Please enter the full path.'; elseif (!is_dir($directory)) $error = 'This is a file. Please enter the full path of a directory.'; elseif (!is_writable($directory)) $error = 'This directory is not writable by the web server. Please choose a different directory, use chown/chmod to change permissions, or contact your web hosting company for assistance.'; // Create the form for display qa_set_display_rules($qa_content, array( 'event_logger_directory_display' => 'event_logger_to_files_field', 'event_logger_hide_header_display' => 'event_logger_to_files_field', )); return array( 'ok' => ($saved && !isset($error)) ? 'Event log settings saved' : null, 'fields' => array( array( 'label' => 'Log events to <code>' . QA_MYSQL_TABLE_PREFIX . 'eventlog</code> database table', 'tags' => 'name="event_logger_to_database_field"', 'value' => qa_opt('event_logger_to_database'), 'type' => 'checkbox', ), array( 'label' => 'Log events to daily log files', 'tags' => 'name="event_logger_to_files_field" id="event_logger_to_files_field"', 'value' => qa_opt('event_logger_to_files'), 'type' => 'checkbox', ), array( 'id' => 'event_logger_directory_display', 'label' => 'Directory for log files - enter full path:', 'value' => qa_html($directory), 'tags' => 'name="event_logger_directory_field"', 'note' => $note, 'error' => qa_html($error), ), array( 'id' => 'event_logger_hide_header_display', 'label' => 'Include header lines at top of each log file', 'type' => 'checkbox', 'tags' => 'name="event_logger_hide_header_field"', 'value' => !qa_opt('event_logger_hide_header'), ), ), 'buttons' => array( array( 'label' => 'Save Changes', 'tags' => 'name="event_logger_save_button"', ), ), ); } public function value_to_text($value) { if (is_array($value)) $text = 'array(' . count($value) . ')'; elseif (strlen($value) > 40) $text = substr($value, 0, 38) . '...'; else $text = $value; return strtr($text, "\t\n\r", ' '); } public function process_event($event, $userid, $handle, $cookieid, $params) { if (qa_opt('event_logger_to_database')) { $paramstring = ''; foreach ($params as $key => $value) { $paramstring .= (strlen($paramstring) ? "\t" : '') . $key . '=' . $this->value_to_text($value); } qa_db_query_sub( 'INSERT INTO ^eventlog (datetime, ipaddress, userid, handle, cookieid, event, params) ' . 'VALUES (NOW(), $, $, $, #, $, $)', qa_remote_ip_address(), $userid, $handle, $cookieid, $event, $paramstring ); } if (qa_opt('event_logger_to_files')) { // Substitute some placeholders if certain information is missing if (!strlen($userid)) $userid = 'no_userid'; if (!strlen($handle)) $handle = 'no_handle'; if (!strlen($cookieid)) $cookieid = 'no_cookieid'; $ip = qa_remote_ip_address(); if (!strlen($ip)) $ip = 'no_ipaddress'; // Build the log file line to be written $fixedfields = array( 'Date' => date('Y\-m\-d'), 'Time' => date('H\:i\:s'), 'IPaddress' => $ip, 'UserID' => $userid, 'Username' => $handle, 'CookieID' => $cookieid, 'Event' => $event, ); $fields = $fixedfields; foreach ($params as $key => $value) { $fields['param_' . $key] = $key . '=' . $this->value_to_text($value); } $string = implode("\t", $fields); // Build the full path and file name $directory = qa_opt('event_logger_directory'); if (substr($directory, -1) != '/') $directory .= '/'; $filename = $directory . 'q2a-log-' . date('Y\-m\-d') . '.txt'; // Open, lock, write, unlock, close (to prevent interference between multiple writes) $exists = file_exists($filename); $file = @fopen($filename, 'a'); if (is_resource($file)) { if (flock($file, LOCK_EX)) { if (!$exists && filesize($filename) === 0 && !qa_opt('event_logger_hide_header')) { $string = "Question2Answer " . QA_VERSION . " log file generated by Event Logger plugin.\n" . "This file is formatted as tab-delimited text with UTF-8 encoding.\n\n" . implode("\t", array_keys($fixedfields)) . "\textras...\n\n" . $string; } fwrite($file, $string . "\n"); flock($file, LOCK_UN); } fclose($file); } } } }