. * * A copy of the GPL can be found in the file "COPYING" in this * distribution. ********************************************************************* */ // --- Avoid directly accessing this file! if ( !defined('IN_PHPLOGCON') ) { die('Hacking attempt'); exit; } // --- // --- Required Includes! require_once($gl_root_path . 'include/constants_errors.php'); // --- class LogStreamMongoDB extends LogStream { private $_dbhandle = null; // Helper to store the database records private $bufferedRecords = null; private $_currentRecordStart = 0; private $_currentRecordNum = 0; private $_totalRecordCount = -1; private $_previousPageUID = -1; private $_lastPageUID = -1; private $_firstPageUID = -1; private $_currentPageNumber = 0; private $_SQLwhereClause = ""; private $_myDBQuery = null; private $_myMongoCon = null; private $_myMongoDB = null; private $_myMongoCollection = null; private $_myMongoFields = null; private $_myMongoQuery = null; // Constructor public function LogStreamMongoDB($streamConfigObj) { $this->_logStreamConfigObj = $streamConfigObj; // Probe if a function exists! if ( !function_exists("bson_encode") ) DieWithFriendlyErrorMsg("Error, MongoDB PHP Driver Extensions is not installed! Please see http://www.php.net/manual/en/mongo.installation.php for installation details."); } /** * Open and verifies the database conncetion * * @param arrProperties array in: Properties wish list. * @return integer Error stat */ public function Open($arrProperties) { global $dbmapping; // Initialise Basic stuff within the Classs $this->RunBasicInits(); // Verify database connection (This also opens the database!) $res = $this->Verify(); if ( $res != SUCCESS ) return $res; // Copy the Property Array $this->_arrProperties = $arrProperties; // Check if DB Mapping exists if ( !isset($dbmapping[ $this->_logStreamConfigObj->DBTableType ]) ) return ERROR_DB_INVALIDDBMAPPING; // Create Needed Fields Array first! $res = $this->CreateFieldsArray(); if ( $res != SUCCESS ) return $res; // Create Filters for first time! $res = $this->CreateQueryArray(UID_UNKNOWN); if ( $res != SUCCESS ) return $res; // Success, this means we init the Pagenumber to ONE! $this->_currentPageNumber = 1; // reached this point means success! return SUCCESS; } /* * Helper function to clear the current querystring! */ public function ResetFilters() { // Clear _SQLwhereClause variable! $this->_SQLwhereClause = ""; } /** * Close the database connection. * * @return integer Error state */ public function Close() { $bReturn = SUCCESS; if ($this->_myMongoCon) { if (!$this->_myMongoCon->close()) $bReturn = false; // return fail } // Reset variables $this->_myMongoCon = null; $this->_myMongoDB = null; $this->_myMongoCollection = null; return $bReturn; } /** * Verify if the database connection exists! * * @return integer Error state */ public function Verify() { // Try to connect to the database if ( $this->_myMongoCon == null ) { try { // TODO: USername and Password support! // Forces to open a new Connection $this->_myMongoCon = new Mongo("mongodb://" . $this->_logStreamConfigObj->DBServer . ":" . $this->_logStreamConfigObj->DBPort ); // Connect to Mongo Server } catch ( MongoConnectionException $e ) { global $extraErrorDescription; $extraErrorDescription = $e->getMessage; // Return error code return ERROR_DB_CONNECTFAILED; } } try { $this->_myMongoDB = $this->_myMongoCon->selectDB( $this->_logStreamConfigObj->DBName ); // Connect to Database } catch ( MongoException $e ) { global $extraErrorDescription; $extraErrorDescription = $e->getMessage; // Return error code return ERROR_DB_CANNOTSELECTDB; } // Check if the table exists! try { $this->_myMongoCollection = $this->_myMongoDB->selectCollection ( $this->_logStreamConfigObj->DBCollection ); } catch ( MongoException $e ) { global $extraErrorDescription; $extraErrorDescription = $e->getMessage; // Return error code return ERROR_DB_TABLENOTFOUND; } // reached this point means success ;)! return SUCCESS; } /* * Implementation of VerifyFields: Checks if fields exist in table */ public function VerifyFields( $arrProperitesIn ) { /* TODO!!! global $dbmapping, $fields; // Get List of Indexes as Array $arrFieldKeys = $this->GetFieldsAsArray(); $szTableType = $this->_logStreamConfigObj->DBTableType; // Loop through all fields to see which one is missing! foreach ( $arrProperitesIn as $myproperty ) { // echo $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "
"; if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrFieldKeys) ) { OutputDebugMessage("LogStreamDB|VerifyFields: Found Field for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_ULTRADEBUG); continue; } else { // Index is missing for this field! OutputDebugMessage("LogStreamDB|VerifyFields: Missing Field for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_WARN); return ERROR_DB_DBFIELDNOTFOUND; } } */ // Successfull return SUCCESS; } /* * Implementation of VerifyIndexes: Checks if indexes exist for desired fields */ public function VerifyIndexes( $arrProperitesIn ) { /* TODO!!! global $dbmapping, $fields; // Get List of Indexes as Array $arrIndexKeys = $this->GetIndexesAsArray(); $szTableType = $this->_logStreamConfigObj->DBTableType; // Loop through all fields to see which one is missing! foreach ( $arrProperitesIn as $myproperty ) { // echo $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "
"; if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrIndexKeys) ) { OutputDebugMessage("LogStreamDB|VerifyIndexes: Found INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_ULTRADEBUG); continue; } else { // Index is missing for this field! OutputDebugMessage("LogStreamDB|VerifyIndexes: Missing INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_WARN); return ERROR_DB_INDEXESMISSING; } } */ // Successfull return SUCCESS; } /* * Implementation of VerifyChecksumTrigger: Checks if checksum trigger exists */ public function VerifyChecksumTrigger( $myTriggerProperty ) { /* TODO global $dbmapping, $fields; // Get List of Triggers as Array $arrIndexTriggers = $this->GetTriggersAsArray(); $szTableType = $this->_logStreamConfigObj->DBTableType; $szDBName = $this->_logStreamConfigObj->DBName; $szTableName = $this->_logStreamConfigObj->DBTableName; $szDBTriggerField = $dbmapping[$szTableType]['DBMAPPINGS'][$myTriggerProperty]; // Create Triggername | lowercase! $szTriggerName = strtolower( $szDBName . "_" . $szTableName . "_" . $szDBTriggerField ); // Try to find logstream trigger if ( count($arrIndexTriggers) > 0 ) { if ( in_array($szTriggerName, $arrIndexTriggers) ) return SUCCESS; else { // Index is missing for this field! OutputDebugMessage("LogStreamDB|VerifyChecksumTrigger: Missing TRIGGER '" . $szTriggerName . "' for Table '" . $szTableName . "'", DEBUG_WARN); return ERROR_DB_TRIGGERMISSING; } } else { // Index is missing for this field! OutputDebugMessage("LogStreamDB|VerifyChecksumTrigger: No TRIGGERS found in your database", DEBUG_WARN); return ERROR_DB_TRIGGERMISSING; } */ // Successfull return SUCCESS; } /* * Implementation of CreateMissingIndexes: Checks if indexes exist for desired fields */ public function CreateMissingIndexes( $arrProperitesIn ) { /* TODO global $dbmapping, $fields, $querycount; // Get List of Indexes as Array $arrIndexKeys = $this->GetIndexesAsArray(); $szTableType = $this->_logStreamConfigObj->DBTableType; // Loop through all fields to see which one is missing! foreach ( $arrProperitesIn as $myproperty ) { if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrIndexKeys) ) continue; else { // Update Table schema now! $szSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD INDEX ( " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " )"; // Index is missing for this field! OutputDebugMessage("LogStreamDB|CreateMissingIndexes: Createing missing INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' - " . $szSql, DEBUG_INFO); // Add missing INDEX now! $myQuery = mysql_query($szSql, $this->_dbhandle); if (!$myQuery) { // Return failure! $this->PrintDebugError("Dynamically Adding INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' failed with Statement: '" . $szSql . "'"); return ERROR_DB_INDEXFAILED; } } } */ // Successfull return SUCCESS; } /* * Implementation of CreateMissingFields: Checks if indexes exist for desired fields */ public function CreateMissingFields( $arrProperitesIn ) { /* TODO global $dbmapping, $fields, $querycount; // Get List of Indexes as Array $arrFieldKeys = $this->GetFieldsAsArray(); $szTableType = $this->_logStreamConfigObj->DBTableType; // Loop through all fields to see which one is missing! foreach ( $arrProperitesIn as $myproperty ) { if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrFieldKeys) ) continue; else { if ( $this->HandleMissingField( $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrProperitesIn ) == SUCCESS ) { // Index is missing for this field! OutputDebugMessage("LogStreamDB|CreateMissingFields: Createing missing FIELD for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], DEBUG_INFO); } else { // Return failure! $this->PrintDebugError("Dynamically Adding FIELD for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' failed!"); return ERROR_DB_ADDDBFIELDFAILED; } } } */ // Successfull return SUCCESS; } /* * Implementation of GetCreateMissingTriggerSQL: Creates SQL needed to create a TRIGGER */ public function GetCreateMissingTriggerSQL( $myDBTriggerField, $myDBTriggerCheckSumField ) { /* global $dbmapping, $fields, $querycount; // Get List of Triggers as Array $szDBName = $this->_logStreamConfigObj->DBName; $szTableName = $this->_logStreamConfigObj->DBTableName; // Create Triggername $szTriggerName = $szDBName . "_" . $szTableName . "_" . $myDBTriggerField; // Create TRIGGER SQL! $szSql = "CREATE TRIGGER " . $szTriggerName . " BEFORE INSERT ON `" . $szTableName . "` FOR EACH ROW BEGIN SET NEW." . $myDBTriggerCheckSumField . " = crc32(NEW." . $myDBTriggerField . "); END ;"; return $szSql; */ return ""; } /* * Implementation of CreateMissingTrigger: Creates missing triggers ! */ public function CreateMissingTrigger( $myTriggerProperty, $myCheckSumProperty ) { /* TODO global $dbmapping, $fields, $querycount; // Get List of Triggers as Array $szTableName = $this->_logStreamConfigObj->DBTableName; $szTableType = $this->_logStreamConfigObj->DBTableType; $szDBTriggerField = $dbmapping[$szTableType]['DBMAPPINGS'][$myTriggerProperty]; $szDBTriggerCheckSumField = $dbmapping[$szTableType]['DBMAPPINGS'][$myCheckSumProperty]; // Get SQL Code to create the trigger! $szSql = $this->GetCreateMissingTriggerSQL( $szDBTriggerField, $szDBTriggerCheckSumField ); // Index is missing for this field! OutputDebugMessage("LogStreamDB|CreateMissingTrigger: Creating missing TRIGGER for '" . $szTableName . "' - $szDBTriggerCheckSumField = crc32(NEW.$szDBTriggerField)" . $szSql, DEBUG_INFO); // Add missing INDEX now! $myQuery = mysql_query($szSql, $this->_dbhandle); if (!$myQuery) { // Return failure! $this->PrintDebugError("Dynamically Adding TRIGGER for '" . $szTableName . "' failed!

If you want to manually add the TRIGGER, use the following SQL Command:
" . str_replace("\n", "
", $szSql) . "
"); return ERROR_DB_TRIGGERFAILED; } */ // Successfull return SUCCESS; } /* * Implementation of ChangeChecksumFieldUnsigned: Changes the Checkusm field to unsigned! */ public function ChangeChecksumFieldUnsigned() { /* TODO!!! global $dbmapping, $fields, $querycount; // Get variables $szTableType = $this->_logStreamConfigObj->DBTableType; // Change Checksumfield to use UNSIGNED! $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` CHANGE `" . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "` `" . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "` INT(11) UNSIGNED NOT NULL DEFAULT '0'"; // Update Table schema now! $myQuery = mysql_query($szUpdateSql, $this->_dbhandle); if (!$myQuery) { // Return failure! $this->PrintDebugError("ER_BAD_FIELD_ERROR - Failed to Change field '" . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "' from signed to unsigned with sql statement: '" . $szUpdateSql . "'"); return ERROR_DB_CHECKSUMCHANGEFAILED; } */ // return results return SUCCESS; } /* * Implementation of VerifyChecksumField: Verifies if the checkusm field is signed or unsigned! */ public function VerifyChecksumField() { /* TODO global $dbmapping, $fields, $querycount; // Get variables $szTableType = $this->_logStreamConfigObj->DBTableType; // Create SQL and Get INDEXES for table! $szSql = "SHOW COLUMNS FROM " . $this->_logStreamConfigObj->DBTableName . " WHERE Field = '" . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "'"; $myQuery = mysql_query($szSql, $this->_dbhandle); if ($myQuery) { // Get result! $myRow = mysql_fetch_array($myQuery, MYSQL_ASSOC); if (strpos( strtolower($myRow['Type']), "unsigned") === false ) { // return error code! return ERROR_DB_CHECKSUMERROR; } // Free query now mysql_free_result ($myQuery); // Increment for the Footer Stats $querycount++; } */ // return results return SUCCESS; } /** * Read the data from a specific uID which means in this * case beginning with from the Database ID * * @param uID integer in/out: unique id of the data row * @param arrProperitesOut array out: array filled with properties * @return integer Error state * @see ReadNext() */ public function Read($uID, &$arrProperitesOut) { // Seek the first uID! if ( $this->Sseek($uID, EnumSeek::UID, 0) == SUCCESS) { // Read the next record! $ret = $this->ReadNext($uID, $arrProperitesOut); } else $ret = ERROR_NOMORERECORDS; // return result! return $ret; } /** * Read the next line from the file depending on the current * read direction. * * Hint: If the current stream becomes unavailable an error * stated is retuned. A typical case is if a log rotation * changed the original data source. * * @param uID integer out: uID is the offset of data row * @param arrProperitesOut array out: properties * @return integer Error state * @see ReadNext */ public function ReadNext(&$uID, &$arrProperitesOut, $bParseMessage = true) { // Helpers needed for DB Mapping global $content, $gl_starttime; global $dbmapping, $fields; $szTableType = $this->_logStreamConfigObj->DBTableType; // define $ret $ret = SUCCESS; do { // No buffer? then read from DB! if ( $this->bufferedRecords == null ) $ret = $this->ReadNextRecordsFromDB($uID); else { if ( !isset($this->bufferedRecords[$this->_currentRecordNum] ) ) { // We need to load new records, so clear the old ones first! $this->ResetBufferedRecords(); // Set new Record start, will be used in the SQL Statement! $this->_currentRecordStart = $this->_currentRecordNum; // + 1; // Now read new ones $ret = $this->ReadNextRecordsFromDB($uID); // Check if we found more records if ( !isset($this->bufferedRecords[$this->_currentRecordNum] ) ) $ret = ERROR_NOMORERECORDS; } } if ( $ret == SUCCESS && $this->_arrProperties != null ) { // Init and set variables foreach ( $this->_arrProperties as $property ) { // Check if mapping exists if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$property]) ) { // Copy property if available! $dbfieldname = $dbmapping[$szTableType]['DBMAPPINGS'][$property]; if ( isset($this->bufferedRecords[$this->_currentRecordNum][$dbfieldname]) ) { if ( isset($fields[$property]['FieldType']) && $fields[$property]['FieldType'] == FILTER_TYPE_DATE ) // Handle as date! { $myDateField = $this->bufferedRecords[$this->_currentRecordNum][$dbfieldname]; if ( gettype($myDateField) == "object" && get_class($myDateField) == "MongoDate" ) { $arrProperitesOut[$property][EVTIME_TIMESTAMP] = $myDateField->sec; $arrProperitesOut[$property][EVTIME_TIMEZONE] = date('O'); // Get default Offset $arrProperitesOut[$property][EVTIME_MICROSECONDS] = $myDateField->usec; } else // Try to parse Date! $arrProperitesOut[$property] = GetEventTime( $myDateField ); } else $arrProperitesOut[$property] = $this->bufferedRecords[$this->_currentRecordNum][$dbfieldname]; } else $arrProperitesOut[$property] = ''; } else $arrProperitesOut[$property] = ''; } // Run optional Message Parsers now if ( isset($arrProperitesOut[SYSLOG_MESSAGE]) ) { $retParser = $this->_logStreamConfigObj->ProcessMsgParsers($arrProperitesOut[SYSLOG_MESSAGE], $arrProperitesOut); // Check if we have to skip the message! if ( $retParser == ERROR_MSG_SKIPMESSAGE ) $ret = $retParser; } // Set uID to the PropertiesOut! //DEBUG -> $this->_currentRecordNum; $uID = $arrProperitesOut[SYSLOG_UID] = $this->bufferedRecords[$this->_currentRecordNum][$dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID]]; // Increment $_currentRecordNum $this->_currentRecordNum++; } // Check how long we are running. If only two seconds of execution time are left, we abort further reading! $scriptruntime = intval(microtime_float() - $gl_starttime); if ( $content['MaxExecutionTime'] > 0 && $scriptruntime > ($content['MaxExecutionTime']-2) ) { // This may display a warning message, so the user knows we stopped reading records because of the script timeout. $content['logstream_warning'] = "false"; $content['logstream_warning_details'] = $content['LN_WARNING_LOGSTREAMDISK_TIMEOUT']; $content['logstream_warning_code'] = ERROR_FILE_NOMORETIME; // Return error code return ERROR_FILE_NOMORETIME; } // This additional filter check will take care on dynamic fields from the message parser! } while ( $this->ApplyFilters($ret, $arrProperitesOut) != SUCCESS && $ret == SUCCESS ); // reached here means return result! return $ret; } /** * Implementation of Seek */ public function Sseek(&$uID, $mode, $numrecs) { // predefine return value $ret = SUCCESS; switch ($mode) { case EnumSeek::UID: // if ( $uID == UID_UNKNOWN ) // set uID to first ID! { // No buffer? then read from DB! if ( $this->bufferedRecords == null ) $ret = $this->ReadNextRecordsFromDB($uID); if ( $ret == SUCCESS ) { $this->_currentRecordNum = 0; $uID = $this->bufferedRecords[ $this->_currentRecordNum ]; } } break; } // Return result! return $ret; } /** * GetMessageCount will return the count of Message. * If this count is not available, the function will * return the default -1 */ public function GetMessageCount() { return $this->_totalRecordCount; } /** * This function returns the first UID for previous PAGE, if availbale! * Otherwise will return -1! */ public function GetPreviousPageUID() { return $this->_previousPageUID; } /** * This function returns the FIRST UID for the FIRST PAGE! * Will be done by a seperated SQL Statement. */ public function GetFirstPageUID() { /* TODO global $querycount, $dbmapping; $szTableType = $this->_logStreamConfigObj->DBTableType; // Only perform query if row counting is enabled! if ( strlen($this->_SQLwhereClause) > 0 && !$this->_logStreamConfigObj->DBEnableRowCounting ) return $this->_firstPageUID; $szSql = "SELECT MAX(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] . ") FROM " . $this->_logStreamConfigObj->DBTableName . $this->_SQLwhereClause; $myQuery = mysql_query($szSql, $this->_dbhandle); if ($myQuery) { // obtain first and only row $myRow = mysql_fetch_row($myQuery); $this->_firstPageUID = $myRow[0]; // Free query now mysql_free_result ($myQuery); // Increment for the Footer Stats $querycount++; } // Return result! return $this->_firstPageUID; */ return -1; } /** * This function returns the first UID for the last PAGE! * Will be done by a seperated SQL Statement. */ public function GetLastPageUID() { /* TODO global $querycount, $dbmapping; $szTableType = $this->_logStreamConfigObj->DBTableType; // Only perform query if row counting is enabled! if ( strlen($this->_SQLwhereClause) > 0 && !$this->_logStreamConfigObj->DBEnableRowCounting ) return $this->_lastPageUID; $szSql = "SELECT MIN(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] . ") FROM " . $this->_logStreamConfigObj->DBTableName . $this->_SQLwhereClause; $myQuery = mysql_query($szSql, $this->_dbhandle); if ($myQuery) { // obtain first and only row $myRow = mysql_fetch_row($myQuery); $this->_lastPageUID = $myRow[0]; // Free query now mysql_free_result ($myQuery); // Increment for the Footer Stats $querycount++; } // Return result! return $this->_lastPageUID; */ return -1; } /** * This function returns the current Page number, if availbale! * Otherwise will return 0! We also assume that this function is * only called once DB is open! */ public function GetCurrentPageNumber() { return $this->_currentPageNumber; } /* * Implementation of IsPropertySortable * * For now, sorting is only possible for the UID Property! */ public function IsPropertySortable($myProperty) { global $fields; // TODO: HARDCODED | FOR NOW only FALSE! return false; } /** * Implementation of GetLogStreamStats * * Returns an Array og logstream statsdata * Count of Data Items * Total Filesize */ public function GetLogStreamStats() { /* global $querycount, $dbmapping; $szTableType = $this->_logStreamConfigObj->DBTableType; // Perform if Connection is true! if ( $this->_dbhandle != null ) { // Obtain Stats data for this table! $szSql = "SHOW TABLE STATUS FROM " . $this->_logStreamConfigObj->DBName; $myQuery = mysql_query($szSql, $this->_dbhandle); if ($myQuery) { // Loop through results while ($myRow = mysql_fetch_array($myQuery, MYSQL_ASSOC)) { // Set tablename! $tableName = $myRow['Name']; $myStats = null; $myStats[] = array( 'StatsDisplayName' => 'Table name', 'StatsValue' => $tableName ); // copy usefull statsdata if ( isset($myRow['Engine']) ) $myStats[] = array( 'StatsDisplayName' => 'Table engine', 'StatsValue' => $myRow['Engine'] ); if ( isset($myRow['Rows']) ) $myStats[] = array( 'StatsDisplayName' => 'Rowcount', 'StatsValue' => $myRow['Rows'] ); if ( isset($myRow['Data_length']) ) $myStats[] = array( 'StatsDisplayName' => 'Table filesize (bytes)', 'StatsValue' => $myRow['Data_length'] ); if ( isset($myRow['Collation']) ) $myStats[] = array( 'StatsDisplayName' => 'Collation', 'StatsValue' => $myRow['Collation'] ); if ( isset($myRow['Comment']) ) $myStats[] = array( 'StatsDisplayName' => 'Comment', 'StatsValue' => $myRow['Comment'] ); $stats[]['STATSDATA'] = $myStats; } // Free query now mysql_free_result ($myQuery); // Increment for the Footer Stats $querycount++; } // return results! return $stats; } else return null; */ // NOT IMPLEMENTED YET! return null; } /** * Implementation of GetLogStreamTotalRowCount * * Returns the total amount of rows in the main datatable */ public function GetLogStreamTotalRowCount() { global $querycount, $dbmapping; // Set default rowcount $rowcount = null; // Perform if Connection is true! if ( $this->_myMongoCollection != null ) { $rowcount = $this->_myMongoCollection->count(); } //return result return $rowcount; } /** * Implementation of the CleanupLogdataByDate function! Returns affected rows! */ public function CleanupLogdataByDate( $nDateTimeStamp ) { /* TODO global $querycount, $dbmapping; $szTableType = $this->_logStreamConfigObj->DBTableType; // Set default rowcount $rowcount = null; // Perform if Connection is true! if ( $this->_dbhandle != null ) { // --- Init Filters if necessary! if ( $this->_filters == null ) $this->SetFilter( "" ); // This will init filters! // Create SQL Where Clause! $this->CreateSQLWhereClause(); // --- // --- Add default WHERE clause if ( strlen($this->_SQLwhereClause) > 0 ) $szWhere = $this->_SQLwhereClause; else $szWhere = ""; // Add Datefilter if necessary! if ( $nDateTimeStamp > 0 ) { if ( strlen($szWhere) > 0 ) $szWhere .= " AND "; else $szWhere = " WHERE "; // Append Date Filter! $szWhere .= " UNIX_TIMESTAMP(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] . ") < " . $nDateTimeStamp; } // --- // DELETE DATA NOW! $szSql = "DELETE FROM " . $this->_logStreamConfigObj->DBTableName . $szWhere; OutputDebugMessage("LogStreamDB|CleanupLogdataByDate: Created SQL Query:
" . $szSql, DEBUG_DEBUG); $myQuery = mysql_query($szSql, $this->_dbhandle); if ($myQuery) { // Get affected rows and return! $rowcount = mysql_affected_rows(); // Reset AUTO_INCREMENT if all records were deleted! if ( $nDateTimeStamp == 0 ) { $szSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " AUTO_INCREMENT=0"; $myQuery = mysql_query($szSql, $this->_dbhandle); // error occured, output DEBUG message if (!$myQuery) $this->PrintDebugError("CleanupLogdataByDate failed to reset AUTO_INCREMENT for '" . $this->_logStreamConfigObj->DBTableName . "' table. "); } // Free result not needed here! //mysql_free_result ($myQuery); } else { // error occured, output DEBUG message $this->PrintDebugError("CleanupLogdataByDate failed with SQL Statement ' " . $szSql . " '"); } } //return affected rows return $rowcount; */ //not implemented return null; } /* * Implementation of the UpdateAllMessageChecksum * * Update all missing checksum properties in the current database */ public function UpdateAllMessageChecksum( ) { /* global $querycount, $dbmapping; $szTableType = $this->_logStreamConfigObj->DBTableType; // UPDATE DATA NOW! $szSql = "UPDATE " . $this->_logStreamConfigObj->DBTableName . " SET " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = crc32(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_MESSAGE] . ") " . " WHERE " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " IS NULL OR " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = 0"; // Output Debug Informations OutputDebugMessage("LogStreamDB|UpdateAllMessageChecksum: Running Created SQL Query:
" . $szSql, DEBUG_ULTRADEBUG); // Running SQL Query $myQuery = mysql_query($szSql, $this->_dbhandle); if ($myQuery) { // Debug Output OutputDebugMessage("LogStreamDB|UpdateAllMessageChecksum: Successfully updated Checksum of '" . mysql_affected_rows($this->_dbhandle) . "' datarecords", DEBUG_INFO); // Return success return SUCCESS; } else { // error occured, output DEBUG message $this->PrintDebugError("SaveMessageChecksum failed with SQL Statement ' " . $szSql . " '"); // Failed return ERROR; } */ return SUCCESS; } /* * Implementation of the SaveMessageChecksum * * Creates an database UPDATE Statement and performs it! */ public function SaveMessageChecksum( $arrProperitesIn ) { /* global $querycount, $dbmapping; $szTableType = $this->_logStreamConfigObj->DBTableType; if ( isset($arrProperitesIn[SYSLOG_UID]) && isset($arrProperitesIn[MISC_CHECKSUM]) && isset($dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM]) ) { // UPDATE DATA NOW! $szSql = "UPDATE " . $this->_logStreamConfigObj->DBTableName . " SET " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = " . $arrProperitesIn[MISC_CHECKSUM] . " WHERE " . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] . " = " . $arrProperitesIn[SYSLOG_UID]; $myQuery = mysql_query($szSql, $this->_dbhandle); if ($myQuery) { // Return success return SUCCESS; } else { // error occured, output DEBUG message $this->PrintDebugError("SaveMessageChecksum failed with SQL Statement ' " . $szSql . " '"); // Failed return ERROR; } } else // Missing important properties return ERROR; */ return SUCCESS; } /** * Implementation of ConsolidateItemListByField * * In the native MYSQL Logstream, the database will do most of the work * * @return integer Error stat */ public function ConsolidateItemListByField($szConsFieldId, $nRecordLimit, $szSortFieldId, $nSortingOrder) { /* TODO!!! global $content, $dbmapping, $fields; // Copy helper variables, this is just for better readability $szTableType = $this->_logStreamConfigObj->DBTableType; // Check if fields are available if ( !isset($dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId]) || !isset($dbmapping[$szTableType]['DBMAPPINGS'][$szSortFieldId]) ) return ERROR_DB_DBFIELDNOTFOUND; // --- Set Options $nConsFieldType = $fields[$szConsFieldId]['FieldType']; if ( $nSortingOrder == SORTING_ORDER_DESC ) $szSortingOrder = "DESC"; else $szSortingOrder = "ASC"; // --- // --- Set DB Field names $myDBConsFieldName = $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId]; $myDBGroupByFieldName = $myDBConsFieldName; $myDBQueryFields = $myDBConsFieldName . ", "; // Set Sorted Field if ( $szConsFieldId == $szSortFieldId ) $myDBSortedFieldName = "itemcount"; else $myDBSortedFieldName = $szSortFieldId; // --- // Special handling for date fields if ( $nConsFieldType == FILTER_TYPE_DATE ) { // Helper variable for the select statement $mySelectFieldName = $myDBGroupByFieldName . "Grouped"; $myDBQueryFieldName = "DATE( " . $myDBConsFieldName . ") AS " . $myDBGroupByFieldName ; } // Set Limit String if ( $nRecordLimit > 0 ) $szLimitSql = " LIMIT " . $nRecordLimit; else $szLimitSql = ""; // Create SQL Where Clause! if ( $this->_SQLwhereClause == "" ) { $res = $this->CreateSQLWhereClause(); if ( $res != SUCCESS ) return $res; } // Create SQL String now! $szSql = "SELECT " . $myDBQueryFields . "count(" . $myDBConsFieldName . ") as itemcount " . " FROM " . $this->_logStreamConfigObj->DBTableName . $this->_SQLwhereClause . " GROUP BY " . $myDBGroupByFieldName . " ORDER BY " . $myDBSortedFieldName . " " . $szSortingOrder . $szLimitSql ; // Output Debug Informations OutputDebugMessage("LogStreamDB|ConsolidateItemListByField: Running Created SQL Query:
" . $szSql, DEBUG_ULTRADEBUG); // Perform Database Query $myquery = mysql_query($szSql, $this->_dbhandle); if ( !$myquery ) return ERROR_DB_QUERYFAILED; // Initialize Array variable $aResult = array(); // read data records while ($myRow = mysql_fetch_array($myquery, MYSQL_ASSOC)) { // Create new row $aNewRow = array(); foreach ( $myRow as $myFieldName => $myFieldValue ) { if ( $myFieldName == $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId] ) $aNewRow[$szConsFieldId] = $myFieldValue; else $aNewRow[$myFieldName] = $myFieldValue; } // Add new row to result $aResult[] = $aNewRow; } // return finished array if ( count($aResult) > 0 ) return $aResult; else return ERROR_NOMORERECORDS; */ // NOT IMPLEMENTED return ERROR_NOMORERECORDS; } /** * Implementation of ConsolidateDataByField * * In the native MYSQL Logstream, the database will do most of the work * * @return integer Error stat */ public function ConsolidateDataByField($szConsFieldId, $nRecordLimit, $szSortFieldId, $nSortingOrder, $aIncludeCustomFields = null, $bIncludeLogStreamFields = false, $bIncludeMinMaxDateFields = false) { /* TODO!!! global $content, $dbmapping, $fields; // Copy helper variables, this is just for better readability $szTableType = $this->_logStreamConfigObj->DBTableType; // Check if fields are available if ( !isset($dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId]) || !isset($dbmapping[$szTableType]['DBMAPPINGS'][$szSortFieldId]) ) return ERROR_DB_DBFIELDNOTFOUND; // --- Set Options $nConsFieldType = $fields[$szConsFieldId]['FieldType']; if ( $nSortingOrder == SORTING_ORDER_DESC ) $szSortingOrder = "DESC"; else $szSortingOrder = "ASC"; // --- // --- Set DB Field names $myDBConsFieldName = $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId]; $myDBGroupByFieldName = $myDBConsFieldName; // Check which fields to include if ( $aIncludeCustomFields != null ) { $myDBQueryFields = ""; foreach ( $aIncludeCustomFields as $myFieldName ) { if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName]) ) $myDBQueryFields .= $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", "; } // Append Sortingfield if ( !in_array($szConsFieldId, $aIncludeCustomFields) ) $myDBQueryFields .= $myDBConsFieldName . ", "; } else if ( $bIncludeLogStreamFields ) { $myDBQueryFields = ""; foreach ( $this->_arrProperties as $myFieldName ) { if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName]) ) $myDBQueryFields .= $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", "; } } else // Only Include ConsolidateField $myDBQueryFields = $myDBConsFieldName . ", "; // Add Min and Max fields for DATE if desired if ( $bIncludeMinMaxDateFields ) { $myDBQueryFields .= "Min(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] . ") as firstoccurrence_date, "; $myDBQueryFields .= "Max(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] . ") as lastoccurrence_date, "; } if ( $szConsFieldId == $szSortFieldId ) $myDBSortedFieldName = "itemcount"; else $myDBSortedFieldName = $szSortFieldId; // --- // Special handling for date fields if ( $nConsFieldType == FILTER_TYPE_DATE ) { // Helper variable for the select statement $mySelectFieldName = $myDBGroupByFieldName . "Grouped"; $myDBQueryFieldName = "DATE( " . $myDBConsFieldName . ") AS " . $myDBGroupByFieldName ; } // Set Limit String if ( $nRecordLimit > 0 ) $szLimitSql = " LIMIT " . $nRecordLimit; else $szLimitSql = ""; // Create SQL Where Clause! if ( strlen($this->_SQLwhereClause) <= 0 ) { $res = $this->CreateSQLWhereClause(); if ( $res != SUCCESS ) return $res; } // Create SQL String now! $szSql = "SELECT " . $myDBQueryFields . "count(" . $myDBConsFieldName . ") as itemcount " . " FROM " . $this->_logStreamConfigObj->DBTableName . $this->_SQLwhereClause . " GROUP BY " . $myDBGroupByFieldName . " ORDER BY " . $myDBSortedFieldName . " " . $szSortingOrder . $szLimitSql ; // Output Debug Informations OutputDebugMessage("LogStreamDB|ConsolidateDataByField: Running Created SQL Query:
" . $szSql, DEBUG_ULTRADEBUG); // Perform Database Query $myquery = mysql_query($szSql, $this->_dbhandle); if ( !$myquery ) return ERROR_DB_QUERYFAILED; // Initialize Array variable $aResult = array(); // read data records while ($myRow = mysql_fetch_array($myquery, MYSQL_ASSOC)) { // Create new row $aNewRow = array(); foreach ( $myRow as $myFieldName => $myFieldValue ) { $myFieldID = $this->GetFieldIDbyDatabaseMapping($szTableType, $myFieldName); $aNewRow[ $myFieldID ] = $myFieldValue; // } } // Add new row to result $aResult[] = $aNewRow; } // return finished array if ( count($aResult) > 0 ) return $aResult; else return ERROR_NOMORERECORDS; */ // NOT IMPLEMENTED return ERROR_NOMORERECORDS; } /** * Implementation of GetCountSortedByField * * In the native MYSQL Logstream, the database will do most of the work * * @return integer Error stat */ public function GetCountSortedByField($szFieldId, $nFieldType, $nRecordLimit) { /* TODO!!! global $content, $dbmapping; // Copy helper variables, this is just for better readability $szTableType = $this->_logStreamConfigObj->DBTableType; if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$szFieldId]) ) { // Set DB Field name first! $myDBFieldName = $dbmapping[$szTableType]['DBMAPPINGS'][$szFieldId]; $myDBQueryFieldName = $myDBFieldName; $mySelectFieldName = $myDBFieldName; // Special handling for date fields if ( $nFieldType == FILTER_TYPE_DATE ) { // Helper variable for the select statement $mySelectFieldName = $mySelectFieldName . "Grouped"; $myDBQueryFieldName = "DATE( " . $myDBFieldName . ") AS " . $mySelectFieldName ; } // Create SQL Where Clause! if ( $this->_SQLwhereClause == "" ) { $res = $this->CreateSQLWhereClause(); if ( $res != SUCCESS ) return $res; } // Create SQL String now! $szSql = "SELECT " . $myDBQueryFieldName . ", " . "count(" . $myDBFieldName . ") as TotalCount " . " FROM " . $this->_logStreamConfigObj->DBTableName . $this->_SQLwhereClause . " GROUP BY " . $mySelectFieldName . " ORDER BY TotalCount DESC" . " LIMIT " . $nRecordLimit; // Perform Database Query $myquery = mysql_query($szSql, $this->_dbhandle); if ( !$myquery ) return ERROR_DB_QUERYFAILED; // Initialize Array variable $aResult = array(); // read data records while ($myRow = mysql_fetch_array($myquery, MYSQL_ASSOC)) $aResult[ $myRow[$mySelectFieldName] ] = $myRow['TotalCount']; // return finished array if ( count($aResult) > 0 ) return $aResult; else return ERROR_NOMORERECORDS; } else { // return error code, field mapping not found return ERROR_DB_DBFIELDNOTFOUND; } */ // NOT IMPLEMENTED return ERROR_NOMORERECORDS; } /* * ============= Beginn of private functions ============= */ /* * Helper function to create the Field Array */ private function CreateFieldsArray() { global $dbmapping; $szTableType = $this->_logStreamConfigObj->DBTableType; // Init Array $this->_myMongoFields = array(); // Init Fields Array foreach ( $this->_arrProperties as $property ) { // Check if mapping exists if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$property]) ) { $this->_myMongoFields[ $dbmapping[$szTableType]['DBMAPPINGS'][$property] ] = true; } } // Success return SUCCESS; } /* * Helper function to create the Query Array */ private function CreateQueryArray($uID) { global $dbmapping; $szTableType = $this->_logStreamConfigObj->DBTableType; // Init Array $this->_myMongoQuery = array(); if ( $this->_filters != null ) { // Init Fields Array foreach ( $this->_arrProperties as $property ) { // Check if mapping exists if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$property]) ) { $this->_myMongoQuery[ $dbmapping[$szTableType]['DBMAPPINGS'][$property] ] = true; } } } if ( $uID != UID_UNKNOWN ) { // Add uID Filter as well! $myMongoID = new MongoId( base_convert($uID, 10, 16) ); $this->_myMongoQuery[ $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] ] = array( '$lt' => $myMongoID ); } // Success return SUCCESS; } /* * This function expects the filters to already being set earlier. * Otherwise no usual WHERE Clause can be created! */ private function CreateSQLWhereClause() { // DEBUG FOF NOW return SUCCESS; if ( $this->_filters != null ) { global $dbmapping; $szTableType = $this->_logStreamConfigObj->DBTableType; // Reset WhereClause $this->_SQLwhereClause = ""; // --- Build Query Array $arrayQueryProperties = $this->_arrProperties; if ( isset($this->_arrFilterProperties) && $this->_arrFilterProperties != null) { foreach ( $this->_arrFilterProperties as $filterproperty ) { if ( $this->_arrProperties == null || !in_array($filterproperty, $this->_arrProperties) ) $arrayQueryProperties[] = $filterproperty; } } // --- // Loop through all available properties foreach( $arrayQueryProperties as $propertyname ) { // If the property exists in the filter array, we have something to filter for ^^! if ( array_key_exists($propertyname, $this->_filters) ) { // Process all filters foreach( $this->_filters[$propertyname] as $myfilter ) { // Only perform if database mapping is available for this filter! if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$propertyname]) ) { switch( $myfilter[FILTER_TYPE] ) { case FILTER_TYPE_STRING: // --- Either make a LIKE or a equal query! if ( $myfilter[FILTER_MODE] & FILTER_MODE_SEARCHFULL ) { // Set addnot to nothing $addnod = ""; // --- Check if user wants to include or exclude! if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE) { $szSearchBegin = " = '"; $szSearchEnd = "' "; } else { $szSearchBegin = " <> '"; $szSearchEnd = "' "; } // --- } else if ( $myfilter[FILTER_MODE] & FILTER_MODE_SEARCHREGEX ) { // --- Check if user wants to include or exclude! if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE) $addnod = ""; else $addnod = " NOT"; // --- $szSearchBegin = " REGEXP '"; $szSearchEnd = "' "; } else { // --- Check if user wants to include or exclude! if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE) $addnod = ""; else $addnod = " NOT"; // --- $szSearchBegin = " LIKE '%"; $szSearchEnd = "%' "; } // --- // --- If Syslog message, we have AND handling, otherwise OR! if ( $propertyname == SYSLOG_MESSAGE ) $addor = " AND "; else { // If we exclude filters, we need to combine with AND if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE) $addor = " OR "; else $addor = " AND "; } // --- // Now Create LIKE Filters if ( isset($tmpfilters[$propertyname]) ) $tmpfilters[$propertyname][FILTER_VALUE] .= $addor . $dbmapping[$szTableType]['DBMAPPINGS'][$propertyname] . $addnod . $szSearchBegin . DB_RemoveBadChars($myfilter[FILTER_VALUE]) . $szSearchEnd; else { $tmpfilters[$propertyname][FILTER_TYPE] = FILTER_TYPE_STRING; $tmpfilters[$propertyname][FILTER_VALUE] = $dbmapping[$szTableType]['DBMAPPINGS'][$propertyname] . $addnod . $szSearchBegin . DB_RemoveBadChars($myfilter[FILTER_VALUE]) . $szSearchEnd; } break; case FILTER_TYPE_NUMBER: // --- Check if user wants to include or exclude! if ( $myfilter[FILTER_MODE] & FILTER_MODE_EXCLUDE ) { // Add to filterset $szArrayKey = $propertyname . "-NOT"; if ( isset($tmpfilters[$szArrayKey]) ) $tmpfilters[$szArrayKey][FILTER_VALUE] .= ", " . $myfilter[FILTER_VALUE]; else { $tmpfilters[$szArrayKey][FILTER_TYPE] = FILTER_TYPE_NUMBER; $tmpfilters[$szArrayKey][FILTER_VALUE] = $dbmapping[$szTableType]['DBMAPPINGS'][$propertyname] . " NOT IN (" . DB_RemoveBadChars($myfilter[FILTER_VALUE]); } } else { // Add to filterset if ( isset($tmpfilters[$propertyname]) ) $tmpfilters[$propertyname][FILTER_VALUE] .= ", " . $myfilter[FILTER_VALUE]; else { $tmpfilters[$propertyname][FILTER_TYPE] = FILTER_TYPE_NUMBER; $tmpfilters[$propertyname][FILTER_VALUE] = $dbmapping[$szTableType]['DBMAPPINGS'][$propertyname] . " IN (" . DB_RemoveBadChars($myfilter[FILTER_VALUE]); } } // --- break; case FILTER_TYPE_DATE: if ( isset($tmpfilters[$propertyname]) ) $tmpfilters[$propertyname][FILTER_VALUE] .= " AND "; else { $tmpfilters[$propertyname][FILTER_VALUE] = ""; $tmpfilters[$propertyname][FILTER_TYPE] = FILTER_TYPE_DATE; } if ( $myfilter[FILTER_DATEMODE] == DATEMODE_LASTX ) { // Get current timestamp $nNowTimeStamp = time(); if ( $myfilter[FILTER_VALUE] == DATE_LASTX_HOUR ) $nNowTimeStamp -= 60 * 60; // One Hour! else if ( $myfilter[FILTER_VALUE] == DATE_LASTX_12HOURS ) $nNowTimeStamp -= 60 * 60 * 12; // 12 Hours! else if ( $myfilter[FILTER_VALUE] == DATE_LASTX_24HOURS ) $nNowTimeStamp -= 60 * 60 * 24; // 24 Hours! else if ( $myfilter[FILTER_VALUE] == DATE_LASTX_7DAYS ) $nNowTimeStamp -= 60 * 60 * 24 * 7; // 7 days else if ( $myfilter[FILTER_VALUE] == DATE_LASTX_31DAYS ) $nNowTimeStamp -= 60 * 60 * 24 * 31; // 31 days else { // Set filter to unknown and Abort in this case! $tmpfilters[$propertyname][FILTER_TYPE] = FILTER_TYPE_UNKNOWN; break; } // Append filter $tmpfilters[$propertyname][FILTER_VALUE] .= $dbmapping[$szTableType]['DBMAPPINGS'][$propertyname] . " > '" . date("Y-m-d H:i:s", $nNowTimeStamp) . "'"; } else if ( $myfilter[FILTER_DATEMODE] == DATEMODE_RANGE_FROM ) { // Obtain Event struct for the time! $myeventtime = GetEventTime($myfilter[FILTER_VALUE]); $tmpfilters[$propertyname][FILTER_VALUE] .= $dbmapping[$szTableType]['DBMAPPINGS'][$propertyname] . " > '" . date("Y-m-d H:i:s", $myeventtime[EVTIME_TIMESTAMP]) . "'"; } else if ( $myfilter[FILTER_DATEMODE] == DATEMODE_RANGE_TO ) { // Obtain Event struct for the time! $myeventtime = GetEventTime($myfilter[FILTER_VALUE]); $tmpfilters[$propertyname][FILTER_VALUE] .= $dbmapping[$szTableType]['DBMAPPINGS'][$propertyname] . " < '" . date("Y-m-d H:i:s", $myeventtime[EVTIME_TIMESTAMP]) . "'"; } break; default: // Nothing to do! break; } } else { // Check how to treat not found db mappings / filters if ( GetConfigSetting("TreatNotFoundFiltersAsTrue", 0, CFGLEVEL_USER) == 0 ) return ERROR_DB_DBFIELDNOTFOUND; } } } } // Check and combine all filters now! if ( isset($tmpfilters) ) { // Append filters foreach( $tmpfilters as $tmpfilter ) { // Init WHERE or Append AND if ( strlen($this->_SQLwhereClause) > 0 ) $this->_SQLwhereClause .= " AND "; else $this->_SQLwhereClause = " WHERE "; switch( $tmpfilter[FILTER_TYPE] ) { case FILTER_TYPE_STRING: $this->_SQLwhereClause .= "( " . $tmpfilter[FILTER_VALUE] . ") "; break; case FILTER_TYPE_NUMBER: $this->_SQLwhereClause .= $tmpfilter[FILTER_VALUE] . ") "; break; case FILTER_TYPE_DATE: $this->_SQLwhereClause .= $tmpfilter[FILTER_VALUE]; break; default: // Should not happen, wrong filters! // We add a dummy into the where clause, just as a place holder $this->_SQLwhereClause .= " 1=1 "; break; } } } // echo $this->_SQLwhereClause; //$dbmapping[$szTableType][SYSLOG_UID] } else // No filters means nothing to do! return SUCCESS; } /* * This helper function will read the next records into the buffer. */ private function ReadNextRecordsFromDB($uID) { global $querycount, $dbmapping; $szTableType = $this->_logStreamConfigObj->DBTableType; // return error if there was one! if ( ($res = $this->CreateQueryArray($uID)) != SUCCESS ) return $res; // Append LIMIT clause // $szSql .= " LIMIT " . $this->_currentRecordStart . ", " . $this->_logStreamConfigObj->RecordsPerQuery; $myCursor = $this->_myMongoCollection->find($this->_myMongoQuery, $this->_myMongoFields); // ->limit(10); // $collection->find(); OutputDebugMessage("Cursor verbose: " . var_export($myCursor->explain(), true), DEBUG_DEBUG); $myCursor = $myCursor->sort(array("_id" => -1)); // Copy rows into the buffer! $iBegin = $this->_currentRecordNum; while ($myRow = $myCursor->getNext()) { // Check if result was successfull! if ( $myRow === FALSE || !$myRow ) break; $myRow[ "_id" ] = base_convert($myRow[ "_id" ], 16, 10); // ($myRow["_id"]->{'$id'}); // $myRow[ "_id" ] = $myRow["_id"]->getInc(); // Use Inc value for now, easier to read! // Keys will be converted into lowercase! $this->bufferedRecords[$iBegin] = array_change_key_case( $myRow, CASE_LOWER); $iBegin++; } // --- Check if results were found if ( $iBegin == $this->_currentRecordNum ) return ERROR_NOMORERECORDS; // --- /* // Only obtain count if enabled and not done before if ( $this->_logStreamConfigObj->DBEnableRowCounting && $this->_totalRecordCount == -1 ) { $this->_totalRecordCount = $this->GetRowCountFromTable(); if ( $this->_totalRecordCount <= 0 ) return ERROR_NOMORERECORDS; } */ // Increment for the Footer Stats $querycount++; // return success state if reached this point! return SUCCESS; } /* * Creates the SQL Statement we are going to use! */ private function CreateSQLStatement($uID, $includeFields = true) { /* global $dbmapping; // Copy helper variables, this is just for better readability $szTableType = $this->_logStreamConfigObj->DBTableType; $szSortColumn = $this->_logStreamConfigObj->SortColumn; // Create Basic SQL String if ( $this->_logStreamConfigObj->DBEnableRowCounting ) // with SQL_CALC_FOUND_ROWS $sqlString = "SELECT SQL_CALC_FOUND_ROWS " . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID]; else // without row calc $sqlString = "SELECT " . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID]; // Append fields if needed if ( $includeFields && $this->_arrProperties != null ) { // Loop through all requested fields foreach ( $this->_arrProperties as $myproperty ) { // SYSLOG_UID already added! if ( $myproperty != SYSLOG_UID && isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) ) { // Append field! $sqlString .= ", " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]; } } } // Append FROM 'table'! $sqlString .= " FROM " . $this->_logStreamConfigObj->DBTableName; // Append precreated where clause $sqlString .= $this->_SQLwhereClause; // Append UID QUERY! if ( $uID != -1 ) { if ( $this->_readDirection == EnumReadDirection::Forward ) $myOperator = ">="; else $myOperator = "<="; if ( strlen($this->_SQLwhereClause) > 0 ) $sqlString .= " AND " . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] . " $myOperator $uID"; else $sqlString .= " WHERE " . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] . " $myOperator $uID"; } // Append ORDER clause if ( $this->_readDirection == EnumReadDirection::Forward ) $sqlString .= " ORDER BY " . $dbmapping[$szTableType]['DBMAPPINGS'][$szSortColumn]; else if ( $this->_readDirection == EnumReadDirection::Backward ) $sqlString .= " ORDER BY " . $dbmapping[$szTableType]['DBMAPPINGS'][$szSortColumn] . " DESC"; // return SQL result string: return $sqlString; */ return ""; } /* * Reset record buffer in this function! */ private function ResetBufferedRecords() { if ( isset($this->bufferedRecords) ) { // Loop through all subrecords first! foreach ($this->bufferedRecords as $mykey => $myrecord) unset( $this->bufferedRecords[$mykey] ); // Set buffered records to NULL! $this->bufferedRecords = null; } } /* * Helper function to display SQL Errors for now! */ private function PrintDebugError($szErrorMsg) { global $extraErrorDescription; $errdesc = mysql_error(); $errno = mysql_errno(); $errormsg="$szErrorMsg
"; $errormsg.="Detail error: $errdesc
"; $errormsg.="Error Code: $errno
"; // Add to additional error output $extraErrorDescription = $errormsg; //Output! OutputDebugMessage("LogStreamDB|PrintDebugError: $errormsg", DEBUG_ERROR); } /* * Returns the number of possible records by using a query */ private function GetRowCountByString($szQuery) { if ($myQuery = mysql_query($szQuery)) { $num_rows = mysql_num_rows($myQuery); mysql_free_result ($myQuery); } return $num_rows; } /* * Returns the number of possible records by using an existing queryid */ private function GetRowCountByQueryID($myQuery) { $num_rows = mysql_num_rows($myQuery); return $num_rows; } /* * Returns the number of possible records by using a select count statement! */ private function GetRowCountFromTable() { if ( $myquery = mysql_query("Select FOUND_ROWS();", $this->_dbhandle) ) { // Get first and only row! $myRow = mysql_fetch_array($myquery); // copy row count $numRows = $myRow[0]; } else $numRows = -1; // return result! return $numRows; /* OLD slow code! global $dbmapping,$querycount; $szTableType = $this->_logStreamConfigObj->DBTableType; // Create Statement and perform query! $szSql = "SELECT count(" . $dbmapping[$szTableType][SYSLOG_UID] . ") FROM " . $this->_logStreamConfigObj->DBTableName . $this->_SQLwhereClause; if ($myQuery = mysql_query($szSql, $this->_dbhandle)) { // obtain first and only row $myRow = mysql_fetch_row($myQuery); $numRows = $myRow[0]; // Increment for the Footer Stats $querycount++; // Free query now mysql_free_result ($myQuery); } else $numRows = -1; */ } /* * Function handles missing database fields automatically! */ private function HandleMissingField( $szMissingField = null, $arrProperties = null ) { global $dbmapping, $fields; // Get Err description $errdesc = mysql_error(); // Try to get missing field from SQL Error of not specified as argument if ( $szMissingField == null ) { if ( preg_match("/Unknown column '(.*?)' in '(.*?)'$/", $errdesc, $errOutArr ) ) $szMissingField = $errOutArr[1]; else { $this->PrintDebugError("ER_BAD_FIELD_ERROR - SQL Statement: ". $errdesc); return ERROR_DB_DBFIELDNOTFOUND; } } // Set Properties to default if NULL if ( $arrProperties == null ) $arrProperties = $this->_arrProperties; // Get Tabletype $szTableType = $this->_logStreamConfigObj->DBTableType; // Loop through all fields to see which one is missing! foreach ( $arrProperties as $myproperty ) { if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && $szMissingField == $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] ) { // Create SQL Numeric field $szUpdateSql = ""; $szUnsigned = ""; if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_NUMBER ) { // This will add the checksum field as unsigned automatically! if ( $myproperty == MISC_CHECKSUM ) $szUnsigned = "UNSIGNED"; $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` int(11) " . $szUnsigned . " NOT NULL DEFAULT '0'"; } if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_STRING ) $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` varchar(60) NOT NULL DEFAULT ''"; if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_DATE ) $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'"; if ( strlen($szUpdateSql) > 0 ) { // Update Table schema now! $myQuery = mysql_query($szUpdateSql, $this->_dbhandle); if (!$myQuery) { // Return failure! $this->PrintDebugError("ER_BAD_FIELD_ERROR - Dynamically Adding field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' with Statement failed: '" . $szUpdateSql . "'"); return ERROR_DB_ADDDBFIELDFAILED; } } else { // Return failure! $this->PrintDebugError("ER_BAD_FIELD_ERROR - Field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' is missing has to be added manually to the database layout!'"); return ERROR_DB_ADDDBFIELDFAILED; } } } // Reached this point means success! return SUCCESS; } /* * Helper function to return a list of Indexes for the logstream table */ private function GetIndexesAsArray() { global $querycount; // Verify database connection (This also opens the database!) $res = $this->Verify(); if ( $res != SUCCESS ) return $res; // Init Array $arrIndexKeys = array(); // Create SQL and Get INDEXES for table! $szSql = "SHOW INDEX FROM " . $this->_logStreamConfigObj->DBTableName; $myQuery = mysql_query($szSql, $this->_dbhandle); if ($myQuery) { // Loop through results while ($myRow = mysql_fetch_array($myQuery, MYSQL_ASSOC)) { // Add to index keys $arrIndexKeys[] = strtolower($myRow['Key_name']); } // Free query now mysql_free_result ($myQuery); // Increment for the Footer Stats $querycount++; } // return Array return $arrIndexKeys; } /* * Helper function to return a list of Fields from the logstream table */ private function GetFieldsAsArray() { global $querycount; // Verify database connection (This also opens the database!) $res = $this->Verify(); if ( $res != SUCCESS ) return $res; // Init Array $arrFieldKeys = array(); // Create SQL and Get INDEXES for table! $szSql = "SHOW FIELDS FROM " . $this->_logStreamConfigObj->DBTableName; $myQuery = mysql_query($szSql, $this->_dbhandle); if ($myQuery) { // Loop through results while ($myRow = mysql_fetch_array($myQuery, MYSQL_ASSOC)) { // Add to index keys $arrFieldKeys[] = strtolower($myRow['Field']); } // Free query now mysql_free_result ($myQuery); // Increment for the Footer Stats $querycount++; } // return Array return $arrFieldKeys; } /* * Helper function to return a list of Indexes for the logstream table */ private function GetTriggersAsArray() { global $querycount; // Verify database connection (This also opens the database!) $res = $this->Verify(); if ( $res != SUCCESS ) return $res; // Init Array $arrIndexTriggers = array(); // Create SQL and Get INDEXES for table! $szSql = "SHOW TRIGGERS"; $myQuery = mysql_query($szSql, $this->_dbhandle); if ($myQuery) { // Loop through results while ($myRow = mysql_fetch_array($myQuery, MYSQL_ASSOC)) { // print_r ( $myRow ); // Add to index keys $arrIndexTriggers[] = strtolower($myRow['Trigger']); } // Free query now mysql_free_result ($myQuery); // Increment for the Footer Stats $querycount++; } // return Array return $arrIndexTriggers; } // --- End of Class! } ?>