/** * perform log * * @param object $params * @param object form model * @param string message type * @returns bool */ protected function log($params, $formModel, $messageType) { $this->formModel = $formModel; $app = JFactory::getApplication(); $db = FabrikWorker::getDBO(); $query = $db->getQuery(true); $rowid = JRequest::getVar('rowid', ''); $loading = strstr($messageType, 'form.load'); $http_referrer = JRequest::getVar('HTTP_REFERER', 'no HTTP_REFERER', 'SERVER'); $user = JFactory::getUser(); $userid = $user->get('id'); $username = $user->get('username'); // Generate random filename if ($params->get('logs_random_filename') == 1) { function generate_filename($length) { $key = ""; $possible = "0123456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRTVWXYZ"; $i = 0; while ($i < $length) { $char = substr($possible, mt_rand(0, strlen($possible) - 1), 1); $key .= $char; $i++; } return $key; } $random_filename = '_' . generate_filename($params->get('logs_random_filename_length')); } else { $random_filename = ''; } $w = new FabrikWorker(); $logs_path = $w->parseMessageForPlaceHolder($params->get('logs_path')); if (strpos($logs_path, DS) !== 0) { $logs_path = JPATH_ROOT . DS . $logs_path; } $logs_path = rtrim($logs_path, DS); if (!JFolder::exists($logs_path)) { if (!JFolder::create($logs_path)) { return; } } $ext = $params->get('logs_file_format'); $sep = $params->get('logs_separator'); // Making complete path + filename + extension $w = new FabrikWorker(); $logs_file = $logs_path . DS . $w->parseMessageForPlaceHolder($params->get('logs_file')) . $random_filename . '.' . $ext; $logs_mode = $params->get('logs_append_or_overwrite'); $date_element = $params->get('logs_date_field'); $date_now = $params->get('logs_date_now'); // COMPARE DATA $result_compare = ''; if ($params->get('compare_data')) { if ($ext == 'csv') { $sep_compare = ''; $sep_2compare = '/ '; } else { if ($ext == 'txt') { $sep_compare = "\n"; $sep_2compare = "\n"; } else { if ($ext == 'htm') { $sep_compare = '<br/>'; $sep_2compare = '<br/>'; } } } if ($loading) { $result_compare = JText::_('COMPARE_DATA_LOADING') . $sep_2compare; } else { $data = $this->getEmailData(); $newData = $this->getNewData($formModel); if (!empty($data)) { $post = JRequest::get('post'); $elementModel = JModel::getInstance('element', 'FabrikModel'); $element = $elementModel->getElement(true); $tableModel = $formModel->getTable(); $origDataCount = count(array_keys(JArrayHelper::fromObject($formModel->_origData[0]))); if ($origDataCount > 0) { $c = 0; $origData = $formModel->_origData; $log_elements = explode(',', str_replace(' ', '', $params->get('logs_element_list', ''))); $groups = $formModel->getGroupsHiarachy(); foreach ($groups as $groupModel) { $group = $groupModel->getGroup(); $elementModels = $groupModel->getPublishedElements(); foreach ($elementModels as $elementModel) { $element = $elementModel->getElement(); $fullName = $elementModel->getFullName(false, true, false); if (empty($log_elements) || in_array($fullName, $log_elements)) { if ($newData[$c]->{$fullName} != $origData[$c]->{$fullName}) { $result_compare .= JText::_('COMPARE_DATA_CHANGE_ON') . ' ' . $element->label . ' ' . $sep_compare . JText::_('COMPARE_DATA_FROM') . ' ' . $origData[0]->{$fullName} . ' ' . $sep_compare . JText::_('COMPARE_DATA_TO') . ' ' . $newData[$c]->{$fullName} . ' ' . $sep_2compare; } } } } if (empty($result_compare)) { $result_compare = JText::_('COMPARE_DATA_NO_DIFFERENCES'); } } else { $result_compare .= "New record:" . $sep_2compare; foreach ($data as $key => $val) { if (isset($val) && substr($key, -4, 4) != '_raw') { $result_compare .= "{$key} : {$val}" . $sep_2compare; } } } } else { $result_compare = "No data to compare!"; } } } // Defining the date to use - Not used anymore as logs should really only record the current time_date if ($date_now != '') { $date = date("{$date_now}"); } else { $date = date("Y-m-d H:i:s"); } // Custom Message if ($params->get('custom_msg') != '') { $rep_add_edit = $messageType == 'form.add' ? JText::_('REP_ADD') : ($messageType == 'form.edit' ? JText::_('REP_EDIT') : JText::_('DETAILS')); $custom_msg = $params->get('custom_msg'); $custom_msg = preg_replace('/{Add\\/Edit}/', $rep_add_edit, $custom_msg); $custom_msg = preg_replace('/{DATE}/', $date, $custom_msg); $excl_clabels = preg_replace('/([-{2}| |"][0-9a-zA-Z.:$_>]*)/', '', $custom_msg); $split_clabels = preg_split('/[+]{1,}/', $excl_clabels); $clabels = preg_replace('/[={2}]+[a-zA-Z0-9_-]*/', '', $split_clabels); $ctypes = preg_replace('/[a-zA-Z0-9_-]*[={2}]/', '', $split_clabels); $labtyp = array_combine($clabels, $ctypes); $w = new FabrikWorker(); $custom_msg = $w->parseMessageForPlaceHolder($custom_msg); $excl_cdata = preg_replace('/((?!("[^"]*))([ |\\w|+|.])+(?=[^"]*"\\b)|(?!\\b"[^"]*)( +)+(?=([^"]*)$)|(?=\\b"[^"]*)( +)+(?=[^"]*"\\b))/', '', $custom_msg); $cdata = preg_split('/["]{1,}/', $excl_cdata); // Labels for CSV & for DB $clabels_csv_imp = implode("\",\"", $clabels); $clabels_csv_p1 = preg_replace('/^(",)/', '', $clabels_csv_imp); $clabels_csv = ''; $clabels_csv .= preg_replace('/(,")$/', '', $clabels_csv_p1); if ($params->get('compare_data') == 1) { $clabels_csv .= ', "' . JText::_('PLG_FORM_LOG_COMPARE_DATA_LABEL_CSV') . '"'; } $clabels_createdb_imp = ''; foreach ($labtyp as $klb => $vlb) { $klb = $db->quoteName($klb); if ($vlb == 'varchar') { $clabels_createdb_imp .= $klb . ' ' . $vlb . '(255) NOT NULL, '; } else { if ($vlb == 'int') { $clabels_createdb_imp .= $klb . ' ' . $vlb . '(11) NOT NULL, '; } else { if ($vlb == 'datetime') { $clabels_createdb_imp .= $klb . ' ' . $vlb . ' NOT NULL, '; } } } } $clabels_createdb = substr_replace($clabels_createdb_imp, '', -2); if ($params->get('compare_data') == 1) { $clabels_createdb .= ', ' . $db->quoteName(JText::_('COMPARE_DATA_LABEL_DB')) . ' text NOT NULL'; } // @todo - what if we use differnt db driver which doesnt name quote with `?? $clabels_db_imp = implode("`,`", $clabels); $clabels_db_p1 = preg_replace('/^(`,)/', '', $clabels_db_imp); $clabels_db = preg_replace('/(,`)$/', '', $clabels_db_p1); if ($params->get('compare_data') == 1) { $clabels_db .= ', ' . $db->quoteName(JText::_('PLG_FORM_LOG_COMPARE_DATA_LABEL_DB')); } // data for CSV & for DB $cdata_csv_imp = implode("\",\"", $cdata); $cdata_csv_p1 = preg_replace('/^(",)/', '', $cdata_csv_imp); $cdata_csv = preg_replace('/(,")$/', '', $cdata_csv_p1); $cdata_csv = preg_replace('/={1,}",/', '', $cdata_csv); $cdata_csv = preg_replace('/""/', '"', $cdata_csv); if ($params->get('compare_data') == 1) { $cdata_csv .= ', "' . $result_compare . '"'; } $cdata_db_imp = implode("','", $cdata); $cdata_db_p1 = preg_replace("/^(',)/", '', $cdata_db_imp); $cdata_db = preg_replace("/(,')\$/", '', $cdata_db_p1); $cdata_db = preg_replace("/={1,}',/", '', $cdata_db); $cdata_db = preg_replace("/''/", "'", $cdata_db); if ($params->get('compare_data') == 1 && !$loading) { $result_compare = preg_replace('/<br\\/>/', '- ', $result_compare); $result_compare = preg_replace('/\\n/', '- ', $result_compare); $cdata_db .= ", '" . $result_compare . "'"; } $custom_msg = preg_replace('/([++][0-9a-zA-Z.:_]*)/', '', $custom_msg); $custom_msg = preg_replace('/^[ ]/', '', $custom_msg); $custom_msg = preg_replace('/ /', ' ', $custom_msg); $custom_msg = preg_replace('/"/', '', $custom_msg); if ($params->get('compare_data') == 1 && !$loading) { $custom_msg .= '<br />' . $result_compare; } } else { $clabelsCreateDb = array(); $clabelsDb = array(); $cdataDb = array(); $clabelsCreateDb[] = $db->quoteName('date') . " datetime NOT NULL"; $clabelsDb[] = $db->quoteName('date'); $cdataDb[] = "NOW()"; $clabelsCreateDb[] = $db->quoteName('ip') . " varchar(32) NOT NULL"; $clabelsDb[] = $db->quoteName('ip'); $cdataDb[] = $params->get('logs_record_ip') == '1' ? $db->Quote($_SERVER['REMOTE_ADDR']) : $db->Quote(''); $clabelsCreateDb[] = $db->quoteName('referer') . " varchar(255) NOT NULL"; $clabelsDb[] = $db->quoteName('referer'); $cdataDb[] = $params->get('logs_record_referer') == '1' ? $db->Quote($http_referrer) : $db->Quote(''); $clabelsCreateDb[] = $db->quoteName('user_agent') . " varchar(255) NOT NULL"; $clabelsDb[] = $db->quoteName('user_agent'); $cdataDb[] = $params->get('logs_record_useragent') == '1' ? $db->Quote($_SERVER['HTTP_USER_AGENT']) : $db->Quote(''); $clabelsCreateDb[] = $db->quoteName('data_comparison') . " TEXT NOT NULL"; $clabelsDb[] = $db->quoteName('data_comparison'); $cdataDb[] = $params->get('compare_data') == '1' ? $db->Quote($result_compare) : $db->Quote(''); $clabelsCreateDb[] = $db->quoteName('rowid') . " INT(11) NOT NULL"; $clabelsDb[] = $db->quoteName('rowid'); $cdataDb[] = $db->Quote((int) $rowid); $clabelsCreateDb[] = $db->quoteName('userid') . " INT(11) NOT NULL"; $clabelsDb[] = $db->quoteName('userid'); $cdataDb[] = $db->Quote((int) $userid); $clabelsCreateDb[] = $db->quoteName('tableid') . " INT(11) NOT NULL"; $clabelsDb[] = $db->quoteName('tableid'); $cdataDb[] = $db->Quote($formModel->getTableModel()->getId()); $clabelsCreateDb[] = $db->quoteName('formid') . " INT(11) NOT NULL"; $clabelsDb[] = $db->quoteName('formid'); $cdataDb[] = $db->Quote($formModel->getId()); $clabels_createdb = implode(", ", $clabelsCreateDb); $clabels_db = implode(", ", $clabelsDb); $cdata_db = implode(", ", $cdataDb); } /* For CSV files * If 'Append' method is used, you don't want to repeat the labels (Date, IP, ...) * each time you add a line in the file */ $labels = !JFile::exists($logs_file) || $logs_mode == 'w' ? 1 : 0; $buffer = $logs_mode == 'a' && JFile::exists($logs_file) ? JFile::read($logs_file) : ''; $send_email = $params->get('log_send_email') == '1'; $make_file = $params->get('make_file') == '1'; if ($send_email && !$make_file) { $ext = 'txt'; } $email_msg = ''; //@TODO redo all this with JFile API and only writing a string once - needless overhead doing fwrite all the time if ($make_file || $send_email) { // Opening or creating the file if ($params->get('custom_msg') != '') { if ($send_email) { $email_msg = $custom_msg; } if ($make_file) { $custMsg = $buffer; if ($ext != 'csv') { JFile::write($logs_file, $buffer . $custom_msg . "\n" . $sep . "\n"); } else { // Making the CSV file // If the file already exists, do not add the 'label line' if ($labels == 1) { $custMsg .= $clabels_csv; } // Inserting data in CSV with actual line break as row separator $custMsg .= "\n" . $cdata_csv; JFile::write($logs_file, $custMsg); } } } else { // Making HTM File if ($ext == 'htm') { $htmlMsg = "<b>Date:</b> " . $date . "<br/>"; if ($params->get('logs_record_ip') == 1) { $htmlMsg .= "<b>IP Address:</b> " . $_SERVER['REMOTE_ADDR'] . "<br/>"; } if ($params->get('logs_record_referer') == 1) { $htmlMsg .= "<b>Referer:</b> " . $http_referrer . "<br/>"; } if ($params->get('logs_record_useragent') == 1) { $htmlMsg .= "<b>UserAgent: </b>" . $_SERVER['HTTP_USER_AGENT'] . "<br/>"; } $htmlMsg .= $result_compare . $sep . "<br/>"; if ($send_email) { $email_msg = $htmlMsg; } if ($make_file) { $htmlMsg = $buffer . $htmlMsg; $res = JFile::write($logs_file, $htmlMsg); if (!$res) { JError::raiseNotice(E_NOTICE, "error writing html to log file: " . $logs_file); } } } else { if ($ext == 'txt') { $txtMsg = "Date: " . $date . "\n"; $txtMsg .= "Form ID: " . $formModel->getId() . "\n"; $txtMsg .= "Table ID: " . $formModel->getListModel()->getId() . "\n"; $txtMsg .= "Row ID: " . (int) $rowid . "\n"; $txtMsg .= "User ID: {$userid} ({$username})\n"; if ($params->get('logs_record_ip') == 1) { $txtMsg .= "IP Address: " . $_SERVER['REMOTE_ADDR'] . "\n"; } if ($params->get('logs_record_referer') == 1) { $txtMsg .= "Referer: " . $http_referrer . "\n"; } if ($params->get('logs_record_useragent') == 1) { $txtMsg .= "UserAgent: " . $_SERVER['HTTP_USER_AGENT'] . "\n"; } $txtMsg .= $result_compare . $sep . "\n"; if ($send_email) { $email_msg = $txtMsg; } if ($make_file) { $txtMsg = $buffer . $txtMsg; JFile::write($logs_file, $txtMsg); } } else { // Making the CSV file if ($ext == 'csv') { $csvMsg = array(); // If the file already exists, do not add the 'label line' if ($labels == 1) { $csvMsg[] = "Date"; if ($params->get('logs_record_ip') == 1) { // Putting some "" around the label to avoid two different fields $csvMsg[] = "\"IP Address\""; } if ($params->get('logs_record_referer') == 1) { $csvMsg[] = "Referer"; } if ($params->get('logs_record_useragent') == 1) { $csvMsg[] = "UserAgent"; } if ($params->get('compare_data') == 1) { $csvMsg[] = "\"" . JText::_('COMPARE_DATA_LABEL_CSV') . "\""; } } // Inserting data in CSV with actual line break as row separator $csvMsg[] = "\n\"" . $date . "\""; if ($params->get('logs_record_ip') == 1) { $csvMsg[] = "\"" . $_SERVER['REMOTE_ADDR'] . "\""; } if ($params->get('logs_record_referer') == 1) { $csvMsg[] = "\"" . $http_referrer . "\""; } if ($params->get('logs_record_useragent') == 1) { $csvMsg[] = "\"" . $_SERVER['HTTP_USER_AGENT'] . "\""; } if ($params->get('compare_data') == 1) { $csvMsg[] = "\"" . $result_compare . "\""; } $csvMsg = implode(",", $csvMsg); if ($send_email) { $email_msg = $csvMsg; } if ($make_file) { if ($buffer !== '') { $csvMsg = $buffer . $csvMsg; } JFile::write($logs_file, $csvMsg); } } } } } } if ($params->get('logs_record_in_db') == 1) { // In which table? if ($params->get('record_in') == '') { $rdb = '#__fabrik_log'; } else { $db_suff = $params->get('record_in'); $form = $formModel->getForm(); $fid = $form->id; $db->setQuery("SELECT " . $db->quoteName('db_table_name') . " FROM " . $db->quoteName('#__fabrik_lists') . " WHERE " . $db->quoteName('form_id') . " = " . (int) $fid); $tname = $db->loadResult(); $rdb = $db->quoteName($tname . $db_suff); } // Making the message to record if ($params->get('custom_msg') != '') { $message = preg_replace('/<br\\/>/', ' ', $custom_msg); } else { $message = $this->makeStandardMessage($params, $result_compare); } // $$$ hugh - FIXME - not sure about the option driven $create_custom_table stuff, as this won't work // if they add an option to an existing log table. We should probably just create all the optional columns // regardless. if ($params->get('record_in') == '') { $in_db = "INSERT INTO {$rdb} (" . $db->quoteName('referring_url') . ", " . $db->quoteName('message_type') . ", " . $db->quoteName('message') . ") VALUES (" . $db->Quote($http_referrer) . ", " . $db->Quote($messageType) . ", " . $db->Quote($message) . ");"; $db->setQuery($in_db); $db->query(); } else { $create_custom_table = "CREATE TABLE IF NOT EXISTS {$rdb} (" . $db->quoteName('id') . " int(11) NOT NULL auto_increment PRIMARY KEY, {$clabels_createdb});"; $db->setQuery($create_custom_table); $db->query(); $in_db = "INSERT INTO {$rdb} ({$clabels_db}) VALUES ({$cdata_db});"; $db->setQuery($in_db); if (!$db->query()) { // $$$ changed to always use db fields even if not selected // so logs already created may need optional fields added. // try adding every field we should have, don't care if query fails. foreach ($clabelsCreateDb as $insert) { $db->setQuery("ALTER TABLE ADD {$insert} AFTER `id`"); $db->query(); } // ... and try the insert query again $db->setQuery($in_db); $db->query(); } } } if ($send_email) { jimport('joomla.mail.helper'); $config =& JFactory::getConfig(); $email_from = $config->getValue('mailfrom'); $email_to = explode(',', $w->parseMessageForPlaceholder($params->get('log_send_email_to', ''))); $subject = strip_tags($w->parseMessageForPlaceholder($params->get('log_send_email_subject', 'log event'))); foreach ($email_to as $email) { $email = trim($email); if (empty($email)) { continue; } if (JMailHelper::isEmailAddress($email)) { $res = JUtility::sendMail($email_from, $email_from, $email, $subject, $email_msg, true); } else { JError::raiseNotice(500, JText::sprintf('DID_NOT_SEND_EMAIL_INVALID_ADDRESS', $email)); } } } return true; }