loganalyzer-3.6.6/ 0000755 0001750 0001750 00000000000 12401304543 013323 5 ustar daniel daniel loganalyzer-3.6.6/ChangeLog 0000644 0001750 0001750 00000126757 12401304543 015117 0 ustar daniel daniel ---------------------------------------------------------------------------
Version 3.6.6 (stable), 2014-09-02
- Fixed bug in databasemapping admin. The form parameter and database
fieldname of EventID field were interfering.
- Fixed a bug in maintenance.php, the ID parameter was forced to
an integer. A leftover from earlier loganalyzer days.
- Fixed Cross Site Scripting Issue in index.php/detail.php for
stringtype fields discovered by Dolev Farhi dolevf@yahoo.com
from F5 Networks.
---------------------------------------------------------------------------
Version 3.6.5 (stable), 2013-10-08
- LogStreamDB Driver, LogStreamPDO Driver, UserDB:
Added backticks arround tablenames in all SQL Statements.
This fixes http://bugzilla.adiscon.com/show_bug.cgi?id=479
- LogStreamPDO Driver: Fixed hardcoded tablename in trigger
create statement
- Fixed LDAP login problem when special characters like quotes were
used in passwords.
This fixes http://bugzilla.adiscon.com/show_bug.cgi?id=480
---------------------------------------------------------------------------
Version 3.6.4 (stable), 2013-08-16
- Added MYSQL hint in install script when enabling User Database System.
- Using default header encoding in GetStringWithHTMLCodes() function now.
This should solve http://bugzilla.adiscon.com/show_bug.cgi?id=433.
- Added SyslogNG logline parser, thanks to Mulyadi Santosa for
providing the a patch to us. A customized template in SyslogNG is needed:
template("$FACILITY_NUM $LEVEL_NUM $DATE $FULLHOST $MESSAGE\n")
---------------------------------------------------------------------------
Version 3.6.3 (stable), 2013-02-25
- Updated Search documentation
- Fixed Bug in the ApplyFilters function which applies to all logstreams.
This caused most REGEX filters to fail, if supported by the
LogStream driver.
- Added support for dynamic fields in MongoDB logstream sources. This
enables Loganalyzer to view data written by rsyslog into
MongoDB from CEE sources.
- Fixed wrong UID calculation in MongoDB Logstream class.
- Fixed an issue deleting all data in MongoDB LogStream class.
---------------------------------------------------------------------------
Version 3.6.2 (stable), 2013-01-09
- Fixed another DiskAllowed Checked in Disk logstream class, no works as
expected.
- Fixed Cross Site Scripting Issue in userchange.php
(viewid parameter)
---------------------------------------------------------------------------
Version 3.6.1 (stable), 2012-12-19
- Cosmetic fix in login.php, fixed static language strings.
- Fixed Cross Site scripting issue in asktheoracle.php
(oracle_query parameter)
---------------------------------------------------------------------------
Version 3.6.0 (stable), 2012-12-04
- Bugfix: Fixed "DiskAllowed" checking in Disklogstream. Filenames are now
correctly checked against allowed folders. This check was added for
security reasons before.
- Fixes #bugid 369: http://bugzilla.adiscon.com/show_bug.cgi?id=369
The DefaultviewID was accidentally overwritten with default value.
- Fixes #bugid 375: http://bugzilla.adiscon.com/show_bug.cgi?id=369
User and Group data is now deleted when removing them from the UserDB.
- Bugfix: Added missing dependency for the Checksum field in
"EventLog Audit" and "EventLog Logon/Logoff" report.
---------------------------------------------------------------------------
Version 3.5.6 (beta), 2012-09-10
- bugfix: Changed intval() handling in details.php into is_numeric.
This fixes problems with 64 Bit unsigned uid's.
Fixes #bugid 345: http://bugzilla.adiscon.com/show_bug.cgi?id=345
---------------------------------------------------------------------------
Version 3.4.5 (stable), 2012-09-10
- Merged fix from beta branch in function_db.php. DB_RemoveBadChars
function supports arrays now, this caused invisible notice errors.
---------------------------------------------------------------------------
Version 3.5.5 (beta), 2012-06-19
- Merged security fixes into beta branch
---------------------------------------------------------------------------
Version 3.4.4 (stable), 2012-06-19
- Fixed cross-site scripting vulnerability of highlight parameter
on index.php page.
---------------------------------------------------------------------------
Version 3.5.4 (beta), 2012-05-22
- Merged security fixes into beta branch
---------------------------------------------------------------------------
Version 3.4.3 (stable), 2012-05-22
- Fixed several security vulnerabilities discovered by Filippo Cavallarin.
This contains the following fixes:
- Fixed SQL Injection vulnerability in admin/view.php
- Fixed Cross Site scripting issue filter parameter on index.php
- Fixed Cross site scripting issue of id parameter on admin/reports.php
- Fixed Cross site scripting issue of id parameter on admin/searches.php
- Fixed arbitrary file read issue in Disk LogStream class.
The config.php file does now contain an array "DiskAllowed" which
contains allowed directories. Only files located within these allowed
directories can be accessed in LogAnalyzer. By default,
only /var/log is allowed.
---------------------------------------------------------------------------
Version 3.5.3 (beta), 2012-05-09
- Fixed some issues in the new MongoDB Logstream Class. To name a few,
add resultlimits to speedup performance. Changed and fixed some issues
when grouping data for consolidation. Added support to create Indexes
on fields. This should also speedup report generation.
- Added support to filter by date string, example: timereported:=2012-01-01
A new Datetype hasbeen added to support filtering by date.
- Updated jpgraph code to latest version which is 3.0.7
---------------------------------------------------------------------------
Version 3.4.2 (stable), 2012-05-07
- Fixed a #bugid 303, VerifyChecksumTrigger function in logstreamdb
class did not generate a lowercase triggername.
- Fixed typo in lang files
- Changed processid field type to string in logstreamclass. Filtering
for non-numeric processids is now possible.
- Added support to filter by day (Date field - for example:
timereported:=2012-01-01
---------------------------------------------------------------------------
Version 3.5.2 (beta), 2012-04-23
- Added new Logstream driver for MongoDB. The initial version contains
all features needed to use MongoDB with Loganalyzer and it's reports.
You will need the Mongo PHP extension installed (see here for more:
http://www.php.net/manual/en/mongo.installation.php ).
- Extended ID Field handling in Loganalyzer which is needed in order
to work with MongoDB IDs.
- Changed processid field type to string in logstreamclass.
This caused problems when filtering for non-numeric processids.
- Added support to use MongoDB logstream in LogAnalyzer installer.
---------------------------------------------------------------------------
Version 3.5.1 (beta), 2012-03-16
- Added Support for LDAP Authentication based on the modification
from forum user "Prune". LDAP Support can be configured during the
installation of LogAnalyzer, but can also be turned on later by
editing the config.php. More Details will be found in our wiki:
http://wiki.rsyslog.com/index.php/LogAnalyzer
- Fixed a #bugid 303, VerifyChecksumTrigger function had trouble
with mixed cased triggernames.
---------------------------------------------------------------------------
Version 3.5.0 (beta), 2012-01-24
- Added new Report "Eventlog Audit Summary Report" which can generate
detailed security reports for Windows Eventlog security records.
It supports Windows 2003 and 2008 Server and is compliant with the
Sarbanes-Oxley (SOX) Act, 2002.
- Added support for customized boolean report filters. This enhancement
is also used by the new "Eventlog Audit Summary Report".
---------------------------------------------------------------------------
Version 3.4.1 (stable), 2012-01-10
- Fixed a bug in Syslog and Eventlog summary report which consolidated
wrong events when the source filter was used in the report.
---------------------------------------------------------------------------
Version 3.4.0 (stable), 2011-12-06
- Added initial version of a new free report for consolidating
Windows Eventlog Logon / Logoff events
- PDO LogStream, the RowCount function is now only used
with MYSQL, PGSQL and MSSQL. Other PDO Drivers may not return a
useful value.
- Removed language files from source, can be found here from now on:
http://loganalyzer.adiscon.com/translations
- Straighten out a couple of issues
- Doc: Redirected professional support options to proper page
---------------------------------------------------------------------------
Version 3.2.3 (stable), 2011-11-08
- Removed magic quotes check from database functions (obselete due
the changes in the last version)
- Merged Changes from BUGID #288 (Thanks to User Jeff)
- Fixed internal Filter parsing bug introduced in 3.2.2.
- Fixed bug in syslog summary report missing checksum in report generation
- Fixed bug in preparing filters for display in basic report class
- Fixed bug in verification routine of sources admin when backslashes
were in any other variables
- Fixed BUGID #291, custom filters are now taken care in database
logstream sources when cleaning up data.
- Changed minwidth for context menus from 200 to 250px due display
problems in some browsers.
---------------------------------------------------------------------------
Version 3.2.2 (stable), 2011-09-28
- Implemented support to use User or Group configured logstream sources
in commandline report generator (cmdreportgen.php). The Report Admin
will generate an additional parameter for the sample commandline:
userid=$uid or groupid=$gid
- Fixed syntaxlogic bugs in proxy utilisation, thanks to forum
member pierre: http://kb.monitorware.com/post-t10570.html#p20033
- Fixed ignoring "IPAddressResolve" setting when "EnableContextLinks"
was disabled.
- Fixed filter detection bug in report class which could lead to problems
with certain filter evaluations.
- Fixed error in parsing include/exclude filters for numeric fields
in report admin panel. Changes in the main filter parser were
also necessary to fix this issue.
- Added function to automatically remove MagicQuotes (performed if
the php "magic_quotes_gpc" is on).
- Added support to search for full phrases instead of words only. Kindly
use Quotes to mark the start and end of a phrase, for example:
"Search for this" // Searches for full phrase
-"Search for this" // Excludes full phrase
- Report admin, fixed filter editor issues when full phrase strings
(with spaces) were configured.
- Report admin, the custom filterstring was not saved if new report
was created or the previous custom filterstring was empty.
---------------------------------------------------------------------------
Version 3.2.1 (stable), 2011-04-12
- Fixed timezone parsing in GetEventTime function. This caused problems
reading date/time strings with negative timezone offsets.
- Added option to disable context links in LogAnalyzer.
---------------------------------------------------------------------------
Version 3.2.0 (stable), 2011-03-30
- Added new logline parser for Syslog23 Format (RFC 5424). This format
is suported by the RSYSLOG_SyslogProtocol23Format template in RSyslog.
This format also includes syslog facility and priority.
- Added php session_write_close to certain places to avoid hanging
browser sessions.
- Eventlog Summary Report now also detects and processes data from
EventLog Monitor V2 (from EventReporter/MonitorWare Agent).
- Fixed typo in Syslog Report, Last Occurrence date is now correctly
printed in the report.
---------------------------------------------------------------------------
Version 3.0.7 (beta), 2011-02-25
- Added UserDBPort Parameter into DB_Connect function. Thanks to forum
user "plebreton" pointing to this bug.
- Added Output of report generation time into templates and common
report variabes.
- Fixed a bug in logstream DB causing unnecessary mysql_free_result
calls when updating Checksum data.
- Fixed filter dialog issue parsing message filters wrong in Report
Admin Panel. An semicolon was added while saving report settings.
- Added missing mapping for ProcessID field for monitorware database
mapping (logstream constants).
---------------------------------------------------------------------------
Version 3.0.6 (beta), 2011-02-11
- Added missing filterstring url parameter into statistics.php.
- You can enabled/disable charts by clicking on the checkbox now in
the Charts Admin panel.
- Added support to select character encoding in HTML Header. This enables
Loganalyzer to process and display UTF-8 encoded logs properly.
The default encoding is ISO-8859-1 and can be switched in the general
admin panel, or by adding the $CFG['HeaderDefaultEncoding'] configuration
variable into config.php. Possible values are ENC_ISO_8859_1
and ENC_UTF8. The supported encodings can be extended by adding
new encoding definitions in include/constats_general.php.
---------------------------------------------------------------------------
Version 3.0.5 (beta), 2011-02-10
- Fixed javascript compatibility issue related to Internet Explorer
in reports admin.
- Fixed spelling error in german language translation
- Fixed problem with german special characters (Umlaute) in Form captions.
Some admin panels did not work properly because of this issue.
- Filters were ignored in chart generation if the according filter fields
were not included in the chart data.
- The auto-increment value of the ID field is now resetted if all data
is cleared using the mysql logstream maintenance functions.
---------------------------------------------------------------------------
Version 3.0.4 (beta), 2010-11-16
- Fixed Copy and Paste error in db_template.txt.
---------------------------------------------------------------------------
Version 3.0.3 (beta), 2010-10-28
- Added support for using custom filter for charts, for example if you
want to create charts for single servers.
- Added support for using custom default filters in logstream sources.
This filter will always prepended for all other custom search filters.
- Added new UserDB fields and updated database version to 10
---------------------------------------------------------------------------
Version 3.0.2 (beta), 2010-10-22
- Added support to use a proxy server for internal url request. For
example the update check request which is done during login
will use this proxy server if configured.
- Fixed TYPO in maintenance.sh, the parameter is cleandata, not cleardata.
- Added favicon which was submitted by Chris Hartman.
---------------------------------------------------------------------------
Version 3.0.1 (beta), 2010-04-14
- Fixed record height issue when "Show Onlinesearch icons within fields"
option was enabled
- Added support to automatically add missing fields in Mysql and PDO
Logstreams. Currently MySQL and PostgreSQL are support only.
- Error details of logstream sources will now be shown on detail.php
page as well.
---------------------------------------------------------------------------
Version 3.0.0 (beta), 2010-03-29
- All references to phpLogCon have now been renamed to LogAnalyzer,
which will be the new name for the phpLogCon project from now on.
- Added initial implementation of the new Report engine along with
two free reports called "EventLog Summary" and "Syslog Summary"
- Autoreload time in admin panels is now configureable.
- Added Read-Only User functionality.
- Added Updatecheck functionality for future update notifications.
- Fixed alignment of formfields in all admin panels.
---------------------------------------------------------------------------
Version 2.8.1 (v2-stable), 2010-02-23
- Added Inline searchicon, will be visible in each online
searchable field. Can be disabled in admin center.
- Added Updatecheck which will be performed during login only, so once per
session. If a newer Version is available, you will be notified in
Admin Center.
- Secured Views, Sources, Searches and Charts Admin access from users
without admin access.
- Settings will be remembered now when configuring columns in Views
Admin Panel.
- Normal users cannot init or remove message parsers anymore
- Added Time-extension on search page (send by Sergey Sireskin).
---------------------------------------------------------------------------
Version 2.9.0 (beta), 2010-01-14
- Merged previous devel branch into Stable branch and set
new version number 2.9
---------------------------------------------------------------------------
Version 2.8.0 (v2-stable), 2010-01-14
- Merged previous Beta branch into Stable branch and set
new version number 2.8
- As of RFC5424, changed ProcessID Field into string valuetype, which has
effect on how searches are done.
---------------------------------------------------------------------------
Version 2.7.3 (beta), 2009-11-17
- Merged bugfixes and changes from 2.6.5 stable into beta branch
---------------------------------------------------------------------------
Version 2.6.5 (v2-stable), 2009-11-17
- Fixed wrong include in maintenance.php which caused the script to fail
---------------------------------------------------------------------------
Version 2.7.2 (beta), 2009-08-17
- Merged bugfixes and changes from 2.6.4 stable into beta branch
---------------------------------------------------------------------------
Version 2.6.4 (v2-stable), 2009-08-14
- Removed unneeded call for define_syslog_variables, which is
depreceated in php 5.3 and will be removed in php6
- Replaced SPLIT call in install.php with preg_split because SPLIT
is a depreceated function and will proberly be removed in php6
- Updated jpgraph classes to version 3.0.2 which also removes some
issues with depreaced functions in php 5.3
---------------------------------------------------------------------------
Version 2.7.1 (beta), 2009-05-06
- Merged bugfixes from 2.6.3 stable into beta branch
---------------------------------------------------------------------------
Version 2.6.3 (v2-stable), 2009-04-29
- Fixed a bug that caused fields like syslog facily, severity or
messagetype to be shown numeric instead of readable
coloured replacements.
- Fixed a bug in the detail page which could cause numeric fields
to be missing.
- Added support for debug output in the data cleanup routine of
mysql and pdo logstreams. This will help troubleshooting.
---------------------------------------------------------------------------
Version 2.7.0 (beta), 2009-03-26
- Added support for dynamic filenames in disk logstream by using
replacement characters. See the doc for details.
- Added support for using REGEXP on supported logstream sources. Currently
MYSQL and PostGRESQL are supported due the native support of REGEXP. To
use REGEXP in searches, prepend the search phrase with the ~ character.
- Added support for configuring and administrating custom database
mappings in the Admin Center. This makes it easier to
support custom table layouts.
---------------------------------------------------------------------------
Version 2.6.2 (v2-stable), 2009-03-24
- Fixed minor spelling errors in language files (BugID #115)
- Fixed number of records exported when using the export (BugID #110).
- Added missing filter selection for message type filter on search page.
- Fixed Filtering issues when using multiple filters on the same field.
Numeric based filters will now work as expected again (BugID #108).
- Fixed table detection method in PDO LogStream.
- Added support to parse date only values like "2009-03-24".
---------------------------------------------------------------------------
Version 2.6.1 (v2-stable), 2009-03-23
- Fixed an issue with case sensitive fieldnames in db and pdo logstream.
This issue could cause unexpected results depending on how fieldnames
were returned by the database layer. Now, all fieldnames and array keys
are automatically converted into lowercase.
- Fixed minor database template definition issues with the logcon_config
table, the propvalue and propvalue_text field can be NULL now.
---------------------------------------------------------------------------
Version 2.6.0 (v2-stable), 2009-03-20
- Merged beta branch into v2-stable branch.
---------------------------------------------------------------------------
Version 2.5.24 (beta), 2009-01-27
- Added italian language files, translated by Luigi Rosa
- Improved loading of language files, to avoid display error's if
translation is incomplete.
- Enhanced database performance of MYSQL and PDO logstream source drivers.
Searching and paging through results is much faster on larger
databases now.
- Enhanced Pager performance on index and detail page.
- Hardened db logstream classes against invalid parameters.
- Added missing include file for debug functions
- Debug Messages are now printed well formated below the site content
- Improved Documentation
---------------------------------------------------------------------------
Version 2.5.23 (beta), 2008-12-23
- Fixed typo in textual month detection, which caused date detection
problems in december month only.
- Fixed missing include of debug functions in maintenance.php
- Added some performance tweaks into mysql db driver, which will make
searching for strings within messages faster.
---------------------------------------------------------------------------
Version 2.5.22 (beta), 2008-12-10
- Added workaround for year detection for RFC 3164 like timestamps.
This also resolves issues of the syslog date detection on new year.
- Fixed a notice error in chartgenerator, only visible if debug
options were enabled.
---------------------------------------------------------------------------
Version 2.5.21 (beta), 2008-11-24
- Fixed an infinite search loop which occured of the option
"Suppress Duplicated Messages was enabled". This caused the index page
to timeout once a duplicated message was hit.
- Fixed that filters were ignored when exporting results to cvs/xml
---------------------------------------------------------------------------
Version 2.5.20 (beta), 2008-11-19
- Fixed a performance issue in the logstream db and pdo drivers when
using filters. This bug could cause script timeouts when using complex
filters.
- Added default .htaccess to prevent webserver access on cron folder
---------------------------------------------------------------------------
Version 2.5.19 (beta), 2008-11-18
- Added a new "cron" folder which contains a maintenance.php script.
This script can be used on command line level for database maintenance.
For more information, see the documentation.
- Fixed typo of new column "DBRecordsPerQuery" in admin/sources.php
which caused an error when adding new database logstream sources.
---------------------------------------------------------------------------
Version 2.5.18 (beta), 2008-11-12
- Added logstream statistic and maintenance option which are accessable
in the sources admin panel. You can view overall stats of database
logstreams, and cleanup data based on the date field.
- Added option to use a custom phpLogCon logo in the header.
The logo url can be configured in the admin panel
---------------------------------------------------------------------------
Version 2.5.17 (beta), 2008-11-03
- Fixed default database template, updates for DB Version 6 and 7 were
missing.
- Added expandable submenu for help into the top menu. Also fixed some
minor stylesheet issues, to optimize usebility in the main view.
- The detail page hides empty fields now.
---------------------------------------------------------------------------
Version 2.5.16 (beta), 2008-10-27
- Fixed a problem when adding a mysql logstream source. Due a problem of
how php mysql_connect function handels second conenctions, the Verify
of a newly added logstream source could cause the first database
connection to be overwritten. The following error is, that the wrong
database was used for the UserDB after the new logstream was verified.
- Added a check into the redirect function to STOP redirecting if an
error happens in the UserDB.
- Fixed minor issues handling form input which happened when
magic_quotes_gpc was enabled.
- Fixed a bug in the convert.php script which inserted the wrong
database version number. This caused phpLogCon to force an database
upgrade which is not needed at all.
- Added dummy db update scripts, so the db upgrade script won't fail
in future. This is for the case when the db version is not correctly
or missing in the user database.
- Added support to filter for dynamic fields within the logstream
database sources. This was not possible yet. The filtering also has a
secure end timer, which avoids that the timelimit hits the script.
- Added support to suppress unparseable messages when using msgparsers.
This enhances useability if you have mixed data sources, and want to
filter out unparseable messages.
- Added new setting for MYSQL logstream sources to control the amount
of data per query. This value can be used to tweak the MYSQL
performance. For example when filtering for fields which are generated
by a message parser, highering the value does improve the database
performance. The default value is 100, and should only be changed if
you know what you are doing.
---------------------------------------------------------------------------
Version 2.5.15 (beta), 2008-10-22
- Corrected the check for magic_quotes_gpc which is important when saving
configuration values are saved into the UserDB. This also fixes a
problem of duplicating backslahes when using \ or ' in string fields.
- Fixed a minor bug of handling and saving the ViewEntriesPerPage option.
- Added Option to inject custom html code into the header and footer.
- Added Help Links into the message parser admin panel.
- Cleaned up and enhanced the default and dark theme.
- Improved documentation
---------------------------------------------------------------------------
Version 2.5.14 (beta), 2008-10-10
- Added support for fully customizeable fields. This includes a fields
admin with possibility to customize width and alignment of fields,
and add new custom ones.
- Added new table into user database to support the custom fields. This
requires a database upgrade.
- Add admin panel for message parsers. This includes further information
on the parsers as well as the option to import necessary custom fields
for the message parsers.
- Overall simplified code related to field definitions and types.
---------------------------------------------------------------------------
Version 2.5.13 (beta), 2008-10-07
- Improved documentation, added general and search description.
- The conversion script does convert the charts now as well.
- Added global warning which will be displayed on all pages if a
database update is pending
- Added button below searchfield which becomes visible when
you run searches which links to the asktheoracle site.
- Fixed a race condition in the installer which could cause phpLogCon
to fail at Step 8.
- Added parser for apache2 common format. So we support apache combine
and common now.
---------------------------------------------------------------------------
Version 2.5.12 (beta), 2008-09-29
- Fixed several SQL issues in the logstream classes when filtering
was used.
- Enhanced all content menus in the main site, reduced coding as well.
- Added support for URL detection within the data of string fields, these
links can be opened in new windows.
- Fixed bug when excluding more then one string filter from the
same field type.
- Fixed wrong database version insert in install.php as well as
incorrect redirect login page during install.
---------------------------------------------------------------------------
Version 2.5.11 (beta), 2008-09-25
- Fixed the "next page" button when a logstream disk source was used.
The "next page" button stopped working as a side effect of some
performance changes made in the last version.
- Added new description field for logstream sources. If the description
field is used, the description is shown below the pager on the
main index site. The database version has also been incremented, this
only affects you if you are using the user system.
---------------------------------------------------------------------------
Version 2.5.10 (beta), 2008-09-24
- Merged devel branch into beta branch.
- Enhanced search performance in disk logstream, specially when searching
in large files.
- Enhanced critical error display, and added better error details if the
user db server is not reachable
---------------------------------------------------------------------------
Version 2.4.0 (v2-stable), 2008-09-24
- Merged beta branch into v2-stable branch.
---------------------------------------------------------------------------
Version 2.5.9 (devel), 2008-09-19
- Implemented support to analyze Webserver logfiles from Apache and
Microsoft IIS Webserver. There is a collection of new fields available,
filtering is possible. . In order to read Apache or IIS logfiles,
you need to use the "iis" or "apache2" message parser in your disk
sources.
- Added a new page called "asktheoracle.php" which will be automatically
linked on IP's and domain names. It is a simple helper page which
creates a bunch of usefull filter links.
- Added some basic documentation into the doc folder. phpLogCon
does also link to this documentation now (Help Menu Entry).
- Added a general option to limit the display of string fields.
- Added a general option to configure the timeout value of popup menus.
- Added a general option to alter the php scrip timeout. This is of course
only possible if the php interpreter is allowed to change the script
timeout.
- Added checks for the script timeout in the disk logstream, this avoids
that the script is suddenly stopped by the php interpreter.
- Fixed a sorting bug in the disk logstream, which removed numeric
values in the charts
- Added support to filter for a + character as well now. In order to filter
for strings containing the + character, just add replace it with ++.
A single + will still be equal to a space character in the filter engine.
---------------------------------------------------------------------------
Version 2.5.8 (devel), 2008-09-16
- Added Bitstream Vera Fonts into the package which will be used by the
chart generator. So there won't be a problem of missing truetype fonts
anymore.
- Tweaked the visual appereance of all chart types.
---------------------------------------------------------------------------
Version 2.5.7 (devel), 2008-09-15
- Added Statistics page for chart generation. The following charts are
possible right now: Pie, bars vertical and bars horicontal.
All charts can be configured within the Admin Center, if the user system
is installed and enabled. Custom charts can be added as well.
- Added filter / search support for processid, event category and the
event user field
- Added database update, as we now have a new table to store
configured charts into.
- Fixed a few minor filtering issues, specially with numeric filters.
---------------------------------------------------------------------------
Version 2.3.11 (beta), 2008-09-08
- Fix another parsing issue in the logline parser. Most of RFC 3164
formatted syslog messages should now be correctly splitted into their
fields.
---------------------------------------------------------------------------
Version 2.5.6 (devel), 2008-09-03
- Implemented Message Parser facility. This new extendable facility of
phpLogCon helps splitting messages into fields. And the fields can
be filtered and searched for, this expands the full potential of
phpLogCon. A message parser for windows eventlog logfiles generated
by Adiscon products is included.
- Linebreaks within messages are now displayed in the popup window,
and the detail page.
- Added Database Upgrade functionalety, the reason is simple, because
there was an update to the database structure. If you are using the
User Management system, you will be prompted to upgrade your database
next time you login.
---------------------------------------------------------------------------
Version 2.5.5 (devel), 2008-08-28
- Added option to send debug messages (warnings and error's) from
phpLogCon to the local syslog server on linux. On Windows, the debug
messages will appear in the application event log.
- Enhanced the PDO Logstream Driver for better performance on large
databases. On MYSQL and POSTGRES, the PDO Logstream does not uses the
LIMIT statement to minimize database usage.
---------------------------------------------------------------------------
Version 2.3.10 (beta), 2008-08-27
- Fixed a few parsing issues with prior RFC 3164 syslog messages.
These messages are now correctly parsed, or better do not cause
any parsing problems anymore.
---------------------------------------------------------------------------
Version 2.5.4 (devel), 2008-08-05
- Included fixed from Beta v2.3.9
---------------------------------------------------------------------------
Version 2.3.9 (beta), 2008-08-07
- Fixed a bug in the parsing of RFC 3164 date and time stamps which
occured from the 1st to the 9th of each month. During this time, the
date was not correctly parsed.
- Enhanced detail popup window, it performs much better now and is less
annoying. It still can be turned off very easily.
- Fixed an image alignment problem of the message once and for all.
---------------------------------------------------------------------------
Version 2.5.3 (devel), 2008-08-05
- Added support to export the current visible events into a XML or CSV
file. If you have further recommendations for useful export file
formats, just let us know in the phpLogCon forums or mailinglist.
- Extended Filter Engine to support Full and Partial Text searches on
string fields. The submenu buttons also now use the Full Text search
by default, which performs much better on database logstream sources.
- A new menu entry on each value on each field in the main EventView
gives you the option to search for this field only, or extend an
existing filterset.
---------------------------------------------------------------------------
Version 2.5.2 (devel), 2008-08-01
- General Options are now configureable on user basis, if UserDB System
is installed of course. This means first, phpLogCon used the global
configured options, then the user configured - if available.
- When you add new Sources, the source is checked with better error details.
If you have a database connection, even the existence of the configured
table is checked. This helps locating configuration problems.
- Fixed minor bug in the installer which was added in v2.5.0.
- Fixed spelling errors in the admin index template.
- Error messages in the admin center contain more useful details now.
---------------------------------------------------------------------------
Version 2.5.1 (devel), 2008-07-29
- Added a new option to suppress displaying multiple messages. This
means if you have two or more messages of the exact same text one after
another, only ONE message will be shown. This helps to "compress" the
logview a little bit.
- New feature, added Maximize/Normalize button into the menu. You can
hide the header now by using this feature for maximum log display.
- If the UserDB System is enabled, the donate button will only being
shown within the Admin Center.
- Fixed a bug in the input checking of files when a Diskfile source
was added or reconfigured.
- Fixed minor bug reading the correct default view for sources from DB.
- Fixed a problem in the Views Admin, a set of predefined columns could be
in the list.
- Enhanced error display in all admin templates.
---------------------------------------------------------------------------
Version 2.3.8 (beta), 2008-07-28
- Fixed a "notice" bug in the installer, which was missing to save the
DBType for MYSQL Datasource.
- Fixed a bug in the pdo logstream class which caused display of empty
rows when no records where found.
- Fixed Bug ID82 from bugtracker. Internal and invalid IP Addresses are
not linked to whois anymore.
- Fixed Line Ending to Unix in some code files.
---------------------------------------------------------------------------
Version 2.5.0 (devel), 2008-07-24
- Fully implemented the UserDB System. This is the next major milestone
in the development of phpLogCon. The new UserDB System allows you to
fully customize phpLogCon using an admin interface and offers the
following sub-features: Users, Groups, Sources, Views, Searches and
general options. Exiting configurations can be imported into the
user system using the convert.php script. The installer has an option
to install the user system.
- Added Icons to all Topmenu entries, as well as into the Admin
Topmenu entries.
- Improved stylesheets
---------------------------------------------------------------------------
Version 2.3.7 (beta), 2008-07-07
- Added missing db mapping for program field of syslogng - thanks to
Micha "Wolvverine" Panasiewicz
- Added translation for Brazilian Portuguese, thanks to Ricardo Maraschini
---------------------------------------------------------------------------
Version 2.5.0 (devel), 2008-06-10
- Moved older devel branch to beta branch. Increment Version minor number.
---------------------------------------------------------------------------
Version 2.2.0 (v2-stable), 2008-06-10
- Moved beta branch to v2-stable branch.
---------------------------------------------------------------------------
Version 2.3.6 (devel), 2008-06-09
- Added new feature, multiple configureable views which can be configured
and selected for each source seperately. Old configurations can still
be used with the new Views feature. The installer also supports
selecting the default View for the first added source.
---------------------------------------------------------------------------
Version 2.3.5 (devel), 2008-06-06
- Enhanced the detected of IP Addresses and domain names, so the automatic
generated context links match better now.
- Added new option (enabled by default) to resolve IP Addresses into
hostnames. Note that this will only be done if the IP Address is NOT in
square brackets. The resolved names will be cached in the users session,
to speed up the resolving process. The resolved IP Addresses will be
injected behind the IP Address in curly brackets, and a diffirent colour.
---------------------------------------------------------------------------
Version 2.3.4 (devel), 2008-06-02
- Added new feature to automatically link IP and domain names with our
whois search engine. So you can research these informations with one
click.
- Changed Online Search Parameters. For Eventlog related search links,
you will now directly directed to entries in our knowledge base, if
found.
---------------------------------------------------------------------------
Version 2.3.3 (devel), 2008-05-23
- Initial Added the new DB Driver (Logstream) which uses PHP PDO.
PDO is the latest generic database interface for PHP5 and recommended
for best performance. It is possible to use other database engines with
this new logstream class like mssql, postgres sql, odbc, oracle
or even ibm db2.
- Optimized the logic of the pager and increased performance
related to it.
- Added support for the new Database driver into the installation script.
The old driver has been renamed to MYSQL Native and is also
recommended if you use MYSQL as database server.
---------------------------------------------------------------------------
Version 2.3.2 (devel), 2008-05-20
- Implemented Online Search button into the field submenus. The search
uses our new repository at kb.monitorware.com.
- Added pager to the bottom of the index page as well (bugtracker id 76)
- Added filtering support for the new Eventlog fields
- Adding field mapping definitions for Windows Eventlog which are:
SYSLOG_EVENT_LOGTYPE, SYSLOG_EVENT_SOURCE, SYSLOG_EVENT_CATEGORY,
SYSLOG_EVENT_ID and SYSLOG_EVENT_USER
- Simplified columns configuration definition in config.sample.php
- Fixed minor css issues.
---------------------------------------------------------------------------
Version 2.1.6 (beta), 2008-05-19
- Fixed filter bug, if you want to filter with ":", you can do this by
using "\:" now.
- Added donate button ;)
- Changed install.php handling, so it is not necessary to remove the
script after installation anymore. It is only possible to use
install.php if the config.php is empty or does not exist.
- Added check for installed PHP Version. phpLogCon will refuse to run
on PHP4 or lower from now on!
---------------------------------------------------------------------------
Version 2.3.1 (devel), 2008-05-02
- The page title is now created with Source, and other useful informations.
It is also possible to configure a custom title string with the
configuration, which will be prepended into each phpLogcon page.
- Added support for gzip compression (configurable), this will reduce
bandwidth and page load time.
- Added Auto reload function into main list view, can be enabled by default
in the configuration as well. Done using a META REFRESH.
- Added new configuration variable to set the default SourceID. The source
parameter will be appened to all necessary links and forms within
phplogcon, if the session sources differs from the default one.
Version 2.1.5 (beta), 2008-05-05
- Converted all files into UNIX format (^M has been removed)
---------------------------------------------------------------------------
Version 2.3.0 (devel), 2008-04-30
- Added "Back to Listview" button in the detailview.
- Added filter for message type
- Added inline button menus into the listview. Most values can be clicked
now, which opens a menu with additional useful links.
- Added Pagesite Selection into listview, so you can change the amount of
records you want to see on one page at any time you want.
- greatly improved database performance, runs much better now, but there
is still room for further optimization
---------------------------------------------------------------------------
Version 2.1.4 (beta), 2008-04-29
- Added missing facility 10 to 15 from RFC3164 into phhlogcon
---------------------------------------------------------------------------
Version 2.1.3 (beta), 2008-04-28
- Fixed a bug in the installer, the table type was not written into the
configuration.
Version 2.1.2 (beta), 2008-04-28
---------------------------------------------------------------------------
- Removed syslog sample logfile from samplelogs, fixed minor issue in the
installer
- Fixed bug in logstreamlineparsersyslog.class which failed to parse
some rsyslog loglines.
- Special characters like german "umlaute" are now proberly replaced
- Added link to help page, pointing to rsyslog wiki
- Changed database layout from winsyslog to monitorware.
Added more debug handling
---------------------------------------------------------------------------
Version 2.1.1 (beta), 2008-04-25
- added detail page into phpLogCon. The detail page shows all possible
details of a syslog message. It also possible to page in the
detail view.
- fixed minor notices bugs in the functions_db.php, which is really used
right now. But it will become important once the user-ui will be added.
- fixed "NEXT" button bug in the install script. Infact only ONE next
button is available now in the install script. This removes the
duplicated ones from before.
- added full german translation (thanks to Tom Bergfeld for providing it)
---------------------------------------------------------------------------
Version 2.1.0 (beta), 2008-04-24
- initial release of the rewritten phpLogCon v2
loganalyzer-3.6.6/INSTALL 0000644 0001750 0001750 00000020401 12401304543 014351 0 ustar daniel daniel
LogAnalyzer Installation help
----------------------------------
To install LogAnalyzer, you will need:
* Apache or IIS Webserver
* PHP5
Optionally, you may need:
* MySQL Database
For obvious reasons, you also need some syslog data. Any standard
syslogd will do. From a feature and stability point of view, we
recommend either one of these (which we also wrote ;)):
- WinSyslog (for Windows Environments - http://www.winsyslog.com)
- rsyslog (for Linux/Unix Environments - http://www.rsyslog.com)
Both of them are also capable to writing to a database. Rsyslog is
a drop-in replacement for stock syslogd and also *is* the stock
syslogd on some platforms (e.g. Fedora 8 and above).
Installation in Detail
----------------------
1. Upload all files from the loganalyzer/src/ folder to you webserver.
The other files are not needed on the webserver.
2. If your webserver has write access to the LogAnalyzer folder,
you can skip the following step:
Upload the scripts configure.sh and secure.sh from the
contrib folder to your webserver, into the same folder
where you uploaded the other LogAnalyzer files into. Then set
the execution flag to them (chmod +x configure.sh secure.sh).
Now run ./configure.sh, this will create a blank config.php,
and will also set write access to everyone to it.
You can of course do this manually if you want.
3. Now open your LogAnalyzer installation in your favourite webbrowser,
you will see an error, and you will be pointed to the installation
script. The install script will guide you through the LogAnalyzer
installation, just follow the instructions.
3.1 Step 1 - Prerequisites Beginning of installation / welcome site
This is the first page of the installation. It just tells
you, that before installing, some file permission have to
be checked. Simply click "Next" to start the process.
3.2 Step 2 - Verify the file permissions
Here you will see, if the config.php can be written or not.
If it cannot be written, you have to repeat the complete
Step 2.
3.3 Step 3 - Basic Configuration
You can set several basic options here.
- Number of syslog messages per page = 50 (default)
This is the number of syslog messages displayed on each page.
You can increase the value (makes LogAnalyzer slower) or decrease
the value (makes it faster).
- Message character limit for the main view = 80 (default)
Set the number of characters per message which will be shown
in the last column of the main view. Full messages can be
reviewed by hovering the mouse over it.
- Show message details popup (default yes) = yes (default)
Here you can set, if you want the small window with the complete
message to pop up if you are hovering over a event with the
cursor. If you choose "No", then you have to click on the
message to see the details.
3.4 Step 4 - not implemented yet
3.5 Step 5 - not implemented yet
3.6 Step 6 - not implemented yet
3.7 Step 7 - Create the first source for syslog messages
This is the most important step. Here, you will configure
your first data source, which holds all your syslog data.
Mainly, you have to choose a "Name of the Source" and a
"Source Type". The name will be displayed later in a drop-down
menu with which you choose your active syslog source. The
"Source Type" can be a file, a MySQL database or the PHP PDO
which supports different database types like mssql, PostgreSQL,
odbc, oracle or even ibm db2.
If you choose the diskfile, you have to provide the following
information:
- Logline Type = Syslog / Rsyslog (default) or Adiscon WinSyslog
This tells LogAnalyzer, how the lines look like. This is
necessary for show the log messages properly.
- Syslog File = /var/log/syslog (default)
This is the position of the logfile in your file system.
If you choose MySQL native as data source, following information
is needed:
- Table Type = monitorware (default)
This is the table layout. Currently, you can use "monitorware"
or "syslogng". For more details see "Note on MySQL Databases"
below.
- Database Host = localhost (default)
This is the host, where the database is located. By default this
is localhost. You can specify any other host if necessary.
- Database Name = loganalyzer (default)
The name of the database you want to use.
- Database Tablename = systemevents (default)
This is the name of the table in which the data is stored. The
default tablename corresponds to the tables created with the
MonitorWare Line of products.
- Database User = user (default)
The username for the database.
- Database Password = not set by default
The password for the username.
- Enable Row Counting = No (default)
If configured to "Yes", the amount of rows in the table will be
counted with every query, giving you the total records for your
search, though having a lot of impact on your system when using
a very large database. If configured to "No", the rows will not
be counted, providing you a lot more performance.
If you choose Database (PDO), the following has to be defined:
- Database Storage Engine = MySQL Server (default)
Choose the engine of the database you are using. The databases
are available: MySQL Server, Microsoft SQL Server, ODBC
Database Connection, PostgreSQL, Oracle Call Interface, IBM
DB2, Firebird/Interbase 6, IBM Informix Dynamic Server,
SQLite 2.
- Table Type = monitorware (default)
This is the table layout. Currently, you can use "monitorware"
or "syslogng". For more details see "Note on MySQL Databases"
below.
- Database Host = localhost (default)
This is the host, where the database is located. By default this
is localhost. You can specify any other host if necessary.
- Database Name = loganalyzer (default)
The name of the database you want to use.
- Database Tablename = systemevents (default)
This is the name of the table in which the data is stored. The
default tablename corresponds to the tables created with the
MonitorWare Line of products.
- Database User = user (default)
The username for the database.
- Database Password = not set by default
The password for the username.
- Enable Row Counting = No (default)
If configured to "Yes", the amount of rows in the table will be
counted with every query, giving you the total records for your
search, though having a lot of impact on your system when using
a very large database. If configured to "No", the rows will not
be counted, providing you a lot more performance.
3.8 Step 8 - Finish
4. If everything went right, you should see syslog messages already
in your LogAnalyzer installation. You can now remove the install.php
script now.
Note on Accesing Files
--------------------------------
In most environments the webserver has only access to the web directory.
If you want to read files e.g. from /var/log/ you have to grant
the necessary permisson to your webserver.
Of course, you always need to make sure that the user the web server
runs under also has the correct file permissions. Be careful when doing
this, you may create a security vulnerability by granting too much
to too many users.
Note on MySQL Databases
--------------------------------
LogAnalyzer does support using a MySQL database as syslog source.
LogAnalyzer supports Adiscon's MonitorWare database schema. The schema
used by php-syslog-ng is also partly supported. That schema, however, is
somewhat inefficient in that it stores facility and severity codes as
textual values. We do not currently convert these values back to their
native format and consequently facility and severity can not be taken
from a php-syslog-ng database.
loganalyzer-3.6.6/doc/ 0000755 0001750 0001750 00000000000 12401305611 014065 5 ustar daniel daniel loganalyzer-3.6.6/doc/free_support.html 0000644 0001750 0001750 00000006730 12401304543 017501 0 ustar daniel daniel
Free Support for LogAnalyzer
Free Services for LogAnalyzer
A personal word from the authors of LogAnalyzer:
The LogAnalyzer community provides ample free support resources. Please see our
troubleshooting guide to get started.
Every now and then we receive private mail with support questions. We appreciate
all feedback, but we must limit my resources so that we can help drive a great project
forward.
To do so, we have decided not to reply to unsolicited support emails, at least not
with a solution (but rather a link to this page ;)). We hope this does not offend you. The
reason is quite simple: If we do personal support, you gain some advantage without
contributing something back. Think about it: if you ask your question on the public
forum or mailing list, others with the same problem can see it and, most importantly, even
years later find your post (and the answer) and get the problem solved. So by
solving your issue in public, you help create a great community ressource and also
help your fellow users finding solutions quicker. In the long term, this
also contributes to improved code because the more questions users can find
solutions to themselves, the fewer we need to look at.
But it comes even better: the LogAnalyzer community is much broader than the authors ;) - there
are helpful other members hanging around at the public places. They often answer
questions, so that we do not need to look at them (btw, once again a big "thank you", folks!).
And, more important, those folks have different background than us. So they often
either know better how to solve your problem (e.g. because it is distro-specific)
or they know how to better phrase it.
So you do yourself a favor if you use the public places.
An excellent place to go to is the
LogAnalyzer forum inside the
knowledge base (which in itself is a great place to visit!). For those used to
mailing lists, the
LogAnalyzer mailing list
also offers excellent advise.
Don't like to post your question in a public place? Well, then you should
consider purchasing LogAnalyzer professional support.
The fees are very low and help fund the project. If you use LogAnalyzer seriously inside
a corporate environment, there is no excuse for not getting one of the support
packages ;)
Of course, things are different when we ask you to mail us privately. We'll usually do
that when we think it makes sense, for example when we exchange debug logs.
I hope you now understand the free support options and the reasoning for them.
I hope we haven't offended you with our words - this is not our intension. We just needed to
make clear why there are some limits on our responsiveness. Happy analyzing!
loganalyzer-3.6.6/doc/manual.html 0000644 0001750 0001750 00000010253 12401304543 016234 0 ustar daniel daniel
LogAnalyzer documentation
LogAnalyzer - Documentation
The LogAnalyzer
project provides an easy to use but powerful front end for
searching, reviewing and analyzing network event data, including
syslog, windows event log and many other event sources.
It focusses on the user-interface side of this project, so the
data itself needs to be gathered by another program,
for example the stock syslogd,
rsyslog (often the distro's default syslogd),
WinSyslog or
MonitorWare Agent.
LogAnalyzer works equally well on Linux and
Windows. It is a free, GPLed open source application written mostly in php.
Data can be obtained from databases but also from plain text files, for
example those that are written by the syslogd.
Don't forget about the
LogAnalyzer
mailing list. If you are interested in the "backstage" behind the overall idea that
LogAnalyzer contributes to, you may find
Rainer's
blog an interesting read.
Feedback is always welcome, but if you have a support question, please do not
mail the authors directly (why not?).
loganalyzer-3.6.6/doc/windowsevent.html 0000644 0001750 0001750 00000003743 12401304543 017521 0 ustar daniel daniel
Using Windows Event Logs with LogAnalyzer
Using Windows Event Logs with LogAnalyzer
LogAnalyzer provides a message parser that understand Windows Event Log entries
in Adiscon common format. With that parser, all Windows event log properties can be
easily accessed, displayed and searched for.
How to get hold of the Windows Event Log Data
LogAnalyzer does not (yet) provide a data source driver to natively pull the log entries
from the Windows event logs. So it needs to be delivered to it. This can be done with
Adiscon's EventReporter or
MonitorWare Agent software. These Agents are
excuted either on each Windows machine (or a single machine doing remote monitoring)
and the events extracted are written to LogAnalyzer's datasource (either a file or
database). Depending on your network setup, you may have some intermediate systems,
in which case the actual write to the data source is done by something like
WinSyslog or rsyslog.
Once the data is inside the data source, the event log subparser does the rest. Together
with proper view defininitions, it provides a native-like view and search capability of
that data. Please note that Windows Event Log Fields can also be used as sources for
drawing graphics.
loganalyzer-3.6.6/doc/textfiles.html 0000644 0001750 0001750 00000007307 12401304543 016774 0 ustar daniel daniel
Using text log files with LogAnalyzer
Using text log files with LogAnalyzer
LogAnalyzer natively supports operting on text log files. So there
is no need to put log data into databases. Each approach has advantages
and disadvantages, which we will not discuss in this paper. Here, we focus
on how text log files are supported.
We assume that the reader is familiar with basic
LogAnalyzer concepts. If you are not, get aquainted to them, first.
Requirements for text log files
LogAnalyzer can operate on any standard text log file, that means a file that
purely consists of printable characters and uses LF (linefeed, newline) characters
as log line terminators. Most importantly, this includes standard syslog files
as well as web server and other application logs.
A data source is defined to pull data from a text log file. Note that only a single
text log file can be contained in any data source.
Working with text log files
Text log files are just regular data sources. You can work with them like
with any other data sources, for example, you can browse them, search them,
generate graphics from the or base reports on their content. Depending on the
size of the text log and on the operation being performed, performance may be
worse or even better than with using database-based data sources. For typical
operations and typical text file sizes, performance should be quite well.
Note that some options make limited sense when working with text log files.
For example, you may set a filter with a broad date range, but the text log
file will, for obvious reasons, only provide what is currently contained in it.
For typical syslog files, that will probably mean they contain maximum one
day's data.
Use Cases for Text Log Files
A typical use case is in a hosting environment. There, LogAnalyzer may
be used to do an online review of log data, via the web and without the need
to log into an SSH session. This can be very handy to learn what is currently
going on or, for example, to verify if an important mail left your system.
Another use case is that you would like to keep an eye on some local text files,
for example while debugging an installation. Instead of reconfiguring your whole
logging system, you can set up a LogAnalyzer instance and point it to the log files
in question. Keep in mind that you are not restricted to syslog files. For example,
you may want to add additional application text log files as data sources as well.
With the cross-datasource search capability, you can quickly follow events across
the boundaries of log servers.
For secuity sensitive-environments, the access to LogAnalyzer can be protected
by several levels, e.g. user authentication or IP ranges at the firewall or
http server level. Also, one may consider to activate a LogAnalyzer instance only
when actually needed to do troubleshooting and keep it "turned off" at other times.
The beauty of text log files is that you do not need to reconfigure the whole
logging system to do so. All that is needed is to disable the web site inside
the http server.
loganalyzer-3.6.6/doc/install.html 0000644 0001750 0001750 00000023214 12401304543 016426 0 ustar daniel daniel
HOWTO install LogAnalyzer
Abstract
In this paper, I describe how to install LogAnalyzer.
It is intentionally a brief step-by-step guide, targeted to those who
want to quickly get it up and running. For more elaborate
information, please consult the rest of the manual
set.
Steps To Do
To install LogAnalyzer, you need:
Apache or IIS Webserver
PHP5
Optionally, you may need:
MySQL Database
For obvious reasons, you also
need some syslog data. Any standard syslogd will do. From a feature
and stability point of view, we recommend either one of these (which
we also wrote ;) ):
Both of them are also capable
of writing to databases. Rsyslog is a drop-in replacement for stock
syslogd and also *is* the stock syslogd on some platforms (e.g.
Fedora 8 and above).
Step 1 - Download Software
For obvious reasons, you need to download LogAnalyzer. Here, I
assume that you use a distribution tarball.
Load the most recent build from
http://loganalyzer.adiscon.comdownloads.
Extract the software with "tar xzf -nameOfDownloadSet-".
This will create a new subdirectory LogAnalyzer-version in the current
working directory. CD into that.
Step 2
Upload all files from the loganalyzer/src/ folder to you webserver.
The other files are not needed on the webserver.
Step 3
If your webserver has write access to the LogAnalyzer folder, you
can skip the following step:
Upload the scripts configure.sh and secure.sh from the contrib
folder to your webserver, into the same folder where you uploaded
the other LogAnalyzer files into. Then set the execution flag to them
(chmod +x configure.sh secure.sh).
Now run ./configure.sh, this will create a blank config.php, and
will also set write access to everyone to it.
You can of course do this manually if you want.
Step 4
Now open your LogAnalyzer installation in your favourite webbrowser,
you will see an error, and you will be pointed to the installation
script. The install script will guide you through the LogAnalyzer
installation, just follow the instructions.
Step 4.1
Prerequisites Beginning of installation / welcome site. This is
the first page of the installation. It just tells you, that before
installing, some file permission have to be checked. Simply click
"Next" to start the process.
Step 4.2
Verify the file permissions Here you will see, if the config.php
can be written or not. If it cannot be written, you have to repeat
the complete Step 2.
Step 4.3
Basic Configuration
You can set several basic options here.
Number of syslog messages per page = 50 (default)
This is the number of syslog messages displayed on each page. You
can increase the value (makes LogAnalyzer slower) or decrease the
value (makes it faster).
Message character limit for the main view = 80 (default)
Set the number of characters per message which will be shown in
the last column of the main view. Full messages can be reviewed by
hovering the mouse over it. Many folks prefer to use a setting
of "0", which means complete messages will be displayed<
Show message details popup (default yes) = yes (default). Note that many
people find the popups intrusive and prefer to disable them. Use "no" in this
case.
Step 4.4
Not implemented yet, some real magic may happen here at a later stage ;-) - for
now, just skip it.
Step 4.5
Create the first source for syslog messages. This is the most
important step. Here, you will configure your first data source,
which holds all your syslog data.
Mainly, you have to choose a "Name of the Source" and a
"Source Type". The name will be displayed later in a
drop-down menu with which you choose your active syslog source. The
"Source Type" can be a file, a MySQL database or the
PHP PDO which supports different database types like mssql,
PostgreSQL, odbc, oracle or even ibm db2.
If you choose the diskfile, you have to provide
the following information:
Logline Type = Syslog / Rsyslog (default) or Adiscon
WinSyslog
This tells LogAnalyzer, how the lines look like. This is necessary
for show the log messages properly.
Syslog File = /var/log/syslog (default)
This is the position of the logfile in your file system.
If you choose MySQL native as data source,
following information is needed:
Table Type = monitorware (default)
This is the table layout. Currently, you can use "monitorware"
or "syslogng". For more details see "Note on MySQL
Databases" below.
Database Host = localhost (default)
This is the host, where the database is located. By default this
is localhost. You can specify any other host if necessary.
Database Name = loganalyzer (default)
The name of the database you want to use.
Database Tablename = systemevents (default)
This is the name of the table in which the data is stored. The
default tablename corresponds to the tables created with the
MonitorWare Line of products.
Database User = user (default)
The username for the database.
Database Password = not set by default
The password for the username.
Enable Row Counting = No (default)
If configured to "Yes", the amount of rows in the table
will be counted with every query, giving you the total records for
your search, though having a lot of impact on your system when using
a very large database. If configured to "No", the
rows will not be counted, providing you a lot more performance.
If you choose Database (PDO), the following has
to be defined:
Database Storage Engine = MySQL Server (default)
Choose the engine of the database you are using. These databases
are supported: MySQL Server, Microsoft SQL Server, ODBC Database
Connection, PostgreSQL, Oracle Call Interface, IBM DB2,
Firebird/Interbase 6, IBM Informix Dynamic Server, SQLite 2.
Table Type = monitorware (default)
This is the table layout. Currently, you can use "monitorware"
or "syslogng". For more details see "Note on MySQL
Databases" below.
Database Host = localhost (default)
This is the host, where the database is located. By default this
is localhost. You can specify any other host if necessary.
Database Name = loganalyzer (default)
The name of the database you want to use.
Database Tablename = systemevents (default)
This is the name of the table in which the data is stored. The
default tablename corresponds to the tables created with the
MonitorWare Line of products.
Database User = user (default)
The username for the database.
Database Password = not set by default
The password for the username.
Enable Row Counting = No (default)
If configured to "Yes", the amount of rows in the table
will be counted with every query, giving you the total records for
your search, though having a lot of impact on your system when using
a very large database. If configured to "No", the rows
will not be counted, providing you a lot more performance.
Step 4.6
Finish :)
Step 5
If everything went right, you should see syslog messages already
in your LogAnalyzer installation. You can now remove the install.php
script now.
Note on Accesing Files
In most environments the webserver has only access to the web
directory. If you want to read files e.g. from /var/log/ you have to
grant the necessary permisson to your webserver.
Of course, you always need to make sure that the user the web
server runs under also has the correct file permissions. Be careful
when doing this, you may create a security vulnerability by granting
too much to too many users.
Note on MySQL Databases
LogAnalyzer does support using a MySQL database as syslog source.
LogAnalyzer supports Adiscon's MonitorWare database schema. The schema
used by php-syslog-ng is also partly supported. That schema, however,
is somewhat inefficient in that it stores facility and severity codes
as textual values. We do not currently convert these values back to
their native format and consequently facility and severity can not be
taken from a php-syslog-ng database.
loganalyzer-3.6.6/doc/searching.html 0000644 0001750 0001750 00000013630 12401304543 016724 0 ustar daniel daniel
LogAnalyzer Search Syntax
LogAnalyzer Search Syntax
This document describes how you can search in LogAnalyzer. Please note that
you can also always use the "advanced search" dialog to build the search string.
A search term is always in the format "property:search" where property is the
data item you will search (for example the syslog tag, source system).
Available properties depend on the data source in use, parsers present,
and even the actual data. What usually is available is listed below. Please note that there
is a special case. Because it is so common to search inside the message text itself,
there is no property name for this - to perform this search, simply omit the
"property:" part.
In LogAnalyzer we basically have two different types of data types which
are handled different from each other, these are: string and number. There is
also a date type filter and the message field, but these are handled separately
from the others fields. Every filter usually is delimited by spaces, and filters
from different fields are combined by AND.
String Fields
For the string type fields, you can search for partially or full string
matches. Searching for full string matches can improve performance in your
logstream. If you have spaces in your search string, you need to replace them
with a + character, the reason is simple, because the space character splits the
filters. If you want to search for a single + sign, you need to replace it with
a double +, so + becomes ++ in your search string. To separate multiple search
values for the same fieldtype, you just need to separate them commas - but
remember, no spaces!
String filters can be included in your search as well as excluded. All
included filter of a field type will be combined by OR which means if you search
for "Search1" and "Search2", you will results matching both strings. This is
different if you exclude strings from your search. Excluded filters from a field
type will be combined with AND for the simple reason, if you want to exclude
"Search1" and "Search2", you want that both are excluded, and one or the other.
Below you will see how the syntax looks like:
Search for a partially string match: property:search
Search for multiple partially string matches: property:search1,search2
Search for a full string match: property:=search1,search2
Search for multiple full string matches: property:=search
Exclude by a partially string match: property:-search
Exclude multiple full string matches: property:-=search1,-=search2
Additionally some Logstream sources support REGEX Searches when supported native. Currently the MySQL LogStream and PDO Logstream (MySQL and PostGRESQL only) support REGEX searches. To use REGEXP in searches, prepend the search phrase with the ~ character. See the samples below:
Search samples with REGEX support:
Search for REGEX string match: property:~search
Exclude string by REGEX match: property:-~search
Number Fields
Number fields work similar to string fields, except that there are partially
matches, and the search value obviously must be a number. There are a few
exceptions where you can use string representations instead of numbers, but
these will be explained later.
Below you will see how the syntax looks like:
Search for a number: property:1234
Search for multiple numbers: property:1234,5678
Exclude a number from the search: property:-1234
Exclude multiple numbers from the search: property:-1234,-5678
Date Field
There is currently only one date field possible, and so we have two different
kinds of date filters we can use on this date field. The first option is to
search for a time range where you need to use the datefrom and dateto
properties. The date/time format has to be ISO TIMESTAMP (see RFC 3339 for more)
for both properties. The other option is datelastx which will filter for the
last hour (filter value 1), last 12 hours (filter value 2), last 24 hours
(filter value 3), last 7 days (filter value 4) and last 31 days (filter value
5).
This search will filter for events starting at 2007-10-01 and ending at
2008-10-01: datefrom:2007-10-1T00:00:00 dateto:2008-10-1T23:59:59
This search will show events from the last 24 hours: datelastx:3
Message Field
The message field is a string type field and does not require the use of a
property. You can have include and exclude filters here as well. The main
difference to ordinary string filters is, that include filters are combined with
AND instead of OR.
This search will include "test1": test1
This search will include "test1" and "test2": test1 test2
This search will exclude "test1": -test1
This search will exclude "test1" and "test2": -test1 -test2
loganalyzer-3.6.6/doc/troubleshoot.html 0000644 0001750 0001750 00000004717 12401304543 017520 0 ustar daniel daniel
troubleshooting LogAnalyzer
troubleshooting LogAnalyzer
Having trouble with LogAnalyzer?
This page provides some tips on where to look for help and what to do
if you need to ask for assistance. This page is continously being expanded.
Useful troublehshooting ressources are:
The LogAnalyzer documentation - note that the online version always covers
the most recent development version. However, there is a version-specific
doc set in each tarball. If you installed LogAnalyzer from a package, there usually
is a LogAnalyzer-doc package, that often needs to be installed separately. If running the default
installation, you should simply be able to get to the correct documentation version
by clicking on the "help" button on any LogAnalyzer page.
The LogAnalyzer wiki
(part of the larger rsyslog wiki) provides user tips and experiences.
Check the bugzilla to see if your problem is a known
(and even fixed ;)) bug.
Configuration Problems
Validate your text configuration settings and, if you use the user system, also the
configuration stored in your database. Some very few configuration settings can only
be applied in the text config files.
Asking for Help
If you can't find the answer yourself, you should look at these places for
community help.
The LogAnalyzer forum. This is
the preferred method of obtaining support.
The LogAnalyzer mailing list.
This is a low-volume list which occasional gets traffic spikes.
The mailing list is probably a good place for complex questions.
loganalyzer-3.6.6/doc/basics.html 0000644 0001750 0001750 00000026005 12401304543 016225 0 ustar daniel daniel
LogAnalyzer Basics
LogAnalyzer Basics
This documentation describes some basic concepts of LogAnalyzer. It
is meant as a useful guide for understanding concepts, the application itself
as well as the rest of the documentation.
Configuring LogAnalyzer
LogAnalyzer is configured via a master configuration file. If the userDB system
(see below) is enabled, most settings can be made via the web-application itself
without any further need to change the config file.
Intial configuration can also be done during a setup wizard, which writes
an initial configuration file itself. This wizard can also enable the userDB system,
so in this case you probably never need to touch the configuration file.
Data Sources
A data source is a set of syslog (and other) data that is gathered. Data sources
can be text files or databases. Any text file is supported, as long as it contains
purely printable characters and LF is used as a line terminator. This applies to
all regular text files so in short you can use whatver is present in text format.
Obviously, these are files written by the syslogd, but this also includes any
other text file, e.g. written by an application as its log file. Note that at
this time, a file data source can contain exactly one file (and NOT multiple).
For the database, tabels in either MonitorWare format or the format used by
php-syslog-ng is supported. We support php-syslog-ng schema mainly for migration
scenarios: it is sub-optimal in that it uses text strings where integer values are sufficient.
This results in the need for more database space plus slower response time. If
you set up something new, be sure the use MonitorWare schema. If you use
rsyslog to create the database, please note
that rsyslog uses MonitorWare schema by default, too. So you probably need not to
do anything special.
Searches
With LogAnalyzer, you can search any datasource for a variety of properties.
By default, text is searched within the msg part of the message. However, quite
complex searches can be performed. It is suggested to use the "advanced search"
button to build these. Alternatively, you can also review the
"LogAnalyzer search syntax" documentation to see how
to craft complex searches manually.
Note that searches are done via http get requests. That
means you can copy and paste an url (or bookmark and email it) and that URL
will contain a complete source. This is actually a great way to send searches
to a co-worker or have some automatted process (eg via cron " wget) pull specific
data on a periodic schedule.
The search part of LogAnalyzer is used much like any major search engine
and hopefully is quite intuitive.
Note that a search is currently limited to a single data source only. If you
would like to search across different data sources, you need to do this on the basis
of individual data sources. To support you at least a bit in the process, there
is a special page (for historical reasons called "the Oracle") which generates canned
searches for you, so that you only need to click the individual search links to perform
these searches. We know this is not perfect, but we hope this is useful.
Context Links and Menues
At appropriate places, LogAnalyzer generates context links to potentially helpful
information. For example, links to domain or IP range owner lookup or troubleshooting
information (via the external knowledge base)
are generated. At other places, links to the cross-datasource search capability are
generated.
Consider this example to understand why it is done and how it may be useful. Let's
assume you have two data sources, one with your firewall log and one with the mail log.
Now you wonder why a recent spam attack could happen. You review the mail log and find
indication of the spammer. Now, you can lookup the IP addresses and domain names used.
Probably more interesting, you can invoke the cross-datasource search tool and obtain
information on what the firewall log has recorded about the IPs in question. Finally,
you may want to check the online knowledge based if there is some information
recorded about this or a similar event (for example, if you found a message that
puzzels you). You may even ask you peers for help via the knowledge base.
In addition to the links, there are helpful popup menues for most of the
properties being displayed. To find out what you can do, please simply click the values
(even those that do NOT look like a link) and see what the popup has to offer (and, yes,
we will improve doc on these topics... ;)).
Windows Event Log Data
LogAnalyzer contains automatic support for displaying Windows Event Log data
in a useful format if that data is generated by either the
EventReporter
or the
MonitorWare Agent
forwarding agents. This includes proper detection, and ability to filter, on
event-log specific properties (like Windows event id and such).
The UserDB System
The so-called userDB system allows different user accounts to be created and
user-specific settings to be made. This is a great aid if multiple people share
a single instance of LogAnalyzer.
The userDB system is disabled by default. This is because
a database is needed for the userDB system as user profiles are stored
inside it. Setting up the database tables requires some additonal work,
so we do not expect users to do this by default. Please do not confuse this with
database (log) data sources: these are not necessarily needed. You can use
the userDB system and still store the log data in text files (which may be
desirable from a performance point of view). To enable the userDB system,
the LogAnalyzer configuration file needs to be changed. Note that once the
userDB system is active, most system settings can be made via the web application.
There are basically two types of users: admins and non-admins. Admins can
change anything, non-admins can only change their personal preferences.
The userDB system is not yet a strong security tool, but helps greatly with
moderate security needs. User groups can be created and data sources be assigned
to a specific user group. So only users of this group can access the data
source in question. This is useful if you have a group of people caring about
the firewall logs and another group caring about the mail logs. You can then define
two different groups and assign the data source accordingly. Then, assign the
user's the group they should belong to. The end result is that every user only
sees what he or she is expected to see.
Do I need a Database?
Not necessarily. LogAnalyzer only needs databases if you plan to use
the userDB system or use database data sources. Without that, no database is
needed. A typical scenario, for example, is private review of server-based
syslog files. For this use case, no database is required.
Securing LogAnalyzer
Log data is very valuable to an attacker. So it is highly suggested that you
secure access to any LogAnalyzer instance, especially if it contains live log
data. We suggest to place it on local, non-internet accessible servers, only.
In a hosting environment, it may be useful to place it on an internet-accessible
server. In this case, access should be protected on the http layer at least.
In any case, the use of https is suggested to prevent accidental loss
of confidentiality (this is important in the local network, too!).
The userDB system can be used as a tool to tune user's ability to
view data sources (users can only view those sources that belong to
one of their groups). However, this is currently considered a secondary access
control mechanism. An Internet-accessible instance of LogAnalyzer should
NOT rely on that as the sole source of protection.
Please note that this section gives just a few rough, common-sense
recommendations. Evaluate the risk yourself, check with your policies and
do not blame us if you made a mistake ;) In short: use LogAnalyzer at your
sole risk, and reduce this risk by thinking about what you do.
You may consider to purchase
professional services
if you are serious about the risk implications in an (enterprise) environment.
External Tool Integration
As already described, LogAnalyzer accesses external tools, most importantly the
MonitorWare Knowledge Base to aid you
in your analysis effort. The goal is to provide useful information that helps
you get the job done better and quicker.
No private data (except the obious one, eg a domain name for a domain search)
is provided to the external entity nor is anything recorded (except for what
can be seen from regular web logs). However, you need to decide yourself, as with
all external accesses, if this functionality fits into your security policy.
Please note that the external tool is able to call back into your local
LogAnalyzer installation if you provide it with the local URL. This can be done via
the user profile in the external part. Note that both the local as well as
the external part are programmed in such a way that no private data (except
for the URL) needs to be kept externally and, most important, local data
is never visible to a third-party observer. The notable exception is if you
host your local LogAnalyzer on an external server without any further security
measure (e.g. https, access restrictions). Even in that case the external
part will not be able to access data from the local part, but an attacker
may find it easy to get hold of your log data (which is always the case
with such a local setup and not specifically related to the local/external integration).
Upgrades
LogAnalyzer is actively being developed. So chances are good you want to
upgrade to a later release at some time. In general, it is always a good idea
to backup everything before you upgrade. We highly recommend doing so. Other than that,
the upgrade should be fairly easy without the installed userDB system. If the
userDB system is installed, it may be necessary to upgrade the database schema. This
can be done via the admin center. No access to LogAnalyzer is possible unless the
database schema has been upgraded.
Again, as a general precaution, you should have a solid backup available
before you run the upgrade procedure (and this specifically applies to any
database content!).
loganalyzer-3.6.6/doc/build_from_repo.html 0000644 0001750 0001750 00000004560 12401304543 020132 0 ustar daniel daniel
Installing LogAnalyzer from the source repository
Installing LogAnalyzer from the source repository
In most cases, people install LogAnalyzer either via a package or use an "official"
distribution tarball to generate it. But there may be situations where it is desirable
to install directly from the source repository. This is useful for people who would like to
participate in development or who would like to use the latest, not-yet-released code.
The later may especially be the case if you are asked to try out an experimental version.
Installing from the repsitory is not much different than building from the source
tarball, except that you need to know how to obtain things.
Obtaining the Source
You need to download the sources. LogAnalyzer is currently kept in a git
repository. You can clone this repository either via http or git protocol (with the later
being much faster. URLS are:
git://git.adiscon.com/git/phplogcon.git
http://git.adiscon.com/git/phplogcon.git
There is also a browsable version (gitweb) available at
http://git.adiscon.com/?p=phplogcon.git;a=summary.
This version also offers snapshots of each commit for easy download. You can use these if
you do not have git present on your system.
After you have cloned the repository, you are in the master branch by default. This
is where we keep the devel branch. If you need any other branch, you need to do
a "git checkout --track -b branch origin/branch". For example, the command to check out
the beta branch is "git checkout --track -b beta origin/beta".
Actual Install Process
The actual installation does not differ from a version obtained via
a tarball. Please see the
LogAnalyzer install guide for details on how to do that.
loganalyzer-3.6.6/COPYING 0000644 0001750 0001750 00000105251 12401304543 014362 0 ustar daniel daniel This work is released to the free software world via the GNU GPLv3, which can
be found below. However, Adiscon GmbH also offers commercial licenses for
those in the need. For questions, please contact info@adiscon.com or visit
http://loganalyzer.adiscon.com/commercial
-------------------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
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 3 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.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
.
loganalyzer-3.6.6/contrib/ 0000755 0001750 0001750 00000000000 12401304543 014763 5 ustar daniel daniel loganalyzer-3.6.6/contrib/configure.sh 0000644 0001750 0001750 00000000061 12401304543 017275 0 ustar daniel daniel #!/bin/sh
touch config.php
chmod 666 config.php
loganalyzer-3.6.6/contrib/secure.sh 0000644 0001750 0001750 00000000037 12401304543 016605 0 ustar daniel daniel #!/bin/sh
chmod 644 config.php
loganalyzer-3.6.6/src/ 0000755 0001750 0001750 00000000000 12401305611 014107 5 ustar daniel daniel loganalyzer-3.6.6/src/install.php 0000644 0001750 0001750 00000121162 12401304543 016274 0 ustar daniel daniel Installer File
*
* All directives are explained within this file
*
* Copyright (C) 2008-2010 Adiscon GmbH.
*
* This file is part of LogAnalyzer.
*
* LogAnalyzer 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 3 of the License, or
* (at your option) any later version.
*
* LogAnalyzer 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.
*
* You should have received a copy of the GNU General Public License
* along with LogAnalyzer. If not, see .
*
* A copy of the GPL can be found in the file "COPYING" in this
* distribution
*
* Adiscon LogAnalyzer is also available under a commercial license.
* For details, contact info@adiscon.com or visit
* http://loganalyzer.adiscon.com/commercial
*********************************************************************
*/
// *** Default includes and procedures *** //
define('IN_PHPLOGCON', true);
define('IN_PHPLOGCON_INSTALL', true); // Extra for INSTALL Script!
define('STEPSCRIPTNAME', "install.php"); // Helper variable for the STEP helper functions
$gl_root_path = './';
// Now include necessary include files!
include($gl_root_path . 'include/functions_common.php');
include($gl_root_path . 'include/functions_frontendhelpers.php');
include($gl_root_path . 'include/functions_installhelpers.php');
// Init Langauge first!
IncludeLanguageFile( $gl_root_path . '/lang/' . $LANG . '/main.php' );
InitBasicPhpLogCon();
if ( InitPhpLogConConfigFile(false) )
DieWithErrorMsg( $content['LN_INSTALL_ERRORINSTALLED'] );
// Set some static values
define('MAX_STEPS', 8);
$content['web_theme'] = "default";
$content['user_theme'] = "default";
$configsamplefile = $content['BASEPATH'] . "include/config.sample.php";
$content['HeaderDefaultEncoding'] = ENC_ISO_8859_1; // Set Default encoding!
//ini_set('error_reporting', E_ALL); // DEBUG ENABLE
// *** *** //
// --- CONTENT Vars
$content['TITLE'] = "LogAnalyzer :: " . $content['LN_INSTALL_TITLE'];
// ---
// --- Read Vars
if ( isset($_GET['step']) )
{
$content['INSTALL_STEP'] = intval(DB_RemoveBadChars($_GET['step']));
if ( $content['INSTALL_STEP'] > MAX_STEPS )
$content['INSTALL_STEP'] = 1;
}
else
$content['INSTALL_STEP'] = 1;
// Set Next Step
$content['INSTALL_NEXT_STEP'] = $content['INSTALL_STEP'];
if ( MAX_STEPS > $content['INSTALL_STEP'] )
{
$content['NEXT_ENABLED'] = "true";
$content['FINISH_ENABLED'] = "false";
$content['INSTALL_NEXT_STEP']++;
}
else
{
$content['NEXT_ENABLED'] = "false";
$content['FINISH_ENABLED'] = "true";
}
// ---
// --- BEGIN Custom Code
// --- Set Bar Image
$content['BarImagePlus'] = $gl_root_path . "images/bars/bar-middle/green_middle_17.png";
$content['BarImageLeft'] = $gl_root_path . "images/bars/bar-middle/green_left_17.png";
$content['BarImageRight'] = $gl_root_path . "images/bars/bar-middle/green_right_17.png";
$content['WidthPlus'] = intval( $content['INSTALL_STEP'] * (100 / MAX_STEPS) ) - 8;
$content['WidthPlusText'] = "Installer Step " . $content['INSTALL_STEP'];
// ---
// --- Set Title
$content['TITLE'] = GetAndReplaceLangStr( $content['TITLE'], $content['INSTALL_STEP'] );
$content['INSTALL_TITLETOP'] = GetAndReplaceLangStr( $content['LN_INSTALL_TITLETOP'], $content['BUILDNUMBER'], $content['INSTALL_STEP'] );
// ---
// --- Start Setup Processing
if ( $content['INSTALL_STEP'] == 2 )
{
// Check if file permissions are correctly
$content['fileperm'][0]['FILE_NAME'] = $content['BASEPATH'] . "config.php";
$content['fileperm'][0]['FILE_TYPE'] = "file";
// $content['fileperm'][1]['FILE_NAME'] = $content['BASEPATH'] . "gamelogs/";
// $content['fileperm'][1]['FILE_TYPE'] = "dir";
// Check file by file
$bSuccess = true;
for($i = 0; $i < count($content['fileperm']); $i++)
{
// --- Set CSS Class
if ( $i % 2 == 0 )
$content['fileperm'][$i]['cssclass'] = "line1";
else
$content['fileperm'][$i]['cssclass'] = "line2";
// ---
if ( $content['fileperm'][$i]['FILE_TYPE'] == "dir" )
{
// Get Permission mask
$perms = fileperms( $content['fileperm'][$i]['FILE_NAME'] );
// World
$iswriteable = (($perms & 0x0004) ? true : false) && (($perms & 0x0002) ? true : false);
if ( $iswriteable )
{
$content['fileperm'][$i]['BGCOLOR'] = "#007700";
$content['fileperm'][$i]['ISSUCCESS'] = "Writeable";
}
else
{
$content['fileperm'][$i]['BGCOLOR'] = "#770000";
$content['fileperm'][$i]['ISSUCCESS'] = "NOT Writeable";
$bSuccess = false;
}
}
else
{
if ( !is_file($content['fileperm'][$i]['FILE_NAME']) )
{
// Try to create an empty file
@touch($content['fileperm'][$i]['FILE_NAME']);
}
if ( is_file($content['fileperm'][$i]['FILE_NAME']) )
{
if ( is_writable($content['fileperm'][$i]['FILE_NAME']) )
{
$content['fileperm'][$i]['BGCOLOR'] = "#007700";
$content['fileperm'][$i]['ISSUCCESS'] = "Writeable";
}
else
{
$content['fileperm'][$i]['BGCOLOR'] = "#770000";
$content['fileperm'][$i]['ISSUCCESS'] = "NOT Writeable";
$bSuccess = false;
}
}
else
{
$content['fileperm'][$i]['BGCOLOR'] = "#770000";
$content['fileperm'][$i]['ISSUCCESS'] = "File does NOT exist!";
$bSuccess = false;
}
}
}
if ( !$bSuccess )
{
$content['NEXT_ENABLED'] = "false";
$content['RECHECK_ENABLED'] = "true";
$content['iserror'] = "true";
$content['errormsg'] = $content['LN_INSTALL_FILEORDIRNOTWRITEABLE'];
}
// Check if sample config file is available
if ( !is_file($configsamplefile) || GetFileLength($configsamplefile) <= 0 )
{
$content['NEXT_ENABLED'] = "false";
$content['RECHECK_ENABLED'] = "true";
$content['iserror'] = "true";
$content['errormsg'] = GetAndReplaceLangStr( $content['LN_INSTALL_SAMPLECONFIGMISSING'], $configsamplefile);
}
}
else if ( $content['INSTALL_STEP'] == 3 )
{
// --- Read and predefine Database options
if ( isset($_SESSION['UserDBEnabled']) ) { $content['UserDBEnabled'] = $_SESSION['UserDBEnabled']; } else { $content['UserDBEnabled'] = false; }
if ( isset($_SESSION['UserDBServer']) ) { $content['UserDBServer'] = $_SESSION['UserDBServer']; } else { $content['UserDBServer'] = "localhost"; }
if ( isset($_SESSION['UserDBPort']) ) { $content['UserDBPort'] = $_SESSION['UserDBPort']; } else { $content['UserDBPort'] = "3306"; }
if ( isset($_SESSION['UserDBName']) ) { $content['UserDBName'] = $_SESSION['UserDBName']; } else { $content['UserDBName'] = "loganalyzer"; }
if ( isset($_SESSION['UserDBPref']) ) { $content['UserDBPref'] = $_SESSION['UserDBPref']; } else { $content['UserDBPref'] = "logcon_"; }
if ( isset($_SESSION['UserDBUser']) ) { $content['UserDBUser'] = $_SESSION['UserDBUser']; } else { $content['UserDBUser'] = "user"; }
if ( isset($_SESSION['UserDBPass']) ) { $content['UserDBPass'] = $_SESSION['UserDBPass']; } else { $content['UserDBPass'] = ""; }
if ( isset($_SESSION['UserDBLoginRequired']) ) { $content['UserDBLoginRequired'] = $_SESSION['UserDBLoginRequired']; } else { $content['UserDBLoginRequired'] = false; }
// Init Auth Options
if ( isset($_SESSION['UserDBAuthMode']) ) { $content['UserDBAuthMode'] = $_SESSION['UserDBAuthMode']; } else { $content['UserDBAuthMode'] = USERDB_AUTH_INTERNAL; }
CreateAuthTypesList($content['UserDBAuthMode']);
// LDAP related properties
if ( isset($_SESSION['LDAPServer']) ) { $content['LDAPServer'] = $_SESSION['LDAPServer']; } else { $content['LDAPServer'] = "localhost"; }
if ( isset($_SESSION['LDAPPort']) ) { $content['LDAPPort'] = $_SESSION['LDAPPort']; } else { $content['LDAPPort'] = "389"; }
if ( isset($_SESSION['LDAPBaseDN']) ) { $content['LDAPBaseDN'] = $_SESSION['LDAPBaseDN']; } else { $content['LDAPBaseDN'] = "CN=Users,DC=domain,DC=local"; }
if ( isset($_SESSION['LDAPSearchFilter']) ) { $content['LDAPSearchFilter'] = $_SESSION['LDAPSearchFilter']; } else { $content['LDAPSearchFilter'] = "(objectClass=user)"; }
if ( isset($_SESSION['LDAPUidAttribute']) ) { $content['LDAPUidAttribute'] = $_SESSION['LDAPUidAttribute']; } else { $content['LDAPUidAttribute'] = "sAMAccountName"; }
if ( isset($_SESSION['LDAPBindDN']) ) { $content['LDAPBindDN'] = $_SESSION['LDAPBindDN']; } else { $content['LDAPBindDN'] = "CN=Searchuser,CN=Users,DC=domain,DC=local"; }
if ( isset($_SESSION['LDAPBindPassword']) ) { $content['LDAPBindPassword'] = $_SESSION['LDAPBindPassword']; } else { $content['LDAPBindPassword'] = "Password"; }
if ( isset($_SESSION['LDAPDefaultAdminUser']) ) { $content['LDAPDefaultAdminUser'] = $_SESSION['LDAPDefaultAdminUser']; } else { $content['LDAPDefaultAdminUser'] = "Administrator"; }
// Set template variables
if ( $content['UserDBEnabled'] == 1 )
{
$content['UserDBEnabled_true'] = "checked";
$content['UserDBEnabled_false'] = "";
}
else
{
$content['UserDBEnabled_true'] = "";
$content['UserDBEnabled_false'] = "checked";
}
if ( $content['UserDBLoginRequired'] == 1 )
{
$content['UserDBLoginRequired_true'] = "checked";
$content['UserDBLoginRequired_false'] = "";
}
else
{
$content['UserDBLoginRequired_true'] = "";
$content['UserDBLoginRequired_false'] = "checked";
}
// ---
// --- Read and predefine Frontend options
if ( isset($_SESSION['ViewMessageCharacterLimit']) ) { $content['ViewMessageCharacterLimit'] = $_SESSION['ViewMessageCharacterLimit']; } else { $content['ViewMessageCharacterLimit'] = 80; }
if ( isset($_SESSION['ViewStringCharacterLimit']) ) { $content['ViewStringCharacterLimit'] = $_SESSION['ViewStringCharacterLimit']; } else { $content['ViewStringCharacterLimit'] = 30; }
if ( isset($_SESSION['ViewEntriesPerPage']) ) { $content['ViewEntriesPerPage'] = $_SESSION['ViewEntriesPerPage']; } else { $content['ViewEntriesPerPage'] = 50; }
if ( isset($_SESSION['ViewEnableDetailPopups']) ) { $content['ViewEnableDetailPopups'] = $_SESSION['ViewEnableDetailPopups']; } else { $content['ViewEnableDetailPopups'] = 1; }
if ( $content['ViewEnableDetailPopups'] == 1 )
{
$content['ViewEnableDetailPopups_true'] = "checked";
$content['ViewEnableDetailPopups_false'] = "";
}
else
{
$content['ViewEnableDetailPopups_true'] = "";
$content['ViewEnableDetailPopups_false'] = "checked";
}
if ( isset($_SESSION['EnableIPAddressResolve']) ) { $content['EnableIPAddressResolve'] = $_SESSION['EnableIPAddressResolve']; } else { $content['EnableIPAddressResolve'] = 1; }
if ( $content['EnableIPAddressResolve'] == 1 )
{
$content['EnableIPAddressResolve_true'] = "checked";
$content['EnableIPAddressResolve_false'] = "";
}
else
{
$content['EnableIPAddressResolve_true'] = "";
$content['EnableIPAddressResolve_false'] = "checked";
}
// ---
// Disable the bottom next button, as the Form in this step has its own button!
// $content['NEXT_ENABLED'] = "false";
// Check for Error Msg
if ( isset($_GET['errormsg']) )
{
$content['iserror'] = "true";
$content['errormsg'] = urldecode( DB_StripSlahes($_GET['errormsg']) );
}
}
else if ( $content['INSTALL_STEP'] == 4 )
{
// --- Read Database Vars
if ( isset($_POST['UserDBEnabled']) )
{
$_SESSION['UserDBEnabled'] = DB_RemoveBadChars($_POST['UserDBEnabled']);
if ( $_SESSION['UserDBEnabled'] == 1 )
{
// Read vars
if ( isset($_POST['UserDBServer']) )
$_SESSION['UserDBServer'] = DB_RemoveBadChars($_POST['UserDBServer']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_DBSERVER'] );
if ( isset($_POST['UserDBPort']) )
$_SESSION['UserDBPort'] = intval(DB_RemoveBadChars($_POST['UserDBPort']));
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_DBPORT'] );
if ( isset($_POST['UserDBName']) )
$_SESSION['UserDBName'] = DB_RemoveBadChars($_POST['UserDBName']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_DBNAME'] );
if ( isset($_POST['UserDBPref']) )
$_SESSION['UserDBPref'] = DB_RemoveBadChars($_POST['UserDBPref']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_DBPREF'] );
if ( isset($_POST['UserDBUser']) )
$_SESSION['UserDBUser'] = DB_RemoveBadChars($_POST['UserDBUser']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_DBUSER'] );
if ( isset($_POST['UserDBPass']) )
$_SESSION['UserDBPass'] = DB_RemoveBadChars($_POST['UserDBPass']);
else
$_SESSION['UserDBPass'] = "";
if ( isset($_POST['UserDBLoginRequired']) )
$_SESSION['UserDBLoginRequired'] = intval(DB_RemoveBadChars($_POST['UserDBLoginRequired']));
else
$_SESSION['UserDBLoginRequired'] = false;
if ( isset($_POST['UserDBAuthMode']) )
$_SESSION['UserDBAuthMode'] = intval(DB_RemoveBadChars($_POST['UserDBAuthMode']));
else
$_SESSION['UserDBAuthMode'] = USERDB_AUTH_INTERNAL;
// LDAP Properties
if ( $_SESSION['UserDBAuthMode'] == USERDB_AUTH_LDAP )
{
if ( isset($_POST['LDAPServer']) )
$_SESSION['LDAPServer'] = DB_RemoveBadChars($_POST['LDAPServer']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_LDAPServer'] );
if ( isset($_POST['LDAPPort']) )
$_SESSION['LDAPPort'] = intval(DB_RemoveBadChars($_POST['LDAPPort']));
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_LDAPPort'] );
if ( isset($_POST['LDAPBaseDN']) )
$_SESSION['LDAPBaseDN'] = DB_RemoveBadChars($_POST['LDAPBaseDN']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_LDAPBaseDN'] );
if ( isset($_POST['LDAPSearchFilter']) )
$_SESSION['LDAPSearchFilter'] = DB_RemoveBadChars($_POST['LDAPSearchFilter']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_LDAPSearchFilter'] );
if ( isset($_POST['LDAPUidAttribute']) )
$_SESSION['LDAPUidAttribute'] = DB_RemoveBadChars($_POST['LDAPUidAttribute']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_LDAPUidAttribute'] );
if ( isset($_POST['LDAPBindDN']) )
$_SESSION['LDAPBindDN'] = DB_RemoveBadChars($_POST['LDAPBindDN']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_LDAPBindDN'] );
if ( isset($_POST['LDAPBindPassword']) )
$_SESSION['LDAPBindPassword'] = DB_RemoveBadChars($_POST['LDAPBindPassword']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_LDAPBindPassword'] );
if ( isset($_POST['LDAPDefaultAdminUser']) )
$_SESSION['LDAPDefaultAdminUser'] = DB_RemoveBadChars($_POST['LDAPDefaultAdminUser']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_LDAPDefaultAdminUser'] );
}
// Now Check database connect
$link_id = mysql_connect( $_SESSION['UserDBServer'], $_SESSION['UserDBUser'], $_SESSION['UserDBPass']);
if (!$link_id)
RevertOneStep( $content['INSTALL_STEP']-1, GetAndReplaceLangStr( $content['LN_INSTALL_ERRORCONNECTFAILED'], $_SESSION['UserDBServer']) . " " . DB_ReturnSimpleErrorMsg() );
// Try to select the DB!
$db_selected = mysql_select_db($_SESSION['UserDBName'], $link_id);
if(!$db_selected)
RevertOneStep( $content['INSTALL_STEP']-1, GetAndReplaceLangStr( $content['LN_INSTALL_ERRORACCESSDENIED'], $_SESSION['UserDBName']) . " " . DB_ReturnSimpleErrorMsg());
}
}
// ---
// --- Read Frontend Vars
if ( isset($_POST['ViewMessageCharacterLimit']) )
{
$_SESSION['ViewMessageCharacterLimit'] = intval( DB_RemoveBadChars($_POST['ViewMessageCharacterLimit']) );
if ( $_SESSION['ViewMessageCharacterLimit'] < 0 )
$_SESSION['ViewMessageCharacterLimit'] = 80; // Fallback default!
}
else
$_SESSION['ViewMessageCharacterLimit'] = 80; // Fallback default!
if ( isset($_POST['ViewStringCharacterLimit']) )
{
$_SESSION['ViewStringCharacterLimit'] = intval( DB_RemoveBadChars($_POST['ViewStringCharacterLimit']) );
if ( $_SESSION['ViewStringCharacterLimit'] < 0 )
$_SESSION['ViewStringCharacterLimit'] = 30; // Fallback default!
}
else
$_SESSION['ViewStringCharacterLimit'] = 30; // Fallback default!
if ( isset($_POST['ViewEntriesPerPage']) )
{
$_SESSION['ViewEntriesPerPage'] = intval( DB_RemoveBadChars($_POST['ViewEntriesPerPage']) );
if ( $_SESSION['ViewEntriesPerPage'] < 0 )
$_SESSION['ViewEntriesPerPage'] = 50; // Fallback default!
}
else
$_SESSION['ViewEntriesPerPage'] = 50; // Fallback default!
if ( isset($_POST['ViewEnableDetailPopups']) )
$_SESSION['ViewEnableDetailPopups'] = intval( DB_RemoveBadChars($_POST['ViewEnableDetailPopups']) );
else
$_SESSION['ViewEnableDetailPopups'] = 1; // Fallback default!
if ( isset($_POST['EnableIPAddressResolve']) )
$_SESSION['EnableIPAddressResolve'] = intval( DB_RemoveBadChars($_POST['EnableIPAddressResolve']) );
else
$_SESSION['EnableIPAddressResolve'] = 1; // Fallback default!
// ---
// If UserDB is disabled, skip next step!
if ( $_SESSION['UserDBEnabled'] == 0 )
ForwardOneStep();
else
{
if ( $_SESSION['UserDBAuthMode'] == USERDB_AUTH_LDAP )
{
// We need the user system now!
ini_set('error_reporting', E_WARNING); // Enable Warnings!
InitUserDbSettings(); // We need some DB Settings
InitUserSystemPhpLogCon();
// LDAP Variables
$content['LDAPServer'] = $_SESSION['LDAPServer'];
$content['LDAPPort'] = $_SESSION['LDAPPort'];
$content['LDAPBindDN'] = $_SESSION['LDAPBindDN'];
$content['LDAPBindPassword'] = $_SESSION['LDAPBindPassword'];
// try LDAP Connect!
$ldapConn = DoLDAPConnect();
if ( $ldapConn )
{
$bBind = DoLDAPBind($ldapConn);
if ( !$bBind )
RevertOneStep( $content['INSTALL_STEP']-1, GetAndReplaceLangStr( $content['LN_LOGIN_LDAP_USERBINDFAILED'], $_SESSION['LDAPBindDN']) );
}
else
RevertOneStep( $content['INSTALL_STEP']-1, GetAndReplaceLangStr( $content['LN_INSTALL_LDAPCONNECTFAILED'], $_SESSION['LDAPServer']) );
}
}
}
else if ( $content['INSTALL_STEP'] == 5 )
{
$content['sql_sucess'] = 0;
$content['sql_failed'] = 0;
// Import default database if user db is enabled!
if ( $_SESSION['UserDBEnabled'] == 1 )
{
// Init $totaldbdefs
$totaldbdefs = "";
// Read the table GLOBAL definitions
ImportDataFile( $content['BASEPATH'] . "include/db_template.txt" );
// Process definitions ^^
if ( strlen($totaldbdefs) <= 0 )
{
$content['failedstatements'][ $content['sql_failed'] ]['myerrmsg'] = GetAndReplaceLangStr( $content['LN_INSTALL_ERRORINVALIDDBFILE'], $content['BASEPATH'] . "include/db_template.txt");
$content['failedstatements'][ $content['sql_failed'] ]['mystatement'] = "";
$content['sql_failed']++;
}
// Replace stats_ with the custom one ;)
$totaldbdefs = str_replace( "`logcon_", "`" . $_SESSION["UserDBPref"], $totaldbdefs );
// Now split by sql command
// $mycommands = split( ";\n", $totaldbdefs ); DEPRECEATED CALL!
$mycommands = preg_split('/;\n/', $totaldbdefs, -1, PREG_SPLIT_NO_EMPTY);
// // check for different linefeed
// if ( count($mycommands) <= 1 )
// $mycommands = split( ";\n", $totaldbdefs );
//Still only one? Abort
if ( count($mycommands) <= 1 )
{
$content['failedstatements'][ $content['sql_failed'] ]['myerrmsg'] = GetAndReplaceLangStr( $content['LN_INSTALL_ERRORINSQLCOMMANDS'], $content['BASEPATH'] . "include/db_template.txt");
$content['failedstatements'][ $content['sql_failed'] ]['mystatement'] = "";
$content['sql_failed']++;
}
// Append INSERT Statement for Config Table to set the Database Version ^^!
$mycommands[count($mycommands)] = "INSERT INTO `" . $_SESSION["UserDBPref"] . "config` (`propname`, `propvalue`, `is_global`) VALUES ('database_installedversion', '" . $content['database_internalversion'] . "', 1)";
// --- Now execute all commands
ini_set('error_reporting', E_WARNING); // Enable Warnings!
InitUserDbSettings();
// Establish DB Connection
DB_Connect();
for($i = 0; $i < count($mycommands); $i++)
{
if ( strlen(trim($mycommands[$i])) > 1 )
{
$result = DB_Query( $mycommands[$i], false );
if ($result == FALSE)
{
$content['failedstatements'][ $content['sql_failed'] ]['myerrmsg'] = DB_ReturnSimpleErrorMsg();
$content['failedstatements'][ $content['sql_failed'] ]['mystatement'] = $mycommands[$i];
// --- Set CSS Class
if ( $content['sql_failed'] % 2 == 0 )
$content['failedstatements'][ $content['sql_failed'] ]['cssclass'] = "line1";
else
$content['failedstatements'][ $content['sql_failed'] ]['cssclass'] = "line2";
// ---
$content['sql_failed']++;
}
else
$content['sql_sucess']++;
// Free result
DB_FreeQuery($result);
}
}
}
else // Skip this step in this case!
ForwardOneStep();
}
else if ( $content['INSTALL_STEP'] == 6 )
{
if ( $_SESSION['UserDBEnabled'] == 1 )
{
if ( $_SESSION['UserDBAuthMode'] == USERDB_AUTH_INTERNAL )
{
if ( isset($_SESSION['MAIN_Username']) )
$content['MAIN_Username'] = $_SESSION['MAIN_Username'];
else
$content['MAIN_Username'] = "";
$content['MAIN_Password1'] = "";
$content['MAIN_Password2'] = "";
// Check for Error Msg
if ( isset($_GET['errormsg']) )
{
$content['iserror'] = "true";
$content['errormsg'] = urldecode( DB_StripSlahes($_GET['errormsg']) );
}
}
else // USERDB_AUTH_LDAP does not need this steo!
ForwardOneStep();
}
else // NO Database means NO user management, so next step!
ForwardOneStep();
}
else if ( $content['INSTALL_STEP'] == 7 )
{
if ( $_SESSION['UserDBEnabled'] == 1 )
{
if ( $_SESSION['UserDBAuthMode'] == USERDB_AUTH_INTERNAL )
{
if ( isset($_POST['username']) )
$_SESSION['MAIN_Username'] = DB_RemoveBadChars($_POST['username']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_INSTALL_MISSINGUSERNAME'] );
if ( isset($_POST['password1']) )
$_SESSION['MAIN_Password1'] = DB_RemoveBadChars($_POST['password1']);
else
$_SESSION['MAIN_Password1'] = "";
if ( isset($_POST['password2']) )
$_SESSION['MAIN_Password2'] = DB_RemoveBadChars($_POST['password2']);
else
$_SESSION['MAIN_Password2'] = "";
if (
strlen($_SESSION['MAIN_Password1']) < 4 ||
$_SESSION['MAIN_Password1'] != $_SESSION['MAIN_Password2']
)
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_INSTALL_PASSWORDNOTMATCH'] );
}
else if ( $_SESSION['UserDBAuthMode'] == USERDB_AUTH_LDAP )
{
$_SESSION['MAIN_Username'] = $_SESSION['LDAPDefaultAdminUser'];
$_SESSION['MAIN_Password1'] = "";
$_SESSION['MAIN_Password2'] = "";
}
// --- Now execute all commands
ini_set('error_reporting', E_WARNING); // Enable Warnings!
InitUserDbSettings(); // We need some DB Settings
InitUserSystemPhpLogCon(); // We need the user system now!
// Establish DB Connection
DB_Connect();
// Everything is fine, lets go create the User!
CreateUserName( $_SESSION['MAIN_Username'], $_SESSION['MAIN_Password1'], 1 );
// Show User success!
$content['MAIN_Username'] = $_SESSION['MAIN_Username'];
$content['createduser'] = true;
}
// Init Source Options
if ( isset($_SESSION['SourceType']) ) { $content['SourceType'] = $_SESSION['SourceType']; } else { $content['SourceType'] = SOURCE_DISK; }
CreateSourceTypesList($content['SourceType']);
if ( isset($_SESSION['SourceName']) ) { $content['SourceName'] = $_SESSION['SourceName']; } else { $content['SourceName'] = "My Syslog Source"; }
// Init default View
if ( isset($_SESSION['SourceViewID']) ) { $content['SourceViewID'] = $_SESSION['SourceViewID']; } else { $content['SourceViewID'] = 'SYSLOG'; }
foreach ( $content['Views'] as $myView )
{
if ( $myView['ID'] == $content['SourceViewID'] )
$content['Views'][ $myView['ID'] ]['selected'] = "selected";
else
$content['Views'][ $myView['ID'] ]['selected'] = "";
}
// SOURCE_DISK specific
if ( isset($_SESSION['SourceLogLineType']) ) { $content['SourceLogLineType'] = $_SESSION['SourceLogLineType']; } else { $content['SourceLogLineType'] = ""; }
CreateLogLineTypesList($content['SourceLogLineType']);
if ( isset($_SESSION['SourceDiskFile']) ) { $content['SourceDiskFile'] = $_SESSION['SourceDiskFile']; } else { $content['SourceDiskFile'] = "/var/log/syslog"; }
// SOURCE_DB specific
if ( isset($_SESSION['SourceDBType']) ) { $content['SourceDBType'] = $_SESSION['SourceDBType']; } else { $content['SourceDBType'] = DB_MYSQL; }
CreateDBTypesList($content['SourceDBType']);
if ( isset($_SESSION['SourceDBTableType']) ) { $content['SourceDBTableType'] = $_SESSION['SourceDBTableType']; } else { $content['SourceDBTableType'] = "monitorware"; }
CreateDBMappingsList($content['SourceDBTableType']);
if ( isset($_SESSION['SourceDBName']) ) { $content['SourceDBName'] = $_SESSION['SourceDBName']; } else { $content['SourceDBName'] = "loganalyzer"; }
if ( isset($_SESSION['SourceDBServer']) ) { $content['SourceDBServer'] = $_SESSION['SourceDBServer']; } else { $content['SourceDBServer'] = "localhost"; }
if ( isset($_SESSION['SourceDBTableName']) ) { $content['SourceDBTableName'] = $_SESSION['SourceDBTableName']; } else { $content['SourceDBTableName'] = "systemevents"; }
if ( isset($_SESSION['SourceDBUser']) ) { $content['SourceDBUser'] = $_SESSION['SourceDBUser']; } else { $content['SourceDBUser'] = "user"; }
if ( isset($_SESSION['SourceDBPassword']) ) { $content['SourceDBPassword'] = $_SESSION['SourceDBPassword']; } else { $content['SourceDBPassword'] = ""; }
if ( isset($_SESSION['SourceDBEnableRowCounting']) ) { $content['SourceDBEnableRowCounting'] = $_SESSION['SourceDBEnableRowCounting']; } else { $content['SourceDBEnableRowCounting'] = "false"; }
if ( $content['SourceDBEnableRowCounting'] == "true" )
{
$content['SourceDBEnableRowCounting_true'] = "checked";
$content['SourceDBEnableRowCounting_false'] = "";
}
else
{
$content['SourceDBEnableRowCounting_true'] = "";
$content['SourceDBEnableRowCounting_false'] = "checked";
}
// Check for Error Msg
if ( isset($_GET['errormsg']) )
{
$content['iserror'] = "true";
$content['errormsg'] = urldecode( DB_StripSlahes($_GET['errormsg']) );
}
}
else if ( $content['INSTALL_STEP'] == 8 )
{
// --- Write Config File!
// Read vars
if ( isset($_POST['SourceType']) )
$_SESSION['SourceType'] = DB_RemoveBadChars($_POST['SourceType']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_SOURCETYPE'] );
if ( isset($_POST['SourceName']) )
$_SESSION['SourceName'] = DB_RemoveBadChars($_POST['SourceName']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_NAMEOFTHESOURCE'] );
if ( isset($_POST['SourceViewID']) )
$_SESSION['SourceViewID'] = DB_RemoveBadChars($_POST['SourceViewID']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_VIEW'] );
// Check DISK Parameters!
if ( $_SESSION['SourceType'] == SOURCE_DISK)
{
if ( isset($_POST['SourceLogLineType']) )
$_SESSION['SourceLogLineType'] = DB_RemoveBadChars($_POST['SourceLogLineType']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_LOGLINETYPE'] );
if ( isset($_POST['SourceDiskFile']) )
$_SESSION['SourceDiskFile'] = DB_RemoveBadChars($_POST['SourceDiskFile']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_SYSLOGFILE'] );
// Check if access to the configured file is possible
if ( !is_file($_SESSION['SourceDiskFile']) )
RevertOneStep( $content['INSTALL_STEP']-1, GetAndReplaceLangStr($content['LN_INSTALL_FAILEDTOOPENSYSLOGFILE'], $_SESSION['SourceDiskFile']) );
}
// DB Params
else if ( $_SESSION['SourceType'] == SOURCE_DB ||
$_SESSION['SourceType'] == SOURCE_PDO ||
$_SESSION['SourceType'] == SOURCE_MONGODB )
{
if ( isset($_POST['SourceDBType']) )
$_SESSION['SourceDBType'] = DB_RemoveBadChars($_POST['SourceDBType']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_DATABASETYPEOPTIONS'] );
if ( isset($_POST['SourceDBName']) )
$_SESSION['SourceDBName'] = DB_RemoveBadChars($_POST['SourceDBName']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_DBNAME'] );
if ( isset($_POST['SourceDBTableType']) )
$_SESSION['SourceDBTableType'] = DB_RemoveBadChars($_POST['SourceDBTableType']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_DBTABLETYPE'] );
if ( isset($_POST['SourceDBServer']) )
$_SESSION['SourceDBServer'] = DB_RemoveBadChars($_POST['SourceDBServer']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_DBSERVER'] );
if ( isset($_POST['SourceDBTableName']) )
$_SESSION['SourceDBTableName'] = DB_RemoveBadChars($_POST['SourceDBTableName']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_DBTABLENAME'] );
if ( isset($_POST['SourceDBUser']) )
$_SESSION['SourceDBUser'] = DB_RemoveBadChars($_POST['SourceDBUser']);
else
RevertOneStep( $content['INSTALL_STEP']-1, $content['LN_CFG_PARAMMISSING'] . $content['LN_CFG_DBUSER'] );
if ( isset($_POST['SourceDBPassword']) )
$_SESSION['SourceDBPassword'] = DB_RemoveBadChars($_POST['SourceDBPassword']);
else
$_SESSION['SourceDBPassword'] = "";
if ( isset($_POST['SourceDBEnableRowCounting']) )
{
$_SESSION['SourceDBEnableRowCounting'] = DB_RemoveBadChars($_POST['SourceDBEnableRowCounting']);
if ( $_SESSION['SourceDBEnableRowCounting'] != "true" )
$_SESSION['SourceDBEnableRowCounting'] = "false";
}
// Check Database Access!
}
// If we reached this point, we have gathered all necessary information to create our configuration file ;)!
$filebuffer = LoadDataFile($configsamplefile);
// Set helper variables and init user vars if needed!
if ( isset($_SESSION['UserDBEnabled']) && $_SESSION['UserDBEnabled'] ) { $_SESSION['UserDBEnabled_value'] = "true"; } else { $_SESSION['UserDBEnabled_value'] = "false"; }
if ( isset($_SESSION['UserDBLoginRequired']) && $_SESSION['UserDBLoginRequired'] ) { $_SESSION['UserDBLoginRequired_value'] = "true"; } else { $_SESSION['UserDBLoginRequired_value'] = "false"; }
if ( !isset($_SESSION['UserDBServer'])) { $_SESSION['UserDBServer'] = "localhost"; }
if ( !isset($_SESSION['UserDBPort'])) { $_SESSION['UserDBPort'] = "3306"; }
if ( !isset($_SESSION['UserDBName'])) { $_SESSION['UserDBName'] = "loganalyzer"; }
if ( !isset($_SESSION['UserDBPref'])) { $_SESSION['UserDBPref'] = "logcon_"; }
if ( !isset($_SESSION['UserDBUser'])) { $_SESSION['UserDBUser'] = "root"; }
if ( !isset($_SESSION['UserDBPass'])) { $_SESSION['UserDBPass'] = ""; }
if ( !isset($_SESSION['UserDBAuthMode'])) { $_SESSION['UserDBAuthMode'] = USERDB_AUTH_INTERNAL; }
// LDAP vars
if ( !isset($_SESSION['LDAPServer'])) { $_SESSION['LDAPServer'] = "127.0.0.1"; }
if ( !isset($_SESSION['LDAPPort'])) { $_SESSION['LDAPPort'] = "389"; }
if ( !isset($_SESSION['LDAPBaseDN'])) { $_SESSION['LDAPBaseDN'] = "CN=Users,DC=domain,DC=local"; }
if ( !isset($_SESSION['LDAPSearchFilter'])) { $_SESSION['LDAPSearchFilter'] = "(objectClass=user)"; }
if ( !isset($_SESSION['LDAPUidAttribute'])) { $_SESSION['LDAPUidAttribute'] = "sAMAccountName"; }
if ( !isset($_SESSION['LDAPBindDN'])) { $_SESSION['LDAPBindDN'] = "CN=Searchuser,CN=Users,DC=domain,DC=local"; }
if ( !isset($_SESSION['LDAPBindPassword'])) { $_SESSION['LDAPBindPassword'] = "Password"; }
// Start replacing existing sample configurations
$patterns[] = "/\\\$CFG\['ViewMessageCharacterLimit'\] = [0-9]{1,2};/";
$patterns[] = "/\\\$CFG\['ViewStringCharacterLimit'\] = [0-9]{1,2};/";
$patterns[] = "/\\\$CFG\['ViewEntriesPerPage'\] = [0-9]{1,2};/";
$patterns[] = "/\\\$CFG\['ViewEnableDetailPopups'\] = [0-9]{1,2};/";
$patterns[] = "/\\\$CFG\['EnableIPAddressResolve'\] = [0-9]{1,2};/";
$patterns[] = "/\\\$CFG\['UserDBEnabled'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['UserDBServer'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['UserDBPort'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['UserDBName'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['UserDBPref'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['UserDBUser'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['UserDBPass'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['UserDBLoginRequired'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['UserDBAuthMode'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['LDAPServer'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['LDAPPort'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['LDAPBaseDN'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['LDAPSearchFilter'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['LDAPUidAttribute'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['LDAPBindDN'\] = (.*?);/";
$patterns[] = "/\\\$CFG\['LDAPBindPassword'\] = (.*?);/";
$replacements[] = "\$CFG['ViewMessageCharacterLimit'] = " . $_SESSION['ViewMessageCharacterLimit'] . ";";
$replacements[] = "\$CFG['ViewStringCharacterLimit'] = " . $_SESSION['ViewStringCharacterLimit'] . ";";
$replacements[] = "\$CFG['ViewEntriesPerPage'] = " . $_SESSION['ViewEntriesPerPage'] . ";";
$replacements[] = "\$CFG['ViewEnableDetailPopups'] = " . $_SESSION['ViewEnableDetailPopups'] . ";";
$replacements[] = "\$CFG['EnableIPAddressResolve'] = " . $_SESSION['EnableIPAddressResolve'] . ";";
$replacements[] = "\$CFG['UserDBEnabled'] = " . $_SESSION['UserDBEnabled_value'] . ";";
$replacements[] = "\$CFG['UserDBServer'] = '" . $_SESSION['UserDBServer'] . "';";
$replacements[] = "\$CFG['UserDBPort'] = " . $_SESSION['UserDBPort'] . ";";
$replacements[] = "\$CFG['UserDBName'] = '" . $_SESSION['UserDBName'] . "';";
$replacements[] = "\$CFG['UserDBPref'] = '" . $_SESSION['UserDBPref'] . "';";
$replacements[] = "\$CFG['UserDBUser'] = '" . $_SESSION['UserDBUser'] . "';";
$replacements[] = "\$CFG['UserDBPass'] = '" . $_SESSION['UserDBPass'] . "';";
$replacements[] = "\$CFG['UserDBLoginRequired'] = " . $_SESSION['UserDBLoginRequired_value'] . ";";
$replacements[] = "\$CFG['UserDBAuthMode'] = " . $_SESSION['UserDBAuthMode'] . ";";
$replacements[] = "\$CFG['LDAPServer'] = '" . $_SESSION['LDAPServer'] . "';";
$replacements[] = "\$CFG['LDAPPort'] = " . $_SESSION['LDAPPort'] . ";";
$replacements[] = "\$CFG['LDAPBaseDN'] = '" . $_SESSION['LDAPBaseDN'] . "';";
$replacements[] = "\$CFG['LDAPSearchFilter'] = '" . $_SESSION['LDAPSearchFilter'] . "';";
$replacements[] = "\$CFG['LDAPUidAttribute'] = '" . $_SESSION['LDAPUidAttribute'] . "';";
$replacements[] = "\$CFG['LDAPBindDN'] = '" . $_SESSION['LDAPBindDN'] . "';";
$replacements[] = "\$CFG['LDAPBindPassword'] = '" . $_SESSION['LDAPBindPassword'] . "';";
//User Database Options
if ( isset($_SESSION['UserDBEnabled']) && $_SESSION['UserDBEnabled'] )
{
// TODO!
}
//Add the first source!
$firstsource = "\$CFG['DefaultSourceID'] = 'Source1';\n\n" .
"\$CFG['Sources']['Source1']['ID'] = 'Source1';\n" .
"\$CFG['Sources']['Source1']['Name'] = '" . $_SESSION['SourceName'] . "';\n" .
"\$CFG['Sources']['Source1']['ViewID'] = '" . $_SESSION['SourceViewID'] . "';\n";
if ( $_SESSION['SourceType'] == SOURCE_DISK )
{
$firstsource .= "\$CFG['Sources']['Source1']['SourceType'] = SOURCE_DISK;\n" .
"\$CFG['Sources']['Source1']['LogLineType'] = '" . $_SESSION['SourceLogLineType'] . "';\n" .
"\$CFG['Sources']['Source1']['DiskFile'] = '" . $_SESSION['SourceDiskFile'] . "';\n" .
"";
}
else if ( $_SESSION['SourceType'] == SOURCE_DB )
{
// Need to create the LIST first!
CreateDBTypesList($_SESSION['SourceDBType']);
$firstsource .= "\$CFG['Sources']['Source1']['SourceType'] = SOURCE_DB;\n" .
"\$CFG['Sources']['Source1']['DBTableType'] = '" . $_SESSION['SourceDBTableType'] . "';\n" .
"\$CFG['Sources']['Source1']['DBType'] = " . $content['DBTYPES'][$_SESSION['SourceDBType']]['typeastext'] . ";\n" .
"\$CFG['Sources']['Source1']['DBServer'] = '" . $_SESSION['SourceDBServer'] . "';\n" .
"\$CFG['Sources']['Source1']['DBName'] = '" . $_SESSION['SourceDBName'] . "';\n" .
"\$CFG['Sources']['Source1']['DBUser'] = '" . $_SESSION['SourceDBUser'] . "';\n" .
"\$CFG['Sources']['Source1']['DBPassword'] = '" . $_SESSION['SourceDBPassword'] . "';\n" .
"\$CFG['Sources']['Source1']['DBTableName'] = '" . $_SESSION['SourceDBTableName'] . "';\n" .
"\$CFG['Sources']['Source1']['DBEnableRowCounting'] = " . $_SESSION['SourceDBEnableRowCounting'] . ";\n" .
"";
}
else if ( $_SESSION['SourceType'] == SOURCE_PDO )
{
// Need to create the LIST first!
CreateDBTypesList($_SESSION['SourceDBType']);
$firstsource .= "\$CFG['Sources']['Source1']['SourceType'] = SOURCE_PDO;\n" .
"\$CFG['Sources']['Source1']['DBTableType'] = '" . $_SESSION['SourceDBTableType'] . "';\n" .
"\$CFG['Sources']['Source1']['DBType'] = " . $content['DBTYPES'][$_SESSION['SourceDBType']]['typeastext'] . ";\n" .
"\$CFG['Sources']['Source1']['DBServer'] = '" . $_SESSION['SourceDBServer'] . "';\n" .
"\$CFG['Sources']['Source1']['DBName'] = '" . $_SESSION['SourceDBName'] . "';\n" .
"\$CFG['Sources']['Source1']['DBUser'] = '" . $_SESSION['SourceDBUser'] . "';\n" .
"\$CFG['Sources']['Source1']['DBPassword'] = '" . $_SESSION['SourceDBPassword'] . "';\n" .
"\$CFG['Sources']['Source1']['DBTableName'] = '" . $_SESSION['SourceDBTableName'] . "';\n" .
"\$CFG['Sources']['Source1']['DBEnableRowCounting'] = " . $_SESSION['SourceDBEnableRowCounting'] . ";\n" .
"";
}
else if ( $_SESSION['SourceType'] == SOURCE_MONGODB )
{
// Need to create the LIST first!
CreateDBTypesList($_SESSION['SourceDBType']);
$firstsource .= "\$CFG['Sources']['Source1']['SourceType'] = SOURCE_MONGODB;\n" .
"\$CFG['Sources']['Source1']['DBTableType'] = '" . $_SESSION['SourceDBTableType'] . "';\n" .
"\$CFG['Sources']['Source1']['DBServer'] = '" . $_SESSION['SourceDBServer'] . "';\n" .
"\$CFG['Sources']['Source1']['DBName'] = '" . $_SESSION['SourceDBName'] . "';\n" .
"\$CFG['Sources']['Source1']['DBUser'] = '" . $_SESSION['SourceDBUser'] . "';\n" .
"\$CFG['Sources']['Source1']['DBPassword'] = '" . $_SESSION['SourceDBPassword'] . "';\n" .
"\$CFG['Sources']['Source1']['DBTableName'] = '" . $_SESSION['SourceDBTableName'] . "';\n" .
"";
}
$patterns[] = "/\/\/ --- \%Insert Source Here\%/";
$replacements[] = $firstsource;
// One call to replace them all ^^
$filebuffer = preg_replace( $patterns, $replacements, $filebuffer );
// echo $filebuffer;
// Create file and write config into it!
$handle = fopen( $content['BASEPATH'] . "config.php" , "w");
if ( $handle === false )
RevertOneStep( $content['INSTALL_STEP']-1, GetAndReplaceLangStr($content['LN_INSTALL_FAILEDCREATECFGFILE'], $content['BASEPATH'] . "config.php") );
fwrite($handle, $filebuffer);
fflush($handle);
fclose($handle);
// ---
// --- If UserDB is enabled, we need to convert the settings now
if ( $_SESSION['UserDBEnabled'] )
{
// Fully Initialize LogAnalyzer now!
InitPhpLogCon();
InitSourceConfigs();
// Perform conversion of settings into the database now!
ConvertCustomSearches();
ConvertCustomViews();
ConvertCustomSources();
ConvertCustomCharts();
// Import General Settings in the last step!
ConvertGeneralSettings();
}
// ---
}
// ---
// ---
// --- Parsen and Output
InitTemplateParser();
$page -> parser($content, "install.html");
$page -> output();
// ---
// --- Helper functions
function LoadDataFile($szFileName)
{
global $content;
// Lets read the table definitions :)
$buffer = "";
$handle = @fopen($szFileName, "r");
if ($handle === false)
RevertOneStep( $content['INSTALL_STEP']-1, GetAndReplaceLangStr($content['LN_INSTALL_FAILEDREADINGFILE'], $szFileName) );
else
{
while (!feof($handle))
{
$buffer .= fgets($handle, 4096);
}
fclose($handle);
}
// return file buffer!
return $buffer;
}
function InitUserDbSettings()
{
global $CFG;
// Init DB Configs
$CFG['UserDBEnabled'] = true;
$CFG['UserDBServer'] = $_SESSION['UserDBServer'];
$CFG['UserDBPort'] = $_SESSION['UserDBPort'];
$CFG['UserDBName'] = $_SESSION['UserDBName'];
$CFG['UserDBPref'] = $_SESSION['UserDBPref'];
$CFG['UserDBUser'] = $_SESSION['UserDBUser'];
$CFG['UserDBPass'] = $_SESSION['UserDBPass'];
$CFG['UserDBLoginRequired'] = $_SESSION['UserDBLoginRequired'];
// Needed table defs
define('DB_CONFIG', $CFG['UserDBPref'] . "config");
define('DB_USERS', $CFG['UserDBPref'] . "users");
define('DB_SEARCHES', $CFG['UserDBPref'] . "searches");
define('DB_SOURCES', $CFG['UserDBPref'] . "sources");
define('DB_VIEWS', $CFG['UserDBPref'] . "views");
}
// ---
?> loganalyzer-3.6.6/src/export.php 0000644 0001750 0001750 00000030714 12401304543 016151 0 ustar daniel daniel Exports data from a search and site into a data format
*
* All directives are explained within this file
*
* Copyright (C) 2008-2010 Adiscon GmbH.
*
* This file is part of LogAnalyzer.
*
* LogAnalyzer 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 3 of the License, or
* (at your option) any later version.
*
* LogAnalyzer 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.
*
* You should have received a copy of the GNU General Public License
* along with LogAnalyzer. If not, see .
*
* A copy of the GPL can be found in the file "COPYING" in this
* distribution
*
* Adiscon LogAnalyzer is also available under a commercial license.
* For details, contact info@adiscon.com or visit
* http://loganalyzer.adiscon.com/commercial
*********************************************************************
*/
// *** Default includes and procedures *** //
define('IN_PHPLOGCON', true);
$gl_root_path = './';
// Now include necessary include files!
include($gl_root_path . 'include/functions_common.php');
include($gl_root_path . 'include/functions_frontendhelpers.php');
include($gl_root_path . 'include/functions_filters.php');
// Include LogStream facility
include($gl_root_path . 'classes/logstream.class.php');
InitPhpLogCon();
InitSourceConfigs();
InitFrontEndDefaults(); // Only in WebFrontEnd
InitFilterHelpers(); // Helpers for frontend filtering!
// ---
// --- READ CONTENT Vars
if ( isset($_GET['uid']) )
$content['uid_current'] = intval($_GET['uid']);
else
$content['uid_current'] = UID_UNKNOWN;
// Read direction parameter
if ( isset($_GET['direction']) && $_GET['direction'] == "desc" )
$content['read_direction'] = EnumReadDirection::Forward;
else
$content['read_direction'] = EnumReadDirection::Backward;
// If direction is DESC, should we SKIP one?
if ( isset($_GET['skipone']) && $_GET['skipone'] == "true" )
$content['skipone'] = true;
else
$content['skipone'] = false;
// Init variables
$content['searchstr'] = "";
$content['error_occured'] = false;
// Check required input parameters
if (
(isset($_GET['op']) && $_GET['op'] == "export") &&
(isset($_GET['exporttype']) && array_key_exists($_GET['exporttype'], $content['EXPORTTYPES']))
)
{
$content['exportformat'] = $_GET['exporttype'];
/*
// Check for extensions
if ( $content['exportformat'] == EXPORT_PDF && !$content['PDF_IS_ENABLED'] )
{
$content['error_occured'] = true;
$content['error_details'] = $content['LN_GEN_ERROR_PDFMISSINGEXTENSION'];
}
*/
}
else
{
$content['error_occured'] = true;
$content['error_details'] = $content['LN_GEN_ERROR_INVALIDEXPORTTYPE'];
}
// ---
// --- BEGIN CREATE TITLE
$content['TITLE'] = InitPageTitle();
// Append custom title part!
if ( isset($content['searchstr']) && strlen($content['searchstr']) > 0 )
$content['TITLE'] .= " :: Results for the search '" . $content['searchstr'] . "'"; // Append search
else
$content['TITLE'] .= " :: Syslogmessages";
// --- END CREATE TITLE
// --- Read and process filters from search dialog!
if ( (isset($_POST['search']) || isset($_GET['search'])) || (isset($_POST['filter']) || isset($_GET['filter'])) )
{
// Copy search over
if ( isset($_POST['search']) )
$mysearch = $_POST['search'];
else if ( isset($_GET['search']) )
$mysearch = $_GET['search'];
if ( isset($_POST['filter']) )
$myfilter = $_POST['filter'];
else if ( isset($_GET['filter']) )
$myfilter = $_GET['filter'];
// Message is just appended
if ( isset($myfilter) && strlen($myfilter) > 0 )
$content['searchstr'] = $myfilter;
}
// ---
// --- BEGIN Custom Code
if ( !$content['error_occured'] )
{
if ( isset($content['Sources'][$currentSourceID]) )
{
// Obtain and get the Config Object
$stream_config = $content['Sources'][$currentSourceID]['ObjRef'];
// Create LogStream Object
$stream = $stream_config->LogStreamFactory($stream_config);
$stream->SetFilter($content['searchstr']);
// Copy current used columns here!
$content['Columns'] = $content['Views'][$currentViewID]['Columns'];
// --- Init the fields we need
foreach($content['Columns'] as $mycolkey)
{
if ( isset($fields[$mycolkey]) )
{
$content['fields'][$mycolkey]['FieldID'] = $mycolkey;
$content['fields'][$mycolkey]['FieldCaption'] = $fields[$mycolkey]['FieldCaption'];
$content['fields'][$mycolkey]['FieldType'] = $fields[$mycolkey]['FieldType'];
$content['fields'][$mycolkey]['DefaultWidth'] = $fields[$mycolkey]['DefaultWidth'];
}
}
// ---
$res = $stream->Open( $content['Columns'], true );
if ( $res == SUCCESS )
{
// TODO Implement ORDER
$stream->SetReadDirection($content['read_direction']);
// Set current ID and init Counter
$uID = $content['uid_current'];
$counter = 0;
// If uID is known, we need to init READ first - this will also seek for available records first!
if ($uID != UID_UNKNOWN)
{
// First read will also set the start position of the Stream!
$ret = $stream->Read($uID, $logArray);
}
else
$ret = $stream->ReadNext($uID, $logArray);
// --- Check if Read was successfull!
if ( $ret == SUCCESS )
{
// If Forward direction is used, we need to SKIP one entry!
if ( $content['read_direction'] == EnumReadDirection::Forward )
{
if ( $content['skipone'] )
{
// Skip this entry and move to the next
$stream->ReadNext($uID, $logArray);
}
}
}
else
{
// This will disable to Main SyslogView and show an error message
$content['error_occured'] = true;
$content['error_details'] = $content['LN_ERROR_NORECORDS'];
}
// ---
// We found matching records, so continue
if ( $ret == SUCCESS )
{
//Loop through the messages!
do
{
// --- Extra stuff for suppressing messages
if (
GetConfigSetting("SuppressDuplicatedMessages", 0, CFGLEVEL_USER) == 1
&&
isset($logArray[SYSLOG_MESSAGE])
)
{
if ( !isset($szLastMessage) ) // Only set lastmgr
$szLastMessage = $logArray[SYSLOG_MESSAGE];
else
{
// Skip if same msg
if ( $szLastMessage == $logArray[SYSLOG_MESSAGE] )
{
// Set last mgr
$szLastMessage = $logArray[SYSLOG_MESSAGE];
// Skip entry
continue;
}
}
}
// ---
// --- Now we populate the values array!
foreach($content['Columns'] as $mycolkey)
{
if ( isset($fields[$mycolkey]) && isset($logArray[$mycolkey]) )
{
// Set defaults
$content['syslogmessages'][$counter][$mycolkey]['FieldColumn'] = $mycolkey;
$content['syslogmessages'][$counter][$mycolkey]['uid'] = $uID;
// Copy value as it is first!
$content['syslogmessages'][$counter][$mycolkey]['fieldvalue'] = $logArray[$mycolkey];
// Now handle fields types differently
if ( $content['fields'][$mycolkey]['FieldType'] == FILTER_TYPE_DATE )
{
$content['syslogmessages'][$counter][$mycolkey]['fieldvalue'] = GetFormatedDate($logArray[$mycolkey]);
}
else if ( $content['fields'][$mycolkey]['FieldType'] == FILTER_TYPE_NUMBER )
{
// Special style classes and colours for SYSLOG_FACILITY
if ( $mycolkey == SYSLOG_FACILITY )
{
if ( isset($logArray[$mycolkey][SYSLOG_FACILITY]) && strlen($logArray[$mycolkey][SYSLOG_FACILITY]) > 0)
{
// Set Human readable Facility!
$content['syslogmessages'][$counter][$mycolkey]['fieldvalue'] = GetFacilityDisplayName( $logArray[$mycolkey] );
}
}
else if ( $mycolkey == SYSLOG_SEVERITY )
{
if ( isset($logArray[$mycolkey][SYSLOG_SEVERITY]) && strlen($logArray[$mycolkey][SYSLOG_SEVERITY]) > 0)
{
// Set Human readable Facility!
$content['syslogmessages'][$counter][$mycolkey]['fieldvalue'] = GetSeverityDisplayName( $logArray[$mycolkey] );
}
}
else if ( $mycolkey == SYSLOG_MESSAGETYPE )
{
if ( isset($logArray[$mycolkey][SYSLOG_MESSAGETYPE]) )
{
// Set Human readable Facility!
$content['syslogmessages'][$counter][$mycolkey]['fieldvalue'] = GetMessageTypeDisplayName( $logArray[$mycolkey] );
}
}
}
/*
else if ( $content['fields'][$mycolkey]['FieldType'] == FILTER_TYPE_STRING )
{
}
*/
}
}
// ---
// Increment Counter
$counter++;
} while ($counter < $content['CurrentViewEntriesPerPage'] && ($ret = $stream->ReadNext($uID, $logArray)) == SUCCESS);
if ( $content['read_direction'] == EnumReadDirection::Forward )
{
// Back Button was clicked, so we need to flip the array
$content['syslogmessages'] = array_reverse ( $content['syslogmessages'] );
}
// DEBUG
//print_r ( $content['syslogmessages'] );
}
}
else
{
// This will disable to Main SyslogView and show an error message
$content['error_occured'] = true;
$content['error_details'] = GetErrorMessage($res);
if ( isset($extraErrorDescription) )
$content['error_details'] .= "
" . GetAndReplaceLangStr( $content['LN_SOURCES_ERROR_EXTRAMSG'], $extraErrorDescription);
}
// Close file!
$stream->Close();
}
else
{
$content['error_occured'] = true;
$content['error_details'] = GetAndReplaceLangStr( $content['LN_GEN_ERROR_SOURCENOTFOUND'], $currentSourceID);
}
}
// ---
// --- Convert and Output
if ( $content['error_occured'] )
{
InitTemplateParser();
$page -> parser($content, "export.html");
$page -> output();
}
else
{
// Create a CVS File!
$szOutputContent = "";
$szOutputMimeType = "text/plain";
$szOutputCharset = "";
$szOutputFileName = "ExportMessages";
$szOutputFileExtension = ".txt";
if ( $content['exportformat'] == EXPORT_CVS )
{
// Set MIME TYPE and File Extension
$szOutputMimeType = "text/csv";
$szOutputFileExtension = ".csv";
// Set Column line in cvs file!
foreach($content['Columns'] as $mycolkey)
{
if ( isset($fields[$mycolkey]) )
{
// Prepend Comma if needed
if (strlen($szOutputContent) > 0)
$szOutputContent .= ",";
// Append column name
$szOutputContent .= $fields[$mycolkey]['FieldCaption'];
}
}
// Append line break
$szOutputContent .= "\n";
// Append messages into output
foreach ( $content['syslogmessages'] as $myIndex => $mySyslogMessage )
{
$szLine = "";
// --- Process columns
foreach($mySyslogMessage as $myColkey => $mySyslogField)
{
// Prepend Comma if needed
if (strlen($szLine) > 0)
$szLine .= ",";
// Append field contents
$szLine .= '"' . str_replace('"', '\\"', $mySyslogField['fieldvalue']) . '"';
}
// ---
// Append line!
$szOutputContent .= $szLine . "\n";
}
}
else if ( $content['exportformat'] == EXPORT_XML )
{
// Set MIME TYPE and File Extension
$szOutputMimeType = "application/xml";
$szOutputFileExtension = ".xml";
$szOutputCharset = "charset=UTF-8";
// Create XML Header and first node!!
$szOutputContent .= "\xef\xbb\xbf";
$szOutputContent .= "\n";
$szOutputContent .= "\n";
// Append messages into output
foreach ( $content['syslogmessages'] as $myIndex => $mySyslogMessage )
{
$szXmlLine = "\t\n";
// --- Process columns
foreach($mySyslogMessage as $myColkey => $mySyslogField)
{
// Append field content | first run htmlentities,tnen utf8 encoding!!
$szXmlLine .= "\t\t<" . $myColkey . ">" . utf8_encode( htmlentities($mySyslogField['fieldvalue']) ) . "" . $myColkey . ">\n";
}
// ---
$szXmlLine .= "\t\n";
// Append line!
$szOutputContent .= $szXmlLine;
}
// End first XML Node
$szOutputContent .= "";
}
// Set needed Header properties
header('Content-type: ' . $szOutputMimeType . "; " . $szOutputCharset);
header("Content-Length: " . strlen($szOutputContent) );
header('Content-Disposition: attachment; filename="' . $szOutputFileName . $szOutputFileExtension . '"');
// Output Content!
print( $szOutputContent );
}
// ---
?> loganalyzer-3.6.6/src/js/ 0000755 0001750 0001750 00000000000 12401304543 014526 5 ustar daniel daniel loganalyzer-3.6.6/src/js/searchhelpers.js 0000644 0001750 0001750 00000014045 12401304543 017720 0 ustar daniel daniel /*
Helper Javascript Constants
*/
const DATEMODE_ALL = 1, DATEMODE_RANGE = 2, DATEMODE_LASTX = 3;
const DATE_LASTX_HOUR = 1, DATE_LASTX_12HOURS = 2, DATE_LASTX_24HOURS = 3, DATE_LASTX_7DAYS = 4,DATE_LASTX_31DAYS = 5;
/*
Helper Javascript functions
*/
/*
* Helper function to show and hide areas of the filterview
*/
function toggleDatefiltervisibility(FormName)
{
var myform = document.getElementById(FormName);
if (myform.elements['filter_datemode'].value == DATEMODE_ALL)
{
hidevisibility('HiddenDateFromOptions');
hidevisibility('HiddenDateLastXOptions');
toggleformelement('filter_daterange_from_year', false);
toggleformelement('filter_daterange_from_month', false);
toggleformelement('filter_daterange_from_day', false);
toggleformelement('filter_daterange_to_year', false);
toggleformelement('filter_daterange_to_month', false);
toggleformelement('filter_daterange_to_day', false);
toggleformelement('filter_daterange_from_hour', false);
toggleformelement('filter_daterange_from_minute', false);
toggleformelement('filter_daterange_from_second', false);
toggleformelement('filter_daterange_to_hour', false);
toggleformelement('filter_daterange_to_minute', false);
toggleformelement('filter_daterange_to_second', false);
toggleformelement('filter_daterange_last_x', false);
}
else if (myform.elements['filter_datemode'].value == DATEMODE_RANGE)
{
togglevisibility('HiddenDateFromOptions');
hidevisibility('HiddenDateLastXOptions');
toggleformelement('filter_daterange_from_year', true);
toggleformelement('filter_daterange_from_month', true);
toggleformelement('filter_daterange_from_day', true);
toggleformelement('filter_daterange_to_year', true);
toggleformelement('filter_daterange_to_month', true);
toggleformelement('filter_daterange_to_day', true);
toggleformelement('filter_daterange_from_hour', true);
toggleformelement('filter_daterange_from_minute', true);
toggleformelement('filter_daterange_from_second', true);
toggleformelement('filter_daterange_to_hour', true);
toggleformelement('filter_daterange_to_minute', true);
toggleformelement('filter_daterange_to_second', true);
toggleformelement('filter_daterange_last_x', false);
}
else if (myform.elements['filter_datemode'].value == DATEMODE_LASTX)
{
togglevisibility('HiddenDateLastXOptions');
hidevisibility('HiddenDateFromOptions');
toggleformelement('filter_daterange_from_year', false);
toggleformelement('filter_daterange_from_month', false);
toggleformelement('filter_daterange_from_day', false);
toggleformelement('filter_daterange_to_year', false);
toggleformelement('filter_daterange_to_month', false);
toggleformelement('filter_daterange_to_day', false);
toggleformelement('filter_daterange_from_hour', false);
toggleformelement('filter_daterange_from_minute', false);
toggleformelement('filter_daterange_from_second', false);
toggleformelement('filter_daterange_to_hour', false);
toggleformelement('filter_daterange_to_minute', false);
toggleformelement('filter_daterange_to_second', false);
toggleformelement('filter_daterange_last_x', true);
}
}
/*
* Helper function to add a date filter into the search field
*/
function CalculateSearchPreview(szSearchFormName, szPreviewArea)
{
var mySearchform = document.getElementById(szSearchFormName);
var myPreviewArea = document.getElementById(szPreviewArea);
var szOutString = "", szTmpString = "", nCount = 0;
if (mySearchform.elements['filter_datemode'].value == DATEMODE_RANGE)
{
szOutString += "datefrom:" + mySearchform.elements['filter_daterange_from_year'].value + "-"
+ mySearchform.elements['filter_daterange_from_month'].value + "-"
+ mySearchform.elements['filter_daterange_from_day'].value + "T"
+ mySearchform.elements['filter_daterange_from_hour'].value + ":"
+ mySearchform.elements['filter_daterange_from_minute'].value + ":"
+ mySearchform.elements['filter_daterange_from_second'].value + " ";
szOutString += "dateto:" + mySearchform.elements['filter_daterange_to_year'].value + "-"
+ mySearchform.elements['filter_daterange_to_month'].value + "-"
+ mySearchform.elements['filter_daterange_to_day'].value + "T"
+ mySearchform.elements['filter_daterange_to_hour'].value + ":"
+ mySearchform.elements['filter_daterange_to_minute'].value + ":"
+ mySearchform.elements['filter_daterange_to_second'].value + " ";
}
else if (mySearchform.elements['filter_datemode'].value == DATEMODE_LASTX)
{
szOutString += "datelastx:" + mySearchform.elements['filter_daterange_last_x'].value + " ";
}
// --- Syslog Facility
szTmpString = "";
nCount = 0;
for (var i = 0; i < mySearchform.elements['filter_facility[]'].length; i++)
{
if (mySearchform.elements['filter_facility[]'].options[i].selected == true)
{
if ( szTmpString.length > 0)
{
szTmpString += ",";
}
szTmpString += mySearchform.elements['filter_facility[]'].options[i].value;
nCount++;
}
}
if ( nCount < 18 )
{
// Only if not all selected!
szOutString += "facility:" + szTmpString + " ";
}
// ---
// --- Syslog Severity
szTmpString = "";
nCount = 0;
for (var i = 0; i < mySearchform.elements['filter_severity[]'].length; i++)
{
if (mySearchform.elements['filter_severity[]'].options[i].selected == true)
{
if ( szTmpString.length > 0)
{
szTmpString += ",";
}
szTmpString += mySearchform.elements['filter_severity[]'].options[i].value;
nCount++;
}
}
if ( nCount < 8 )
{
// Only if not all selected!
szOutString += "severity:" + szTmpString + " ";
}
// ---
// --- SyslogTag
if (mySearchform.elements['filter_syslogtag'].value.length > 0 )
{
szOutString += "syslogtag:" + mySearchform.elements['filter_syslogtag'].value + " ";
}
// ---
// --- Source
if (mySearchform.elements['filter_source'].value.length > 0 )
{
szOutString += "source:" + mySearchform.elements['filter_source'].value + " ";
}
// ---
// --- Message | Just append as it is
szOutString += mySearchform.elements['filter_message'].value;
// ---
// Set preview area
myPreviewArea.innerHTML = szOutString;
} loganalyzer-3.6.6/src/js/common.js 0000644 0001750 0001750 00000022332 12401304543 016356 0 ustar daniel daniel /* Detect Browser Version */
var szBrowserApp = "MOZILLA"; // Default!
if (/MSIE (\d+\.\d+);/.test(navigator.userAgent))
{
if (!/Opera[\/\s](\d+\.\d+)/.test(navigator.userAgent))
{
// Set browser to Internet Explorer
szBrowserApp = "IEXPLORER";
}
}
/*
Helper Javascript functions
*/
function CheckAlphaPNGImage(ImageName, ImageTrans)
{
var agt=navigator.userAgent.toLowerCase();
var is_ie = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
if (is_ie)
document.images[ImageName].src = ImageTrans;
}
function NewWindow(Location, WindowName,X_width,Y_height,Option) {
var windowReference;
var Addressbar = "location=NO"; //Default
var OptAddressBar = "AddressBar"; //Default fr Adressbar
if (Option == OptAddressBar) { //Falls AdressBar gewnscht wird
Addressbar = "location=YES";
}
windowReference = window.open(Location,WindowName,
'toolbar=no,' + Addressbar + ',directories=no,status=yes,menubar=no,scrollbars=yes,resizable=yes,copyhistory=no,width=' + X_width +
',height=' + Y_height);
if (!windowReference.opener)
windowReference.opener = self;
}
/*
* Helper function for form scripting
*/
function toggleformelement(ElementNameToggle, isEnabled)
{
var myFormElement = document.getElementById(ElementNameToggle);
if ( isEnabled ) {
myFormElement.disabled = false;
}
else {
myFormElement.disabled = true;
}
}
// helper array to keep track of the timeouts!
var runningTimeouts = new Array();
/*
* Helper function to show and hide a div area
*/
function togglevisibility(ElementNameToggle, ElementNameButton)
{
var toggle = document.getElementById(ElementNameToggle);
// Button is optional
if (ElementNameButton != null)
{
var button = document.getElementById(ElementNameButton);
}
else
var button = null;
if (toggle.style.visibility == "visible")
{
if (button != null)
{
button.className = "topmenu2 ExpansionPlus";
}
toggle.style.visibility = "hidden";
toggle.style.display = "none";
}
else
{
if (button != null)
{
button.className = "topmenu2 ExpansionMinus";
}
toggle.style.visibility = "visible";
toggle.style.display = "inline";
}
}
/*
* Helper function to hide a div area
*/
function showvisibility(ElementNameToggle, ElementNameButton)
{
var toggle = document.getElementById(ElementNameToggle);
// Button is optional
if (ElementNameButton != null)
{
var button = document.getElementById(ElementNameButton);
}
else
var button = null;
if (button != null)
{
button.className = "topmenu2 ExpansionMinus";
}
toggle.style.visibility = "visible";
toggle.style.display = "inline";
}
/*
* Helper function to hide a div area
*/
function hidevisibility(ElementNameToggle, ElementNameButton)
{
var toggle = document.getElementById(ElementNameToggle);
// Button is optional
if (ElementNameButton != null)
{
var button = document.getElementById(ElementNameButton);
}
else
var button = null;
if (button != null)
{
button.className = "topmenu2 ExpansionPlus";
}
toggle.style.visibility = "hidden";
toggle.style.display = "none";
}
function ResetFormValues(formName)
{
var myform = document.getElementById(formName);
var i = 0;
var iCount = myform.elements.length;
// Loop through text fields
for(i = 0; i < iCount; i++)
{
if (myform.elements[i].type == "text" )
{
// Reset textfield
myform.elements[i].value = "";
}
}
}
function SubmitForm(formName)
{
var myform = document.getElementById(formName);
if (myform != null)
{
myform.submit();
}
}
/*
* Helper function to show and hide areas of the filterview
*/
function toggleFormareaVisibility(FormFieldName, FirstHiddenArea, SecondHiddenArea )
{
var myfield = document.getElementById(FormFieldName);
if (myfield.value == 1)
{
togglevisibility(FirstHiddenArea);
hidevisibility(SecondHiddenArea);
}
else if (myfield.value == 2)
{
hidevisibility(FirstHiddenArea);
togglevisibility(SecondHiddenArea);
}
}
/*
* Toggle display type from NONE to BLOCK
*/
function ToggleDisplayTypeById(ObjID)
{
var obj = document.getElementById(ObjID);
if (obj != null)
{
if (obj.style.display == '' || obj.style.display == 'none')
{
obj.style.display='block';
// Set Timeout to make sure the menu disappears
ToggleDisplaySetTimeout(ObjID);
}
else
{
obj.style.display='none';
// Abort Timeout if set!
ToggleDisplayClearTimeout(ObjID);
}
}
}
function ToggleDisplaySetTimeout(ObjID)
{
// Set Timeout
var szTimeOut = "ToggleDisplayOffTypeById('" + ObjID + "')";
runningTimeouts[ObjID] = window.setTimeout(szTimeOut, defaultMenuTimeout);
}
function ToggleDisplayClearTimeout(ObjID)
{
// Abort Timeout if set!
if ( runningTimeouts[ObjID] != null )
{
window.clearTimeout(runningTimeouts[ObjID]);
}
}
function ToggleDisplayEnhanceTimeOut(ObjID)
{
// Only perform if timeout exists!
if (runningTimeouts[ObjID] != null)
{
// First clear timeout
ToggleDisplayClearTimeout(ObjID);
// Set new timeout
ToggleDisplaySetTimeout(ObjID);
}
}
/*
* Make Style sheet display OFF in any case
*/
function ToggleDisplayOffTypeById(ObjID)
{
var obj = document.getElementById(ObjID);
if (obj != null)
{
obj.style.display='none';
}
}
/*
* Debug Helper function to read possible properties of an object
*/
function DebugShowElementsById(ObjName)
{
var obj = document.getElementById(ObjName);
for (var key in obj) {
document.write(obj[key]);
}
}
/*
* Detail popup handling functions
*/
var myPopupHovering = false;
function HoveringPopup(event, parentObj)
{
// This will allow the detail window to be relocated
myPopupHovering = true;
}
function FinishHoveringPopup(event, parentObj)
{
// This will avoid moving the detail window when it is open
myPopupHovering = false;
}
function initPopupWindow(parentObj)
{
// Change CSS Class
parentObj.className='syslogdetails_popup';
}
function FinishPopupWindow(parentObj)
{
// Change CSS Class
parentObj.className='syslogdetails';
}
function disableEventPropagation(myEvent)
{
/* This workaround is specially for our beloved Internet Explorer */
if ( window.event)
{
window.event.cancelBubble = true;
}
}
function movePopupWindow(myEvent, ObjName, PopupContentWidth, parentObj)
{
var obj = document.getElementById(ObjName);
var middle = PopupContentWidth / 2;
// alert ( parentObj.className ) ;
if (myPopupHovering == false)
{
obj.style.left = (myEvent.clientX - middle) + 'px';
}
}
function GoToPopupTarget(myTarget, parentObj)
{
if (!myPopupHovering)
{
// Change document location
document.location=myTarget;
}
else /* Close Popup */
{
FinishPopupWindow(parentObj);
}
}
function FinishPopupWindowMenu()
{
// Change CSS Class
var obj = document.getElementById('popupdetails');
if (obj != null)
{
obj.className='popupdetails with_border';
}
}
function movePopupWindowMenu(myEvent, ObjName, parentObj)
{
var obj = document.getElementById(ObjName);
// var PopupContentWidth = 0;
// var middle = PopupContentWidth / 2;
var middle = -10;
if (myPopupHovering == false && obj != null && parentObj != null)
{
// Different mouse position capturing in IE!
if (szBrowserApp == "IEXPLORER")
{
obj.style.top = (event.y+document.body.scrollTop + 10) + 'px';
}
else
{
obj.style.top = (myEvent.pageY + 20) + 'px';
}
obj.style.left = (myEvent.clientX - middle) + 'px';
}
}
function HoverPopup( myObjRef, myPopupTitle, HoverContent, OptionalImage )
{
// Change CSS Class
var obj = document.getElementById('popupdetails');
obj.className='popupdetails_popup with_border';
if ( myObjRef != null)
{
myObjRef.src = OptionalImage;
// "{BASEPATH}images/player/" + myTeam + "/hover/" + ImageBaseName + ".png";
}
// Set title
var obj = document.getElementById("popuptitle");
obj.innerHTML = myPopupTitle;
// Set Content
var obj = document.getElementById("popupcontent");
obj.innerHTML = HoverContent;
}
function HoverPopupHelp( myEvent, parentObj, myPopupTitle, HoverContent )
{
// Change CSS Class
var objPopup = document.getElementById('popupdetails');
objPopup.className='popupdetails_popup with_border';
// Set title
var obj = document.getElementById("popuptitle");
obj.innerHTML = myPopupTitle;
// Set Content
obj = document.getElementById("popupcontent");
obj.innerHTML = HoverContent;
// var PopupContentWidth = 0;
/// var middle = PopupContentWidth / 2;
var middle = -5;
if (myPopupHovering == false && parentObj != null)
{
// Different mouse position capturing in IE!
objPopup.style.top = (event.y+document.body.scrollTop + 24) + 'px';
objPopup.style.left = (myEvent.clientX - middle) + 'px';
}
}
function HoverPopupMenuHelp( myEvent, parentObj, myPopupTitle, HoverContent )
{
if (szBrowserApp !== "IEXPLORER" )
{
// Don't need helper here!
return;
}
// Change CSS Class
var objPopup = document.getElementById('popupdetails');
objPopup.className='popupdetails_popup with_border';
// Set title
var obj = document.getElementById("popuptitle");
obj.innerHTML = myPopupTitle;
// Set Content
obj = document.getElementById("popupcontent");
obj.innerHTML = HoverContent;
// var PopupContentWidth = 0;
// var middle = PopupContentWidth / 2;
var middle = -5;
if (myPopupHovering == false && parentObj != null)
{
// Different mouse position capturing in IE!
objPopup.style.top = (event.y+document.body.scrollTop - 50) + 'px';
objPopup.style.left = (myEvent.clientX - middle) + 'px';
}
}
loganalyzer-3.6.6/src/reports.php 0000644 0001750 0001750 00000010062 12401304543 016320 0 ustar daniel daniel Helps administrating report modules
*
* All directives are explained within this file
*
* Copyright (C) 2008-2010 Adiscon GmbH.
*
* This file is part of LogAnalyzer.
*
* LogAnalyzer 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 3 of the License, or
* (at your option) any later version.
*
* LogAnalyzer 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.
*
* You should have received a copy of the GNU General Public License
* along with LogAnalyzer. If not, see .
*
* A copy of the GPL can be found in the file "COPYING" in this
* distribution
*
* Adiscon LogAnalyzer is also available under a commercial license.
* For details, contact info@adiscon.com or visit
* http://loganalyzer.adiscon.com/commercial
*********************************************************************
*/
// *** Default includes and procedures *** //
define('IN_PHPLOGCON', true);
$gl_root_path = './';
// Now include necessary include files!
include($gl_root_path . 'include/functions_common.php');
include($gl_root_path . 'include/functions_frontendhelpers.php');
include($gl_root_path . 'include/functions_filters.php');
include($gl_root_path . 'include/functions_reports.php');
InitPhpLogCon();
InitSourceConfigs();
InitFrontEndDefaults(); // Only in WebFrontEnd
InitFilterHelpers(); // Helpers for frontend filtering!
// ---
// --- BEGIN Custom Code
// Firts of all init List of Reports!
InitReportModules();
if ( isset($content['REPORTS']) )
{
// This will enable to Stats View
$content['reportsenabled'] = true;
$i = 0; // Help counter!
foreach ($content['REPORTS'] as &$myReport )
{
// Set if help link is enabled
if ( strlen($myReport['ReportHelpArticle']) > 0 )
$myReport['ReportHelpEnabled'] = true;
else
$myReport['ReportHelpEnabled'] = false;
// check for custom fields
if ( $myReport['NeedsInit'] ) // && count($myReport['CustomFieldsList']) > 0 )
{
// Needs custom fields!
$myReport['EnableNeedsInit'] = true;
if ( $myReport['Initialized'] )
{
$myReport['InitEnabled'] = false;
$myReport['DeleteEnabled'] = true;
}
else
{
$myReport['InitEnabled'] = true;
$myReport['DeleteEnabled'] = false;
}
}
// --- Set CSS Class
if ( $i % 2 == 0 )
{
$myReport['cssclass'] = "line1";
$myReport['rowbegin'] = '
";
// Enable pager if the count is above 1 or we don't know the record count!
if ( $content['main_recordcount'] > 1 || $content['main_recordcount'] == -1 )
{
// Enable Pager in any case here!
$content['main_pagerenabled'] = true;
// --- Handle uid_first page button
if ( $content['uid_fromgetrequest'] == $content['uid_first'] && $content['read_direction'] != EnumReadDirection::Forward )
$content['main_pager_first_found'] = false;
else
{
// Probe next item !
$ret = $stream->ReadNext($uID, $tmpArray);
if ( $content['read_direction'] == EnumReadDirection::Backward )
{
if ( $content['uid_fromgetrequest'] != UID_UNKNOWN )
$content['main_pager_first_found'] = true;
else
$content['main_pager_first_found'] = false;
}
else
{
if ( $ret == SUCCESS && $uID != $content['uid_fromgetrequest'])
$content['main_pager_first_found'] = true;
else
$content['main_pager_first_found'] = false;
}
}
// ---
// --- Handle uid_last page button
if ( $content['uid_fromgetrequest'] == $content['uid_last'] && $content['read_direction'] != EnumReadDirection::Backward )
$content['main_pager_last_found'] = false;
else
{
// Probe next item !
$ret = $stream->ReadNext($uID, $tmpArray);
if ( $content['read_direction'] == EnumReadDirection::Forward )
{
if ( $ret != SUCCESS || $uID != $content['uid_current'] )
$content['main_pager_last_found'] = true;
else
$content['main_pager_last_found'] = false;
}
else
{
if ( $ret == SUCCESS && $uID != $content['uid_current'] )
$content['main_pager_last_found'] = true;
else
$content['main_pager_last_found'] = false;
}
}
// ---
// --- Handle uid_last page button
// Option the last UID from the stream!
// $content['uid_last'] = $stream->GetLastPageUID();
// $content['uid_first'] = $stream->GetFirstPageUID();
// --- Handle uid_first and uid_previousbutton
if ( $content['uid_current'] == $content['uid_first'] || !$content['main_pager_first_found'] )
{
$content['main_pager_first_found'] = false;
$content['main_pager_previous_found'] = false;
}
else
{
$content['main_pager_first_found'] = true;
$content['main_pager_previous_found'] = true;
}
// ---
// --- Handle uid_next and uid_last button
if ( /*$content['uid_current'] == $content['uid_last'] ||*/ !$content['main_pager_last_found'] )
{
$content['main_pager_next_found'] = false;
$content['main_pager_last_found'] = false;
}
else
{
$content['main_pager_next_found'] = true;
$content['main_pager_last_found'] = true;
}
// ---
}
else // Disable pager in this case!
$content['main_pagerenabled'] = false;
// This will enable to Main SyslogView
$content['messageenabled'] = "true";
}
else
{
// Disable view and print error state!
$content['messageenabled'] = "false";
// Set error code
$content['error_code'] = $ret;
if ( $ret == ERROR_UNDEFINED )
$content['detailederror'] = "Undefined error happened within the logstream.";
else
$content['detailederror'] = "Unknown or unhandeled error occured.";
// Add extra error stuff
if ( isset($extraErrorDescription) )
$content['detailederror'] .= "
" . GetAndReplaceLangStr( $content['LN_SOURCES_ERROR_EXTRAMSG'], $extraErrorDescription);
}
}
else
{
// This will disable to Main SyslogView and show an error message
$content['messageenabled'] = "false";
// Set error code
$content['error_code'] = $ret;
if ( $ret == ERROR_FILE_NOT_FOUND )
$content['detailederror'] = $content['LN_ERROR_FILE_NOT_FOUND'];
else if ( $ret == ERROR_FILE_NOT_READABLE )
$content['detailederror'] = $content['LN_ERROR_FILE_NOT_READABLE'];
else
$content['detailederror'] = $content['LN_ERROR_UNKNOWN'];
}
// Close file!
$stream->Close();
}
// ---
// --- BEGIN CREATE TITLE
$content['TITLE'] = InitPageTitle();
if ( $content['messageenabled'] == "true" )
{
// Append custom title part!
$content['TITLE'] .= " :: Details for '" . $content['uid_current'] . "'";
}
else
{
// APpend to title Page title
$content['TITLE'] .= " :: Unknown uid";
}
// --- END CREATE TITLE
// --- Parsen and Output
InitTemplateParser();
$page -> parser($content, "details.html");
$page -> output();
// ---
?> loganalyzer-3.6.6/src/css/ 0000755 0001750 0001750 00000000000 12401304543 014702 5 ustar daniel daniel loganalyzer-3.6.6/src/css/defaults.css 0000644 0001750 0001750 00000003767 12401304543 017240 0 ustar daniel daniel /* Generic Style definitions */
.ExpansionPlus
{
background-image: url("../images/icons/navigate_plus.png");
background-repeat: no-repeat;
background-position: left center;
padding-left: 20px;
}
.ExpansionMinus
{
background-image: url("../images/icons/navigate_minus.png");
background-repeat: no-repeat;
background-position: left center;
padding-left: 20px;
}
.HiddenContent
{
visibility: hidden;
/* position: relative; */
display: none;
}
.ShownContent
{
visibility: visible;
display: inline;
}
.borderless
{
border:0px solid;
background-color: transparent;
}
.borderlessbuttons
{
border:0px solid;
background-color: transparent;
width:20px;
padding: 0px;
}
.inlinebutton
{
float:left;
position: relative;
border:0px solid;
background-color: transparent;
padding: 0px;
margin: 0px;
}
.SelectSavedFilter
{
margin-top: 2px;
border: 1px solid;
border-color: #233B51 #124A7C #124A7C #233B51;
}
.syslogdetails, a.syslogdetails, a.syslogdetails:link, a.syslogdetails:active, a.syslogdetails:visited
{
font-weight:normal;
text-decoration:none;
position:relative;
overflow:visible;
}
.syslogdetails
{
position:relative;
overflow:visible;
z-index:4;
}
.syslogdetails:hover
{
position:relative; /*this is the key*/
font-weight:normal;
z-index:5;
}
.syslogdetails span
{
position:relative;
overflow:visible;
display: none;
z-index:-1;
}
/*the span will display just on :hover state*/
.syslogdetails_popup span
{
display:block;
position:absolute;
overflow:auto;
z-index:5;
/* top:15px; */
/* left:15px; */
}
.gridline
{
vertical-align: top;
height: 16px;
}
/*
* POPUP Helper Styles
*/
.popupdetails
{
position: absolute;
visibility: hidden;
z-index:1
}
.popupdetails:hover
{
position: absolute;
visibility: hidden;
z-index: 2;
}
.popupdetails_popup
{
position: absolute;
visibility: visible;
z-index: 2;
}
loganalyzer-3.6.6/src/css/highlight.css 0000644 0001750 0001750 00000002010 12401304543 017354 0 ustar daniel daniel /* Generic Style definitions */
.highlight_1
{
color: #F61313;
background-color: #FFFFFF;
}
.highlight_2
{
color: #F66913;
background-color: #FFFFFF;
}
.highlight_3
{
color: #17911C;
background-color: #FFFFFF;
}
.highlight_4
{
color: #C01695;
background-color: #FFFFFF;
}
.highlight_5
{
color: #1D618B;
background-color: #FFFFFF;
}
.highlight_6
{
color: #6C9117;
background-color: #FFFFFF;
}
.highlight_7
{
color: #0F2B7F;
background-color: #FFFFFF;
}
.highlight_8
{
color: #541791;
background-color: #FFFFFF;
}
.highlight_9
{
color: #146043;
background-color: #FFFFFF;
}
.highlight_10
{
color: #FF5451;
background-color: #333333;
}
.highlight_11
{
color: #F8C858;
background-color: #333333;
}
.highlight_12
{
color: #FCFF84;
background-color: #333333;
}
.highlight_13
{
color: #CEF07A;
background-color: #333333;
}
.highlight_14
{
color: #7AF0C2;
background-color: #333333;
}
.highlight_15
{
color: #84AFFF;
background-color: #333333;
}
.highlight_16
{
color: #A684FF;
background-color: #333333;
}
loganalyzer-3.6.6/src/css/menu.css 0000644 0001750 0001750 00000002252 12401304543 016361 0 ustar daniel daniel
#menu {
z-index: 10;
/* width: 16px; /* set width of menu */
}
#menu ul { /* remove bullets and list indents */
z-index: 10;
position: relative;
/* position: absolute;*/
display: block;
list-style: none;
white-space:nowrap;
margin: 0;
padding: 0;
vertical-align: text-top;
}
/* style, color and size links and headings to suit */
#menu a, #menu h2 {
display: block;
margin: 0px;
padding: 1px 1px;
}
#menu h2 {
font-size: 10px;
font-weight: bold;
text-align: center;
}
#menu a {
text-decoration: none;
}
#menu a:hover {
text-decoration: none;
}
#menu li {
text-align: left;
/* make the list elements a containing block for the nested lists */
position: relative;
}
#menu ul li ul li {
border-width: 1px;
border-style: solid;
border-color: #44617D #203040 #203040 #44617D;
}
#menu ul ul {
z-index: 2;
white-space: nowrap;
position: absolute;
top: 12px; /*14px; */
left: 0px; /* to position them to the right of their containing block */
width: auto;
min-width: 250px; /* workaround for FF */
height: 16px;
}
div#menu ul ul,
div#menu ul li:hover ul ul
{
display: none;
}
div#menu ul li:hover ul,
div#menu ul ul li:hover ul
{
display: block;
}
loganalyzer-3.6.6/src/classes/ 0000755 0001750 0001750 00000000000 12401304543 015547 5 ustar daniel daniel loganalyzer-3.6.6/src/classes/msgparser.class.php 0000644 0001750 0001750 00000004571 12401304543 021376 0 ustar daniel daniel .
*
* A copy of the GPL can be found in the file "COPYING" in this
* distribution.
*
* Adiscon LogAnalyzer is also available under a commercial license.
* For details, contact info@adiscon.com or visit
* http://loganalyzer.adiscon.com/commercial
*********************************************************************
*/
// --- Avoid directly accessing this file!
if ( !defined('IN_PHPLOGCON') )
{
die('Hacking attempt');
exit;
}
// ---
// --- Basic Includes
require_once($gl_root_path . 'classes/enums.class.php');
require_once($gl_root_path . 'include/constants_errors.php');
require_once($gl_root_path . 'include/constants_logstream.php');
// ---
abstract class MsgParser{
// Public configuration properties
public $_MsgNormalize = 0; // If set to one, the msg will be reconstructed if successfully parsed before
// Public Information properties
public $_ClassName = 'Default Messageparser';
public $_ClassDescription = 'This is a placeholder for the message parser description!';
public $_ClassRequiredFields = null;
public $_ClassHelpArticle = "http://www.monitorware.com/en/Articles/";
/**
* ParseLine
*
* @param arrArguments array in&out: properties of interest. There can be no guarantee the logstream can actually deliver them.
* @return integer Error stat
*/
public abstract function ParseMsg($szMsg, &$arrArguments);
}
?> loganalyzer-3.6.6/src/classes/logstreamconfigmongodb.class.php 0000644 0001750 0001750 00000005015 12401304543 024116 0 ustar daniel daniel .
*
* 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;
}
// ---
class LogStreamConfigMongoDB extends LogStreamConfig {
public $DBServer = '127.0.0.1';
public $DBPort = 27017;
public $DBName = 'syslog';
public $DBUser = ''; // Default = No database user!
public $DBPassword = ''; // Default = No Password
public $DBTableType = 'mongodb'; // Default = Use mongodb layout!
public $DBCollection = 'rsyslog'; // Default Tabelname from RSYSLOG
// public $DBEnableRowCounting = true; // Default RowCounting is enabled!
// Runtime configuration variables
public $RecordsPerQuery = 100; // This will determine how to limit sql statements
public $IDsPerQuery = 5000; // When we query ID's, we read a lot more the datarecords at once!
public $SortColumn = SYSLOG_UID; // Default sorting column
// public $FileName = '';
// public $LineParserType = "syslog"; // Default = Syslog!
// public $_lineParser = null;
public function LogStreamFactory($o)
{
// An instance is created, then include the logstreamdisk class as well!
global $gl_root_path;
require_once($gl_root_path . 'classes/logstreammongodb.class.php');
// return LogStreamDisk instance
return new LogStreamMongoDB($o);
}
}
?> loganalyzer-3.6.6/src/classes/logstreamconfig.class.php 0000644 0001750 0001750 00000012477 12401304543 022562 0 ustar daniel daniel .
*
* 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;
}
// ---
abstract class LogStreamConfig {
// Public needed properties
public $_pageCount = 50; // Paging Count number!
// protected properties
protected $_logStreamConfigObj = null;
protected $_logStreamId = -1;
protected $_logStreamName = '';
protected $_defaultFacility = '';
protected $_defaultSeverity = '';
// helpers properties for message parser list!
protected $_msgParserList = null; // Contains a string list of configure msg parsers
protected $_msgParserObjList = null; // Contains an object reference list to the msg parsers
protected $_MsgNormalize = 0; // If set to one, the msg will be reconstructed if successfully parsed before
public $_defaultfilter = ""; // Default filter for this source, will be added to all further filters.
public $_SkipUnparseable = 0; // If set to one, all unparseable message will be ignored! This of course only applies if a msg parser is used
// Constructor prototype
public abstract function LogStreamFactory($o);
/*
* Initialize Msg Parsers!
*/
public function InitMsgParsers()
{
// Init parsers if available and not initialized already!
if ( $this->_msgParserList != null && $this->_msgParserObjList == null )
{
// Loop through parsers
foreach( $this->_msgParserList as $szParser )
{
// Set Classname
$szClassName = "MsgParser_" . $szParser;
// Create OBjectRef!
$NewParser = new $szClassName(); // Create new instance
$NewParser->_MsgNormalize = $this->_MsgNormalize; // Copy property!
$this->_msgParserObjList[] = $NewParser; // Append NewParser to Parser array
}
}
}
/*
* Helper function to init Parserlist
*/
public function SetSkipUnparseable( $nNewVal )
{
if ( $nNewVal == 0 )
$this->_SkipUnparseable = 0;
else
$this->_SkipUnparseable = 1;
}
/*
* Helper function to init Parserlist
*/
public function SetMsgNormalize( $nNewVal )
{
if ( $nNewVal == 0 )
$this->_MsgNormalize = 0;
else
$this->_MsgNormalize = 1;
}
/*
* Helper function to set defautl filters
*/
public function SetDefaultfilter( $szNewVal )
{
$this->_defaultfilter = $szNewVal;
}
/*
* Helper function to init Parserlist
*/
public function SetMsgParserList( $szParsers )
{
global $gl_root_path;
// Check if we have at least something to check
if ( $szParsers == null || strlen($szParsers) <= 0 )
return;
// Set list of Parsers!
if ( strpos($szParsers, ",") )
$aParsers = explode( ",", $szParsers );
else
$aParsers[0] = $szParsers;
// Loop through parsers
foreach( $aParsers as $szParser )
{
// Remove whitespaces
$szParser = trim($szParser);
// Check if parser file include exists
$szIncludeFile = $gl_root_path . 'classes/msgparsers/msgparser.' . $szParser . '.class.php';
if ( file_exists($szIncludeFile) )
{
// Try to include
if ( @include_once($szIncludeFile) )
$this->_msgParserList[] = $szParser;
else
OutputDebugMessage("Error, MsgParser '" . $szParser . "' could not be included. ", DEBUG_ERROR);
}
}
// print_r ( $this->_msgParserList );
}
public function ProcessMsgParsers($szMsg, &$arrArguments)
{
// Abort msgparsers if we have less then 5 seconds of processing time!
global $content, $gl_starttime;
$scriptruntime = intval(microtime_float() - $gl_starttime);
if ( $scriptruntime > ($content['MaxExecutionTime']-5) )
return ERROR_MSG_SCANABORTED;
// Process if set!
if ( $this->_msgParserObjList != null )
{
foreach( $this->_msgParserObjList as $myMsgParser )
{
// Perform Parsing, and return if was successfull or the message needs to be skipped!
// Otherwise the next Parser will be called.
$ret = $myMsgParser->ParseMsg($szMsg, $arrArguments);
if ( $ret == SUCCESS || $ret == ERROR_MSG_SKIPMESSAGE )
return $ret;
// Extra check, if user wants to, we SKIP the message!
if ( $this->_SkipUnparseable == 1 && $ret == ERROR_MSG_NOMATCH )
return ERROR_MSG_SKIPMESSAGE;
}
}
// reached this means all work is done!
return SUCCESS;
}
}
?> loganalyzer-3.6.6/src/classes/msgparsers/ 0000755 0001750 0001750 00000000000 12401305611 017732 5 ustar daniel daniel loganalyzer-3.6.6/src/classes/msgparsers/msgparser.apache2common.class.php 0000644 0001750 0001750 00000011667 12401304543 026303 0 ustar daniel daniel .
*
* 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;
}
// ---
// --- Basic Includes
require_once($gl_root_path . 'classes/enums.class.php');
require_once($gl_root_path . 'classes/msgparser.class.php');
require_once($gl_root_path . 'include/constants_errors.php');
require_once($gl_root_path . 'include/constants_logstream.php');
// ---
class MsgParser_apache2common extends MsgParser {
// Public Information properties
public $_ClassName = 'Apache 2 Common Format';
public $_ClassDescription = 'Parses the common logfile format from Apache2 webservers.';
public $_ClassRequiredFields = null;
public $_ClassHelpArticle = "http://www.monitorware.com/Common/en/Articles/setup_mwagent_webserverlogging_phplogcon_mysql.php";
// Constructor
public function MsgParser_apache2common() {
return; // Nothing
}
/**
* ParseLine
*
* @param arrArguments array in&out: properties of interest. There can be no guarantee the logstream can actually deliver them.
* @return integer Error stat
*/
public function ParseMsg($szMsg, &$arrArguments)
{
global $content, $fields;
//trim the msg first to remove spaces from begin and end
$szMsg = trim($szMsg);
//return ERROR_MSG_NOMATCH;
// LogFormat "%h %l %u %t \"%r\" %>s %b" common
// LogFormat "%{Referer}i -> %U" referer
// LogFormat "%{User-agent}i" agent
// LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
// Sample (apache2): 127.0.0.1 - - [14/Sep/2008:06:50:15 +0200] "GET / HTTP/1.0" 200 19023
// Sample: 65.55.211.112 - - [16/Sep/2008:13:37:47 +0200] "GET /index.php?name=News&file=article&sid=1&theme=Printer HTTP/1.1" 200 4908
if ( preg_match('/(.|.*?) (.|.*?) (.|.*?) \[(.*?)\] "(.*?) (.*?) (.*?)" (.|[0-9]{1,12}) (.|[0-9]{1,12})$/', $szMsg, $out ) )
{
// print_r ( $out );
// exit;
// Set generic properties
$arrArguments[SYSLOG_HOST] = $out[1];
$arrArguments[SYSLOG_DATE] = GetEventTime($out[4]);
// Set weblog specific properties!
$arrArguments[SYSLOG_WEBLOG_USER] = $out[3];
$arrArguments[SYSLOG_WEBLOG_METHOD] = $out[5];
if ( strpos($out[6], "?") === false )
{
$arrArguments[SYSLOG_WEBLOG_URL] = $out[6];
$arrArguments[SYSLOG_WEBLOG_QUERYSTRING]= "";
}
else
{
$arrArguments[SYSLOG_WEBLOG_URL] = substr( $out[6], 0, strpos($out[6], "?"));
$arrArguments[SYSLOG_WEBLOG_QUERYSTRING]= substr( $out[6], strpos($out[6], "?")+1 );
}
// Number based fields
$arrArguments[SYSLOG_WEBLOG_PVER] = $out[7];
$arrArguments[SYSLOG_WEBLOG_STATUS] = $out[8];
$arrArguments[SYSLOG_WEBLOG_BYTESSEND] = $out[9];
// Set msg to whole logline
$arrArguments[SYSLOG_MESSAGE] = $out[0];
if ( $this->_MsgNormalize == 1 )
{
//Init tmp msg
$szTmpMsg = "";
// Create Field Array to prepend into msg! Reverse Order here
$myFields = array( SYSLOG_WEBLOG_USER, SYSLOG_WEBLOG_PVER, SYSLOG_WEBLOG_BYTESSEND, SYSLOG_WEBLOG_STATUS, SYSLOG_WEBLOG_METHOD, SYSLOG_WEBLOG_QUERYSTRING, SYSLOG_WEBLOG_URL );
foreach ( $myFields as $myField )
{
// Set Field Caption
if ( isset($fields[$myField]['FieldCaption']) )
$szFieldName = $fields[$myField]['FieldCaption'];
else
$szFieldName = $myField;
// Append Field into msg
$szTmpMsg = $szFieldName . ": '" . $arrArguments[$myField] . "'\n" . $szTmpMsg;
}
// copy finished MSG back!
$arrArguments[SYSLOG_MESSAGE] = $szTmpMsg;
}
}
else
{
// return no match in this case!
return ERROR_MSG_NOMATCH;
}
// Set IUT Property if success!
$arrArguments[SYSLOG_MESSAGETYPE] = IUT_WEBSERVERLOG;
// If we reached this position, return success!
return SUCCESS;
}
}
?> loganalyzer-3.6.6/src/classes/msgparsers/msgparser.apache2.class.php 0000644 0001750 0001750 00000012254 12401304543 025063 0 ustar daniel daniel .
*
* 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;
}
// ---
// --- Basic Includes
require_once($gl_root_path . 'classes/enums.class.php');
require_once($gl_root_path . 'classes/msgparser.class.php');
require_once($gl_root_path . 'include/constants_errors.php');
require_once($gl_root_path . 'include/constants_logstream.php');
// ---
class MsgParser_apache2 extends MsgParser {
// Public Information properties
public $_ClassName = 'Apache 2 Combined Format';
public $_ClassDescription = 'Parses the combined logfile format from Apache2 webservers.';
public $_ClassRequiredFields = null;
public $_ClassHelpArticle = "http://www.monitorware.com/Common/en/Articles/setup_mwagent_webserverlogging_phplogcon_mysql.php";
// Constructor
public function MsgParser_apache2() {
return; // Nothing
}
/**
* ParseLine
*
* @param arrArguments array in&out: properties of interest. There can be no guarantee the logstream can actually deliver them.
* @return integer Error stat
*/
public function ParseMsg($szMsg, &$arrArguments)
{
global $content, $fields;
//trim the msg first to remove spaces from begin and end
$szMsg = trim($szMsg);
//return ERROR_MSG_NOMATCH;
// LogFormat "%h %l %u %t \"%r\" %>s %b" common
// LogFormat "%{Referer}i -> %U" referer
// LogFormat "%{User-agent}i" agent
// LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
// Sample (apache2): 127.0.0.1 - - [14/Sep/2008:06:50:15 +0200] "GET / HTTP/1.0" 200 19023 "-" "VoilaBot link checker"
// Sample: 65.55.211.112 - - [16/Sep/2008:13:37:47 +0200] "GET /index.php?name=News&file=article&sid=1&theme=Printer HTTP/1.1" 200 4908 "-" "msnbot/1.1 (+http://search.msn.com/msnbot.htm)"
if ( preg_match('/(.|.*?) (.|.*?) (.|.*?) \[(.*?)\] "(.*?) (.*?) (.*?)" (.|[0-9]{1,12}) (.|[0-9]{1,12}) "(.|.*?)" "(.*?)("|)$/', $szMsg, $out ) )
{
// print_r ( $out );
// exit;
// Set generic properties
$arrArguments[SYSLOG_HOST] = $out[1];
$arrArguments[SYSLOG_DATE] = GetEventTime($out[4]);
// Set weblog specific properties!
$arrArguments[SYSLOG_WEBLOG_USER] = $out[3];
$arrArguments[SYSLOG_WEBLOG_METHOD] = $out[5];
if ( strpos($out[6], "?") === false )
{
$arrArguments[SYSLOG_WEBLOG_URL] = $out[6];
$arrArguments[SYSLOG_WEBLOG_QUERYSTRING]= "";
}
else
{
$arrArguments[SYSLOG_WEBLOG_URL] = substr( $out[6], 0, strpos($out[6], "?"));
$arrArguments[SYSLOG_WEBLOG_QUERYSTRING]= substr( $out[6], strpos($out[6], "?")+1 );
}
// Number based fields
$arrArguments[SYSLOG_WEBLOG_PVER] = $out[7];
$arrArguments[SYSLOG_WEBLOG_STATUS] = $out[8];
$arrArguments[SYSLOG_WEBLOG_BYTESSEND] = $out[9];
$arrArguments[SYSLOG_WEBLOG_REFERER] = $out[10];
$arrArguments[SYSLOG_WEBLOG_USERAGENT] = $out[11];
// Set msg to whole logline
$arrArguments[SYSLOG_MESSAGE] = $out[0];
if ( $this->_MsgNormalize == 1 )
{
//Init tmp msg
$szTmpMsg = "";
// Create Field Array to prepend into msg! Reverse Order here
$myFields = array( SYSLOG_WEBLOG_USER, SYSLOG_WEBLOG_PVER, SYSLOG_WEBLOG_USERAGENT, SYSLOG_WEBLOG_BYTESSEND, SYSLOG_WEBLOG_STATUS, SYSLOG_WEBLOG_REFERER, SYSLOG_WEBLOG_METHOD, SYSLOG_WEBLOG_QUERYSTRING, SYSLOG_WEBLOG_URL );
foreach ( $myFields as $myField )
{
// Set Field Caption
if ( isset($fields[$myField]['FieldCaption']) )
$szFieldName = $fields[$myField]['FieldCaption'];
else
$szFieldName = $myField;
// Append Field into msg
$szTmpMsg = $szFieldName . ": '" . $arrArguments[$myField] . "'\n" . $szTmpMsg;
}
// copy finished MSG back!
$arrArguments[SYSLOG_MESSAGE] = $szTmpMsg;
}
}
else
{
// return no match in this case!
return ERROR_MSG_NOMATCH;
}
// Set IUT Property if success!
$arrArguments[SYSLOG_MESSAGETYPE] = IUT_WEBSERVERLOG;
// If we reached this position, return success!
return SUCCESS;
}
}
?> loganalyzer-3.6.6/src/classes/msgparsers/msgparser.eventlog.class.php 0000644 0001750 0001750 00000010111 12401304543 025371 0 ustar daniel daniel .
*
* 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;
}
// ---
// --- Basic Includes
require_once($gl_root_path . 'classes/enums.class.php');
require_once($gl_root_path . 'classes/msgparser.class.php');
require_once($gl_root_path . 'include/constants_errors.php');
require_once($gl_root_path . 'include/constants_logstream.php');
// ---
class MsgParser_eventlog extends MsgParser {
// Public Information properties
public $_ClassName = 'Adiscon Eventlog Format';
public $_ClassDescription = 'This is a parser for a special format which can be created with Adiscon Eventreporter or MonitorWare Agent.';
public $_ClassRequiredFields = null;
public $_ClassHelpArticle = "http://www.monitorware.com/en/Articles/";
// Constructor
public function MsgParser_eventlog() {
return; // Nothing
}
/**
* ParseLine
*
* @param arrArguments array in&out: properties of interest. There can be no guarantee the logstream can actually deliver them.
* @return integer Error stat
*/
public function ParseMsg($szMsg, &$arrArguments)
{
global $content, $fields;
//trim the msg first to remove spaces from begin and end
$szMsg = trim($szMsg);
// Sample (WinSyslog/EventReporter): 7035,XPVS2005\Administrator,Service Control Manager,System,[INF],0,The Adiscon EvntSLog service was successfully sent a start control.
// Source: %id%,%user%,%sourceproc%,%NTEventLogType%,%severity%,%category%,%msg%%$CRLF%
if ( preg_match("/([0-9]{1,12}),(.*?),(.*?),(.*?),(.*?),([0-9]{1,12}),(.*?)$/", $szMsg, $out ) )
{
// Copy parsed properties!
$arrArguments[SYSLOG_EVENT_ID] = $out[1];
$arrArguments[SYSLOG_EVENT_USER] = $out[2];
$arrArguments[SYSLOG_EVENT_SOURCE] = $out[3];
$arrArguments[SYSLOG_EVENT_LOGTYPE] = $out[4];
/// $arrArguments[SYSLOG_SEVERITY] = $out[5];
$arrArguments[SYSLOG_EVENT_CATEGORY] = $out[6];
$arrArguments[SYSLOG_MESSAGE] = $out[7];
if ( $this->_MsgNormalize == 1 )
{
//Init tmp msg
$szTmpMsg = "";
// Create Field Array to prepend into msg! Reverse Order here
$myFields = array( SYSLOG_MESSAGE, SYSLOG_EVENT_CATEGORY, SYSLOG_EVENT_LOGTYPE, SYSLOG_EVENT_SOURCE, SYSLOG_EVENT_USER, SYSLOG_EVENT_ID );
foreach ( $myFields as $myField )
{
// Set Field Caption
if ( isset($fields[$myField]['FieldCaption']) )
$szFieldName = $fields[$myField]['FieldCaption'];
else
$szFieldName = $myField;
// Append Field into msg
$szTmpMsg = $szFieldName . ": '" . $arrArguments[$myField] . "'\n" . $szTmpMsg;
}
// copy finished MSG back!
$arrArguments[SYSLOG_MESSAGE] = $szTmpMsg;
}
}
else
{
// return no match in this case!
return ERROR_MSG_NOMATCH;
}
// Set IUT Property if success!
$arrArguments[SYSLOG_MESSAGETYPE] = IUT_NT_EventReport;
// If we reached this position, return success!
return SUCCESS;
}
}
?> loganalyzer-3.6.6/src/classes/msgparsers/msgparser.iis.class.php 0000644 0001750 0001750 00000013210 12401304543 024335 0 ustar daniel daniel .
*
* 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;
}
// ---
// --- Basic Includes
require_once($gl_root_path . 'classes/enums.class.php');
require_once($gl_root_path . 'classes/msgparser.class.php');
require_once($gl_root_path . 'include/constants_errors.php');
require_once($gl_root_path . 'include/constants_logstream.php');
// ---
class MsgParser_iis extends MsgParser {
// Public Information properties
public $_ClassName = 'Microsoft IIS Weblogs';
public $_ClassDescription = 'Parses the common weblog format used by the Microsoft IIS webserver.';
public $_ClassRequiredFields = null;
public $_ClassHelpArticle = "http://www.monitorware.com/en/Articles/";
// Constructor
public function MsgParser_iis() {
return; // Nothing
}
/**
* ParseLine
*
* @param arrArguments array in&out: properties of interest. There can be no guarantee the logstream can actually deliver them.
* @return integer Error stat
*/
public function ParseMsg($szMsg, &$arrArguments)
{
global $content, $fields;
//trim the msg first to remove spaces from begin and end
$szMsg = trim($szMsg);
// $iSharpPos = strpos($szMsg, "#");
// if ( $iSharpPos !== false && $iSharpPos == 0 )
// return ERROR_MSG_SKIPMESSAGE;
// Special case here, if loglines start with #, they are comments and have to be skipped!
if ( ($iSharpPos = strpos($szMsg, "#")) !== false && $iSharpPos == 0 )
{
// Only init fields then
// Set generic properties
$arrArguments[SYSLOG_DATE] = "";
$arrArguments[SYSLOG_HOST] = "";
// Set weblog specific properties!
$arrArguments[SYSLOG_WEBLOG_METHOD] = "";
$arrArguments[SYSLOG_WEBLOG_URL] = "";
$arrArguments[SYSLOG_WEBLOG_QUERYSTRING] = "";
$arrArguments[SYSLOG_WEBLOG_USER] = "";
$arrArguments[SYSLOG_WEBLOG_PVER] = "";
$arrArguments[SYSLOG_WEBLOG_USERAGENT] = "";
$arrArguments[SYSLOG_WEBLOG_REFERER] = "";
$arrArguments[SYSLOG_WEBLOG_STATUS] = "";
$arrArguments[SYSLOG_WEBLOG_BYTESSEND] = "";
// Set msg to whole logline
$arrArguments[SYSLOG_MESSAGE] = $szMsg;
}
// LogFormat: date time cs-method cs-uri-stem cs-uri-query cs-username c-ip cs-version cs(User-Agent) cs(Referer) sc-status sc-bytes
// Sample: 2008-09-17 00:15:24 GET /Include/MyStyleV2.css - - 208.111.154.249 HTTP/1.0 Mozilla/5.0+(X11;+U;+Linux+i686+(x86_64);+en-US;+rv:1.8.1.11)+Gecko/20080109+(Charlotte/0.9t;+http://www.searchme.com/support/) http://www.adiscon.com/Common/en/News/MWCon-2005-09-12.php 200 1812
if ( preg_match('/([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}) (.*?) (.|.*?) (.|.*?) (.|.*?) (.|.*?) (.|.*?) (.|.*?) (.|.*?) (.|.*?) (.|.*?)$/', $szMsg, $out ) )
{
// print_r ( $out );
// exit;
// Set generic properties
$arrArguments[SYSLOG_DATE] = GetEventTime($out[1]);
$arrArguments[SYSLOG_HOST] = $out[6];
// Set weblog specific properties!
$arrArguments[SYSLOG_WEBLOG_METHOD] = $out[2];
$arrArguments[SYSLOG_WEBLOG_URL] = $out[3];
$arrArguments[SYSLOG_WEBLOG_QUERYSTRING]= $out[4];
$arrArguments[SYSLOG_WEBLOG_USER] = $out[5];
$arrArguments[SYSLOG_WEBLOG_PVER] = $out[7];
$arrArguments[SYSLOG_WEBLOG_USERAGENT] = $out[8];
$arrArguments[SYSLOG_WEBLOG_REFERER] = $out[9];
$arrArguments[SYSLOG_WEBLOG_STATUS] = $out[10];
$arrArguments[SYSLOG_WEBLOG_BYTESSEND] = $out[11];
// Set msg to whole logline
$arrArguments[SYSLOG_MESSAGE] = $out[0];
if ( $this->_MsgNormalize == 1 )
{
//Init tmp msg
$szTmpMsg = "";
// Create Field Array to prepend into msg! Reverse Order here
$myFields = array( SYSLOG_WEBLOG_USER, SYSLOG_WEBLOG_PVER, SYSLOG_WEBLOG_USERAGENT, SYSLOG_WEBLOG_BYTESSEND, SYSLOG_WEBLOG_STATUS, SYSLOG_WEBLOG_REFERER, SYSLOG_WEBLOG_METHOD, SYSLOG_WEBLOG_QUERYSTRING, SYSLOG_WEBLOG_URL );
foreach ( $myFields as $myField )
{
// Set Field Caption
if ( isset($fields[$myField]['FieldCaption']) )
$szFieldName = $fields[$myField]['FieldCaption'];
else
$szFieldName = $myField;
// Append Field into msg
$szTmpMsg = $szFieldName . ": '" . $arrArguments[$myField] . "'\n" . $szTmpMsg;
}
// copy finished MSG back!
$arrArguments[SYSLOG_MESSAGE] = $szTmpMsg;
}
}
else
{
// return no match in this case!
return ERROR_MSG_NOMATCH;
}
// Set IUT Property if success!
$arrArguments[SYSLOG_MESSAGETYPE] = IUT_WEBSERVERLOG;
// If we reached this position, return success!
return SUCCESS;
}
}
?> loganalyzer-3.6.6/src/classes/logstreamlineparsermisc.class.php 0000644 0001750 0001750 00000004461 12401304543 024327 0 ustar daniel daniel .
*
* A copy of the GPL can be found in the file "COPYING" in this
* distribution.
*
* Adiscon LogAnalyzer is also available under a commercial license.
* For details, contact info@adiscon.com or visit
* http://loganalyzer.adiscon.com/commercial
*********************************************************************
*/
// --- Avoid directly accessing this file!
if ( !defined('IN_PHPLOGCON') )
{
die('Hacking attempt');
exit;
}
// ---
// --- Basic Includes
require_once($gl_root_path . 'classes/enums.class.php');
require_once($gl_root_path . 'include/constants_errors.php');
require_once($gl_root_path . 'include/constants_logstream.php');
// ---
class LogStreamLineParsermisc extends LogStreamLineParser {
// protected $_arrProperties = null;
// Constructor
public function LogStreamLineParsermisc() {
return; // Nothing
}
/**
* ParseLine
*
* @param arrArguments array in&out: properties of interest. There can be no guarantee the logstream can actually deliver them.
* @return integer Error stat
*/
public function ParseLine($szLine, &$arrArguments)
{
// Set MSG Property
$arrArguments[SYSLOG_MESSAGE] = $szLine;
// Set IUT Property
$arrArguments[SYSLOG_MESSAGETYPE] = IUT_Unknown;
// Return success!
return SUCCESS;
}
}
?> loganalyzer-3.6.6/src/classes/logstreamlineparsersyslogng.class.php 0000644 0001750 0001750 00000015741 12401304543 025244 0 ustar daniel daniel severity
* +--------> facility
*
* destination messages { file("/var/log/messages"
* template("$FACILITY_NUM $LEVEL_NUM $DATE $FULLHOST $MESSAGE\n")
* );
* };
*
* Referensi macro:
* http://www.balabit.com/sites/default/files/documents/syslog-ng-ose-3.3
* -guides/en/syslog-ng-ose-v3.3-guide-admin-en/html/reference_macros.html
*
*
* All directives are explained within this file *
*
* Copyright (C) 2008-2010 Adiscon GmbH.
*
* This file is part of LogAnalyzer.
*
* LogAnalyzer 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 3 of the License, or
* (at your option) any later version.
*
* LogAnalyzer 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.
*
* You should have received a copy of the GNU General Public License
* along with LogAnalyzer. If not, see .
*
* A copy of the GPL can be found in the file "COPYING" in this
* distribution.
*
* Adiscon LogAnalyzer is also available under a commercial license.
* For details, contact info@adiscon.com or visit
* http://loganalyzer.adiscon.com/commercial
*********************************************************************
*/
// --- Avoid directly accessing this file!
if ( !defined('IN_PHPLOGCON') )
{
die('Hacking attempt');
exit;
}
// ---
// --- Basic Includes
require_once($gl_root_path . 'classes/enums.class.php');
require_once($gl_root_path . 'include/constants_errors.php');
require_once($gl_root_path . 'include/constants_logstream.php');
// ---
class LogStreamLineParsersyslog extends LogStreamLineParser {
// protected $_arrProperties = null;
// Constructor
public function LogStreamLineParsersyslog() {
return; // Nothing
}
/**
* ParseLine
*
* @param arrArguments array in&out: properties of interest. There can be no guarantee the logstream can actually deliver them.
* @return integer Error stat
*/
public function ParseLine($szLine, &$arrArguments)
{
// Set IUT Property first!
$arrArguments[SYSLOG_MESSAGETYPE] = IUT_Syslog;
// MULYADI: add code to parse facility and level number (each 1 digit decimal)
// Sample (Syslog): 2 2 Mar 10 14:45:44 debandre anacron[3226]: Job `cron.daily' terminated (mailing output)
if ( preg_match("/([0-9]) ([0-9]) (...)(?:.|..)([0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}) ([a-zA-Z0-9_\-\.]{1,256}) ([A-Za-z0-9_\-\/\.]{1,32})\[(.*?)\]:(.*?)$/", $szLine, $out ) )
{
// Copy parsed properties!
$arrArguments[SYSLOG_FACILITY] = $out[1];
$arrArguments[SYSLOG_SEVERITY] = $out[2];
$arrArguments[SYSLOG_DATE] = GetEventTime($out[3] . " " . $out[4]);
$arrArguments[SYSLOG_HOST] = $out[5];
$arrArguments[SYSLOG_SYSLOGTAG] = $out[6];
$arrArguments[SYSLOG_PROCESSID] = $out[7];
$arrArguments[SYSLOG_MESSAGE] = $out[8];
}
// Sample (Syslog): 2 2 Mar 10 14:45:39 debandre syslogd 1.4.1#18: restart
else if ( preg_match("/([0-9]) ([0-9]) (...)(?:.|..)([0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}) ([a-zA-Z0-9_\-\.]{1,256}) ([A-Za-z0-9_\-\/\.]{1,32}):(.*?)$/", $szLine, $out ) )
{
// Copy parsed properties!
$arrArguments[SYSLOG_FACILITY] = $out[1];
$arrArguments[SYSLOG_SEVERITY] = $out[2];
$arrArguments[SYSLOG_DATE] = GetEventTime($out[3] . " " . $out[4]);
$arrArguments[SYSLOG_HOST] = $out[5];
$arrArguments[SYSLOG_SYSLOGTAG] = $out[6];
$arrArguments[SYSLOG_MESSAGE] = $out[7];
}
// Sample (Syslog): 2 2 Mar 10 14:45:39 debandre syslogd restart
else if ( preg_match("/([0-9]) ([0-9]) (...)(?:.|..)([0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}) ([a-zA-Z0-9_\-\.]{1,256}) ([A-Za-z0-9_\-\/\.]{1,32}) (.*?)$/", $szLine, $out ) )
{
// Copy parsed properties!
$arrArguments[SYSLOG_FACILITY] = $out[1];
$arrArguments[SYSLOG_SEVERITY] = $out[2];
$arrArguments[SYSLOG_DATE] = GetEventTime($out[3] . " " . $out[4]);
$arrArguments[SYSLOG_HOST] = $out[5];
$arrArguments[SYSLOG_SYSLOGTAG] = $out[6];
$arrArguments[SYSLOG_MESSAGE] = $out[7];
}
// Sample (Syslog): 2 2 Mar 7 17:18:35 debandre exiting on signal 15
else if ( preg_match("/([0-9]) ([0-9]) (...)(?:.|..)([0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}) (.*?) (.*?)$/", $szLine, $out ) )
{
// Copy parsed properties!
$arrArguments[SYSLOG_FACILITY] = $out[1];
$arrArguments[SYSLOG_SEVERITY] = $out[2];
$arrArguments[SYSLOG_DATE] = GetEventTime($out[3] . " " . $out[4]);
$arrArguments[SYSLOG_HOST] = $out[5];
$arrArguments[SYSLOG_MESSAGE] = $out[6];
}
// Sample (RSyslog): 2008-03-28T11:07:40+01:00 localhost rger: test 1
else if ( preg_match("/([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}.[0-9]{1,2}:[0-9]{1,2}) (.*?) (.*?):(.*?)$/", $szLine, $out ) )
{
// Copy parsed properties!
$arrArguments[SYSLOG_DATE] = GetEventTime($out[1]);
$arrArguments[SYSLOG_HOST] = $out[2];
$arrArguments[SYSLOG_SYSLOGTAG] = $out[3];
$arrArguments[SYSLOG_MESSAGE] = $out[4];
}
// Sample (RSyslog): 2008-03-28T11:07:40.591633+01:00 localhost rger: test 1
else if ( preg_match("/([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}\.[0-9]{1,6}.[0-9]{1,2}:[0-9]{1,2}) (.*?) (.*?):(.*?)$/", $szLine, $out ) )
{
// Copy parsed properties!
$arrArguments[SYSLOG_DATE] = GetEventTime($out[1]);
$arrArguments[SYSLOG_HOST] = $out[2];
$arrArguments[SYSLOG_SYSLOGTAG] = $out[3];
$arrArguments[SYSLOG_MESSAGE] = $out[4];
}
// Sample: 2008-03-28T15:17:05.480876+01:00,**NO MATCH**
else if ( preg_match("/([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}\.[0-9]{1,6}.[0-9]{1,2}:[0-9]{1,2}),(.*?)$/", $szLine, $out ) )
{
// Some kind of debug message or something ...
$arrArguments[SYSLOG_DATE] = GetEventTime($out[1]);
$arrArguments[SYSLOG_MESSAGE] = $out[2];
}
else
{
if ( isset($arrArguments[SYSLOG_MESSAGE]) && strlen($arrArguments[SYSLOG_MESSAGE]) > 0 )
OutputDebugMessage("Unparseable syslog msg - '" . $arrArguments[SYSLOG_MESSAGE] . "'", DEBUG_ERROR);
}
// If SyslogTag is set, we check for MessageType!
if ( isset($arrArguments[SYSLOG_SYSLOGTAG]) )
{
if ( strpos($arrArguments[SYSLOG_SYSLOGTAG], "EvntSLog" ) !== false )
$arrArguments[SYSLOG_MESSAGETYPE] = IUT_NT_EventReport;
}
// Return success!
return SUCCESS;
}
}
?> loganalyzer-3.6.6/src/classes/logstream.class.php 0000644 0001750 0001750 00000122747 12401304543 021376 0 ustar daniel daniel .
*
* 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;
}
// ---
// --- Basic Includes
require_once($gl_root_path . 'classes/enums.class.php');
require_once($gl_root_path . 'classes/msgparser.class.php');
require_once($gl_root_path . 'include/constants_errors.php');
require_once($gl_root_path . 'include/constants_logstream.php');
// ---
abstract class LogStream {
protected $_readDirection = EnumReadDirection::Forward;
protected $_sortOrder = EnumSortingOrder::Descending;
protected $_filters = null;
protected $_current_uId = -1;
protected $_logStreamConfigObj = null;
protected $_arrProperties = null;
protected $_arrFilterProperties = null; // Helper Array to store all detected properties from Filterstring
/**
* Open the stream for read access.
*
* @param arrProperties string in: properties of interest. There can be no guarantee the logstream can actually deliver them.
* @return integer Error stat
*/
public abstract function Open($arrProperties);
/**
* Close the current stream.
*
* @return integer Error stat
*/
public abstract function Close();
/**
* Verifies the logstream source
*
* @return integer Error stat
*/
public abstract function Verify();
/**
* Read the next data from the current stream. If it reads
* forwards or backwards depends on the current read direction.
*
* Example for reading forward:
* Is the current uID == 4, readDirection set to forwards
* ReadNext will provide uID 5 or EOS if no more data exist.
*
* Exampe for reading backward:
* Is the current uID == 4, readDirection set to backwards
* ReadNext will provide uID 3.
*
* 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: unique id of the data row
* @param arrProperitesOut array out: list with properties
* @return integer Error state
*/
public abstract function ReadNext(&$uID, &$arrProperitesOut, $bParseMessage = true);
/**
* Read the data from a specific uID.
*
* @param uID integer in: unique id of the data row
* @param arrProperitesOut array out: list with properties
* @return integer Error state
* @see ReadNext()
*/
public abstract function Read($uID, &$arrProperitesOut);
/**
* Sseek - a strange seek which has a skip capability
*
* This method was introduced to enable the upper layer to jump to a specific
* position within the stream and/or skip some records. Probably this method is used by
* a pager or to navigate from an overview page to a detailed page.
*
* mm: We had some discussion about the name of the this method. Initially we named
* it Seek. While implementing I got pain in the stomach forced me to start a discussion about
* the name and the functionality. The outcome is here - a strange seek method. Please do not
* confuse it with a seek method, it is no seek, it is a strange seek. rger suggested to name
* it diddledaddle, but I still feel uncomfortable with that name. Probably my imagination is
* too poor associating any functionality of this method with such a name. So strange seek
* is much better. It reminds me that is no seek, but a strange seek which does not work like
* a typical seek like fseek in php but in some way similar. Here is how it works:
*
* If you Sseek to EOS for example and then call a NextRead you do not get a EOS return status.
* Instead you will obtain the last record in the stream. The similarity of Sseek with a seek
* is when you use Sseek to jump to BOS. After calling a ReadNext will give you the first record
* in the stream. Here are some samples:
*
*
* Sample:
* To read the last record of a stream, do a
* seek(uid_out, EOS, 0)
* ReadNext
*
* For the first record, similarly:
* seek(uid_out, BOS, 0)
* ReadNext
*
* To skip the next, say, 49 records from the current position, you first need to know the
* current uid. You may have obtained it by a previous ReadNext call. Then, do
* seek(uidCURR, UID, 50)
* ReadNext
*
* @param uID integer in/out: is a unique ID from where to start, ignored in all modes except UID.
* On return, uID contains the uID of the record seeked to. It is undefined if an error occured.
* If no error ocucrred, the next call to ReadNext() will read the record whom's uID has been returned.
* @param mode EnumSeek in: how the seek should be performed
* @param numrecs integer in: number of records to seek from this position. Use 0 to seek to the
* actual position, a positive value to seek the the record numrecs records forward or a negative
* value to seek to a position numrecs backward
* @return integer Error state
*/
public abstract function Sseek(&$uID, $mode, $numrecs);
/**
* If you are interested in how many messages are in the stream, call this method.
* But be aware of that some stream can not provide a message count. This is probably
* because of performance reason or any other. However, if GetMessageCount return -1
* this does not mean that there is no message in the stream, it is just not countable.
* If there is no message 0 will be returned.
*
* @return integer Amount of messages within the stream. -1 means that no count is available.
*/
public abstract function GetMessageCount();
/**
* This function returns the first UID for previous PAGE, if availbale! Otherwise will
* return -1!
*/
public abstract function GetPreviousPageUID();
/**
* This function returns the first UID for the last PAGE, if availbale! Otherwise will
* return -1!
*/
public abstract function GetLastPageUID();
/**
* This function returns the FIRST UID for the FIRST PAGE, if availbale! Otherwise will
* return -1!
*/
public abstract function GetFirstPageUID();
/**
* This function returns the current Page number, if availbale! Otherwise will
* return -1!
*/
public abstract function GetCurrentPageNumber();
/**
* This functions is used by charts/graph generator to obtain data
*
* @return integer Error stat
*/
public abstract function GetCountSortedByField($szFieldId, $nFieldType, $nRecordLimit);
/**
* This functions is used by reports to consolidate data
*
* @return integer Error stat
*/
public abstract function ConsolidateDataByField($szConsFieldId, $nRecordLimit, $szSortFieldId, $nSortingOrder, $bIncludeLogStreamFields = false, $bIncludeMinMaxDateFields = false);
/**
* This functions is used by reports to consolidate data
*
* @return integer Error stat
*/
public abstract function ConsolidateItemListByField($szConsFieldId, $nRecordLimit, $szSortFieldId, $nSortingOrder);
/**
* Gets a property and checks if the class is able to sort the records
* by this property.
*
* @ Returns either true or false.
*
*/
public abstract function IsPropertySortable($myProperty);
/**
* This returns an Array of useful statsdata for this logstream source
*/
public abstract function GetLogStreamStats();
/**
* This returns just the count of records of the main data source
*/
public abstract function GetLogStreamTotalRowCount();
/**
* Helper function to cleanup all logdata which is older then the nDateTimeStamp!
*/
public abstract function CleanupLogdataByDate( $nDateTimeStamp );
/*
* Helper function to set the message checksum, this will be used for database based logstream classes only
*/
public abstract function SaveMessageChecksum( $arrProperitesIn );
/*
* Helper function to set the checksum for all messages in the current logstream class
*/
public abstract function UpdateAllMessageChecksum( );
/*
* Helper function for logstream classes to clear filter based stuff
*/
public abstract function ResetFilters( );
/*
* Helper function for logstream classes to check if all fields are available!
*/
public abstract function VerifyFields( $arrProperitesIn );
/*
* Helper function for logstream classes to create missing indexes, only applies to database based logstream classes
*/
public abstract function CreateMissingFields( $arrProperitesIn );
/*
* Helper function for logstream classes to check for data indexes, only applies to database based logstream classes
*/
public abstract function VerifyIndexes( $arrProperitesIn );
/*
* Helper function for logstream classes to create missing indexes, only applies to database based logstream classes
*/
public abstract function CreateMissingIndexes( $arrProperitesIn );
/*
* Helper function for logstream classes to check for missing triggers, only applies to database based logstream classes
*/
public abstract function VerifyChecksumTrigger( $myTriggerProperty );
/*
* Helper function for logstream classes to create missing trigger, only applies to database based logstream classes
*/
public abstract function CreateMissingTrigger( $myTriggerProperty, $myCheckSumProperty );
/*
* Helper function for logstream classes to create the SQL statement needed to create the trigger, only applies to database based logstream classes
*/
public abstract function GetCreateMissingTriggerSQL( $myDBTriggerField, $myDBTriggerCheckSumField );
/*
* Helper function for logstream classes to check if the checksum field is configured correctly
*/
public abstract function VerifyChecksumField( );
/*
* Helper function for logstream classes to change the checksum field from unsigned INT
*/
public abstract function ChangeChecksumFieldUnsigned( );
/*
* Helper functino to trigger initialisation of MsgParsers
*/
public function RunBasicInits()
{
$this->_logStreamConfigObj->InitMsgParsers();
}
/**
* Set the filter for the current stream.
*
* @param filter object in: filter object
* @return integer Error state
*/
public function SetFilter($szFilters)
{
// prepend default Filters
if ( strlen($this->_logStreamConfigObj->_defaultfilter) > 0 )
$finalfilters = $this->_logStreamConfigObj->_defaultfilter . " " . $szFilters;
else
$finalfilters = $szFilters;
OutputDebugMessage("LogStream|SetFilter: SetFilter combined = '" . $finalfilters . "'. ", DEBUG_DEBUG);
// Reset Filters first to make sure we do not add multiple filters!
$this->_filters = null;
// Parse Filters from string
$this->ParseFilters($finalfilters);
// return success
return SUCCESS;
}
/**
* Append filter definition for the current stream.
*
* @param filter object in: filter object
* @return integer Error state
*/
public function AppendFilter($szFilters)
{
OutputDebugMessage("LogStream|AppendFilter: SetFilter combined = '" . $szFilters . "'. ", DEBUG_DEBUG);
// Parse Filters from string
$this->ParseFilters($szFilters);
// return success
return SUCCESS;
}
/**
* Remove filters for a specific Fieldtype
*
* @param filter object in: FieldID
* @return integer Error state
*/
public function RemoveFilters($szFieldID)
{
// Removing Filters for this field!
if ( isset($this->_filters[$szFieldID]) )
unset($this->_filters[$szFieldID]);
// return success
return SUCCESS;
}
/**
* Set the direction the stream should read data.
*
* @param enumReadDirectionfilter EnumReadDirection in: The new direction.
* @return integer Error state
*/
public function SetReadDirection($enumReadDirection)
{
// Set the new read direction!
$this->_readDirection = $enumReadDirection;
return SUCCESS;
}
/**
* Set the sorting order for the stream
*
* @param newSortOrder EnumSortingOrder in: The new sort order.
* @return integer Error state
*/
public function SetSortOrder($newSortOrder)
{
// Set the new read direction!
$this->_sortOrder = $newSortOrder;
return SUCCESS;
}
/**
* Implementation of ApplyFilters which can be used by all LogStream Classes!
* This function performs a check on the filters and actually triggers the
* syslog parsers as well.
*/
public function ApplyFilters($myResults, &$arrProperitesOut)
{
// IF result was unsuccessfull, return success - nothing we can do here.
if ( $myResults >= ERROR )
return SUCCESS;
// Evaluation default is true
$bFinalEval = true;
// Process all filters
if ( $this->_filters != null )
{
// Loop through set properties
foreach( $arrProperitesOut as $propertyname => $propertyvalue )
{
// TODO: NOT SURE IF THIS WILL WORK ON NUMBERS AND OTHER TYPES RIGHT NOW
if (
array_key_exists($propertyname, $this->_filters) &&
isset($propertyvalue) /* &&
!(is_string($propertyvalue) && strlen($propertyvalue) <= 0)*/ /* Negative because it only matters if the propvalure is a string*/
)
{
// Perform first loop to determine the bEval Default
foreach( $this->_filters[$propertyname] as $myfilter )
{
if (
($myfilter[FILTER_TYPE] == FILTER_TYPE_NUMBER) ||
($myfilter[FILTER_TYPE] == FILTER_TYPE_STRING && $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE && $propertyname != SYSLOG_MESSAGE)
)
{
$bEval = false;
break; // IF found one INCLUDE or NUMERIC filter, the default has to be false!
}
else
$bEval = true;
}
// Extra var needed for number checks!
$bIsOrFilter = false; // If enabled we need to check for numbereval later
$bOrFilter = false;
// Perform second loop through all filters, to perform filtering
foreach( $this->_filters[$propertyname] as $myfilter )
{
switch( $myfilter[FILTER_TYPE] )
{
case FILTER_TYPE_STRING:
// Only filter if value is non zero
if ( strlen($propertyvalue) > 0 && strlen($myfilter[FILTER_VALUE]) > 0 )
{
// If Syslog message, we have AND handling!
if ( $propertyname == SYSLOG_MESSAGE )
{
// Include Filter
if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE )
{
if ( stripos($propertyvalue, $myfilter[FILTER_VALUE]) === false )
$bEval = false;
}
// Exclude Filter
else if ( $myfilter[FILTER_MODE] & FILTER_MODE_EXCLUDE )
{
if ( stripos($propertyvalue, $myfilter[FILTER_VALUE]) !== false )
$bEval = false;
}
}
// Otherwise we use OR Handling!
else
{
// Include Filter
if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE )
{
// Set isOrFilter to true in this case
$bIsOrFilter = true;
if ( $myfilter[FILTER_MODE] & FILTER_MODE_SEARCHFULL )
{
if ( strtolower($propertyvalue) == strtolower($myfilter[FILTER_VALUE]) )
$bOrFilter = true;
}
else
{
if ( stripos($propertyvalue, $myfilter[FILTER_VALUE]) !== false )
$bOrFilter = true;
}
}
// Exclude Filter - handeled with AND filtering!
else if ( $myfilter[FILTER_MODE] & FILTER_MODE_EXCLUDE )
{
if ( $myfilter[FILTER_MODE] & FILTER_MODE_SEARCHFULL )
{
if ( strtolower($propertyvalue) == strtolower($myfilter[FILTER_VALUE]) )
$bEval = false;
}
else
{
if ( stripos($propertyvalue, $myfilter[FILTER_VALUE]) !== false )
$bEval = false;
}
}
break;
}
}
else
{
// Either filter value or property value was empty!
// This means we have no match
$bEval = false;
}
break;
case FILTER_TYPE_NUMBER:
$bIsOrFilter = true; // Default is set to TRUE
if ( is_numeric($arrProperitesOut[$propertyname]) )
{
if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE )
{
if ( $myfilter[FILTER_VALUE] == $arrProperitesOut[$propertyname] )
$bOrFilter = true;
else
$bOrFilter = false;
}
else if ( $myfilter[FILTER_MODE] & FILTER_MODE_EXCLUDE )
{
if ( $myfilter[FILTER_VALUE] == $arrProperitesOut[$propertyname] )
$bOrFilter = false;
else
$bOrFilter = true;
}
}
else
{
// If wanted, we treat this filter as a success!
if ( GetConfigSetting("TreatNotFoundFiltersAsTrue", 0, CFGLEVEL_USER) == 1 )
$bOrFilter = true;
else
$bOrFilter = false;
}
break;
case FILTER_TYPE_DATE:
// Get Log TimeStamp
$nLogTimeStamp = $arrProperitesOut[$propertyname][EVTIME_TIMESTAMP];
if ( $myfilter[FILTER_DATEMODE] == DATEMODE_LASTX )
{
// Get current timestamp
$nNowTimeStamp = time();
if ( $myfilter[FILTER_VALUE] == DATE_LASTX_HOUR )
$nLastXTime = 60 * 60; // One Hour!
else if ( $myfilter[FILTER_VALUE] == DATE_LASTX_12HOURS )
$nLastXTime = 60 * 60 * 12; // 12 Hours!
else if ( $myfilter[FILTER_VALUE] == DATE_LASTX_24HOURS )
$nLastXTime = 60 * 60 * 24; // 24 Hours!
else if ( $myfilter[FILTER_VALUE] == DATE_LASTX_7DAYS )
$nLastXTime = 60 * 60 * 24 * 7; // 7 days
else if ( $myfilter[FILTER_VALUE] == DATE_LASTX_31DAYS )
$nLastXTime = 60 * 60 * 24 * 31; // 31 days
else
// WTF default?
$nLastXTime = 86400;
// If Nowtime + LastX is higher then the log timestamp, the this logline is to old for us.
if ( ($nNowTimeStamp - $nLastXTime) > $nLogTimeStamp )
$bEval = false;
}
else if ( $myfilter[FILTER_DATEMODE] == DATEMODE_RANGE_FROM )
{
// Get filter timestamp!
$nFromTimeStamp = GetTimeStampFromTimeString($myfilter[FILTER_VALUE]);
// If logtime is smaller then FromTime, then the Event is outside of our scope!
if ( $nLogTimeStamp < $nFromTimeStamp )
$bEval = false;
}
else if ( $myfilter[FILTER_DATEMODE] == DATEMODE_RANGE_TO )
{
// Get filter timestamp!
// echo $myfilter[FILTER_VALUE];
$nToTimeStamp = GetTimeStampFromTimeString($myfilter[FILTER_VALUE]);
// If logtime is smaller then FromTime, then the Event is outside of our scope!
if ( $nLogTimeStamp > $nToTimeStamp )
$bEval = false;
}
else if ( $myfilter[FILTER_DATEMODE] == DATEMODE_RANGE_DATE )
{
// Get filter timestamp!
// echo $myfilter[FILTER_VALUE];
$nDateTimeStamp = GetTimeStampFromTimeString($myfilter[FILTER_VALUE]);
// If not on logfile day, the Event is outside of our scope!
if ( $nLogTimeStamp < $nDateTimeStamp || $nLogTimeStamp > ($nDateTimeStamp+86400) )
$bEval = false;
}
break;
default:
// TODO!
break;
}
// If was number filter, we apply it the evaluation.
if ( $bIsOrFilter ) // && $bOrFilter )
{
// Fixed binary comparison to | instead of &!
$bEval |= $bOrFilter;
//echo "!" . $bOrFilter . "-" . $bEval . "! ";
}
// else
// $bEval &= $bOrFilter;
}
// Combine filters with AND
$bFinalEval &= $bEval;
}
}
// Check if evaluation was successfull
if ( !$bFinalEval )
{
// unmatching filter, reset property array
foreach ( $this->_arrProperties as $property )
$arrProperitesOut[$property] = '';
// return error!
return ERROR_FILTER_NOT_MATCH;
}
// Reached this point means filters did match!
return SUCCESS;
}
else // No filters at all means success!
return SUCCESS;
}
/**
* Helper function to obtain internal Filters Array
*/
public function ReturnFiltersArray()
{
return $this->_filters;
}
/**
* Helper function to find a fieldkey by using the SearchField
*/
public function ReturnFilterKeyBySearchField($szSearchField)
{
global $fields;
foreach ($fields as $myField)
{
if ( $myField['SearchField'] == $szSearchField )
return $myField['FieldID'];
}
return FALSE;
}
/**
* Helper function to return all fields needed for filters
* Can be helpful for functions which need to add filtering fields
*/
public function ReturnFieldsByFilters()
{
global $fields;
if ( $this->_filters != null )
{
// Return array keys
$aResult = array_keys($this->_filters);
return $aResult;
}
else // No fields at all!
return null;
}
/*
* Helper function to get the internal Field ID by database field name!
*/
public function GetFieldIDbyDatabaseMapping($szTableType, $szFieldName)
{
global $content, $dbmapping;
foreach( $dbmapping[$szTableType]['DBMAPPINGS'] as $myFieldID => $myDBMapping )
{
if ( $myDBMapping == $szFieldName )
return $myFieldID;
}
// Default return!
return $szFieldName;
}
/*
* Helper function to check a if a fieldname exists in the mapping
*/
public function CheckFieldnameInMapping($szTableType, $szFieldName)
{
global $content, $dbmapping;
foreach( $dbmapping[$szTableType]['DBMAPPINGS'] as $myFieldID => $myDBMapping )
{
if ( $myDBMapping == $szFieldName )
return true; // return found!
}
// Default FALSE!
return false;
}
/*
* --- PIRVATE HELPERS!
*/
/**
* Helper function to parse filters into a useful filter array we can work with.
*/
private function ParseFilters($szFilters)
{
global $fields;
if ( isset($szFilters) && strlen($szFilters) > 0 )
{
//OLD $tmpEntries = explode(" ", $szFilters);
// Use RegEx for intelligent splitting
$szFilterRgx = '/[\s]++(?=(?:(?:[^"]*+"){2})*+[^"]*+$)(?=(?:(?:[^\']*+\'){2})*+[^\']*+$)(?=(?:[^()]*+\([^()]*+\))*+[^()]*+$)/x';
$tmpEntries = preg_split($szFilterRgx, $szFilters, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
//DEBUG print_r ( $tmpEntries );
foreach($tmpEntries as $myEntry)
{
// Continue if empty filter!
if ( strlen(trim($myEntry)) <= 0 )
continue;
if (
($pos = strpos($myEntry, ":")) !== false
&&
($pos > 0 && substr($myEntry, $pos-1,1) != '\\') /* Only if character before is no backslash! */
)
{
// Split key and value
$tmpArray = explode(":", $myEntry, 2);
//print_r ( $tmpArray );
// Continue if empty filter!
if ( strlen(trim($tmpArray[FILTER_TMP_VALUE])) == 0 )
continue;
// Check for multiple values!
if ( strpos($tmpArray[FILTER_TMP_VALUE], ",") )
{
// Split by comma and fill tmp Value array
$tmpValueArray = explode(",", $tmpArray[FILTER_TMP_VALUE]);
foreach($tmpValueArray as $myValueEntry)
{
// Append to temp array
$tmpValues[] = array( FILTER_TMP_MODE => $this->SetFilterIncludeMode($myValueEntry), FILTER_TMP_VALUE => $myValueEntry );
}
}
// Handle filter based
switch( $tmpArray[FILTER_TMP_KEY] )
{
case "facility":
$tmpKeyName = SYSLOG_FACILITY;
$tmpFilterType = FILTER_TYPE_NUMBER;
// --- Extra Check to convert string representations into numbers!
if ( isset($tmpValues) )
{
foreach( $tmpValues as $mykey => $szValue )
{
if ( !is_numeric($szValue[FILTER_TMP_VALUE]) )
{
$tmpFacilityCode = $this->ConvertFacilityString($szValue[FILTER_TMP_VALUE]);
if ( $tmpFacilityCode != -1 )
$tmpValues[$mykey][FILTER_TMP_VALUE] = $tmpFacilityCode;
}
}
}
else
{
// First set Filter Mode
$tmpArray[FILTER_TMP_MODE] = $this->SetFilterIncludeMode($tmpArray[FILTER_TMP_VALUE],$tmpFilterType);
if ( !is_numeric($tmpArray[FILTER_TMP_VALUE]) )
{
$tmpFacilityCode = $this->ConvertFacilityString($tmpArray[FILTER_TMP_VALUE]);
if ( $tmpFacilityCode != -1 )
$tmpArray[FILTER_TMP_VALUE] = $tmpFacilityCode;
}
}
// ---
break;
case "severity":
$tmpKeyName = SYSLOG_SEVERITY;
$tmpFilterType = FILTER_TYPE_NUMBER;
// --- Extra Check to convert string representations into numbers!
if ( isset($tmpValues) )
{
foreach( $tmpValues as $mykey => $szValue )
{
if ( !is_numeric($szValue[FILTER_TMP_VALUE]) )
{
$tmpFacilityCode = $this->ConvertSeverityString($szValue[FILTER_TMP_VALUE]);
if ( $tmpFacilityCode != -1 )
$tmpValues[$mykey][FILTER_TMP_VALUE] = $tmpFacilityCode;
}
}
}
else
{
// First set Filter Mode
$tmpArray[FILTER_TMP_MODE] = $this->SetFilterIncludeMode($tmpArray[FILTER_TMP_VALUE], $tmpFilterType);
if ( !is_numeric($tmpArray[FILTER_TMP_VALUE]) )
{
$tmpFacilityCode = $this->ConvertSeverityString($tmpArray[FILTER_TMP_VALUE]);
if ( $tmpFacilityCode != -1 )
$tmpArray[FILTER_TMP_VALUE] = $tmpFacilityCode;
}
}
// ---
break;
case "messagetype":
$tmpKeyName = SYSLOG_MESSAGETYPE;
$tmpFilterType = FILTER_TYPE_NUMBER;
// --- Extra Check to convert string representations into numbers!
if ( isset($tmpValues) )
{
foreach( $tmpValues as $mykey => $szValue )
{
if ( !is_numeric($szValue[FILTER_TMP_VALUE]) )
{
$tmpMsgTypeCode = $this->ConvertMessageTypeString($szValue[FILTER_TMP_VALUE]);
if ( $tmpMsgTypeCode != -1 )
$tmpValues[$mykey][FILTER_TMP_VALUE] = $tmpMsgTypeCode;
}
}
/* OBSELETE CODE
foreach( $tmpValues as $mykey => $szValue )
{
// First set Filter Mode
$tmpValues[$mykey][FILTER_TMP_MODE] = $this->SetFilterIncludeMode($szValue);
}
*/
}
else
{
// First set Filter Mode
$tmpArray[FILTER_TMP_MODE] = $this->SetFilterIncludeMode($tmpArray[FILTER_TMP_VALUE], $tmpFilterType);
if ( !is_numeric($tmpArray[FILTER_TMP_VALUE]) )
{
$tmpMsgTypeCode = $this->ConvertMessageTypeString($tmpArray[FILTER_TMP_VALUE]);
if ( $tmpMsgTypeCode != -1 )
$tmpArray[FILTER_TMP_VALUE] = $tmpMsgTypeCode;
}
}
// ---
break;
/* BEGIN Eventlog based fields */
case "eventid":
$tmpKeyName = SYSLOG_EVENT_ID;
$tmpFilterType = FILTER_TYPE_NUMBER;
// --- Extra numeric Check
if ( isset($tmpValues) )
{
foreach( $tmpValues as $mykey => $szValue )
{
if ( is_numeric($szValue[FILTER_TMP_VALUE]) )
$tmpValues[$mykey][FILTER_TMP_VALUE] = $szValue[FILTER_TMP_VALUE];
else
$tmpValues[$mykey][FILTER_TMP_VALUE] = "";
}
}
else
{
// First set Filter Mode
$tmpArray[FILTER_TMP_MODE] = $this->SetFilterIncludeMode($tmpArray[FILTER_TMP_VALUE], $tmpFilterType);
if ( !is_numeric($tmpArray[FILTER_TMP_VALUE]) )
$tmpArray[FILTER_TMP_VALUE] = "";
}
// ---
break;
case "eventcategory":
$tmpKeyName = SYSLOG_EVENT_CATEGORY;
$tmpFilterType = FILTER_TYPE_NUMBER;
// --- Extra numeric Check
if ( isset($tmpValues) )
{
foreach( $tmpValues as $mykey => $szValue )
{
if ( is_numeric($szValue[FILTER_TMP_VALUE]) )
$tmpValues[$mykey][FILTER_TMP_VALUE] = $szValue[FILTER_TMP_VALUE];
else
$tmpValues[$mykey][FILTER_TMP_VALUE] = "";
}
}
else
{
// First set Filter Mode
$tmpArray[FILTER_TMP_MODE] = $this->SetFilterIncludeMode($tmpArray[FILTER_TMP_VALUE], $tmpFilterType);
if ( !is_numeric($tmpArray[FILTER_TMP_VALUE]) )
$tmpArray[FILTER_TMP_VALUE] = "";
}
// ---
break;
case "eventlogtype":
$tmpKeyName = SYSLOG_EVENT_LOGTYPE;
$tmpFilterType = FILTER_TYPE_STRING;
break;
case "eventlogsource":
$tmpKeyName = SYSLOG_EVENT_SOURCE;
$tmpFilterType = FILTER_TYPE_STRING;
break;
case "eventuser":
$tmpKeyName = SYSLOG_EVENT_USER;
$tmpFilterType = FILTER_TYPE_STRING;
break;
/* END Eventlog based fields */
case "syslogtag":
$tmpKeyName = SYSLOG_SYSLOGTAG;
$tmpFilterType = FILTER_TYPE_STRING;
break;
case "source":
$tmpKeyName = SYSLOG_HOST;
$tmpFilterType = FILTER_TYPE_STRING;
break;
case "datefrom":
$tmpKeyName = SYSLOG_DATE;
$tmpFilterType = FILTER_TYPE_DATE;
$tmpTimeMode = DATEMODE_RANGE_FROM;
break;
case "dateto":
$tmpKeyName = SYSLOG_DATE;
$tmpFilterType = FILTER_TYPE_DATE;
$tmpTimeMode = DATEMODE_RANGE_TO;
break;
case "datelastx":
$tmpKeyName = SYSLOG_DATE;
$tmpFilterType = FILTER_TYPE_DATE;
$tmpTimeMode = DATEMODE_LASTX;
break;
case "timereported":
$tmpKeyName = SYSLOG_DATE;
$tmpFilterType = FILTER_TYPE_DATE;
$tmpTimeMode = DATEMODE_RANGE_DATE;
break;
case "processid":
$tmpKeyName = SYSLOG_PROCESSID;
$tmpFilterType = FILTER_TYPE_STRING;
break;
/* BEGIN WebLog based fields */
case SYSLOG_WEBLOG_USER:
$tmpKeyName = SYSLOG_WEBLOG_USER;
$tmpFilterType = FILTER_TYPE_STRING;
break;
case SYSLOG_WEBLOG_METHOD:
$tmpKeyName = SYSLOG_WEBLOG_METHOD;
$tmpFilterType = FILTER_TYPE_STRING;
break;
case SYSLOG_WEBLOG_URL:
$tmpKeyName = SYSLOG_WEBLOG_URL;
$tmpFilterType = FILTER_TYPE_STRING;
break;
case SYSLOG_WEBLOG_QUERYSTRING:
$tmpKeyName = SYSLOG_WEBLOG_QUERYSTRING;
$tmpFilterType = FILTER_TYPE_STRING;
break;
case SYSLOG_WEBLOG_PVER:
$tmpKeyName = SYSLOG_WEBLOG_PVER;
$tmpFilterType = FILTER_TYPE_STRING;
break;
case SYSLOG_WEBLOG_STATUS:
$tmpKeyName = SYSLOG_WEBLOG_STATUS;
$tmpFilterType = FILTER_TYPE_NUMBER;
// --- Extra numeric Check
if ( isset($tmpValues) )
{
foreach( $tmpValues as $mykey => $szValue )
{
if ( is_numeric($szValue[FILTER_TMP_VALUE]) )
$tmpValues[$mykey][FILTER_TMP_VALUE] = $szValue[FILTER_TMP_VALUE];
else
$tmpValues[$mykey][FILTER_TMP_VALUE] = "";
}
}
else
{
// First set Filter Mode
$tmpArray[FILTER_TMP_MODE] = $this->SetFilterIncludeMode($tmpArray[FILTER_TMP_VALUE], $tmpFilterType);
if ( !is_numeric($tmpArray[FILTER_TMP_VALUE]) )
$tmpArray[FILTER_TMP_VALUE] = "";
}
// ---
break;
case SYSLOG_WEBLOG_BYTESSEND:
$tmpKeyName = SYSLOG_WEBLOG_BYTESSEND;
$tmpFilterType = FILTER_TYPE_NUMBER;
// --- Extra numeric Check
if ( isset($tmpValues) )
{
foreach( $tmpValues as $mykey => $szValue )
{
if ( is_numeric($szValue[FILTER_TMP_VALUE]) )
$tmpValues[$mykey][FILTER_TMP_VALUE] = $szValue[FILTER_TMP_VALUE];
else
$tmpValues[$mykey][FILTER_TMP_VALUE] = "";
}
}
else
{
// First set Filter Mode
$tmpArray[FILTER_TMP_MODE] = $this->SetFilterIncludeMode($tmpArray[FILTER_TMP_VALUE], $tmpFilterType);
if ( !is_numeric($tmpArray[FILTER_TMP_VALUE]) )
$tmpArray[FILTER_TMP_VALUE] = "";
}
// ---
break;
case SYSLOG_WEBLOG_REFERER:
$tmpKeyName = SYSLOG_WEBLOG_REFERER;
$tmpFilterType = FILTER_TYPE_STRING;
break;
case SYSLOG_WEBLOG_USERAGENT:
$tmpKeyName = SYSLOG_WEBLOG_USERAGENT;
$tmpFilterType = FILTER_TYPE_STRING;
break;
/* END WebLog based fields */
default:
// Custom Field, try to find field!
$szSearchFilterKey = $tmpArray[FILTER_TMP_KEY];
foreach ($fields as $aField)
{
if ($aField['SearchField'] == $szSearchFilterKey)
{
$tmpKeyName = $aField['FieldID'];
break;
}
}
if ( isset($fields[$tmpKeyName]) && isset($fields[$tmpKeyName]['SearchField']) )
{
$tmpFilterType = $fields[$tmpKeyName]['FieldType'];
// Handle numeric fields!
if ( $tmpFilterType == FILTER_TYPE_NUMBER )
{
// --- Extra numeric Check
if ( isset($tmpValues) )
{
foreach( $tmpValues as $mykey => $szValue )
{
if ( is_numeric($szValue[FILTER_TMP_VALUE]) )
$tmpValues[$mykey][FILTER_TMP_VALUE] = $szValue[FILTER_TMP_VALUE];
else
$tmpValues[$mykey][FILTER_TMP_VALUE] = "";
}
}
else
{
// First set Filter Mode
$tmpArray[FILTER_TMP_MODE] = $this->SetFilterIncludeMode($tmpArray[FILTER_TMP_VALUE], $tmpFilterType);
if ( !is_numeric($tmpArray[FILTER_TMP_VALUE]) )
$tmpArray[FILTER_TMP_VALUE] = "";
}
// ---
}
// Nothing to do actually!
// else if ( $tmpFilterType == FILTER_TYPE_STRING )
}
else
// Unknown filter
$tmpFilterType = FILTER_TYPE_UNKNOWN;
//done!
}
// Add to detected filter array
if ( $this->_arrFilterProperties == null || !in_array($tmpKeyName, $this->_arrFilterProperties) )
$this->_arrFilterProperties[] = $tmpKeyName;
// Ignore if unknown filter!
if ( $tmpFilterType != FILTER_TYPE_UNKNOWN )
{
// --- Set Filter!
$this->_filters[$tmpKeyName][][FILTER_TYPE] = $tmpFilterType;
$iNum = count($this->_filters[$tmpKeyName]) - 1;
if ( isset($tmpTimeMode) )
{
$this->_filters[$tmpKeyName][$iNum][FILTER_DATEMODE] = $tmpTimeMode;
$this->_filters[$tmpKeyName][$iNum][FILTER_MODE] = $this->SetFilterIncludeMode($tmpArray[FILTER_TMP_VALUE]); // remove FilterMode characters from value
$this->_filters[$tmpKeyName][$iNum][FILTER_VALUE] = $tmpArray[FILTER_TMP_VALUE];
//echo $this->_filters[$tmpKeyName][$iNum][FILTER_VALUE];
//exit;
}
else if ( isset($tmpValues) )
{
//print_r( $tmpValues );
foreach( $tmpValues as $szValue )
{
// Continue if empty!
if ( strlen($szValue[FILTER_TMP_VALUE]) == 0 )
continue;
if ( isset($this->_filters[$tmpKeyName][$iNum][FILTER_VALUE]) )
{
// Create new Filter!
$this->_filters[$tmpKeyName][][FILTER_TYPE] = $tmpFilterType;
$iNum = count($this->_filters[$tmpKeyName]) - 1;
}
// Set Filter Mode
if ( isset($szValue[FILTER_TMP_MODE]) )
$this->_filters[$tmpKeyName][$iNum][FILTER_MODE] = $szValue[FILTER_TMP_MODE];
else
$this->_filters[$tmpKeyName][$iNum][FILTER_MODE] = $this->SetFilterIncludeMode($szValue[FILTER_TMP_VALUE]);
// Set Value
$this->_filters[$tmpKeyName][$iNum][FILTER_VALUE] = $szValue[FILTER_TMP_VALUE];
}
}
else
{
// Set Filter Mode
if ( isset($tmpArray[FILTER_TMP_MODE]) )
$this->_filters[$tmpKeyName][$iNum][FILTER_MODE] = $tmpArray[FILTER_TMP_MODE];
else
$this->_filters[$tmpKeyName][$iNum][FILTER_MODE] = $this->SetFilterIncludeMode($tmpArray[FILTER_TMP_VALUE]);
// Set Filter value!
$this->_filters[$tmpKeyName][$iNum][FILTER_VALUE] = $tmpArray[FILTER_TMP_VALUE];
}
// Reverse string prepareation
$searchArray = array(
'/(?_filters[$tmpKeyName][$iNum][FILTER_VALUE] = str_replace( '+', ' ', $this->_filters[$tmpKeyName][$iNum][FILTER_VALUE]);
$this->_filters[$tmpKeyName][$iNum][FILTER_VALUE] = preg_replace( $searchArray, $replaceArray, $this->_filters[$tmpKeyName][$iNum][FILTER_VALUE] );
// ---
}
// Unset unused variables
if ( isset($tmpArray) )
unset($tmpArray);
if ( isset($tmpValues) )
unset($tmpValues);
if ( isset($tmpTimeMode) )
unset($tmpTimeMode);
}
else
{
// No ":", so we treat it as message filter!
$this->_filters[SYSLOG_MESSAGE][][FILTER_TYPE] = FILTER_TYPE_STRING;
$iNum = count($this->_filters[SYSLOG_MESSAGE]) - 1;
$this->_filters[SYSLOG_MESSAGE][$iNum][FILTER_MODE] = $this->SetFilterIncludeMode($myEntry);
// Replace "\:" with ":", so we can filter with it ^^
if ( strpos($myEntry, ":") !== false )
$myEntry = str_replace("\\:", ":", $myEntry);
// Check for Begin and Ending Quotes and remove them from the search value!
$myEntry = preg_replace('/\\"/i', "$1", $myEntry);
// Assign value to filter array
$this->_filters[SYSLOG_MESSAGE][$iNum][FILTER_VALUE] = $myEntry;
}
}
}
// Debug print
// print_r ($this->_filters);
}
/*
* Helper function needed in SetFilterIncludeMode
*/
private function SetFilterIncludeMode(&$szValue, $myFilterType = FILTER_TYPE_STRING) // Default = String!
{
// Init BIT!
$myBits = FILTER_MODE_INCLUDE;
// If Filter is Included
$pos = strpos($szValue, "+");
if ( $pos !== false && $pos == 0 )
{
//trunscate +
$szValue = substr( $szValue, 1);
$myBits = FILTER_MODE_INCLUDE;
}
// If Filter is Excluded
$pos = strpos($szValue, "-");
if ( $pos !== false && $pos == 0 )
{
//trunscate -
$szValue = substr( $szValue, 1);
$myBits = FILTER_MODE_EXCLUDE;
}
// If Filter is a FULL text match!
$pos = strpos($szValue, "=");
if ( $pos !== false && $pos == 0 )
{
//trunscate -
$szValue = substr( $szValue, 1);
// Add BIT if not NUMBER FIELD!
if ( $myFilterType != FILTER_TYPE_NUMBER )
$myBits |= FILTER_MODE_SEARCHFULL;
}
// If Filter is a REGEX match!
$pos = strpos($szValue, "~");
if ( $pos !== false && $pos == 0 )
{
//trunscate -
$szValue = substr( $szValue, 1);
// Add BIT if not NUMBER FIELD!
if ( $myFilterType != FILTER_TYPE_NUMBER )
$myBits |= FILTER_MODE_SEARCHREGEX;
}
// ---
// return result
return $myBits;
}
/*
* Helper function to convert a facility string into a facility number
*/
private function ConvertFacilityString($szValue)
{
global $content;
foreach ( $content['filter_facility_list'] as $myfacility )
{
if ( stripos( $myfacility['DisplayName'], $szValue) !== false )
return $myfacility['ID'];
}
// reached here means we failed to convert the facility!
return -1;
}
/*
* Helper function to convert a severity string into a severity number
*/
private function ConvertSeverityString($szValue)
{
global $content;
foreach ( $content['filter_severity_list'] as $myfacility )
{
if ( stripos( $myfacility['DisplayName'], $szValue) !== false )
return $myfacility['ID'];
}
// reached here means we failed to convert the facility!
return -1;
}
/*
* Helper function to convert a messagetype string into a messagetype number
*/
private function ConvertMessageTypeString($szValue)
{
global $content;
foreach ( $content['filter_messagetype_list'] as $mymsgtype )
{
if ( stripos( $mymsgtype['DisplayName'], $szValue) !== false )
return $mymsgtype['ID'];
}
// reached here means we failed to convert the facility!
return -1;
}
}
?> loganalyzer-3.6.6/src/classes/logstreampdo.class.php 0000644 0001750 0001750 00000232334 12401304543 022073 0 ustar daniel daniel .
*
* 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 LogStreamPDO 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 = -1;
private $_SQLwhereClause = "";
private $_myDBQuery = null;
// Constructor
public function LogStreamPDO($streamConfigObj) {
$this->_logStreamConfigObj = $streamConfigObj;
// Verify if Extension is enabled
if ( extension_loaded('pdo') == 0 )
DieWithFriendlyErrorMsg("Error, PDO Extensions are not enabled or installed! This Source can not operate.");
/*
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
{
// Probe if a function exists!
if ( !function_exists("mysql_connect") )
DieWithFriendlyErrorMsg("Error, MYSQL Extensions are not enabled! Function 'mysql_connect' does not exist.");
}
*/
}
/**
* 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 driver and 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 SQL Where Clause first!
$res = $this->CreateSQLWhereClause();
if ( $res != SUCCESS )
return $res;
// Only obtain rowcount if enabled and not done before
if ( $this->_logStreamConfigObj->DBEnableRowCounting && $this->_totalRecordCount == -1 )
$this->_totalRecordCount = $this->GetRowCountFromTable();
// 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()
{
// trigger closing database query!
$this->DestroyMainSQLQuery();
// TODO CLOSE DB CONN?!
return true;
}
/**
* Verify if the database connection exists!
*
* @return integer Error state
*/
public function Verify() {
global $content, $dbmapping;
// Create DSN String
$myDBDriver = $this->_logStreamConfigObj->GetPDODatabaseType();
$myDsn = $this->_logStreamConfigObj->CreateConnectDSN();
if ( strlen($myDsn) > 0 )
{
// Check if configured driver is actually loaded!
//print_r(PDO::getAvailableDrivers());
if ( !in_array($myDBDriver, PDO::getAvailableDrivers()) )
{
global $extraErrorDescription;
$extraErrorDescription = "PDO Database Driver not loaded: " . $myDBDriver . " Please check your php configuration extensions";
// OutputDebugMessage("LogStreamPDO|Verify: $extraErrorDescription", DEBUG_ERROR);
// return error code
return ERROR_DB_INVALIDDBDRIVER;
}
try
{
// Try to connect to the database
$this->_dbhandle = new PDO( $myDsn, $this->_logStreamConfigObj->DBUser, $this->_logStreamConfigObj->DBPassword /*, array(PDO::ATTR_TIMEOUT =>25)*/);
//$this->_dbhandle->setAttribute(PDO::ATTR_TIMEOUT, 25);
}
catch (PDOException $e)
{
global $extraErrorDescription;
$extraErrorDescription = "PDO Database Connection failed: " . $e->getMessage();
// Append extra data if admin user
if ( isset($content['SESSION_ISADMIN']) && $content['SESSION_ISADMIN'] )
$extraErrorDescription .= " AdminDebug - DSN: " . $myDsn;
// Debug Output
// OutputDebugMessage("LogStreamPDO|Verify: $extraErrorDescription", DEBUG_ERROR);
// return error code
return ERROR_DB_CONNECTFAILED;
}
// Check if Table Mapping exists
if ( !isset($dbmapping[$this->_logStreamConfigObj->DBTableType]) )
{
// Return error
return ERROR_DB_INVALIDDBMAPPING;
}
// Check if table exists
try
{
// This is one way to check if the table exists! But I don't really like it tbh -.-
$szIdField = $dbmapping[$this->_logStreamConfigObj->DBTableType]['DBMAPPINGS'][SYSLOG_UID];
$szTestQuery = "SELECT MAX(" . $szIdField . ") FROM " . $this->_logStreamConfigObj->DBTableName;
$tmpStmnt = $this->_dbhandle->prepare( $szTestQuery );
$tmpStmnt->execute();
$colcount = $tmpStmnt->columnCount();
if ( $colcount <= 0 )
return ERROR_DB_TABLENOTFOUND;
}
catch (PDOException $e)
{
global $extraErrorDescription;
$extraErrorDescription = "Could not find table: " . $e->getMessage();
// OutputDebugMessage("LogStreamPDO|Verify: $extraErrorDescription", DEBUG_ERROR);
// return error code
return ERROR_DB_TABLENOTFOUND;
}
}
else
{
// Invalid DB Driver!
return ERROR_DB_INVALIDDBDRIVER;
}
// reached this point means success ;)!
return SUCCESS;
}
/*
* Implementation of VerifyFields: Checks if fields exist in table
*/
public function VerifyFields( $arrProperitesIn )
{
global $dbmapping, $fields;
// Get List of Indexes as Array
$arrFieldKeys = $this->GetFieldsAsArray();
$szTableType = $this->_logStreamConfigObj->DBTableType;
// FIELD Listing failed! Nothing we can do in this case!
if ( $arrFieldKeys == null )
return SUCCESS;
// 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("LogStreamPDO|VerifyFields: Found Field for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_ULTRADEBUG);
continue;
}
else
{
// Index is missing for this field!
OutputDebugMessage("LogStreamPDO|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 )
{
global $dbmapping, $fields;
// Get List of Indexes as Array
$arrIndexKeys = $this->GetIndexesAsArray();
$szTableType = $this->_logStreamConfigObj->DBTableType;
// INDEX Listing failed! Nothing we can do in this case!
if ( !isset($arrIndexKeys) )// == null )
return SUCCESS;
// Loop through all fields to see which one is missing!
foreach ( $arrProperitesIn as $myproperty )
{
if ( count($arrIndexKeys) <= 0 )
{
// NO INDEXES at all!
OutputDebugMessage("LogStreamPDO|VerifyIndexes: NO INDEXES found !", DEBUG_WARN);
return ERROR_DB_INDEXESMISSING;
}
if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrIndexKeys) )
{
OutputDebugMessage("LogStreamPDO|VerifyIndexes: Found INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_ULTRADEBUG);
continue;
}
else
{
// Index is missing for this field!
OutputDebugMessage("LogStreamPDO|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 )
{
global $dbmapping, $fields;
// Avoid Check if TRIGGERS are not supported!
if ( $this->_logStreamConfigObj->GetPDOTriggersSupported() == false )
return SUCCESS;
// Get List of Triggers as Array
$arrIndexTriggers = $this->GetTriggersAsArray();
// TRIGGER Listing failed! Nothing we can do in this case!
if ( !isset($arrIndexTriggers) )// == null )
// if ( $arrIndexTriggers == null )
return SUCCESS;
$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) )
{
OutputDebugMessage("LogStreamPDO|VerifyChecksumTrigger: Found TRIGGER '" . $szTriggerName. "' for table '" . $szTableName . "'", DEBUG_ULTRADEBUG);
return SUCCESS;
}
else
{
// Index is missing for this field!
OutputDebugMessage("LogStreamPDO|VerifyChecksumTrigger: Missing TRIGGER '" . $szTriggerName . "' for Table '" . $szTableName . "'", DEBUG_WARN);
return ERROR_DB_TRIGGERMISSING;
}
}
else
{
// Index is missing for this field!
OutputDebugMessage("LogStreamPDO|VerifyChecksumTrigger: No TRIGGERS found in your database", DEBUG_WARN);
return ERROR_DB_TRIGGERMISSING;
}
}
/*
* Implementation of CreateMissingIndexes: Checks if indexes exist for desired fields
*/
public function CreateMissingIndexes( $arrProperitesIn )
{
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!
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
$szSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD INDEX ( " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " )";
else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL )
$szSql = "CREATE INDEX " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "_idx ON \"" . $this->_logStreamConfigObj->DBTableName . "\" (" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . ");";
else if ( $this->_logStreamConfigObj->DBType == DB_MSSQL )
$szSql = "CREATE INDEX " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "_idx ON " . $this->_logStreamConfigObj->DBTableName . " (" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . ");";
else
// Not supported in this case!
return ERROR_DB_INDEXFAILED;
// Index is missing for this field!
OutputDebugMessage("LogStreamPDO|CreateMissingIndexes: Createing missing INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' - " . $szSql, DEBUG_INFO);
// Add missing INDEX now!
$myQuery = $this->_dbhandle->query($szSql);
if (!$myQuery)
{
// Return failure!
$this->PrintDebugError("Dynamically Adding INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' failed with Statement: '" . $szSql . "'");
return ERROR_DB_INDEXFAILED;
}
else // Free query now
$myQuery->closeCursor();
}
}
// Successfull
return SUCCESS;
}
/*
* Implementation of CreateMissingFields: Checks if indexes exist for desired fields
*/
public function CreateMissingFields( $arrProperitesIn )
{
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("LogStreamPDO|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 = strtolower($szDBName . "_" . $szTableName . "_" . $myDBTriggerField);
// Create TRIGGER SQL!
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
$szSql ="CREATE TRIGGER " . $szTriggerName . " BEFORE INSERT ON `" . $szTableName . "`
FOR EACH ROW
BEGIN
SET NEW." . $myDBTriggerCheckSumField . " = crc32(NEW." . $myDBTriggerField . ");
END
;";
else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL )
// Experimental Trigger Support for POSTGRESQL
$szSql ="
CREATE LANGUAGE plpgsql ;
CREATE FUNCTION " . $szTriggerName . "() RETURNS trigger AS $" . $szTriggerName . "$
BEGIN
NEW." . $myDBTriggerCheckSumField . " := hashtext(NEW." . $myDBTriggerField . ");
RETURN NEW;
END;
$" . $szTriggerName . "$ LANGUAGE plpgsql;
CREATE TRIGGER " . $szTriggerName . " BEFORE INSERT OR UPDATE ON \"" . $szTableName . "\"
FOR EACH ROW EXECUTE PROCEDURE " . $szTriggerName . "();
";
else if ( $this->_logStreamConfigObj->DBType == DB_MSSQL )
{
// Trigger code for MSSQL!
$szSql ="CREATE TRIGGER " . $szTriggerName . " ON " . $szTableName . " AFTER INSERT AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for trigger here
UPDATE " . $szTableName . "
SET " . $myDBTriggerCheckSumField . " = checksum(I." . $myDBTriggerField . ")
FROM " . $szTableName . " JOIN inserted I on " . $szTableName . "." . $dbmapping[$szTableType]['DBMAPPINGS']['SYSLOG_UID'] . " = I." . $dbmapping[$szTableType]['DBMAPPINGS']['SYSLOG_UID'] . "
END
";
}
else
// NOT SUPPORTED
return null;
return $szSql;
}
/*
* Implementation of CreateMissingTrigger: Creates missing triggers !
*/
public function CreateMissingTrigger( $myTriggerProperty, $myCheckSumProperty )
{
global $dbmapping, $fields, $querycount;
// Avoid if TRIGGERS are not supported!
if ( $this->_logStreamConfigObj->GetPDOTriggersSupported() == false )
return SUCCESS;
// 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("LogStreamPDO|CreateMissingTrigger: Creating missing TRIGGER for '" . $szTableName . "' - $szDBTriggerCheckSumField = crc32(NEW.$szDBTriggerField)" . $szSql, DEBUG_INFO);
// Add missing INDEX now!
$myQuery = $this->_dbhandle->query($szSql);
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;
}
else // Free query now
$myQuery->closeCursor();
// Successfull
return SUCCESS;
}
/*
* Implementation of ChangeChecksumFieldUnsigned: Changes the Checkusm field to unsigned!
*/
public function ChangeChecksumFieldUnsigned()
{
global $dbmapping, $fields, $querycount;
// Get variables
$szTableType = $this->_logStreamConfigObj->DBTableType;
// TODO if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
// 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 = $this->_dbhandle->query($szUpdateSql);
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;
}
else // Free query now
$myQuery->closeCursor();
// return results
return SUCCESS;
}
/*
* Implementation of VerifyChecksumField: Verifies if the checkusm field is signed or unsigned!
*/
public function VerifyChecksumField()
{
global $dbmapping, $fields, $querycount;
// Get variables
$szTableType = $this->_logStreamConfigObj->DBTableType;
// Create SQL and Get INDEXES for table!
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
$szSql = "SHOW COLUMNS FROM `" . $this->_logStreamConfigObj->DBTableName . "` WHERE Field = '" . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "'";
else
// NOT SUPPORTED or NEEDED
return SUCCESS;
// Run Query to check the Checksum field!
$myQuery = $this->_dbhandle->query($szSql);
if ($myQuery)
{
// Get result!
$myRow = $myQuery->fetch(PDO::FETCH_ASSOC);
if (strpos( strtolower($myRow['Type']), "unsigned") === false )
{
// return error code!
return ERROR_DB_CHECKSUMERROR;
}
// Free query now
$myQuery->closeCursor();
// 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!
$arrProperitesOut[$property] = GetEventTime( $this->bufferedRecords[$this->_currentRecordNum][$dbfieldname] );
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 ];
}
}
/* else
{
// Obtain fieldname for uID
global $dbmapping;
$uidfieldname = $dbmapping[$this->_logStreamConfigObj->DBTableType][SYSLOG_UID];
// Clear if necessary!
if ( $this->bufferedRecords == null )
$this->ResetBufferedRecords();
// Loop through all records for now, maybe optimized later!
$bFound = false;
$tmpuID = $uID;
$ret = ERROR_NOMORERECORDS; // Set Default error code!
// Set totalpages number if available
if ( $this->_totalRecordCount != -1 )
$totalpages = intval($this->_totalRecordCount / $this->_logStreamConfigObj->_pageCount);
else
$totalpages = 1;
while( $bFound == false && $this->ReadNextIDsFromDB() == SUCCESS )
{
foreach ( $this->bufferedRecords as $myRecord )
{
if ( $myRecord[$uidfieldname] == $uID )
{
$bFound = true;
$ret = SUCCESS;
break; // Break foreach loop!
}
else
{
$tmpuID = $myRecord[$uidfieldname];
// Only Increment $_currentRecordNum
$this->_currentRecordNum++;
}
// Increment our Pagenumber if needed!
if ( $this->_currentRecordNum % $this->_logStreamConfigObj->_pageCount == 0 )
$this->_currentPageNumber++;
}
if ( $this->_currentPageNumber > 1 && $this->_readDirection == EnumReadDirection::Forward)
$this->_currentPageNumber = $totalpages - $this->_currentPageNumber + 1;
//--- Extra check to set the correct $_previousPageUID!
if ( $this->_currentRecordNum > $this->_logStreamConfigObj->_pageCount && isset($this->bufferedRecords[$this->_currentRecordNum - 50][$uidfieldname]) )
{
$this->_previousPageUID = $this->bufferedRecords[$this->_currentRecordNum - $this->_logStreamConfigObj->_pageCount - 1][$uidfieldname];
}
// TODO! Handle the case where previous ID is not set in the bufferedrecords!
//---
// 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;
}
// Delete buffered records, then they will be read automatically in ReadNext()
$this->ResetBufferedRecords();
}
*/
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()
{
global $querycount, $dbmapping;
$szTableType = $this->_logStreamConfigObj->DBTableType;
$szSql = "SELECT MAX(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] . ") FROM `" . $this->_logStreamConfigObj->DBTableName . "`" . $this->_SQLwhereClause;
$myQuery = $this->_dbhandle->query($szSql);
if ( $myQuery )
{
$myRow = $myQuery->fetchColumn();
$this->_firstPageUID = $myRow; // $myRow[0];
// Free query now
$myQuery->closeCursor();
// Increment for the Footer Stats
$querycount++;
}
//echo $szSql . " " . $this->_firstPageUID;
//exit;
// finally return result!
return $this->_firstPageUID;
}
/**
* This function returns the first UID for the last PAGE!
* Will be done by a seperated SQL Statement.
*/
public function GetLastPageUID()
{
global $querycount, $dbmapping;
$szTableType = $this->_logStreamConfigObj->DBTableType;
$szSql = "SELECT MIN(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] . ") FROM `" . $this->_logStreamConfigObj->DBTableName . "`" . $this->_SQLwhereClause;
$myQuery = $this->_dbhandle->query($szSql);
if ( $myQuery )
{
$myRow = $myQuery->fetchColumn();
$this->_lastPageUID = $myRow; // $myRow[0];
// Free query now
$myQuery->closeCursor();
// Increment for the Footer Stats
$querycount++;
}
//echo $szSql . " " . $this->_lastPageUID;
//exit;
// finally return result!
return $this->_lastPageUID;
}
/**
* 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;
if ( isset($fields[$myProperty]) && $myProperty == SYSLOG_UID )
return true;
else
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 )
{
$tableName = $this->_logStreamConfigObj->DBTableName;
// SHOW TABLE STATUS FROM
$stats = NULL;
$szSql = "SELECT count(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] . ") as Counter FROM " . $this->_logStreamConfigObj->DBTableName;
$myQuery = $this->_dbhandle->query($szSql);
if ( $myQuery )
{
// Set tablename!
$tableName = $this->_logStreamConfigObj->DBTableName;
$myStats[] = array( 'StatsDisplayName' => 'TableName', 'StatsValue' => $tableName );
// obtain first and only row
$myRow = $myQuery->fetchColumn();
$myStats[] = array( 'StatsDisplayName' => 'Rows', 'StatsValue' => $myRow );
$stats[]['STATSDATA'] = $myStats;
// Free query now
$myQuery->closeCursor();
// Increment for the Footer Stats
$querycount++;
}
// return results!
return $stats;
}
else
return null;
}
/**
* Implementation of GetLogStreamTotalRowCount
*
* Returns the total amount of rows in the main datatable
*/
public function GetLogStreamTotalRowCount()
{
global $querycount, $dbmapping;
$szTableType = $this->_logStreamConfigObj->DBTableType;
// Set default rowcount
$rowcount = null;
// Perform if Connection is true!
if ( $this->_dbhandle != null )
{
// Get Total Rowcount
$szSql = "SELECT count(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] . ") as Counter FROM " . $this->_logStreamConfigObj->DBTableName;
$myQuery = $this->_dbhandle->query($szSql);
if ( $myQuery )
{
// Obtain RowCount!
$myRow = $myQuery->fetchColumn();
$rowcount = $myRow;
// Free query now
$myQuery->closeCursor();
// Increment for the Footer Stats
$querycount++;
}
}
//return result
return $rowcount;
}
/**
* Implementation of the CleanupLogdataByDate function! Returns affected rows!
*/
public function CleanupLogdataByDate( $nDateTimeStamp )
{
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 .= $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] . " < '" . date('Y-m-d H:i:s', $nDateTimeStamp) . "'";
}
// ---
// DELETE DATA NOW!
$szSql = "DELETE FROM " . $this->_logStreamConfigObj->DBTableName . $szWhere;
OutputDebugMessage("LogStreamPDO|CleanupLogdataByDate: Created SQL Query: " . $szSql, DEBUG_DEBUG);
$myQuery = $this->_dbhandle->query($szSql);
if ( $myQuery )
{
// Get affected rows and return!
$rowcount = $myQuery->rowCount();
// Free query now
$myQuery->closeCursor();
}
else
{
// error occured, output DEBUG message
$this->PrintDebugError("CleanupLogdataByDate failed with SQL Statement ' " . $szSql . " '");
}
}
//return affected rows
return $rowcount;
}
/*
* 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!
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
{
$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";
}
elseif ($this->_logStreamConfigObj->DBType == DB_PGSQL )
{
$szSql = "UPDATE \"" . $this->_logStreamConfigObj->DBTableName . "\"" .
" SET " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = hashtext(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_MESSAGE] . ") " .
" WHERE " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " IS NULL OR " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = 0";
}
elseif ($this->_logStreamConfigObj->DBType == DB_MSSQL )
{
$szSql = "UPDATE " . $this->_logStreamConfigObj->DBTableName .
" SET " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = checksum(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_MESSAGE] . ") " .
" WHERE " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " IS NULL OR " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = 0";
}
else
{
// Failed | Checksum function not supported!
$this->PrintDebugError("UpdateAllMessageChecksum failed, PDO LogStream does not support CRC32 Checksums in SQL Statements!");
return ERROR;
}
// Output Debug Informations
OutputDebugMessage("LogStreamPDO|UpdateAllMessageChecksum: Running Created SQL Query: " . $szSql, DEBUG_ULTRADEBUG);
// Running SQL Query
$myQuery = $this->_dbhandle->query($szSql);
if ( $myQuery )
{
// Output Debug Informations
OutputDebugMessage("LogStreamPDO|UpdateAllMessageChecksum: Successfully updated Checksum of '" . $myQuery->rowCount() . "' datarecords", DEBUG_INFO);
// Free query now
$myQuery->closeCursor();
// Return success
return SUCCESS;
}
else
{
// error occured, output DEBUG message
$this->PrintDebugError("UpdateAllMessageChecksum failed with SQL Statement ' " . $szSql . " '");
// Failed
return ERROR;
}
}
/*
* 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]) )
{
// DELETE 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 = $this->_dbhandle->query($szSql);
if ( $myQuery )
{
// Free query now
$myQuery->closeCursor();
// 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;
}
/**
* 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)
{
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 )
{
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ||
$this->_logStreamConfigObj->DBType == DB_PGSQL )
{
// Helper variable for the select statement
$mySelectFieldName = $myDBGroupByFieldName . "Grouped";
$myDBQueryFieldName = "DATE( " . $myDBConsFieldName . ") AS " . $myDBGroupByFieldName ;
}
else if($this->_logStreamConfigObj->DBType == DB_MSSQL )
{
// TODO FIND A WAY FOR MSSQL!
}
}
// Set Limit String
if ( $nRecordLimit > 0 )
{
// Append LIMIT in this case!
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ||
$this->_logStreamConfigObj->DBType == DB_PGSQL )
$szLimitSql = " LIMIT " . $nRecordLimit;
else
$szLimitSql = "";
// TODO FIND A WAY FOR MSSQL!
}
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 ;
// Perform Database Query
$this->_myDBQuery = $this->_dbhandle->query($szSql);
if ( !$this->_myDBQuery )
return ERROR_DB_QUERYFAILED;
if ( $this->_myDBQuery->rowCount() == 0 )
{
$this->_myDBQuery = null;
return ERROR_NOMORERECORDS;
}
// Initialize Array variable
$aResult = array();
// Init Helper counter
$iCount = 0;
// read data records
while ( ($myRow = $this->_myDBQuery->fetch(PDO::FETCH_ASSOC)) && $iCount < $nRecordLimit)
{
// Create new row
$aNewRow = array();
foreach ( $myRow as $myFieldName => $myFieldValue )
{
if ( $myFieldName == $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId] )
$aNewRow[$szConsFieldId] = $myFieldValue;
else
$aNewRow[$myFieldName] = $myFieldValue;
}
// Increment Counter
$iCount++;
// Add new row to result
$aResult[] = $aNewRow;
}
// Delete handle
$this->_myDBQuery = null;
// return finished array
if ( count($aResult) > 0 )
return $aResult;
else
return ERROR_NOMORERECORDS;
}
/**
* Implementation of ConsolidateDataByField
*
* In the PDO DB 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)
{
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]) )
{
if ( $this->_logStreamConfigObj->DBType == DB_PGSQL ||
$this->_logStreamConfigObj->DBType == DB_MSSQL )
$myDBQueryFields .= "Max(" . $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ") AS " . $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", ";
else
// Default for other PDO Engines
$myDBQueryFields .= $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", ";
}
}
// Append Sortingfield
if ( !in_array($szConsFieldId, $aIncludeCustomFields) )
{
if ( $this->_logStreamConfigObj->DBType == DB_PGSQL ||
$this->_logStreamConfigObj->DBType == DB_MSSQL )
$myDBQueryFields .= "Max(" . $myDBConsFieldName . ") AS " . $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", ";
else
// Default for other PDO Engines
$myDBQueryFields .= $myDBConsFieldName . ", ";
}
}
else if ( $bIncludeLogStreamFields )
{
$myDBQueryFields = "";
foreach ( $this->_arrProperties as $myFieldName )
{
if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName]) )
{
if ( $this->_logStreamConfigObj->DBType == DB_PGSQL ||
$this->_logStreamConfigObj->DBType == DB_MSSQL )
$myDBQueryFields .= "Max(" . $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ") AS " . $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", ";
else
// Default for other PDO Engines
$myDBQueryFields .= $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", ";
}
}
}
else // Only Include ConsolidateField
{
if ( $this->_logStreamConfigObj->DBType == DB_PGSQL ||
$this->_logStreamConfigObj->DBType == DB_MSSQL )
$myDBQueryFields = "Max(" . $myDBConsFieldName . ") as " . $myDBConsFieldName. ", ";
else
// Default for other PDO Engines
$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 )
{
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ||
$this->_logStreamConfigObj->DBType == DB_PGSQL )
{
// Helper variable for the select statement
$mySelectFieldName = $myDBGroupByFieldName . "Grouped";
$myDBQueryFieldName = "DATE( " . $myDBConsFieldName . ") AS " . $myDBGroupByFieldName ;
}
else if($this->_logStreamConfigObj->DBType == DB_MSSQL )
{
// TODO FIND A WAY FOR MSSQL!
// Helper variable for the select statement
$mySelectFieldName = $myDBGroupByFieldName . "Grouped";
$myDBQueryFieldName = "DATE( " . $myDBConsFieldName . ") AS " . $myDBGroupByFieldName ;
}
}
// Set Limit String
if ( $nRecordLimit > 0 )
{
// Append LIMIT in this case!
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ||
$this->_logStreamConfigObj->DBType == DB_PGSQL )
{
$szLimitSqlBefore = "";
$szLimitSqlAfter = " LIMIT " . $nRecordLimit;
}
else if( $this->_logStreamConfigObj->DBType == DB_MSSQL )
{
$szLimitSqlBefore = " TOP(" . $nRecordLimit . ") ";
$szLimitSqlAfter = "";
}
else
{
$szLimitSqlBefore = "";
$szLimitSqlAfter = "";
}
}
else
{
$szLimitSqlBefore = "";
$szLimitSqlAfter = "";
}
// Create SQL String now!
$szSql = "SELECT " .
$szLimitSqlBefore .
$myDBQueryFields .
"count(" . $myDBConsFieldName . ") as itemcount " .
" FROM " . $this->_logStreamConfigObj->DBTableName .
$this->_SQLwhereClause .
" GROUP BY " . $myDBGroupByFieldName .
" ORDER BY " . $myDBSortedFieldName . " " . $szSortingOrder .
$szLimitSqlAfter ;
// Output Debug Informations
OutputDebugMessage("LogStreamPDO|ConsolidateDataByField: Running Created SQL Query: " . $szSql, DEBUG_DEBUG);
// Perform Database Query
$this->_myDBQuery = $this->_dbhandle->query($szSql);
if ( !$this->_myDBQuery )
return ERROR_DB_QUERYFAILED;
if ( $this->_myDBQuery->rowCount() == 0 )
{
$this->_myDBQuery = null;
return ERROR_NOMORERECORDS;
}
// Initialize Array variable
$aResult = array();
// read data records
$iCount = 0;
while ( ($myRow = $this->_myDBQuery->fetch(PDO::FETCH_ASSOC)) && ($nRecordLimit == 0 || $iCount < $nRecordLimit) )
{
// Create new row
$aNewRow = array();
foreach ( $myRow as $myFieldName => $myFieldValue )
{
$myFieldID = $this->GetFieldIDbyDatabaseMapping($szTableType, $myFieldName);
$aNewRow[ $myFieldID ] = $myFieldValue;
/*
if ( $myFieldName == $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId] )
$aNewRow[$szConsFieldId] = $myFieldValue;
else
$aNewRow[$myFieldName] = $myFieldValue;
*/
}
// Add new row to result
$aResult[] = $aNewRow;
// Increment Counter
$iCount++;
}
// Delete handle
$this->_myDBQuery = null;
// return finished array
if ( count($aResult) > 0 )
return $aResult;
else
return ERROR_NOMORERECORDS;
}
/**
* Implementation of GetCountSortedByField
*
* In the PDO DB Logstream, the database will do most of the work
*
* @return integer Error stat
*/
public function GetCountSortedByField($szFieldId, $nFieldType, $nRecordLimit)
{
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 )
{
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ||
$this->_logStreamConfigObj->DBType == DB_PGSQL )
{
// Helper variable for the select statement
$mySelectFieldName = $mySelectFieldName . "grouped";
$myDBQueryFieldName = "DATE( " . $myDBFieldName . ") AS " . $mySelectFieldName ;
}
else if($this->_logStreamConfigObj->DBType == DB_MSSQL )
{
// TODO FIND A WAY FOR MSSQL!
}
}
// 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";
// Append LIMIT in this case!
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ||
$this->_logStreamConfigObj->DBType == DB_PGSQL )
$szSql .= " LIMIT " . $nRecordLimit;
// Perform Database Query
$this->_myDBQuery = $this->_dbhandle->query($szSql);
if ( !$this->_myDBQuery )
return ERROR_DB_QUERYFAILED;
if ( $this->_myDBQuery->rowCount() == 0 )
{
$this->_myDBQuery = null;
return ERROR_NOMORERECORDS;
}
// Initialize Array variable
$aResult = array();
// read data records
$iCount = 0;
while ( ($myRow = $this->_myDBQuery->fetch(PDO::FETCH_ASSOC)) && $iCount < $nRecordLimit)
{
if ( isset($myRow[$mySelectFieldName]) )
{
$aResult[ $myRow[$mySelectFieldName] ] = $myRow['totalcount'];
$iCount++;
}
}
// Delete handle
$this->_myDBQuery = null;
// 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;
}
}
/*
* ============= Beginn of private functions =============
*/
/*
* This function expects the filters to already being set earlier.
* Otherwise no usual WHERE Clause can be created!
*/
private function CreateSQLWhereClause()
{
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 )
{
//REGEXP Supported by MYSQL
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
{
// --- Check if user wants to include or exclude!
if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE)
$addnod = " ";
else
$addnod = " NOT";
// ---
$szSearchBegin = "REGEXP '";
$szSearchEnd = "' ";
}
//REGEXP Supported by POSTGRESQL
else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL )
{
// --- Check if user wants to include or exclude!
if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE)
$addnod = " ";
else
$addnod = " !";
// ---
$szSearchBegin = "~* '";
$szSearchEnd = "' ";
}
else //Fallback use LIKE
{
// --- Check if user wants to include or exclude!
if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE)
$addnod = " ";
else
$addnod = " NOT";
// ---
// Database Layer does not support REGEXP
$szSearchBegin = "LIKE '%";
$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 ";
}
// ---
// Not create LIKE Filters
if ( isset($tmpfilters[$propertyname]) )
$tmpfilters[$propertyname][FILTER_VALUE] .= $addor . $dbmapping[$szTableType]['DBMAPPINGS'][$propertyname] . $addnod . $szSearchBegin . DB_RemoveBadChars($myfilter[FILTER_VALUE], $this->_logStreamConfigObj->DBType) . $szSearchEnd;
else
{
$tmpfilters[$propertyname][FILTER_TYPE] = FILTER_TYPE_STRING;
$tmpfilters[$propertyname][FILTER_VALUE] = $dbmapping[$szTableType]['DBMAPPINGS'][$propertyname] . $addnod . $szSearchBegin . DB_RemoveBadChars($myfilter[FILTER_VALUE], $this->_logStreamConfigObj->DBType) . $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], $this->_logStreamConfigObj->DBType);
}
}
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], $this->_logStreamConfigObj->DBType);
}
}
// ---
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]) . "'";
}
else if ( $myfilter[FILTER_DATEMODE] == DATEMODE_RANGE_DATE )
{
// 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]) . "' AND " .
$dbmapping[$szTableType]['DBMAPPINGS'][$propertyname] . " < '" . date("Y-m-d H:i:s", ($myeventtime[EVTIME_TIMESTAMP]+86400) ) . "'";
}
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;
}
/*
* Create the SQL QUery!
*/
private function CreateMainSQLQuery($uID)
{
global $querycount;
// Get SQL Statement
$szSql = $this->CreateSQLStatement($uID);
// --- Append LIMIT if supported by the driver! Why the hell do we still have no unified solution for this crap in the sql language?!
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
$szSql .= " LIMIT " . $this->_logStreamConfigObj->RecordsPerQuery;
else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL )
$szSql .= " LIMIT " . $this->_logStreamConfigObj->RecordsPerQuery;
// ---
// Perform Database Query
$this->_myDBQuery = $this->_dbhandle->query($szSql);
if ( !$this->_myDBQuery )
{
// Check if a field is missing!
if ( $this->_dbhandle->errorCode() == "42S22" || $this->_dbhandle->errorCode() == "42703" ) // 42S22 Means ER_BAD_FIELD_ERROR
{
// Handle missing field and try again!
if ( $this->HandleMissingField() == SUCCESS )
{
$this->_myDBQuery = $this->_dbhandle->query($szSql);
if ( !$this->_myDBQuery )
{
$this->PrintDebugError( "Invalid SQL: " . $szSql );
return ERROR_DB_QUERYFAILED;
}
}
else // Failed to add field dynamically
return ERROR_DB_QUERYFAILED;
}
else
{
$this->PrintDebugError( "Invalid SQL: " . $szSql); // . "
Errorcode: " . $this->_dbhandle->errorCode() );
return ERROR_DB_QUERYFAILED;
}
}
else
{
// Skip one entry in this case
if ( $this->_currentRecordStart > 0 )
{
// Throw away
$myRow = $this->_myDBQuery->fetch(PDO::FETCH_ASSOC);
}
}
// Increment for the Footer Stats
$querycount++;
// Output Debug Informations
OutputDebugMessage("LogStreamDB|CreateMainSQLQuery: Created SQL Query: " . $szSql, DEBUG_DEBUG);
// return success state if reached this point!
return SUCCESS;
}
/*
* Destroy the SQL QUery!
*/
private function DestroyMainSQLQuery()
{
// create query if necessary!
if ( $this->_myDBQuery != null )
{
// Free Query ressources
$this->_myDBQuery->closeCursor();
$this->_myDBQuery = null;
}
// return success state if reached this point!
return SUCCESS;
}
/*
* This helper function will read the next records into the buffer.
*/
private function ReadNextRecordsFromDB($uID)
{
global $querycount;
// Clear SQL Query first!
$this->DestroyMainSQLQuery();
// return error if there was one!
if ( ($res = $this->CreateMainSQLQuery($uID)) != SUCCESS )
return $res;
// Check rowcount property only on supported drivers, others may always return 0 like oracle PDO Driver
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ||
$this->_logStreamConfigObj->DBType == DB_MSSQL ||
$this->_logStreamConfigObj->DBType == DB_PGSQL )
{
// return specially with NO RECORDS when 0 records are returned! Otherwise it will be -1
if ( $this->_myDBQuery->rowCount() == 0 )
return ERROR_NOMORERECORDS;
}
// Copy rows into the buffer!
$iBegin = $this->_currentRecordNum;
$iCount = 0;
while( $this->_logStreamConfigObj->RecordsPerQuery > $iCount)
{
//Obtain next record
$myRow = $this->_myDBQuery->fetch(PDO::FETCH_ASSOC);
// Check if result was successfull!
if ( $myRow === FALSE || !$myRow )
break;
// Keys will be converted into lowercase!
$this->bufferedRecords[$iBegin] = array_change_key_case($myRow);
$iBegin++;
// Increment counter
$iCount++;
}
// --- Check if results were found
if ( $iBegin == $this->_currentRecordNum )
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][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";
//echo $sqlString;
//exit;
// return SQL result string:
return $sqlString;
}
/*
* 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 = $this->_dbhandle == null ? "" : implode( ";", $this->_dbhandle->errorInfo() );
$errno = $this->_dbhandle == null ? "" : $this->_dbhandle->errorCode();
$errormsg="$szErrorMsg ";
$errormsg.="Detail error: $errdesc ";
$errormsg.="Error Code: $errno ";
// Add to additional error output
$extraErrorDescription = $errormsg;
//Output!
OutputDebugMessage("LogStreamPDO|PrintDebugError: $errormsg", DEBUG_ERROR);
}
/*
* 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;
*/
/* OLD slow code! */
global $dbmapping,$querycount;
$szTableType = $this->_logStreamConfigObj->DBTableType;
// Create Statement and perform query!
$szSql = "SELECT count(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] . ") FROM " . $this->_logStreamConfigObj->DBTableName . $this->_SQLwhereClause;
$myQuery = $this->_dbhandle->query($szSql);
if ($myQuery)
{
// obtain first and only row
$myRow = $myQuery->fetchColumn();
$numRows = $myRow; // $myRow[0];
// Increment for the Footer Stats
$querycount++;
// Free query now
$myQuery->closeCursor();
}
else
{
$this->PrintDebugError("RowCount query failed: " . $szSql);
$numRows = -1;
}
// return result!
return $numRows;
}
/*
* Function handles missing database fields automatically!
*/
private function HandleMissingField( $szMissingField = null, $arrProperties = null )
{
global $dbmapping, $fields;
// Get Err description
$errdesc = $this->_dbhandle->errorInfo();
// Try to get missing field from SQL Error of not specified as argument
if ( $szMissingField == null )
{
// check matching of error msg!
if (
preg_match("/Unknown column '(.*?)' in '(.*?)'$/", $errdesc[2], $errOutArr ) || // MySQL
preg_match("/column \"(.*?)\" does not exist/", $errdesc[2], $errOutArr ) || // PostgreSQL
preg_match("/Invalid column name '(.*?)'/", $errdesc[2], $errOutArr ) // MSSQL
// ERROR: column "checksum" does not exist LINE 1: ... eventsource, eventcategory, eventuser, systemid, checksum, ... ^
)
{
$szMissingField = $errOutArr[1];
}
else
{
$this->PrintDebugError("ER_BAD_FIELD_ERROR - SQL Statement: ". $errdesc[2]);
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] )
{
$szUpdateSql = "";
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
{
// MYSQL Statements
if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_NUMBER )
$szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` int(11) NOT NULL DEFAULT '0'";
if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_STRING )
$szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` varchar(60) NULL";
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'";
}
else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL )
{
// MYSQL Statements
if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_NUMBER )
$szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " int NOT NULL DEFAULT '0'";
if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_STRING )
$szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " varchar(60) NULL";
if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_DATE )
$szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " timestamp without time zone NULL";
}
else if ( $this->_logStreamConfigObj->DBType == DB_MSSQL )
{
// MYSQL Statements
if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_NUMBER )
$szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " INT NOT NULL DEFAULT '0'";
if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_STRING )
$szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " VARCHAR(60) NULL";
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'";
}
// Run SQL Command to add the missing field!
if ( strlen($szUpdateSql) > 0 )
{
// Update Table schema now!
$myQuery = $this->_dbhandle->query($szUpdateSql);
if (!$myQuery)
{
// Return failure!
$this->PrintDebugError("ER_BAD_FIELD_ERROR - Dynamically Adding field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' with Statement failed: '" . $szUpdateSql . "'");
return ERROR_DB_DBFIELDNOTFOUND;
}
else // Free query now
$myQuery->closeCursor();
}
else
{
// Return failure!
$this->PrintDebugError("ER_BAD_FIELD_ERROR - Field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' is missing and failed to be added automatically! The fields has to be added manually to the database layout!'");
global $extraErrorDescription;
$extraErrorDescription = "Field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' was missing and has been automatically added to the database layout.";
return ERROR_DB_DBFIELDNOTFOUND;
}
}
}
// 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!
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
$szSql = "SHOW INDEX FROM `" . $this->_logStreamConfigObj->DBTableName . "`";
else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL )
$szSql = "SELECT c.relname AS \"Key_name\" FROM pg_catalog.pg_class c JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid JOIN pg_catalog.pg_class t ON i.indrelid = t.oid WHERE c.relkind = 'i' AND t.relname = 'systemevents' AND c.relname LIKE '%idx%'";
else if ( $this->_logStreamConfigObj->DBType == DB_MSSQL )
$szSql = "SELECT sysindexes.name AS Key_name FROM sysobjects, sysindexes WHERE sysobjects.xtype='U' AND sysindexes.id=object_id(sysobjects.name) and sysobjects.name='" . $this->_logStreamConfigObj->DBTableName . "' ORDER BY sysobjects.name ASC";
else
// Not supported in this case!
return null;
OutputDebugMessage("LogStreamPDO|GetIndexesAsArray: List Indexes for '" . $this->_logStreamConfigObj->DBTableName . "' - " . $szSql, DEBUG_ULTRADEBUG);
$myQuery = $this->_dbhandle->query($szSql);
if ($myQuery)
{
// Loop through results
while ( $myRow = $myQuery->fetch(PDO::FETCH_ASSOC) )
{
// Add to index keys
if ( $this->_logStreamConfigObj->DBType == DB_PGSQL || $this->_logStreamConfigObj->DBType == DB_MSSQL )
$arrIndexKeys[] = str_replace( "_idx", "", strtolower($myRow['Key_name']) );
else
$arrIndexKeys[] = strtolower($myRow['Key_name']);
}
// Free query now
$myQuery->closeCursor();
// 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 FIELDS for table!
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
$szSql = "SHOW FIELDS FROM `" . $this->_logStreamConfigObj->DBTableName . "`";
else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL )
$szSql = "SELECT column_name as \"Field\" FROM information_schema.COLUMNS WHERE table_name = '" . $this->_logStreamConfigObj->DBTableName . "'";
else if ( $this->_logStreamConfigObj->DBType == DB_MSSQL )
$szSql = "SELECT syscolumns.name AS Field FROM sysobjects JOIN syscolumns ON sysobjects.id = syscolumns.id WHERE sysobjects.xtype='U' AND sysobjects.name='" . $this->_logStreamConfigObj->DBTableName . "'";
else
// Not supported in this case!
return null;
OutputDebugMessage("LogStreamPDO|GetFieldsAsArray: List Columns for '" . $this->_logStreamConfigObj->DBTableName . "' - " . $szSql, DEBUG_ULTRADEBUG);
$myQuery = $this->_dbhandle->query($szSql);
if ($myQuery)
{
// Loop through results
while ( $myRow = $myQuery->fetch(PDO::FETCH_ASSOC) )
{
// Add to index keys
$arrFieldKeys[] = strtolower($myRow['Field']);
}
// Free query now
$myQuery->closeCursor();
// Increment for the Footer Stats
$querycount++;
}
else
$this->PrintDebugError("ERROR_DB_QUERYFAILED - GetFieldsAsArray SQL '" . $szSql . "' failed!");
// 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!
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
$szSql = "SHOW TRIGGERS";
else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL )
$szSql = "SELECT tgname as \"Trigger\" from pg_trigger;";
else if ( $this->_logStreamConfigObj->DBType == DB_MSSQL )
$szSql = "SELECT B.Name as TableName,A.name AS 'Trigger' FROM sysobjects A,sysobjects B WHERE A.xtype='TR' AND A.parent_obj = B.id"; // AND B.Name='systemevents'";
else
// Not supported in this case!
return null;
OutputDebugMessage("LogStreamPDO|GetTriggersAsArray: List Triggers for '" . $this->_logStreamConfigObj->DBTableName . "' - " . $szSql, DEBUG_ULTRADEBUG);
$myQuery = $this->_dbhandle->query($szSql);
if ($myQuery)
{
// Loop through results
while ( $myRow = $myQuery->fetch(PDO::FETCH_ASSOC) )
{
// Add to index keys
$arrIndexTriggers[] = strtolower($myRow['Trigger']);
}
// Free query now
$myQuery->closeCursor();
// Increment for the Footer Stats
$querycount++;
}
// return Array
return $arrIndexTriggers;
}
// --- End of Class!
}
?> loganalyzer-3.6.6/src/classes/logstreamdb.class.php 0000644 0001750 0001750 00000171050 12401304543 021673 0 ustar daniel daniel .
*
* 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 LogStreamDB 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;
// Constructor
public function LogStreamDB($streamConfigObj) {
$this->_logStreamConfigObj = $streamConfigObj;
if ( $this->_logStreamConfigObj->DBType == DB_MYSQL )
{
// Probe if a function exists!
if ( !function_exists("mysql_connect") )
DieWithFriendlyErrorMsg("Error, MYSQL Extensions are not enabled! Function 'mysql_connect' does not exist.");
}
}
/**
* 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 SQL Where Clause first!
$res = $this->CreateSQLWhereClause();
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()
{
if ($this->_dbhandle)
mysql_close($this->_dbhandle);
$this->_dbhandle = null;
return SUCCESS;
}
/**
* Verify if the database connection exists!
*
* @return integer Error state
*/
public function Verify() {
// Try to connect to the database
if ( $this->_dbhandle == null )
{
// Forces to open a new link in all cases!
$this->_dbhandle = @mysql_connect($this->_logStreamConfigObj->DBServer,$this->_logStreamConfigObj->DBUser,$this->_logStreamConfigObj->DBPassword, true);
if (!$this->_dbhandle)
{
if ( isset($php_errormsg) )
{
global $extraErrorDescription;
$extraErrorDescription = $php_errormsg;
}
// Return error code
return ERROR_DB_CONNECTFAILED;
}
}
// Select the database now!
$bRet = @mysql_select_db($this->_logStreamConfigObj->DBName, $this->_dbhandle);
if(!$bRet)
{
if ( isset($php_errormsg) )
{
global $extraErrorDescription;
$extraErrorDescription = $php_errormsg;
}
// Return error code
return ERROR_DB_CANNOTSELECTDB;
}
// Check if the table exists!
$numTables = @mysql_num_rows( mysql_query("SHOW TABLES LIKE '%" . $this->_logStreamConfigObj->DBTableName . "%'"));
if( $numTables <= 0 )
return ERROR_DB_TABLENOTFOUND;
// reached this point means success ;)!
return SUCCESS;
}
/*
* Implementation of VerifyFields: Checks if fields exist in table
*/
public function VerifyFields( $arrProperitesIn )
{
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 )
{
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 )
{
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;
}
}
/*
* Implementation of CreateMissingIndexes: Checks if indexes exist for desired fields
*/
public function CreateMissingIndexes( $arrProperitesIn )
{
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 )
{
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;
}
/*
* Implementation of CreateMissingTrigger: Creates missing triggers !
*/
public function CreateMissingTrigger( $myTriggerProperty, $myCheckSumProperty )
{
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()
{
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()
{
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!
$arrProperitesOut[$property] = GetEventTime( $this->bufferedRecords[$this->_currentRecordNum][$dbfieldname] );
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()
{
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;
}
/**
* This function returns the first UID for the last PAGE!
* Will be done by a seperated SQL Statement.
*/
public function GetLastPageUID()
{
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;
}
/**
* 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;
if ( isset($fields[$myProperty]) && $myProperty == SYSLOG_UID )
return true;
else
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;
}
/**
* Implementation of GetLogStreamTotalRowCount
*
* Returns the total amount of rows in the main datatable
*/
public function GetLogStreamTotalRowCount()
{
global $querycount, $dbmapping;
$szTableType = $this->_logStreamConfigObj->DBTableType;
// Set default rowcount
$rowcount = null;
// Perform if Connection is true!
if ( $this->_dbhandle != null )
{
// SHOW TABLE STATUS FROM
$szSql = "SELECT count(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] . ") as Counter FROM `" . $this->_logStreamConfigObj->DBTableName . "`";
$myQuery = mysql_query($szSql, $this->_dbhandle);
if ($myQuery)
{
// Obtain RowCount!
$myRow = mysql_fetch_row($myQuery);
$rowcount = $myRow[0];
// Free query now
mysql_free_result ($myQuery);
// Increment for the Footer Stats
$querycount++;
}
}
//return result
return $rowcount;
}
/**
* Implementation of the CleanupLogdataByDate function! Returns affected rows!
*/
public function CleanupLogdataByDate( $nDateTimeStamp )
{
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;
}
/*
* 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;
}
}
/*
* 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;
}
/**
* 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)
{
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;
}
/**
* 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)
{
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;
/* 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;
}
/**
* 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)
{
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;
}
}
/*
* ============= Beginn of private functions =============
*/
/*
* This function expects the filters to already being set earlier.
* Otherwise no usual WHERE Clause can be created!
*/
private function CreateSQLWhereClause()
{
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]) . "'";
}
else if ( $myfilter[FILTER_DATEMODE] == DATEMODE_RANGE_DATE )
{
// 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]) . "' AND " .
$dbmapping[$szTableType]['DBMAPPINGS'][$propertyname] . " < '" . date("Y-m-d H:i:s", ($myeventtime[EVTIME_TIMESTAMP]+86400) ) . "'";
}
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;
}
/*
* Destroy the SQL QUery!
*/
private function DestroyMainSQLQuery()
{
// create query if necessary!
if ( $this->_myDBQuery != null )
{
// Free Query ressources
mysql_free_result ($this->_myDBQuery);
$this->_myDBQuery = null;
}
// return success state if reached this point!
return SUCCESS;
}
/*
* This helper function will read the next records into the buffer.
*/
private function ReadNextRecordsFromDB($uID)
{
global $querycount;
// Clear SQL Query first!
$this->DestroyMainSQLQuery();
// return error if there was one!
if ( ($res = $this->CreateMainSQLQuery($uID)) != SUCCESS )
return $res;
// Append LIMIT clause
// $szSql .= " LIMIT " . $this->_currentRecordStart . ", " . $this->_logStreamConfigObj->RecordsPerQuery;
// Copy rows into the buffer!
$iBegin = $this->_currentRecordNum;
while ($myRow = mysql_fetch_array($this->_myDBQuery, MYSQL_ASSOC))
{
// Check if result was successfull!
if ( $myRow === FALSE || !$myRow )
break;
// 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;
// ---
// Free Query ressources
// mysql_free_result ($myquery);
// 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;
}
/*
* Create the SQL QUery!
*/
private function CreateMainSQLQuery($uID)
{
global $querycount;
// Get SQL Statement
$szSql = $this->CreateSQLStatement($uID);
// --- Append LIMIT
$szSql .= " LIMIT " . $this->_logStreamConfigObj->RecordsPerQuery;
// ---
// Perform Database Query
$this->_myDBQuery = mysql_query($szSql, $this->_dbhandle);
if ( !$this->_myDBQuery )
{
// Check if a field is missing!
if ( mysql_errno() == 1054 )
{
// Handle missing field and try again!
if ( $this->HandleMissingField() == SUCCESS )
{
$this->_myDBQuery = mysql_query($szSql, $this->_dbhandle);
if ( !$this->_myDBQuery )
{
$this->PrintDebugError("Invalid SQL: ".$szSql);
return ERROR_DB_QUERYFAILED;
}
}
else // Failed to add field dynamically
return ERROR_DB_QUERYFAILED;
}
else
{
$this->PrintDebugError("Invalid SQL: ".$szSql);
return ERROR_DB_QUERYFAILED;
}
}
else
{
// Skip one entry in this case
if ( $this->_currentRecordStart > 0 )
{
// Throw away
$myRow = mysql_fetch_array($this->_myDBQuery, MYSQL_ASSOC);
}
}
// Increment for the Footer Stats
$querycount++;
// Output Debug Informations
OutputDebugMessage("LogStreamDB|CreateMainSQLQuery: Created SQL Query: " . $szSql, DEBUG_DEBUG);
// 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;
}
/*
* 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!
}
?> loganalyzer-3.6.6/src/classes/enums.class.php 0000644 0001750 0001750 00000003742 12401304543 020521 0 ustar daniel daniel .
*
* A copy of the GPL can be found in the file "COPYING" in this
* distribution.
*
* Adiscon LogAnalyzer is also available under a commercial license.
* For details, contact info@adiscon.com or visit
* http://loganalyzer.adiscon.com/commercial
*********************************************************************
*/
// --- Avoid directly accessing this file!
if ( !defined('IN_PHPLOGCON') )
{
die('Hacking attempt');
exit;
}
// ---
/**
* ENUM of available ReadDirection.
*/
abstract class EnumReadDirection {
const Forward = 1;
const Backward = 2;
}
/**
* ENUM of available Sorting Orders.
*/
abstract class EnumSortingOrder {
const Ascending = 1;
const Descending = 2;
}
/**
* Available modes of seek
*/
abstract class EnumSeek {
const BOS = 1; // seek from begin stream
const EOS = 2; // seek from end of stream
const UID = 3; // seek from position uid (which MUST be a *valid* uid!)
}
?>
loganalyzer-3.6.6/src/classes/logstreamdisk.class.php 0000644 0001750 0001750 00000067336 12401304543 022253 0 ustar daniel daniel .
*
* 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 LogStreamDisk extends LogStream {
private $_currentOffset = -1;
private $_currentStartPos = -1;
private $_fp = null;
private $_bEOS = false;
const _BUFFER_length = 8192;
private $_buffer = false;
private $_buffer_length = 0;
private $_p_buffer = -1;
private $_previousPageUID = -1;
private $_lastPageUID = -1;
// Constructor
public function LogStreamDisk($streamConfigObj) {
$this->_logStreamConfigObj = $streamConfigObj;
}
/**
* Open the file with read access.
*
* @param arrProperties array in: Properties wish list.
* @return integer Error stat
*/
public function Open($arrProperties)
{
// Initialise Basic stuff within the Classs
$this->RunBasicInits();
// Check if file exists!
$result = $this->Verify();
if ( $result != SUCCESS)
return $result;
// Now open the file
$this->_fp = fopen($this->_logStreamConfigObj->FileName, 'r');
$this->_currentOffset = ftell($this->_fp);
$this->_currentStartPos = $this->_currentOffset;
$this->_arrProperties = $arrProperties;
return SUCCESS;
}
/**
* Close the file.
*
* @return integer Error state
*/
public function Close() {
if ( isset($this->_fp) )
{
if (!fclose($this->_fp)) {
return ERROR_FILE_CANT_CLOSE;
}
}
// return result
return SUCCESS;
}
/**
* Verify if the file exists!
*
* @return integer Error state
*/
public function Verify() {
global $content;
// --- Check if Filename is within allowed directories!
$szFileDirName = dirname($this->_logStreamConfigObj->FileName) . '/';
$bIsAllowedDir = false;
foreach($content['DiskAllowed'] as $szAllowedDir)
{
if ( strpos($szFileDirName, $szAllowedDir) !== FALSE )
{
$bIsAllowedDir = true;
break;
}
}
if ( !$bIsAllowedDir )
{
global $extraErrorDescription;
$extraErrorDescription = GetAndReplaceLangStr( $content['LN_ERROR_PATH_NOT_ALLOWED_EXTRA'], $this->_logStreamConfigObj->FileName, implode(", ", $content['DiskAllowed']) );
return ERROR_PATH_NOT_ALLOWED;
}
// ---
// Check if file exists!
if(!file_exists($this->_logStreamConfigObj->FileName)) {
return ERROR_FILE_NOT_FOUND;
}
// Check if file is readable!
if(!is_readable($this->_logStreamConfigObj->FileName)) {
return ERROR_FILE_NOT_READABLE;
}
// reached this point means success ;)!
return SUCCESS;
}
private function ReadNextBlock() {
$this->_bEOS = false;
$bCheckForLastLf = false;
if ($this->_readDirection == EnumReadDirection::Backward) {
// in this case we have to adjust a few settings
$this->_p_buffer = self::_BUFFER_length ; // set the point to the right index
// first of all, check if this is the first read
if ($this->_buffer == false) {
// this means that we have to read from the end
fseek($this->_fp, 0, SEEK_END);
$this->_currentOffset = ftell($this->_fp);
$this->_p_buffer -= 1; // eat EOF
$bCheckForLastLf = true;
}
$orig_offset = ftell($this->_fp) - $this->_buffer_length;
if ($orig_offset <= 0) {
// apparently we are at BOF so nothing to read
return ERROR_EOS;
}
// jumb to the new position
$orig_offset -= self::_BUFFER_length;
if ($orig_offset <= 0) {
// ok, we have to adjust the buffer pointer
$this->_p_buffer += $orig_offset; // note orig_offset is negative, see if
$orig_offset = 0;
}
fseek($this->_fp, $orig_offset);
} else {
$this->_p_buffer = 0;
}
$this->_buffer = fread($this->_fp, self::_BUFFER_length);
$this->_buffer_length = strlen($this->_buffer);
if ($bCheckForLastLf && $this->_buffer[$this->_p_buffer] == "\n") {
// skip it (can only occur if you read backwards)
$this->_p_buffer--;
$this->_currentOffset--;
}
if ($this->_buffer == false)
return ERROR_FILE_EOF;
return SUCCESS;
}
/**
* Read the data from a specific uID which means in this
* case from a given offset of the file.
*
* @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) {
$this->Sseek($uID, EnumSeek::UID, 0);
$tmp = $this->_readDirection;
$this->_readDirection = EnumReadDirection::Forward;
$ret = $this->ReadNext($uID, $arrProperitesOut);
if ($tmp == EnumReadDirection::Backward) {
$this->_p_buffer -= 2;
$this->_currentStartPos = $this->_currentOffset -= 1;
$this->_readDirection = $tmp;
// we have to skip one line that we are back on the right position
$this->ReadNext($dummy1, $dummy2);
}
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)
{
global $content, $gl_starttime;
do
{
// Read next entry first!
if ($this->_readDirection == EnumReadDirection::Forward)
$ret = $this->ReadNextForwards($uID, $arrProperitesOut);
else
$ret = $this->ReadNextBackwards($uID, $arrProperitesOut);
// Only PARSE on success!
if ( $ret == SUCCESS && $bParseMessage)
{
// Line Parser Hook here
$retParser = $this->_logStreamConfigObj->_lineParser->ParseLine($arrProperitesOut[SYSLOG_MESSAGE], $arrProperitesOut);
// Run optional Message Parsers now
$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!
$arrProperitesOut[SYSLOG_UID] = $uID;
}
// 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;
}
// Loop until the filter applies, or another error occurs, and we still have TIME!
} while ( $this->ApplyFilters($ret, $arrProperitesOut) != SUCCESS && $ret == SUCCESS );
// reached here means return result!
return $ret;
}
private function ReadNextForwards(&$uID, &$arrProperitesOut) {
if ($this->_bEOS) {
return ERROR_EOS;
}
if ($this->_p_buffer < 0) {
// init read
$this->ReadNextBlock();
}
if (($this->_p_buffer == $this->_buffer_length || $this->_p_buffer == -1) && ($this->ReadNextBlock() != SUCCESS)) {
return ERROR_UNDEFINED;
}
// Init variables dynamically
$line = '';
if ( $this->_arrProperties != null )
{
foreach ( $this->_arrProperties as $property )
$arrProperitesOut[$property] = '';
}
do {
$pos = -1;
if (($pos = strpos($this->_buffer, "\n", $this->_p_buffer)) !== false) {
$uID = $this->_currentStartPos;
$logLine = $line . substr($this->_buffer, $this->_p_buffer, $pos - $this->_p_buffer);
$arrProperitesOut[SYSLOG_MESSAGE] = $logLine;
// the buffer pointer currently points to the linefeed
// so we have to increment the pointer to eat it
$this->_currentOffset += $pos - $this->_p_buffer + 1;
$this->_p_buffer = $pos + 1;
$this->_currentStartPos = $this->_currentOffset;
return SUCCESS;
}
$line .= substr($this->_buffer, $this->_p_buffer, $this->_buffer_length - $this->_p_buffer);
$this->_currentOffset += $this->_buffer_length - $this->_p_buffer;
} while ($this->ReadNextBlock() == SUCCESS);
if ( strlen($line) > 0 ) {
$uID = $this->_currentStartPos;
$arrProperitesOut[SYSLOG_MESSAGE] = $line;
$this->_currentStartPos = $this->_currentOffset;
return SUCCESS;
}
return ERROR_UNDEFINED;
}
private function ReadNextBackwards(&$uID, &$arrProperitesOut) {
if ($this->_bEOS) {
return ERROR_EOS;
}
if ($this->_p_buffer < 0) {
// a negative buffer means that the we have to adjust
// the offset
$this->_currentOffset++;
if ($this->ReadNextBlock() != SUCCESS) {
return ERROR_UNDEFINED;
}
}
// Init variables dynamically
$line = '';
foreach ( $this->_arrProperties as $property )
$arrProperitesOut[$property] = '';
do {
$pos = -1;
$neg_offset = ($this->_buffer_length - $this->_p_buffer) * -1;
if (($pos = strrpos($this->_buffer, "\n", $neg_offset)) !== false) {
// note that we are at the position of the linefeed,
// this is recognize in the next few calculation
$uID = $this->_currentOffset -= $this->_p_buffer - $pos;
$arrProperitesOut[SYSLOG_MESSAGE] = substr($this->_buffer, $pos + 1, $this->_p_buffer - $pos) . $line;
$this->_currentOffset--; // eat the lf
$this->_p_buffer = $pos - 1;
return SUCCESS;
}
$line = substr($this->_buffer, 0, $this->_p_buffer) . $line;
$this->_currentOffset -= $this->_p_buffer;
} while ($this->ReadNextBlock() == SUCCESS);
if ( strlen($line) > 0 ) {
// this case should only happend if we are on BOF
$this->_bEOS = true;
$uID = 0;
$arrProperitesOut[SYSLOG_MESSAGE] = $line;
return SUCCESS;
}
return ERROR_EOS;
}
/**
* Implementation of Seek
*/
public function Sseek(&$uID, $mode, $numrecs) {
// in any case we reset the buffer
$this->ResetBuffer();
$ret = -1;
switch ($mode) {
case EnumSeek::BOS:
$ret = fseek($this->_fp, 0);
$this->_currentOffset = $this->_currentStartPos = 0;
break;
case EnumSeek::EOS:
// a simple ReadNextBackup will do all the work
// for us, because we have reset the buffer
// remember the current readDirection
$tmp = $this->_readDirection;
$this->_readDirection = EnumReadDirection::Backward;
$ret = $this->ReadNextBackwards($uID, $dummy2);
if ($tmp == EnumReadDirection::Forward) {
// in this case we have to correct the buffer,
// because we have read backwards even the current
// readDirection is forwards
$this->_p_buffer += 2;
$this->_currentStartPos = $this->_currentOffset;
}
$this->_readDirection = $tmp;
break;
case EnumSeek::UID:
$ret = fseek($this->_fp, $uID);
$this->_currentOffset = $this->_currentStartPos = $uID;
break;
}
if ($ret != SUCCESS)
return ERROR_UNDEFINED;
return $this->Skip($uID, $numrecs);
}
/**
*
* @param numrecs integer in: If positiv, skip
* @return uid integer Error state
*/
private function Skip($uID, $numrecs) {
if ($numrecs == 0)
return SUCCESS;
if ($numrecs > 0) {
/* due to performance reason we use php's fgets instead of ReadNext method
while (!feof($this->_fp)) {
fgets($this->_fp);
$numrecs--;
if ($numrecs == 0) {
break;
}
$this->_currentOffset = ftell($this->_fp);
}
*/
while ($this->ReadNextForwards($dummy1, $dummy2) == SUCCESS)
{
fgets($this->_fp);
$numrecs--;
//--- Extra check to set the correct $_previousPageUID!
if ( $numrecs == $this->_logStreamConfigObj->_pageCount )
$this->_previousPageUID = $this->_currentOffset;
//---
if ($numrecs == 0) {
break;
}
$this->_currentOffset = ftell($this->_fp);
}
}
else
{
while ($this->ReadNextBackwards($dummy1, $dummy2) == SUCCESS)
{
$numrecs++;
//--- Extra check to set the correct $_previousPageUID!
if ( $numrecs == $this->_logStreamConfigObj->_pageCount )
$this->_previousPageUID = $this->_currentOffset;
//---
if ($numrecs == 0) {
break;
}
}
}
// where we are?
$uID = $this->_currentOffset;
if ($numrecs != 0) {
// obviously there were not enough records to skip
return ERROR_NOMORERECORDS;
}
return SUCCESS;
}
/**
* Set the filter for the current stream.
*
* @param filter object in: filter object
* @return integer Error state
public function SetFilter($filter) {
return SUCCESS;
}
*/
/**
* GetMessageCount will always return -1 which means
* that the message count is not available. We refuse
* the request of the message count due to a count would
* require to read the whole file which would be a big
* pain if the file is e.g. 1 gb.
*/
public function GetMessageCount() {
return -1;
}
/**
* 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!
* NOT IMPLEMENTED RIGHT NOW!
*/
public function GetFirstPageUID()
{
return -1;
}
/**
* This function returns the first UID for the last PAGE!
* This is not possible in this logstream, so it always returns -1!
*/
public function GetLastPageUID()
{
// Only perform lastUID scan if there are NO filters, for performance REASONS!
if ( $this->_filters != null )
return UID_UNKNOWN;
// Helper variables
$myuid = -1;
$counter = 0;
$tmpOldDirection = $this->_readDirection; // Store for later use
$tmpuID = $this->_currentOffset+1; // Store for later use
$tmpArray = array();
if ( $this->_sortOrder == EnumSortingOrder::Ascending )
{
// Move to the beginning of END file!
$this->Sseek($myuid, EnumSeek::EOS, 0);
// Switch reading direction!
$this->_readDirection = EnumReadDirection::Backward;
}
else if ( $this->_sortOrder == EnumSortingOrder::Descending )
{
// Move to the beginning of the file!
$this->Sseek($myuid, EnumSeek::BOS, 0);
// Switch reading direction!
$this->_readDirection = EnumReadDirection::Forward;
}
// Now we move for one page, we do not need to process the syslog messages!
$ret = $this->ReadNext($myuid, $tmpArray, false);
// Save the current UID as LastPage UID!
$this->_lastPageUID = $myuid;
// --- Restore reading direction and file position!
$this->_readDirection = $tmpOldDirection;
$ret = $this->Read($tmpuID, $tmpArray);
// if ( $this->_readDirection == EnumReadDirection::Forward )
// $this->Sseek($myuid, EnumSeek::BOS, 0);
// else
// $this->Sseek($myuid, EnumSeek::EOS, 0);
// ---
// Return result!
return $this->_lastPageUID;
}
/**
* This function returns the current Page number, if availbale!
* Otherwise will return -1!
*/
public function GetCurrentPageNumber()
{
return -1;
}
/*
* 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;
if ( isset($fields[$myProperty]) && $myProperty == SYSLOG_UID )
return true;
else
return false;
}
/**
* Implementation of GetLogStreamStats
*
* Returns an Array og logstream statsdata
* Count of Data Items
* Total Filesize
*/
public function GetLogStreamStats()
{
// Get some file data!
/*
// return results!
return $stats;
}
else
*/
// NOT IMPLEMENTED YET!
return null;
}
/**
* Implementation of GetLogStreamTotalRowCount
*
* not implemented yet!
*/
public function GetLogStreamTotalRowCount()
{
//not implemented
return null;
}
/**
* Implementation of the CleanupLogdataByDate
*
* not implemented!
*/
public function CleanupLogdataByDate( $nDateTimeStamp )
{
//not implemented
return null;
}
/*
* Implementation of the SaveMessageChecksum
*
* not implemented!
*/
public function SaveMessageChecksum( $arrProperitesIn )
{
return SUCCESS;
}
/*
* Implementation of the UpdateAllMessageChecksum
*
* not implemented!
*/
public function UpdateAllMessageChecksum( )
{
return SUCCESS;
}
/*
* Helper function to clear the current querystring!
*/
public function ResetFilters()
{
// nothing todo in this logstream
return SUCCESS;
}
/*
* Helper function to verify fields | not needed in disk logstream!
*/
public function VerifyFields( $arrProperitesIn )
{
return SUCCESS;
}
/*
* Helper function to create missing fields | not needed in disk logstream!
*/
public function CreateMissingFields( $arrProperitesIn )
{
return SUCCESS;
}
/*
* Helper function to verify indexes | not needed in disk logstream!
*/
public function VerifyIndexes( $arrProperitesIn )
{
return SUCCESS;
}
/*
* Helper function to create missing indexes | not needed in disk logstream!
*/
public function CreateMissingIndexes( $arrProperitesIn )
{
return SUCCESS;
}
/*
* Helper function to verify triggers | not needed in disk logstream!
*/
public function VerifyChecksumTrigger( $myTriggerProperty )
{
return SUCCESS;
}
/*
* Helper function to verify triggers | not needed in disk logstream!
*/
public function CreateMissingTrigger( $myTriggerProperty, $myCheckSumProperty )
{
return SUCCESS;
}
/*
* Helper function to create missing triggers | not needed in disk logstream!
*/
public function GetCreateMissingTriggerSQL( $myDBTriggerField, $myDBTriggerCheckSumField )
{
return SUCCESS;
}
/*
* Helper function to verify checksum field | not needed in disk logstream!
*/
public function VerifyChecksumField( )
{
return SUCCESS;
}
/*
* Helper function to correct the checksum field | not needed in disk logstream!
*/
public function ChangeChecksumFieldUnsigned( )
{
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)
{
global $content, $fields;
// --- Set Options
$nConsFieldType = $fields[$szConsFieldId]['FieldType'];
// ---
// We loop through all loglines! this may take a while!
$uID = UID_UNKNOWN;
// Needed to reset file position!
$this->Sseek($uID, EnumSeek::BOS, 0);
$ret = $this->Read($uID, $logArray);
if ( $ret == SUCCESS )
{
// Initialize Array variable
$aResult = array();
// Loop through messages
do
{
if ( isset($logArray[$szConsFieldId]) )
{
if ( $nConsFieldType == FILTER_TYPE_DATE )
{
// Convert to FULL Day Date for now!
$myFieldData = date( "Y-m-d", $logArray[$szFieldId][EVTIME_TIMESTAMP] );
}
else // Just copy the value!
$myFieldData = $logArray[$szConsFieldId];
if ( isset($aResult[ $myFieldData ]) )
$aResult[ $myFieldData ]['ItemCount']++;
else
{
// Initialize entry if we haven't exceeded the RecordLImit yet!
if ( $nRecordLimit == 0 || count($aResult) < ($nRecordLimit-1) ) // -1 because the last entry will become all others
{
// Init entry
$aResult[ $myFieldData ][$szSortFieldId] = $logArray[$szSortFieldId];
$aResult[ $myFieldData ]['ItemCount'] = 1;
}
else
{
// Count record to others
if ( isset($aResult[ $content['LN_STATS_OTHERS'] ]) )
$aResult[ $content['LN_STATS_OTHERS'] ]['ItemCount']++;
else
$aResult[ $content['LN_STATS_OTHERS'] ]['ItemCount'] = 1;
}
}
}
} while ( ($ret = $this->ReadNext($uID, $logArray)) == SUCCESS );
// Use callback function to sort array
if ( $nSortingOrder == SORTING_ORDER_DESC )
uasort($aResult, "MultiSortArrayByItemCountDesc");
else
uasort($aResult, "MultiSortArrayByItemCountAsc");
if ( isset($aResult[ $content['LN_STATS_OTHERS'] ]) )
{
// This will move the "Others" Element to the last position!
$arrEntryCopy = $aResult[ $content['LN_STATS_OTHERS'] ];
unset($aResult[ $content['LN_STATS_OTHERS'] ]);
$aResult[ $content['LN_STATS_OTHERS'] ] = $arrEntryCopy;
}
// finally return result!
if ( count($aResult) > 0 )
return $aResult;
else
return ERROR_NOMORERECORDS;
}
else
return $ret;
}
/**
* 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)
{
global $content, $fields;
// --- Set Options
$nConsFieldType = $fields[$szConsFieldId]['FieldType'];
// ---
// We loop through all loglines! this may take a while!
$uID = UID_UNKNOWN;
// Needed to reset file position!
$this->Sseek($uID, EnumSeek::BOS, 0);
$ret = $this->Read($uID, $logArray);
if ( $ret == SUCCESS )
{
// Initialize Array variable
$aResult = array();
// Loop through messages
do
{
if ( isset($logArray[$szConsFieldId]) )
{
// --- Special Case for the checksum field, we need to generate the checksum ourself!
if ( $szConsFieldId == MISC_CHECKSUM )
$logArray[$szConsFieldId] = crc32( $logArray[SYSLOG_MESSAGE] );
// ---
if ( $nConsFieldType == FILTER_TYPE_DATE )
{
// Convert to FULL Day Date for now!
$myFieldData = date( "Y-m-d", $logArray[$szFieldId][EVTIME_TIMESTAMP] );
}
else // Just copy the value!
$myFieldData = $logArray[$szConsFieldId];
// Extra Check to avoid empty counters!
if ( strlen($myFieldData) <= 0 )
$myFieldData = $content['LN_STATS_OTHERS'];
if ( isset($aResult[ $myFieldData ]) )
{
$aResult[ $myFieldData ]['ItemCount']++;
$aResult[ $myFieldData ]['LastOccurrence_Date'] = $logArray[SYSLOG_DATE];
}
else
{
// Initialize entry if we haven't exceeded the RecordLImit yet!
if ( $nRecordLimit == 0 || count($aResult) < ($nRecordLimit-1) ) // -1 because the last entry will become all others
{
// Init entry
if ( $bIncludeLogStreamFields )
$aResult[ $myFieldData ] = $logArray;
else if ( $aIncludeCustomFields != null )
{
foreach ( $aIncludeCustomFields as $myFieldName )
{
if ( $logArray[$myFieldName] )
$aResult[ $myFieldData ][$myFieldName] = $logArray[$myFieldName];
}
}
else
$aResult[ $myFieldData ][$szSortFieldId] = $logArray[$szSortFieldId];
$aResult[ $myFieldData ]['ItemCount'] = 1;
$aResult[ $myFieldData ]['FirstOccurrence_Date'] = $logArray[SYSLOG_DATE];
$aResult[ $myFieldData ]['LastOccurrence_Date'] = $logArray[SYSLOG_DATE];
}
else
{
// Count record to others
if ( isset($aResult[ $content['LN_STATS_OTHERS'] ]) )
$aResult[ $content['LN_STATS_OTHERS'] ]['ItemCount']++;
else
$aResult[ $content['LN_STATS_OTHERS'] ]['ItemCount'] = 1;
}
}
}
} while ( ($ret = $this->ReadNext($uID, $logArray)) == SUCCESS );
// Use callback function to sort array
if ( $nSortingOrder == SORTING_ORDER_DESC )
uasort($aResult, "MultiSortArrayByItemCountDesc");
else
uasort($aResult, "MultiSortArrayByItemCountAsc");
if ( isset($aResult[ $content['LN_STATS_OTHERS'] ]) )
{
// This will move the "Others" Element to the last position!
$arrEntryCopy = $aResult[ $content['LN_STATS_OTHERS'] ];
unset($aResult[ $content['LN_STATS_OTHERS'] ]);
$aResult[ $content['LN_STATS_OTHERS'] ] = $arrEntryCopy;
}
// finally return result!
if ( count($aResult) > 0 )
return $aResult;
else
return ERROR_NOMORERECORDS;
}
else
return $ret;
}
/**
* Implementation of GetCountSortedByField
*
* For now, the disk source needs to loop through the whole file
* to consolidate and sort the data
*
* @return integer Error stat
*/
public function GetCountSortedByField($szFieldId, $nFieldType, $nRecordLimit)
{
global $content;
// We loop through all loglines! this may take a while!
$uID = UID_UNKNOWN;
$ret = $this->ReadNext($uID, $logArray);
if ( $ret == SUCCESS )
{
// Initialize Array variable
$aResult = array();
// Loop through messages
do
{
if ( isset($logArray[$szFieldId]) )
{
if ( $nFieldType == FILTER_TYPE_DATE )
{
// Convert to FULL Day Date for now!
$myFieldData = date( "Y-m-d", $logArray[$szFieldId][EVTIME_TIMESTAMP] );
}
else // Just copy the value!
$myFieldData = $logArray[$szFieldId];
if ( isset($aResult[ $myFieldData ]) )
$aResult[ $myFieldData ]++;
else
{
// Initialize entry if we haven't exceeded the RecordLImit yet!
if ( count($aResult) < ($nRecordLimit-1) ) // -1 because the last entry will become all others
$aResult[ $myFieldData ] = 1;
else
{
// Count record to others
if ( isset($aResult[ $content['LN_STATS_OTHERS'] ]) )
$aResult[ $content['LN_STATS_OTHERS'] ]++;
else
$aResult[ $content['LN_STATS_OTHERS'] ] = 1;
}
}
}
} while ( ($ret = $this->ReadNext($uID, $logArray)) == SUCCESS );
// Sort Array, so the highest count comes first!
arsort($aResult);
// array_multisort($aResult, SORT_NUMERIC, SORT_DESC);
if ( isset($aResult[ $content['LN_STATS_OTHERS'] ]) )
{
// This will move the "Others" Element to the last position!
$arrEntryCopy = $aResult[ $content['LN_STATS_OTHERS'] ];
unset($aResult[ $content['LN_STATS_OTHERS'] ]);
$aResult[ $content['LN_STATS_OTHERS'] ] = $arrEntryCopy;
}
// finally return result!
if ( count($aResult) > 0 )
return $aResult;
else
return ERROR_NOMORERECORDS;
}
else
return ERROR_NOMORERECORDS;
}
/**
* Set the direction the stream should read data.
*
*
*
* @param enumReadDirectionfilter EnumReadDirection in: The new direction.
* @return integer Error state
*
public function SetReadDirection($enumReadDirection) {
// only if the read direction change we have do do anything
if ($this->_readDirection == $enumReadDirection)
return SUCCESS;
$this->_readDirection = $enumReadDirection;
return SUCCESS;
}
*/
private function ResetBuffer() {
$this->_bEOS = false;
$this->_buffer = false;
$this->_buffer_length = 0;
$this->_p_buffer = -1;
}
}
?> loganalyzer-3.6.6/src/classes/logstreamlineparserwinsyslog.class.php 0000644 0001750 0001750 00000007634 12401304543 025437 0 ustar daniel daniel .
*
* A copy of the GPL can be found in the file "COPYING" in this
* distribution.
*
* Adiscon LogAnalyzer is also available under a commercial license.
* For details, contact info@adiscon.com or visit
* http://loganalyzer.adiscon.com/commercial
*********************************************************************
*/
// --- Avoid directly accessing this file!
if ( !defined('IN_PHPLOGCON') )
{
die('Hacking attempt');
exit;
}
// ---
// --- Basic Includes
require_once($gl_root_path . 'classes/enums.class.php');
require_once($gl_root_path . 'include/constants_errors.php');
require_once($gl_root_path . 'include/constants_logstream.php');
// ---
class LogStreamLineParserwinsyslog extends LogStreamLineParser {
// protected $_arrProperties = null;
// Constructor
public function LogStreamLineParserwinsyslog() {
return; // Nothing
}
/**
* ParseLine
*
* @param arrArguments array in&out: properties of interest. There can be no guarantee the logstream can actually deliver them.
* @return integer Error stat
*/
public function ParseLine($szLine, &$arrArguments)
{
global $content;
// Set IUT Property first!
$arrArguments[SYSLOG_MESSAGETYPE] = IUT_Syslog;
// Sample (WinSyslog/EventReporter): 2008-04-02,15:19:06,2008-04-02,15:19:06,127.0.0.1,16,5,EvntSLog: Performance counters for the RSVP (QoS RSVP) service were loaded successfully.
if ( preg_match("/([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}.[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}),([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}.[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}),(.*?),([0-9]{1,2}),([0-9]{1,2}),(.*?):(.*?)$/", $szLine, $out ) )
{
// Copy parsed properties!
$arrArguments[SYSLOG_DATE] = GetEventTime($out[1]);
$arrArguments[SYSLOG_HOST] = $out[3];
$arrArguments[SYSLOG_FACILITY] = $out[4];
$arrArguments[SYSLOG_SEVERITY] = $out[5];
$arrArguments[SYSLOG_SYSLOGTAG] = $out[6];
$arrArguments[SYSLOG_MESSAGE] = $out[7];
}
else if ( preg_match("/([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}.[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}),([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}.[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}),(.*?),([0-9]{1,2}),([0-9]{1,2}),(.*?)$/", $szLine, $out ) )
{
// Copy parsed properties!
$arrArguments[SYSLOG_DATE] = GetEventTime($out[1]);
$arrArguments[SYSLOG_HOST] = $out[3];
$arrArguments[SYSLOG_FACILITY] = $out[4];
$arrArguments[SYSLOG_SEVERITY] = $out[5];
$arrArguments[SYSLOG_MESSAGE] = $out[6];
}
else
{
if ( isset($arrArguments[SYSLOG_MESSAGE]) && strlen($arrArguments[SYSLOG_MESSAGE]) > 0 )
OutputDebugMessage("Unparseable Winsyslog message - '" . $arrArguments[SYSLOG_MESSAGE] . "'", DEBUG_ERROR);
}
// If SyslogTag is set, we check for MessageType!
if ( isset($arrArguments[SYSLOG_SYSLOGTAG]) )
{
if ( strpos($arrArguments[SYSLOG_SYSLOGTAG], "EvntSLog" ) !== false )
$arrArguments[SYSLOG_MESSAGETYPE] = IUT_NT_EventReport;
}
// Return success!
return SUCCESS;
}
}
?> loganalyzer-3.6.6/src/classes/logstreamlineparsersyslog23.class.php 0000644 0001750 0001750 00000011002 12401304543 025046 0 ustar daniel daniel .
*
* A copy of the GPL can be found in the file "COPYING" in this
* distribution.
*
* Adiscon LogAnalyzer is also available under a commercial license.
* For details, contact info@adiscon.com or visit
* http://loganalyzer.adiscon.com/commercial
*********************************************************************
*/
// --- Avoid directly accessing this file!
if ( !defined('IN_PHPLOGCON') )
{
die('Hacking attempt');
exit;
}
// ---
// --- Basic Includes
require_once($gl_root_path . 'classes/enums.class.php');
require_once($gl_root_path . 'include/constants_errors.php');
require_once($gl_root_path . 'include/constants_logstream.php');
// ---
class LogStreamLineParsersyslog23 extends LogStreamLineParser {
// protected $_arrProperties = null;
// Constructor
public function LogStreamLineParsersyslog23() {
return; // Nothing
}
/**
* ParseLine
*
* @param arrArguments array in&out: properties of interest. There can be no guarantee the logstream can actually deliver them.
* @return integer Error stat
*/
public function ParseLine($szLine, &$arrArguments)
{
// Set IUT Property first!
$arrArguments[SYSLOG_MESSAGETYPE] = IUT_Syslog;
// Sample: <22>1 2011-03-03T15:27:06+01:00 debian507x64 postfix 2454 - - daemon started -- version 2.5.5, configuration /etc/postfix
// Sample: <46>1 2011-03-03T15:27:05+01:00 debian507x64 rsyslogd - - - [origin software="rsyslogd" swVersion="4.6.4" x-pid="2344" x-info="http://www.rsyslog.com"] (re)start
// Sample (RSyslog): 2008-03-28T11:07:40+01:00 localhost rger: test 1
if ( preg_match("/<([0-9]{1,3})>([0-9]) ([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}.[0-9]{1,2}:[0-9]{1,2}) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?)$/", $szLine, $out ) )
{
// Copy parsed properties!
$arrArguments[SYSLOG_FACILITY] = $out[1] >> 3;
$arrArguments[SYSLOG_SEVERITY] = $out[1] & 0x0007;
$arrArguments[SYSLOG_DATE] = GetEventTime($out[3]);
$arrArguments[SYSLOG_HOST] = $out[4];
$arrArguments[SYSLOG_SYSLOGTAG] = $out[5];
$arrArguments[SYSLOG_PROCESSID] = $out[6];
$arrArguments[SYSLOG_MESSAGE] = $out[9];
}
// Sample: <22>1 2011-03-03T15:27:06.501740+01:00 debian507x64 postfix 2454 - - daemon started -- version 2.5.5, configuration /etc/postfix
// Sample: <46>1 2011-03-03T15:27:05.366981+01:00 debian507x64 rsyslogd - - - [origin software="rsyslogd" swVersion="4.6.4" x-pid="2344" x-info="http://www.rsyslog.com"] (re)start
else if ( preg_match("/<([0-9]{1,3})>([0-9]) ([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}\.[0-9]{1,6}.[0-9]{1,2}:[0-9]{1,2}) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?)$/", $szLine, $out ) )
{
// Copy parsed properties!
$arrArguments[SYSLOG_FACILITY] = $out[1] >> 3;
$arrArguments[SYSLOG_SEVERITY] = $out[1] & 0x0007;
$arrArguments[SYSLOG_DATE] = GetEventTime($out[3]);
$arrArguments[SYSLOG_HOST] = $out[4];
$arrArguments[SYSLOG_SYSLOGTAG] = $out[5];
$arrArguments[SYSLOG_PROCESSID] = $out[6];
$arrArguments[SYSLOG_MESSAGE] = $out[9];
}
else
{
if ( isset($arrArguments[SYSLOG_MESSAGE]) && strlen($arrArguments[SYSLOG_MESSAGE]) > 0 )
OutputDebugMessage("Unparseable syslog msg - '" . $arrArguments[SYSLOG_MESSAGE] . "'", DEBUG_ERROR);
}
// If SyslogTag is set, we check for MessageType!
if ( isset($arrArguments[SYSLOG_SYSLOGTAG]) )
{
if ( strpos($arrArguments[SYSLOG_SYSLOGTAG], "EvntSLog" ) !== false )
$arrArguments[SYSLOG_MESSAGETYPE] = IUT_NT_EventReport;
}
// Return success!
return SUCCESS;
}
}
?> loganalyzer-3.6.6/src/classes/logstreamconfigdisk.class.php 0000644 0001750 0001750 00000010045 12401304543 023422 0 ustar daniel daniel .
*
* 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;
}
// ---
class LogStreamConfigDisk extends LogStreamConfig {
// Public properties
public $FileName = '';
public $LineParserType = "syslog"; // Default = Syslog!
public $_lineParser = null;
public function LogStreamFactory($o)
{
// An instance is created, then include the logstreamdisk class as well!
global $gl_root_path;
require_once($gl_root_path . 'classes/logstreamdisk.class.php');
// Create and set LineParser Instance
$this->_lineParser = $this->CreateLineParser();
// return LogStreamDisk instance
return new LogStreamDisk($o);
}
private function CreateLineParser()
{
// We need to include Line Parser on demand!
global $gl_root_path;
require_once($gl_root_path . 'classes/logstreamlineparser.class.php');
// Probe if file exists then include it!
$strIncludeFile = $gl_root_path . 'classes/logstreamlineparser' . $this->LineParserType . '.class.php';
$strClassName = "LogStreamLineParser" . $this->LineParserType;
if ( is_file($strIncludeFile) )
{
require_once($strIncludeFile);
// TODO! Create Parser based on Source Config!
//return LineParser Instance
return new $strClassName();
}
else
DieWithErrorMsg("Couldn't locate LineParser include file '" . $strIncludeFile . "'");
}
/*
* Helper function to Set the FileName property
*/
public function SetFileName( $szNewVal )
{
// Replace dynamic variables if necessary
if ( strpos($szNewVal, "%") !== false )
{
OutputDebugMessage("LogStreamConfigDisk|SetFileName: Filename before replacing: " . $szNewVal, DEBUG_DEBUG);
// Create search and replace array
$search = array (
"%y", /* Year with two digits (e.g. 2002 becomes "02") */
"%Y", /* Year with 4 digits */
"%m", /* Month with two digits (e.g. March becomes "03") */
"%M", /* Minute with two digits */
"%d", /* Day of month with two digits (e.g. March, 1st becomes "01") */
"%h", /* Hour as two digits */
"%S", /* Seconds as two digits. It is hardly believed that this ever be used in reality. */
"%w", /* Weekday as one digit. 0 means Sunday, 1 Monday and so on. */
"%W", /* Weekday as three-character string. Possible values are "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat". */
);
$replace = array (
date("y"),
date("Y"),
date("m"),
date("i"),
date("d"),
date("H"),
date("s"),
date("w"),
date("D"),
);
// Do the replacing
$szNewVal = str_replace( $search, $replace, $szNewVal );
OutputDebugMessage("LogStreamConfigDisk|SetFileName: Filename after replacing: " . $szNewVal, DEBUG_DEBUG);
}
// Set Filename Property!
$this->FileName = $szNewVal;
}
}
?> loganalyzer-3.6.6/src/classes/logstreammongodb.class.php 0000644 0001750 0001750 00000161353 12401304543 022740 0 ustar daniel daniel .
*
* 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!
// NEEDED OR NOT?
// $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
{
// Forces to open a new Connection
$this->_myMongoCon = new Mongo("mongodb://" . $this->_logStreamConfigObj->DBServer . ":" . $this->_logStreamConfigObj->DBPort ); // Connect to Mongo Server
}
catch ( MongoConnectionException $e )
{
// Log error!
$this->PrintDebugError("Verify:Connect failed with error ' " . $e->getMessage() . " '");
// Return error code
return ERROR_DB_CONNECTFAILED;
}
}
try
{
$this->_myMongoDB = $this->_myMongoCon->selectDB( $this->_logStreamConfigObj->DBName ); // Connect to Database
// Only try to auth if Username is configured
if ( strlen($this->_logStreamConfigObj->DBUser) > 0 )
{
// TODO: Not tested yet, sample code!
$szUsrPwd = $this->_logStreamConfigObj->DBUser . ":mongo:" . $this->_logStreamConfigObj->DBPassword;
$hashUsrPwd = md5($szUsrPwd);
// Get Nonce
$myNonce = $this->_myMongoDB->command(array("getnonce" => 1));
$saltedHash = md5($myNonce["nonce"] . $this->_logStreamConfigObj->DBUser . $hashUsrPwd);
$result = $this->_myMongoDB->command(array("authenticate" => 1,
"user" => $this->_logStreamConfigObj->DBUser,
"nonce" => $myNonce["nonce"],
"key" => $saltedHash
));
if ( $result["ok"] == 0 )
{
// Log error!
$this->PrintDebugError("Verify:Auth failed with error ' " . $result["errmsg"] . " '");
// Return error code
return ERROR_DB_CANNOTSELECTDB;
}
}
}
catch ( MongoException $e )
{
// Log error!
$this->PrintDebugError("Verify:selectDB failed with error ' " . $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 )
{
// Log error!
$this->PrintDebugError("Verify:selectCollection failed with error ' " . $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 )
{
// Not needed, successfull
return SUCCESS;
}
/*
* Implementation of VerifyIndexes: Checks if indexes exist for desired fields
*/
public function VerifyIndexes( $arrProperitesIn )
{
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]) )
{
if ( 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 )
{
// Not needed, successfull
return SUCCESS;
}
/*
* Implementation of CreateMissingIndexes: Checks if indexes exist for desired fields
*/
public function CreateMissingIndexes( $arrProperitesIn )
{
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]) )
{
if (in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrIndexKeys) )
continue;
else
{
try
{
// Add Unique Index for DBMapping
$this->_myMongoCollection->ensureIndex(array( $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] => 1) /*, array("unique" => true) */ );
// Index is missing for this field!
OutputDebugMessage("LogStreamDB|CreateMissingIndexes: Createing missing INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_INFO);
}
catch ( MongoException $e )
{
// Log error!
$this->PrintDebugError("CreateMissingIndexes failed with error ' " . $e->getMessage() . " '");
// Return error code
return ERROR_DB_QUERYFAILED;
}
// // 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 )
{
// Successfull
return SUCCESS;
}
/*
* Implementation of GetCreateMissingTriggerSQL: Creates SQL needed to create a TRIGGER
*/
public function GetCreateMissingTriggerSQL( $myDBTriggerField, $myDBTriggerCheckSumField )
{
// Return nothing
return "";
}
/*
* Implementation of CreateMissingTrigger: Creates missing triggers !
*/
public function CreateMissingTrigger( $myTriggerProperty, $myCheckSumProperty )
{
// Successfull
return SUCCESS;
}
/*
* Implementation of ChangeChecksumFieldUnsigned: Changes the Checkusm field to unsigned!
*/
public function ChangeChecksumFieldUnsigned()
{
// return results
return SUCCESS;
}
/*
* Implementation of VerifyChecksumField: Verifies if the checkusm field is signed or unsigned!
*/
public function VerifyChecksumField()
{
// 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] = '';
// echo $property . "=" . $this->bufferedRecords[$this->_currentRecordNum][$dbfieldname];
}
}
// --- Add dynamic fields into record!
foreach( $this->bufferedRecords[$this->_currentRecordNum] as $propName => $propValue)
{
if ( !isset($arrProperitesOut[$propName]) &&
!$this->CheckFieldnameInMapping($szTableType, $propName) &&
(isset($propValue) && strlen($propValue) > 0)
)
{
// Add dynamic Property!
if ( gettype($propValue) == "object" && get_class($propValue) == "MongoDate" )
// Handle Date fields
$arrProperitesOut[$propName] = GetFormatedDate($propValue->sec);
else // Default handling
$arrProperitesOut[$propName] = $propValue;
}
}
// ---
// 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()
{
// functions became obselete
return UID_UNKNOWN;
}
/**
* This function returns the first UID for the last PAGE!
* Will be done by a seperated SQL Statement.
*/
public function GetLastPageUID()
{
// functions became obselete
return UID_UNKNOWN;
}
/**
* 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;
$myStats = null;
$myList = $this->_myMongoDB->listCollections();
foreach ($myList as $myCollection)
{
// Set tablename!
$tableName = $myCollection->getName();
$myStats[] = array( 'StatsDisplayName' => 'Table name', 'StatsValue' => $tableName );
// copy usefull statsdata
$myStats[] = array( 'StatsDisplayName' => 'Datacount', 'StatsValue' => $myCollection->count() );
$myStats[] = array( 'StatsDisplayName' => 'IndexInfo', 'StatsValue' => var_export($myCollection->getIndexInfo(), true) );
// $myStats[] = array( 'StatsDisplayName' => 'validate', 'StatsValue' => var_export($myCollection->validate(), true) );
$stats[]['STATSDATA'] = $myStats;
$querycount++;
}
// return results!
return $stats;
}
/**
* 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 )
{
global $querycount, $dbmapping;
$szTableType = $this->_logStreamConfigObj->DBTableType;
// Set default rowcount
$rowcount = null;
if ( $nDateTimeStamp > 0 )
{
// Create MongoDate Object from Timestamp
$myMongoDate = new MongoDate($nDateTimeStamp);
// Create Criteria Array
$myCriteria = array( $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] => array('$lte' => $myMongoDate) );
}
else
{
// Use EMPTY array to delete all!
$myCriteria = array();
}
try
{
// Get Datacount!
$myCursor = $this->_myMongoCollection->find( $myCriteria );
$rowcount = $myCursor->count();
// we have something to delete!
if ( $rowcount > 0 )
{
// Remove all older records now!
$myResult = $this->_myMongoCollection->remove( $myCriteria );
OutputDebugMessage("LogStreamMongoDB|CleanupLogdataByDate: Result of deleting '$rowcount' objects: '$myResult'", DEBUG_DEBUG);
// error occured, output DEBUG message
// $this->PrintDebugError("CleanupLogdataByDate failed with SQL Statement ' " . $szSql . " '");
}
}
catch ( MongoCursorException $e )
{
// Log error!
$this->PrintDebugError("CleanupLogdataByDate failed with error ' " . $e->getMessage() . " '");
}
//return affected rows
return $rowcount;
}
/*
* Implementation of the UpdateAllMessageChecksum
*
* Update all missing checksum properties in the current database
*/
public function UpdateAllMessageChecksum( )
{
global $querycount, $dbmapping;
$szTableType = $this->_logStreamConfigObj->DBTableType;
// --- Create Query Array!
$myMongoQuery = array();
if ( ($res = $this->CreateQueryArray(UID_UNKNOWN)) != SUCCESS )
return $res;
// Copy array
$myMongoQuery = $this->_myMongoQuery;
// Set default for custom fields!
// $myMongoQuery[ $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] ] = array( '$exists' => FALSE);
$myMongoQuery[ $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] ] = null;
// var_dump ( $myMongoQuery );
// ---
// --- Set DB Fields Array
$myMongoFields = array();
$myMongoFields[ $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] ] = true;
$myMongoFields[ $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_MESSAGE] ] = true;
// ---
// DEBUG CODE: KILL all checksums!
// echo $this->_myMongoCollection->update( array ( "_id" => array( '$exists' => TRUE) ), array( '$set' => array($dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] => null) ), array("multiple" => true) );
// exit;
//
// Append LIMIT clause
$iCount = 0;
$myCursor = $this->_myMongoCollection->find($myMongoQuery, $myMongoFields); // ->limit(10); // $collection->find();
foreach ($myCursor as $mongoid => $myRow)
{
// Check if result was successfull! Compare the queried uID and the MONGOID to abort processing if the same ID was returned! Otherwise we have dupplicated results at the end
if ( $myRow === FALSE || !$myRow && $myCursor->count() <= 1 )
break;
// Create Querydata
$myRow[ "_id" ]; // = base_convert($myRow[ "_id" ], 16, 10); // Convert ID from HEX back to DEC
// $mongoID = new MongoID( $myRow[ "_id" ] );
$queryArray = array('_id' => $myRow[ "_id" ]);
// Create Update Data
$updateChecksum = crc32($myRow[ $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_MESSAGE] ]);
$updateData = array( '$set' => array($dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] => $updateChecksum) );
// Update data in Collection
$this->_myMongoCollection->update( $queryArray, $updateData );
$iCount++; // Debugcounter
//var_dump ( $updateData );
//var_dump ( $queryArray );
//var_dump ( $this->_myMongoCollection->findOne($queryArray) );
//exit;
}
// Debug Output
OutputDebugMessage("LogStreamMongoDB|UpdateAllMessageChecksum: Successfully updated Checksum of '" . $iCount . "' datarecords", DEBUG_INFO);
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]) )
{
// Create Querydata
$myMongoID = new MongoId( $this->convBaseHelper($arrProperitesIn[SYSLOG_UID], 10, 16) );
$queryArray = array('_id' => $myMongoID);
// Create Update Data
$updateData = array( '$set' => array($dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] => $arrProperitesIn[MISC_CHECKSUM]) );
try
{
// Update data in Collection
$this->_myMongoCollection->update( $queryArray, $updateData );
}
catch ( MongoCursorException $e )
{
// Log error!
$this->PrintDebugError("SaveMessageChecksum failed with error ' " . $e->getMessage() . " '");
// Return error code
return ERROR_DB_QUERYFAILED;
}
// Return success
return SUCCESS;
}
else
// Missing important properties
return ERROR;
}
/**
* 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)
{
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'];
// --- Set DB Field names
$myDBConsFieldName = $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId];
$myDBGroupByFieldName = $myDBConsFieldName;
// Set Sorted Field
if ( $szConsFieldId == $szSortFieldId )
$myDBSortedFieldName = "itemcount";
else
$myDBSortedFieldName = $szSortFieldId;
// ---
// --- Set DB Fields Array
$myMongoFields = array();
$myMongoFields[ $myDBConsFieldName ] = true;
// ---
/*
// Special handling for date fields
if ( $nConsFieldType == FILTER_TYPE_DATE )
{
// Helper variable for the select statement
$mySelectFieldName = $myDBGroupByFieldName . "Grouped";
$myDBQueryFieldName = "DATE( " . $myDBConsFieldName . ") AS " . $myDBGroupByFieldName ;
}
*/
// --- Create Query Array!
if ( ($res = $this->CreateQueryArray(UID_UNKNOWN)) != SUCCESS )
return $res;
// Create Options array
$myOptions = array( 'condition' => $this->_myMongoQuery );
// Set default for counter field!
$myMongoInit = array( $myDBSortedFieldName => 0 );
// ---
// --- Process Data and consolidate!
// Create reduce function
$groupReduce = "function (obj, prev) { prev." . $myDBSortedFieldName . "++; }";
try
{
// Output Debug Informations
OutputDebugMessage("LogStreamMongoDB|ConsolidateItemListByField: Running MongoDB group query", DEBUG_ULTRADEBUG);
// mongodb group is simular to groupby from MYSQL
$myResult = $this->_myMongoCollection->group( array($myDBConsFieldName => 1), $myMongoInit, $groupReduce, $myOptions );
}
catch ( MongoCursorException $e )
{
// Log error!
$this->PrintDebugError("ConsolidateItemListByField failed with error ' " . $e->getMessage() . " '");
// Return error code
return ERROR_DB_QUERYFAILED;
}
// Initialize Array variable
$aResult = array();
// Loop through results
if ( isset($myResult['retval']) )
{
foreach ($myResult['retval'] as $myid => $myRow)
{
// Create new row for resultarray
$aNewRow = array();
foreach ( $myRow as $myFieldName => $myFieldValue )
{
if ( !is_array($myFieldValue) && !is_object($myFieldValue) ) // Process normal values
{
$myFieldID = $this->GetFieldIDbyDatabaseMapping($szTableType, $myFieldName);
$aNewRow[ $myFieldID ] = $myFieldValue;
}
}
// Add new row to result
$aResult[] = $aNewRow;
}
}
else
{
// Return error code
OutputDebugMessage("LogStreamMongoDB|ConsolidateItemListByField: myResult['retval'] was empty, see myResult: " . var_export($myResult, true) . ")", DEBUG_WARN);
return ERROR_NOMORERECORDS;
}
// return finished array
if ( count($aResult) > 0 )
{
// Use callback function to sort array
if ( $nSortingOrder == SORTING_ORDER_DESC )
uasort($aResult, "MultiSortArrayByItemCountDesc");
else
uasort($aResult, "MultiSortArrayByItemCountAsc");
// Check if we have to truncate the array
if ($nRecordLimit != 0 && count($aResult) > $nRecordLimit)
{
// Create new stripped array
$aStripResult = array ();
for($iCount = 0; $iCount < $nRecordLimit; $iCount++)
$aStripResult[$iCount] = $aResult[$iCount];
// Overwrite stripped results
$aResult = $aStripResult;
}
OutputDebugMessage("LogStreamMongoDB|ConsolidateItemListByField: Results Array (count " . count($aResult) . ")", DEBUG_ULTRADEBUG);
// OutputDebugMessage("LogStreamMongoDB|ConsolidateItemListByField: Results Array
" . var_export($aResult, true) . "
", DEBUG_ULTRADEBUG);
return $aResult;
}
else
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)
{
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'];
// --- Set DB Field names
$myDBConsFieldName = $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId];
$myDBGroupByFieldName = $myDBConsFieldName;
// Set Sorted Field
if ( $szConsFieldId == $szSortFieldId )
$myDBSortedFieldName = "itemcount";
else
$myDBSortedFieldName = $szSortFieldId;
// ---
// --- Set DB Fields Array
$myMongoFields = array();
$myMongoFields[ $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId] ] = true;
$myMongoFields[ $dbmapping[$szTableType]['DBMAPPINGS'][$szSortFieldId] ] = true;
// Check which fields to include
if ( $aIncludeCustomFields != null )
{
foreach ( $aIncludeCustomFields as $myFieldName )
{
if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName]) )
$myMongoFields[ $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] ] = true;
}
// Append Sortingfield
if ( !in_array($szConsFieldId, $aIncludeCustomFields) )
$myMongoFields[ $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId] ] = true;
}
else if ( $bIncludeLogStreamFields )
{
// var_dump($this->_arrProperties );
foreach ( $this->_arrProperties as $myFieldName )
{
if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName]) )
$myMongoFields[ $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] ] = true;
}
}
//$myMongoFields[ $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId] ] = 1;
//var_dump($myMongoFields);
// --- Create Query Array!
if ( ($res = $this->CreateQueryArray(UID_UNKNOWN)) != SUCCESS )
return $res;
// Create Options array
$myOptions = array( 'condition' => $this->_myMongoQuery );
// Set default for counter field!
$myMongoInit = array( $myDBSortedFieldName => 0 );
//TODO, LIMIT not possible currently!
// $myMongoQuery[ '$limit' ] = 5;
//var_dump($myMongoQuery);
// ---
// --- Process Data and consolidate!
// --- Create reduce function
$groupReduce = "
function (obj, prev)
{
try {\n
prev.$myDBSortedFieldName++;\n
if ( prev.$myDBSortedFieldName == 1 )
{
";
// Add fields!
foreach( $myMongoFields as $key => $myfield )
{
if ( $key != $myDBConsFieldName )
$groupReduce .= " prev.$key = obj.$key;\n";
}
$groupReduce .= "
}
";
if ( $bIncludeMinMaxDateFields )
{
$groupReduce .= "
if ( prev.firstoccurrence_date == null || prev.firstoccurrence_date > obj." . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] . " ) {\n
prev.firstoccurrence_date = obj." . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] . ";\n
}
if ( prev.lastoccurrence_date == null || prev.lastoccurrence_date < obj." . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] . " ) {\n
prev.lastoccurrence_date = obj." . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] . ";\n
}";
}
$groupReduce .= "
}
catch ( e ){
// For now ingore error!
theerror = e.toString();
}
// assert( theerror, \"B3\" )
}
";
// ---
// --- Create Mongo KEY Array
// Workarround to reduce Datekeys by DAY. Otherwise we will run into 20000 unique Key limit
if ( $nConsFieldType == FILTER_TYPE_DATE ) // Handle as date!
$mongoKey = new MongoCode(
"function(doc) {
return {" . $myDBConsFieldName . " : new Date( doc." . $myDBConsFieldName . " - (doc." . $myDBConsFieldName . " % 86400) )};
}");
else
$mongoKey = array($myDBConsFieldName => 1);
/* $mongoKey = new MongoCode(
"function() {
emit(
" . $myDBConsFieldName . ":this." . $myDBConsFieldName . ",
{count:1, _id:this._id}
);
}");
*/
// ---
try
{
// Uncomment for more Debug Informations
OutputDebugMessage("LogStreamMongoDB|ConsolidateDataByField: Running MongoDB group query with mongoKey (type $nConsFieldType):
" . var_export($mongoKey, true) . "
", DEBUG_ULTRADEBUG);
// mongodb group is simular to groupby from MYSQL
$myResult = $this->_myMongoCollection->group( $mongoKey, $myMongoInit, $groupReduce, $myOptions);
}
catch ( MongoCursorException $e )
{
// Log error!
$this->PrintDebugError("ConsolidateDataByField failed with error ' " . $e->getMessage() . " '");
// Return error code
return ERROR_DB_QUERYFAILED;
}
// Initialize Array variable
$aResult = array();
// Loop through results
if ( isset($myResult['retval']) )
{
foreach ($myResult['retval'] as $myid => $myRow)
{
// Create new row for resultarray
$aNewRow = array();
// Handly Datefields for min and max!
if ( $bIncludeMinMaxDateFields )
{
if ( isset($myRow['firstoccurrence_date']) && isset($myRow['lastoccurrence_date']) )
{
$aNewRow['firstoccurrence_date'] = date( "Y-m-d H:i:s ", $myRow['firstoccurrence_date']->sec );
$aNewRow['lastoccurrence_date'] = date( "Y-m-d H:i:s", $myRow['lastoccurrence_date']->sec );
}
else
{
// Get default date
$myDate = $myRow[$dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE]];
if ( gettype($myDate) == "object" && get_class($myDate) == "MongoDate" )
{
$aNewRow['firstoccurrence_date'] = date( "Y-m-d H:i:s ", $myDate->sec );
$aNewRow['lastoccurrence_date'] = date( "Y-m-d H:i:s", $myDate->sec );
}
}
//echo "!". gettype($myDate);
//echo "!" . $myDate->sec;
//var_dump ( $myRow );
//exit;
}
foreach ( $myRow as $myFieldName => $myFieldValue )
{
if ( !is_array($myFieldValue) && !is_object($myFieldValue) ) // Only Copy NON-Array and NON-Object values!
{
$myFieldID = $this->GetFieldIDbyDatabaseMapping($szTableType, $myFieldName);
$aNewRow[ $myFieldID ] = $myFieldValue;
}
}
// Add new row to result
$aResult[] = $aNewRow;
}
}
else
{
// Return error code
OutputDebugMessage("LogStreamMongoDB|ConsolidateDataByField: myResult['retval'] was empty, see myResult: " . var_export($myResult, true) . ")", DEBUG_WARN);
return ERROR_NOMORERECORDS;
}
// return finished array
if ( count($aResult) > 0 )
{
// Use callback function to sort array
if ( $nSortingOrder == SORTING_ORDER_DESC )
uasort($aResult, "MultiSortArrayByItemCountDesc");
else
uasort($aResult, "MultiSortArrayByItemCountAsc");
// Check if we have to truncate the array
if ($nRecordLimit != 0 && count($aResult) > $nRecordLimit)
{
// Create new stripped array
$aStripResult = array ();
for($iCount = 0; $iCount < $nRecordLimit; $iCount++)
$aStripResult[$iCount] = $aResult[$iCount];
// Overwrite stripped results
$aResult = $aStripResult;
}
OutputDebugMessage("LogStreamMongoDB|ConsolidateDataByField: Results Array (count " . count($aResult) . ")", DEBUG_ULTRADEBUG);
// OutputDebugMessage("LogStreamMongoDB|ConsolidateDataByField: Results Array
" . var_export($aResult, true) . "
", DEBUG_ULTRADEBUG);
return $aResult;
}
else
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)
{
global $content, $dbmapping, $fields;
// 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;
// --- Create Query Array!
if ( ($res = $this->CreateQueryArray(UID_UNKNOWN)) != SUCCESS )
return $res;
// Create Options array
$myOptions = array( 'condition' => $this->_myMongoQuery );
// Copy array
$myMongoQuery = $this->_myMongoQuery;
// Set default for counter field!
$myMongoInit = array( 'TotalCount' => 0 );
// ---
// --- Process Data and consolidate!
// Create reduce function
$groupReduce = "function (obj, prev) { prev.TotalCount++; }";
// Workarround to reduce Datekeys by DAY. Otherwise we will run into 20000 unique Key limit
if ( isset($fields[$szFieldId]['FieldType']) && $fields[$szFieldId]['FieldType'] == FILTER_TYPE_DATE ) // Handle as date!
$mongoKey = new MongoCode(
"function(doc) {
return {" . $mySelectFieldName . " : new Date( doc." . $mySelectFieldName . " - (doc." . $mySelectFieldName . " % 86400) )};
}");
else
$mongoKey = array($mySelectFieldName => 1);
try
{
// Uncomment for more Debug Informations
// OutputDebugMessage("LogStreamMongoDB|GetCountSortedByField: Running MongoDB group query with Map Function:
" . $groupReduce . "
", DEBUG_ULTRADEBUG);
// mongodb group is simular to groupby from MYSQL
$myResult = $this->_myMongoCollection->group( $mongoKey, $myMongoInit, $groupReduce, $myOptions);
}
catch ( MongoCursorException $e )
{
// Log error!
$this->PrintDebugError("GetCountSortedByField failed with error ' " . $e->getMessage() . " '");
// Return error code
return ERROR_DB_QUERYFAILED;
}
// Initialize Array variable
$aResult = array();
// Loop through results
if ( isset($myResult['retval']) )
{
foreach ($myResult['retval'] as $myid => $myRow)
{
if ( !is_array($myRow[$mySelectFieldName]) && !is_object($myRow[$mySelectFieldName]) ) // Process normal values
$aResult[ $myRow[$mySelectFieldName] ] = $myRow['TotalCount'];
else
{
// Special Handling for datetype!
if ( gettype($myRow[$mySelectFieldName]) == "object" && get_class($myRow[$mySelectFieldName]) == "MongoDate" )
{
if ( !isset($aResult[ date("Y-m-d", $myRow[$mySelectFieldName]->sec) ]) )
$aResult[ date("Y-m-d", $myRow[$mySelectFieldName]->sec) ] = $myRow['TotalCount'];
else
$aResult[ date("Y-m-d", $myRow[$mySelectFieldName]->sec) ] += $myRow['TotalCount'];
}
else
$aResult[ "Unknown Type" ] = $myRow['TotalCount'];
}
}
}
else
{
// Return error code
OutputDebugMessage("LogStreamMongoDB|GetCountSortedByField: myResult['retval'] was empty, see myResult: " . var_export($myResult, true) . ")", DEBUG_WARN);
return ERROR_NOMORERECORDS;
}
// return finished array
if ( count($aResult) > 0 )
{
// Sort Array
arsort($aResult,SORT_NUMERIC);
// Check if we have to truncate the array
if ($nRecordLimit != 0 && count($aResult) > $nRecordLimit)
{
// Slice all unecessary entries from array!
$aStripResult = array_slice($aResult, 0, $nRecordLimit);
// Overwrite stripped results
$aResult = $aStripResult;
}
OutputDebugMessage("LogStreamMongoDB|GetCountSortedByField: Results Array (count " . count($aResult) . ")", DEBUG_ULTRADEBUG);
// OutputDebugMessage("LogStreamMongoDB|ConsolidateItemListByField: Results Array
" . var_export($aResult, true) . "
", DEBUG_ULTRADEBUG);
// return results
return $aResult;
}
else
return ERROR_NOMORERECORDS;
}
else
{
// return error code, field mapping not found
return ERROR_DB_DBFIELDNOTFOUND;
}
}
/*
* ============= 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 )
{
// Loop through all available properties
foreach( $this->_arrProperties 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]) )
{
$szMongoPropID = $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 )
{
// --- Check if user wants to include or exclude!
if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE)
{
if ( $propertyname == SYSLOG_MESSAGE )
// If we filter for Syslog MSG, we use $ALL to match all values
$this->_myMongoQuery[ $szMongoPropID ]['$all'][] = $myfilter[FILTER_VALUE];
else
// We use $in by default to get results for each value
$this->_myMongoQuery[ $szMongoPropID ]['$in'][] = $myfilter[FILTER_VALUE];
}
else
// $ne equals NOT EQUAL
$this->_myMongoQuery[ $szMongoPropID ]['$ne'][] = $myfilter[FILTER_VALUE];
// ---
}
else if ( $myfilter[FILTER_MODE] & FILTER_MODE_SEARCHREGEX )
{
// --- Check if user wants to include or exclude!
if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE)
{
// Use REGEX to filter for values, NOT TESTED YET!
$this->_myMongoQuery[ $szMongoPropID ]['$regex'][] = $myfilter[FILTER_VALUE];
}
else
// Negate the query using $NOT operator.
$this->_myMongoQuery[ $szMongoPropID ]['$not']['$regex'][] = $myfilter[FILTER_VALUE];
// ---
}
else
{
// This should be a typical LIKE query: Some more checking NEEDED (TODO)!
// --- Check if user wants to include or exclude!
if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE)
{
if ( $propertyname == SYSLOG_MESSAGE )
// If we filter for Syslog MSG, we use $ALL to match all values
$this->_myMongoQuery[ $szMongoPropID ]['$regex'][] = $myfilter[FILTER_VALUE]; // Using REGEX for now!
else
// We use $in by default to get results for each value
$this->_myMongoQuery[ $szMongoPropID ]['$regex'][] = $myfilter[FILTER_VALUE]; // Using REGEX for now!
}
else
// $ne equals NOT EQUAL
$this->_myMongoQuery[ $szMongoPropID ]['$nin'][] = $myfilter[FILTER_VALUE];
// ---
}
// ---
break;
case FILTER_TYPE_NUMBER:
// --- Check if user wants to include or exclude!
if ( $myfilter[FILTER_MODE] & FILTER_MODE_INCLUDE )
{
// We use $in by default to get results for each value
$this->_myMongoQuery[ $szMongoPropID ]['$in'][] = intval($myfilter[FILTER_VALUE]);
}
else
{
// $ne equals NOT EQUAL
$this->_myMongoQuery[ $szMongoPropID ]['$nin'][] = intval($myfilter[FILTER_VALUE]);
}
// ---
break;
case 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;
}
// Create MongoDate Object from Timestamp
$myMongoDate = new MongoDate($nNowTimeStamp);
// add to query array
$this->_myMongoQuery[ $szMongoPropID ]['$gte'] = $myMongoDate;
}
else if ( $myfilter[FILTER_DATEMODE] == DATEMODE_RANGE_FROM )
{
// We use $gt (>) by default to get filter by date
$myeventtime = GetEventTime($myfilter[FILTER_VALUE]);
// Create MongoDate Object from Timestamp
$myMongoDate = new MongoDate($myeventtime[EVTIME_TIMESTAMP]);
// add to query array
$this->_myMongoQuery[ $szMongoPropID ]['$gte'] = $myMongoDate;
}
else if ( $myfilter[FILTER_DATEMODE] == DATEMODE_RANGE_TO )
{
// Obtain Event struct for the time!
$myeventtime = GetEventTime($myfilter[FILTER_VALUE]);
// Create MongoDate Object from Timestamp
$myMongoDate = new MongoDate($myeventtime[EVTIME_TIMESTAMP]);
// add to query array
$this->_myMongoQuery[ $szMongoPropID ]['$lte'] = $myMongoDate;
}
else if ( $myfilter[FILTER_DATEMODE] == DATEMODE_RANGE_DATE )
{
// Obtain Event struct for the time!
$myeventtime = GetEventTime($myfilter[FILTER_VALUE]);
// Create MongoDate Object from Timestamp
$myMongoDateTo = new MongoDate($myeventtime[EVTIME_TIMESTAMP] + 86400);
$myMongoDateFrom = new MongoDate($myeventtime[EVTIME_TIMESTAMP]);
// Add to query array
$this->_myMongoQuery[ $szMongoPropID ]['$lte'] = $myMongoDateTo;
$this->_myMongoQuery[ $szMongoPropID ]['$gte'] = $myMongoDateFrom;
}
break;
default:
// Nothing to do!
break;
}
}
}
}
}
//print_r ( array('x' => array( '$gt' => 5, '$lt' => 20 )) );
OutputDebugMessage("CreateQueryArray verbose: " . var_export($this->_myMongoQuery, true), DEBUG_DEBUG);
}
if ( $uID != UID_UNKNOWN )
{
// Add uID Filter as well!
$myMongoID = new MongoId( $this->convBaseHelper($uID, 10, 16) );
$this->_myMongoQuery[ $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] ] = array( '$lte' => $myMongoID );
}
// Success
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;
try
{
// Debug Informations
OutputDebugMessage("LogStreamMongoDB|ReadNextRecordsFromDB: Running FIND ", DEBUG_ULTRADEBUG);
// Find Data in MongoCollection
$myCursor = $this->_myMongoCollection->find($this->_myMongoQuery)->sort(array("_id" => -1))->limit($this->_logStreamConfigObj->RecordsPerQuery); // , $this->_myMongoFields);
// echo "
", DEBUG_ULTRADEBUG);
/* MOVED to find() call aboev
// Limit records
$myCursor->limit( $this->_logStreamConfigObj->RecordsPerQuery );
// OutputDebugMessage("Cursor verbose: " . var_export($myCursor->explain(), true), DEBUG_DEBUG);
$myCursor = $myCursor->sort(array("_id" => -1));
/**/
try
{
// Copy rows into the buffer!
$iBegin = $this->_currentRecordNum;
$mongoidprev = -1;
foreach ($myCursor as $mongoid => $myRow)
{
// Check if result was successfull! Compare the queried uID and the MONGOID to abort processing if the same ID was returned! Otherwise we have dupplicated results at the end
if ( $myRow === FALSE || !$myRow )
break;
// Convert MongoID
$mongoid = $this->convBaseHelper($mongoid, 16, 10);
// Additional Check to stop processing
if ( ($uID == $mongoid && $myCursor->count() <= 1) ||
(strpos($mongoidprev,$mongoid) !== FALSE) /* Force STRING Type comparison, otherwise PHP will try to compare as NUMBER (INT Limit)!*/
// (count($this->bufferedRecords) > $myCursor->count(true))
)
{
// echo count($this->bufferedRecords) . " " . $myCursor->count(true) . " "; // $mongoidprev $mongoid ";
break;
}
// Convert ID from HEX back to DEC
$myRow[ "_id" ] = $mongoid; // base_convert($mongoid, 16, 10);
$mongoidprev = $mongoid; // Helper variable to compare last row
// Keys will be converted into lowercase!
$this->bufferedRecords[$iBegin] = array_change_key_case( $myRow, CASE_LOWER);
$iBegin++;
}
}
catch ( MongoCursorTimeoutException $e )
{
// Log error!
$this->PrintDebugError("ReadNextRecordsFromDB Timeout while operation ' " . $e->getMessage() . " '");
// Return error code
return ERROR_DB_TIMEOUTFAILED;
}
// Uncomment for debug!
// OutputDebugMessage("LogStreamMongoDB|ReadNextRecordsFromDB: bufferedRecords = Array
" . var_export($this->bufferedRecords, true) . "
", DEBUG_ULTRADEBUG);
OutputDebugMessage("LogStreamMongoDB|ReadNextRecordsFromDB: ibegin = $iBegin, recordnum = " . $this->_currentRecordNum, DEBUG_ULTRADEBUG);
// --- 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 = $myCursor->count();
if ( $this->_totalRecordCount <= 0 )
return ERROR_NOMORERECORDS;
}
// Increment for the Footer Stats
$querycount++;
// return success state if reached this point!
return SUCCESS;
}
/*
* 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 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();
$aMongoIndexes = $this->_myMongoCollection->getIndexInfo();
if (is_array($aMongoIndexes) && count($aMongoIndexes) > 0 )
{
// LOOP through indexes
foreach($aMongoIndexes as $myIndex)
{
if ( strpos($myIndex['ns'], $this->_logStreamConfigObj->DBCollection) !== FALSE )
{
// LOOP through keys
foreach($myIndex['key'] as $myKeyID => $myKey)
{
// Add to index keys
$arrIndexKeys[] = strtolower($myKeyID);
}
}
}
}
//echo "