From: arjen Date: Sat, 5 Oct 2002 10:25:48 +0000 (+0000) Subject: Creation of gcm_input and a first approach to a web interface X-Git-Tag: V0_0_1 X-Git-Url: http://www.andromeda.nl/gitweb/?p=gnucomo.git;a=commitdiff_plain;h=refs%2Ftags%2FV0_0_1 Creation of gcm_input and a first approach to a web interface --- diff --git a/src/gcm_input/gcm_input.cpp b/src/gcm_input/gcm_input.cpp new file mode 100644 index 0000000..51fa9b7 --- /dev/null +++ b/src/gcm_input/gcm_input.cpp @@ -0,0 +1,183 @@ + +/************************************************************************** +** (c) Copyright 2002, Andromeda Technology & Automation +*************************************************************************** +** MODULE INFORMATION * +*********************** +** FILE NAME : gcm_input.cpp +** SYSTEM NAME : Gnucomo - Gnu Computer Monitoring +** VERSION NUMBER : $Revision: 1.1 $ +** +** DESCRIPTION : Application to store client messages into the database +** The client message contains a log file from one of the +** system logs. Gcm_input parses the log file and enters +** the raw data into the 'log' table of the gnucomo database. +** +** The system log may arrive in one of several forms: +** 1. Log file (archived or not) from a client machine. +** 2. Log file from a client system, arriving in a clear Email. +** 3. Log file from a client machine, arriving in an +** encrypted Email. +** +** additional information we need that may not be availble in +** the content of the log is: +** - FQDN of the client. +** - Time of arrival of the log +** - Service that created the log. +** +** If the log arrives in an Email, these items probably are +** available in the mail header. Otherwise, they have to be +** provided as command line arguments. +** +** Command line arguments: +** -c Configuration name (default = gnucomo). +** -d Date and time of log arrival. +** -h FQDN of the client. +** -s Service that created the log. +** -T Test mode. Do not alter the database. +** -v Verbose (debug) output. +** -V Print version and exit. +** +** EXPORTED OBJECTS : +** LOCAL OBJECTS : +** MODULES USED : +*************************************************************************** +** ADMINISTRATIVE INFORMATION * +******************************** +** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl +** CREATION DATE : Aug 29, 2002 +** LAST UPDATE : Sep 30, 2002 +** MODIFICATIONS : +**************************************************************************/ + +/***************************** + $Log: gcm_input.cpp,v $ + Revision 1.1 2002-10-05 10:25:49 arjen + Creation of gcm_input and a first approach to a web interface + +*****************************/ + +static const char *RCSID = "$Id: gcm_input.cpp,v 1.1 2002-10-05 10:25:49 arjen Exp $"; + +#include + +#include "message.h" + +bool verbose = false; +bool testmode = false; + +static char *Version = "gcm_input version 0.0.3 - Sep 30, 2002"; + + +/*========================================================================= +** NAME : main +** SYNOPSIS : int main(int argc, char *argv[]) +** PARAMETERS : +** RETURN VALUE : +** +** DESCRIPTION : Parse command line arguments and establish a connection +** to the database. +** When we have a database connection, parse the log file +** from stdin. +** +** VARS USED : +** VARS CHANGED : +** FUNCTIONS USED : +** SEE ALSO : +** LAST MODIFIED : Sep 30, 2002 +**========================================================================= +*/ + +int main(int argc, char *argv[]) +{ + const char *usage = "Usage: gcm_input [-c configname] [-h hostname] [-d date]" + " [-s service] [-T] [-v] [-V]\n"; + + gnucomo_config cfg; + char *config_name = "gnucomo"; + + /* Parse command line arguments */ + + UTC arrival = Now(); + String hostname(""), service(""); + int option; + + + while ((option = getopt(argc, argv, "c:h:d:s:TvV")) != -1) + { + switch (option) + { + case 'c': + config_name = optarg; + break; + + case 'h': + hostname = optarg; + break; + + case 'd': + arrival = String(optarg); + if (!arrival.proper()) + { + cerr << "gcm_input: Invalid date string: " << optarg << ".\n"; + exit(1); + } + break; + + case 's': + service = optarg; + break; + + case 'T': + testmode = true; + break; + + case 'v': + verbose = true; + break; + + case 'V': + cout << Version << "\n"; + exit(0); + + case '?': + case ':': + cerr << usage; + exit(1); + } + } + + if (verbose) + { + cout << "Hostname = " << hostname; + cout << " Arrival = " << arrival; + cout << " Service = " << service << "\n"; + } + + /* Get the configuration file */ + + if (!cfg.read(config_name)) + { + cerr << "Can not read Gnucomo configuration file for " << config_name << ".\n"; + exit(1); + } + + if (verbose) + { + cout << "Config OK.\n"; + } + + /* Try to connect to the database */ + + gnucomo_database db(&cfg); + + client_message msg(&cin, db); + + if (msg.classify(hostname, arrival, service) > 0.9) + { + msg.enter(); + } + + return 0; +} + diff --git a/src/gcm_input/makefile b/src/gcm_input/makefile new file mode 100644 index 0000000..4341009 --- /dev/null +++ b/src/gcm_input/makefile @@ -0,0 +1,13 @@ +CXXFLAGS = -I/usr/include/gnome-xml -g + +GCMINPUT_O = gcm_input.o gnucomo_config.o database.o message.o + +gcm_input : $(GCMINPUT_O) + $(CXX) -o gcm_input $(GCMINPUT_O) -lAXE -lxml -lpq++ + +gcm_input.o : message.h database.h +database.o : database.h +message.o : message.h + +clean: + rm -f gcm_input $(GCMINPUT_O) diff --git a/src/gcm_input/message.cpp b/src/gcm_input/message.cpp new file mode 100644 index 0000000..9b1ef1a --- /dev/null +++ b/src/gcm_input/message.cpp @@ -0,0 +1,510 @@ + +/************************************************************************** +** (c) Copyright 2002, Andromeda Technology & Automation +*************************************************************************** +** MODULE INFORMATION * +*********************** +** FILE NAME : message.cpp +** SYSTEM NAME : Gnucomo - Gnu Computer Monitoring +** VERSION NUMBER : $Revision: 1.1 $ +** +** DESCRIPTION : Implementation of the message handling classes +** +** EXPORTED OBJECTS : +** LOCAL OBJECTS : +** MODULES USED : +*************************************************************************** +** ADMINISTRATIVE INFORMATION * +******************************** +** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl +** CREATION DATE : Sep 16, 2002 +** LAST UPDATE : Oct 05, 2002 +** MODIFICATIONS : +**************************************************************************/ + +/***************************** + $Log: message.cpp,v $ + Revision 1.1 2002-10-05 10:25:49 arjen + Creation of gcm_input and a first approach to a web interface + +*****************************/ + +static const char *RCSID = "$Id: message.cpp,v 1.1 2002-10-05 10:25:49 arjen Exp $"; + +#include "message.h" + +extern bool verbose; /* Defined in the main application */ +extern bool testmode; + +/* Utility functions */ + +String SQL_Escape(String s); + +/*========================================================================= +** NAME : operator >> +** SYNOPSIS : bool operator >> (message_buffer &, String &) +** PARAMETERS : +** RETURN VALUE : True if input was available. +** +** DESCRIPTION : Input operator. Read the next line from the message. +** +** VARS USED : +** VARS CHANGED : +** FUNCTIONS USED : +** SEE ALSO : +** LAST MODIFIED : Sep 30, 2002 +**========================================================================= +*/ + +bool operator >> (message_buffer &b, String &s) +{ + bool input_ok = false; + + if (b.next_line == b.buffer.end()) + { + String l; + + //cout << " buffer is depleted.\n"; + if (*(b.input) >> l) + { + b.buffer.push_back(l); + + // next_line keeps pointing to the end. + + s = l; + input_ok = true; + //cout << " new line from input.\n"; + } + } + else + { + //cout << " reading from cache.\n"; + s = *(b.next_line); + b.next_line++; + input_ok = true; + } + return input_ok; +} + +client_message::client_message(istream *in, gnucomo_database db) +{ + input.from(in); + database = db; + + hostname = ""; + mail_header = false; + gpg_encrypted = false; + classification = UNKNOWN; + certainty = 0.0; +} + +static const String syslog_date_re("[[:alpha:]]{3} [ 123][0-9] [0-9]{2}:[0-9]{2}:[0-9]{2}"); +static const String mail_date_re("[[:alpha:]]{3}, [ 123]?[0-9] [[:alpha:]]{3} [0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2} [+-][0-9]{4}"); +static const String unix_date_re("[[:alpha:]]{3} [[:alpha:]]{3} [ 123][0-9] [0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{4}"); + +static const regex re_syslog(syslog_date_re + " [a-z]+ [[:alpha:]]+.*:.+"); +static const regex re_PGP("-----BEGIN PGP MESSAGE-----"); +static const regex re_dump("^ *DUMP: Date of this level"); +static const regex re_accesslog("(GET|POST) .+ HTTP"); +static const regex re_errorlog("^\\[" + unix_date_re + "\\] \\[(error|notice)\\] .+"); + +static const regex re_syslog_date("[[:alpha:]]{3} [ 123][0-9] [0-9]{2}:[0-9]{2}:[0-9]{2}"); +static const regex re_uxmail_from("^From - " + unix_date_re); +static const regex re_mail_From("^From:[[:blank:]]+"); +static const regex re_mail_Date("^Date:[[:blank:]]+" + mail_date_re); +static const regex re_email_address("[[:alnum:]_.-]+@[[:alnum:]_.-]+"); +static const regex re_email_user("[[:alnum:]_.-]+@"); + +/*========================================================================= +** NAME : classify +** SYNOPSIS : double classify(String host, date arriv_d, hour arriv_t, String serv) +** PARAMETERS : +** RETURN VALUE : The certainty with which the message is classified. +** +** DESCRIPTION : +** +** VARS USED : +** VARS CHANGED : +** FUNCTIONS USED : +** SEE ALSO : +** LAST MODIFIED : Oct 05, 2002 +**========================================================================= +*/ + +double client_message::classify(String host, UTC arriv, String serv) +{ + String line; + + hostname = host; + arrival = arriv; + service = serv; + + /* First, check if the message has a mail header. */ + + if (input >> line && line == re_uxmail_from) + { + String from_address; + + mail_header = true; + + /* Scan ahead for the hostname and date of arrival. */ + + while (input >> line && line != "") + { + if (line == re_mail_From) + { + from_address = line(re_email_address); + from_address(re_email_user) = ""; // Remove the user part; + hostname = from_address; + } + if (line == re_mail_Date) + { + arrival = UTC(line(regex(mail_date_re))); + } + } + } + else + { + // Push the first line back, we need to read it again. + --input; + } + + /* + * Now that we have the mail header out of the way, try to figure + * out what the content of the message is. + */ + + + while (input >> line && certainty < 0.9) + { + cout << " testing: " << line << "\n"; + if (line == re_syslog) + { + certainty = 1.0; + classification = SYSLOG; + if (verbose) + { + cout << "Syslog detected.\n"; + } + } + else if (line == re_PGP) + { + certainty = 1.0; + gpg_encrypted = true; + cerr << "The message is PGP/GnuPG encrypted.\n"; + } + else if (line == re_dump) + { + certainty = 1.0; + if (verbose) + { + cout << "DUMP output detected.\n"; + } + } + else if (line == re_accesslog) + { + certainty = 1.0; + classification = ACCESSLOG; + service = "httpd"; + if (verbose) + { + cout << "HTTP access log detected.\n"; + } + } + else if (line == re_errorlog) + { + certainty = 1.0; + classification = ERRORLOG; + service = "httpd"; + if (verbose) + { + cout << "HTTP error log detected.\n"; + } + } + } + input.rewind(); + + if (hostname == "") + { + cerr << "Can not determine the hostname where the message came from.\n"; + certainty = 0.0; + } + else if (!arrival.proper()) + { + cerr << "Arrival time is not knwon.\n"; + certainty = 0.0; + } + else + { + certainty = 1.0; + } + + return certainty; +} + +/*========================================================================= +** NAME : enter +** SYNOPSIS : int enter() +** PARAMETERS : +** RETURN VALUE : The number of lines successfully parsed from the input +** +** DESCRIPTION : +** +** VARS USED : +** VARS CHANGED : +** FUNCTIONS USED : +** SEE ALSO : +** LAST MODIFIED : Oct 05, 2002 +**========================================================================= +*/ + +int client_message::enter() +{ + long nr_lines = 0; + String line; + + /* Double-check the classification of the message */ + + if (classification == UNKNOWN || certainty < 0.9 || gpg_encrypted) + { + return 0; + } + + if (mail_header) + { + // Skip the mail header. + + while (input >> line && line != ""); + } + + /* Try to find the host in the database */ + + String objectid; + + objectid = database.find_host(hostname); + if (objectid == "") + { + cerr << "Please define the host " << hostname << " in the database.\n"; + return 0; + } + if (verbose) + { + cout << "Object id for " << hostname << " is " << objectid << "\n"; + } + + /* Scan the input line by line, entring records into the database */ + + String rest; // Rest of the line to be parsed + + while (input >> line) + { + if (verbose) + { + cout << line << "\n"; + } + + + /* Check each line if it contains valid information */ + + const regex *check; + + switch (classification) + { + case SYSLOG: + check = &re_syslog; + break; + case ACCESSLOG: + check = &re_accesslog; + break; + case ERRORLOG: + check = &re_errorlog; + break; + } + + if (line == *check) + { + date log_date; + hour log_time; + int i; + + String insertion("insert into log (objectid, servicecode," + " object_timestamp, timestamp, rawdata) values ("); + String datestring; + + switch (classification) + { + case SYSLOG: + log_date = line; + log_time = line; + if (log_date.Year() < 0 || log_date.Year() > 2500) + { + // The year is not in the log file. Assume the year of arrival + + log_date = date(log_date.Day(), log_date.Month(), date(arrival).Year()); + } + + if (verbose) + { + cout << " Log timestamp = " << log_date << " " << log_time << "\n"; + } + rest = line << 16; + i = rest.index(' '); + if (rest(0,i) == hostname(0,i)) + { + rest <<= i + 1; + if (verbose) + { + cout << " Hostname matches.\n"; + cout << " rest = " << rest << "\n"; + } + for (i = 0; isalpha(rest[i]) && i < ~rest; i++); + if (verbose) + { + cout << " Service name = " << rest(0,i) << "\n"; + } + + /* Insert a new record into the log table */ + + insertion += "'" + objectid + "',"; + insertion += "'" + rest(0,i) + "',"; + insertion += "'" + log_date.format() + " " + log_time.format() + "',"; + insertion += "'" + arrival.format() + "',"; + insertion += "'" + SQL_Escape(line) + "'"; + insertion += ")"; + + if (testmode) + { + cout << insertion << "\n"; + } + else + { + database.Query(insertion); + } + + if (verbose) + { + cout << "\n\n"; + } + + nr_lines++; + } + else + { + cerr << " Hostname " << rest(0,i) << " does not match.\n"; + } + break; + + case ACCESSLOG: + datestring = line(regex("\\[.+\\]")); + datestring <<= 1; + datestring >>= 1; + datestring[datestring.index(':')] = ' '; + log_date = datestring; + log_time = datestring; + if (verbose) + { + cout << " Log timestamp = " << log_date << " " << log_time << "\n"; + } + insertion += "'" + objectid + "',"; + insertion += "'" + service + "',"; + insertion += "'" + log_date.format() + " " + log_time.format() + "',"; + insertion += "'" + arrival.format() + "',"; + insertion += "'" + SQL_Escape(line) + "'"; + insertion += ")"; + + if (testmode) + { + cout << insertion << "\n"; + } + else + { + database.Query(insertion); + } + + if (verbose) + { + cout << "\n\n"; + } + + nr_lines++; + break; + + case ERRORLOG: + datestring = line(regex("\\[.+\\]")); + datestring <<= 1; + datestring >>= 1; + log_date = datestring; + log_time = datestring; + if (verbose) + { + cout << " Log timestamp = " << log_date << " " << log_time << "\n"; + } + insertion += "'" + objectid + "',"; + insertion += "'" + service + "',"; + insertion += "'" + log_date.format() + " " + log_time.format() + "',"; + insertion += "'" + arrival.format() + "',"; + insertion += "'" + SQL_Escape(line) + "'"; + insertion += ")"; + + if (testmode) + { + cout << insertion << "\n"; + } + else + { + database.Query(insertion); + } + + if (verbose) + { + cout << "\n\n"; + } + + nr_lines++; + break; + } + } + else + { + cerr << "gcm_input WARNING: Not a valid line: " << line << "\n"; + } + } + + if (verbose) + { + cout << nr_lines << " lines parsed from the log file.\n"; + } + return nr_lines; +} + +/*========================================================================= +** NAME : SQL_Escape +** SYNOPSIS : String SQL_Escape(String) +** PARAMETERS : +** RETURN VALUE : +** +** DESCRIPTION : Insert backslashes before single quotes. +** +** VARS USED : +** VARS CHANGED : +** FUNCTIONS USED : +** SEE ALSO : +** LAST MODIFIED : +**========================================================================= +*/ + +String SQL_Escape(String s) +{ + int i; + + for (i = 0; i < ~s; i++) + { + if (s[i] == '\'') + { + s(i,0) = "\\"; + i++; + } + } + + return s; +} diff --git a/src/gcm_input/message.h b/src/gcm_input/message.h new file mode 100644 index 0000000..03a8209 --- /dev/null +++ b/src/gcm_input/message.h @@ -0,0 +1,150 @@ + +/************************************************************************** +** (c) Copyright 2002, Andromeda Technology & Automation +*************************************************************************** +** MODULE INFORMATION * +*********************** +** FILE NAME : message.h +** SYSTEM NAME : +** VERSION NUMBER : $Revision: 1.1 $ +** +** DESCRIPTION : Classes to for handling client messages +** +** EXPORTED OBJECTS : +** LOCAL OBJECTS : +** MODULES USED : +*************************************************************************** +** ADMINISTRATIVE INFORMATION * +******************************** +** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl +** CREATION DATE : Sep 16, 2002 +** LAST UPDATE : Oct 05, 2002 +** MODIFICATIONS : +**************************************************************************/ + +/***************************** + $Log: message.h,v $ + Revision 1.1 2002-10-05 10:25:49 arjen + Creation of gcm_input and a first approach to a web interface + +*****************************/ + +/* static const char *RCSID = "$Id: message.h,v 1.1 2002-10-05 10:25:49 arjen Exp $"; */ + +#include +#include +#include +#include + +#include "database.h" + +/* +/////////////////////////////////////////////////////////////////////////// +// NAME : message_buffer +// BASECLASS : +// MEMBERS : +// OPERATORS : +// METHODS : rewind() +// +// DESCRIPTION : +// +// RELATIONS : +// SEE ALSO : +// LAST MODIFIED : Sep 30, 2002 +/////////////////////////////////////////////////////////////////////////// +*/ + +class message_buffer +{ + istream *input; + list buffer; + + list::iterator next_line; + +public: + + message_buffer() + { + input = 0; + next_line = buffer.begin(); + } + + message_buffer(istream *in) + { + input = in; + next_line = buffer.begin(); + } + + void from(istream *in) + { + input = in; + } + + friend bool operator >> (message_buffer &, String &); + + void rewind() + { + next_line = buffer.begin(); + } + + void operator ++() + { + if (next_line != buffer.end()) + { + next_line++; + } + } + + void operator --() + { + if (next_line != buffer.begin()) + { + next_line--; + } + } +}; + +/* +/////////////////////////////////////////////////////////////////////////// +// NAME : client_message +// BASECLASS : +// MEMBERS : +// OPERATORS : +// METHODS : classify() +// enter() +// +// DESCRIPTION : +// +// RELATIONS : +// SEE ALSO : +// LAST MODIFIED : Oct 05, 2002 +/////////////////////////////////////////////////////////////////////////// +*/ + +class client_message +{ + String hostname; // Where the message came from (FQDN) + UTC arrival; // When we got the message. + String service; // Service that created the message + + bool mail_header; // Does the message contain a mail header ? + bool gpg_encrypted; // Is the message encrypted ? + + double certainty; // How certain are we about the message + enum + { + UNKNOWN, SYSLOG, ACCESSLOG, ERRORLOG + } classification; + + + message_buffer input; + gnucomo_database database; + +public: + + client_message(istream *in, gnucomo_database db); + + double classify(String host, UTC arrival = Now(), String serv = ""); + int enter(); +}; + diff --git a/src/gnucomo.conf b/src/gnucomo.conf new file mode 100644 index 0000000..90499ef --- /dev/null +++ b/src/gnucomo.conf @@ -0,0 +1,12 @@ + + + + PostgreSQL + gnucomo + arjen + guess again :-) + localhost + 5432 + + + diff --git a/src/include/database.h b/src/include/database.h new file mode 100644 index 0000000..5fb2323 --- /dev/null +++ b/src/include/database.h @@ -0,0 +1,91 @@ + +/************************************************************************** +** (c) Copyright 2002, Andromeda Technology & Automation +*************************************************************************** +** MODULE INFORMATION * +*********************** +** FILE NAME : database.h +** SYSTEM NAME : +** VERSION NUMBER : $Revision: 1.1 $ +** +** DESCRIPTION : Classes to provide an abstract layer on the Gnucomo +** database. +** +** EXPORTED OBJECTS : +** LOCAL OBJECTS : +** MODULES USED : +*************************************************************************** +** ADMINISTRATIVE INFORMATION * +******************************** +** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl +** CREATION DATE : Sep 10, 2002 +** LAST UPDATE : +** MODIFICATIONS : +**************************************************************************/ + +/***************************** + $Log: database.h,v $ + Revision 1.1 2002-10-05 10:25:49 arjen + Creation of gcm_input and a first approach to a web interface + +*****************************/ + +/* static const char *RCSID = "$Id: database.h,v 1.1 2002-10-05 10:25:49 arjen Exp $"; */ + +#include +#include "gnucomo_config.h" + +/* +/////////////////////////////////////////////////////////////////////////// +// NAME : gnucomo_database +// BASECLASS : configuration +// MEMBERS : +// OPERATORS : +// METHODS : Database - Obtain the database access string +// +// DESCRIPTION : +// +// RELATIONS : +// SEE ALSO : +// LAST MODIFIED : Sep 16, 2002 +/////////////////////////////////////////////////////////////////////////// +*/ + +class gnucomo_database +{ + gnucomo_config *cfg; + PgDatabase *db; + +public: + + gnucomo_database() + { + cfg = 0; + db = 0; + } + + gnucomo_database(gnucomo_config *c); // Use the configuration to connect to the database + + // Low-level database access functions + + int Query(String qry) + { + ExecStatusType result; + + result = db->Exec(qry); + if (result == PGRES_TUPLES_OK || result == PGRES_COMMAND_OK) + { + return db->Tuples(); + } + else + { + cerr << "Database query error: " << db->ErrorMessage() << "\n"; + return -1; + } + } + + // Return the objectid of the host given its name. + + String find_host(const String hostname); +}; + diff --git a/src/include/gnucomo_config.h b/src/include/gnucomo_config.h new file mode 100644 index 0000000..4c854be --- /dev/null +++ b/src/include/gnucomo_config.h @@ -0,0 +1,59 @@ + +/************************************************************************** +** (c) Copyright 2002, Andromeda Technology & Automation +*************************************************************************** +** MODULE INFORMATION * +*********************** +** FILE NAME : gnucomo.h +** SYSTEM NAME : +** VERSION NUMBER : $Revision: 1.1 $ +** +** DESCRIPTION : +** +** EXPORTED OBJECTS : +** LOCAL OBJECTS : +** MODULES USED : +*************************************************************************** +** ADMINISTRATIVE INFORMATION * +******************************** +** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl +** CREATION DATE : Jul 24, 2002 +** LAST UPDATE : +** MODIFICATIONS : +**************************************************************************/ + +/***************************** + $Log: gnucomo_config.h,v $ + Revision 1.1 2002-10-05 10:25:49 arjen + Creation of gcm_input and a first approach to a web interface + +*****************************/ + +/* static const char *RCSID = "$Id: gnucomo_config.h,v 1.1 2002-10-05 10:25:49 arjen Exp $"; */ + +#include + +/* +/////////////////////////////////////////////////////////////////////////// +// NAME : gnucomo_config +// BASECLASS : configuration +// MEMBERS : +// OPERATORS : +// METHODS : Database - Obtain the database access string +// +// DESCRIPTION : +// +// RELATIONS : +// SEE ALSO : +// LAST MODIFIED : +/////////////////////////////////////////////////////////////////////////// +*/ + +class gnucomo_config : public configuration +{ + +public: + + String Database(); // Return the database access string. +}; + diff --git a/src/lib/database.cpp b/src/lib/database.cpp new file mode 100644 index 0000000..134a536 --- /dev/null +++ b/src/lib/database.cpp @@ -0,0 +1,106 @@ + +/************************************************************************** +** (c) Copyright 2002, Andromeda Technology & Automation +*************************************************************************** +** MODULE INFORMATION * +*********************** +** FILE NAME : database.cpp +** SYSTEM NAME : Gnucomo - Gnu Computer Monitoring +** VERSION NUMBER : $Revision: 1.1 $ +** +** DESCRIPTION : Implementation of the gnucomo database classes +** +** EXPORTED OBJECTS : +** LOCAL OBJECTS : +** MODULES USED : +*************************************************************************** +** ADMINISTRATIVE INFORMATION * +******************************** +** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl +** CREATION DATE : Sep 10, 2002 +** LAST UPDATE : Sep 26, 2002 +** MODIFICATIONS : +**************************************************************************/ + +/***************************** + $Log: database.cpp,v $ + Revision 1.1 2002-10-05 10:25:49 arjen + Creation of gcm_input and a first approach to a web interface + +*****************************/ + +static const char *RCSID = "$Id: database.cpp,v 1.1 2002-10-05 10:25:49 arjen Exp $"; + +#include "database.h" + +extern bool verbose; /* Defined in the main application */ + +/*========================================================================= +** NAME : gnucomo_database +** SYNOPSIS : gnucomo_database(gnucomo_config &c); +** PARAMETERS : +** RETURN VALUE : Database constructor. Establishes a connection with +** the database server. +** +** DESCRIPTION : +** +** VARS USED : +** VARS CHANGED : +** FUNCTIONS USED : +** SEE ALSO : +** LAST MODIFIED : Sep 26, 2002 +**========================================================================= +*/ + +gnucomo_database::gnucomo_database(gnucomo_config *c) +{ + cfg = c; + + if (verbose) + { + cout << "Database connection string = " << cfg->Database() << "\n"; + } + + db = new PgDatabase(cfg->Database()); + + if (db->ConnectionBad()) + { + cerr << "Can not connect to database: " << db->ErrorMessage(); + } +} + +/*========================================================================= +** NAME : find_host +** SYNOPSIS : String gnucomo_database::find_host(String hostname); +** PARAMETERS : +** RETURN VALUE : Find a hostname in the 'object' table of the gnucomo database +** and return its object id. +** Return an empty string as objectid if the hostname is +** not found. +** +** DESCRIPTION : +** +** VARS USED : +** VARS CHANGED : +** FUNCTIONS USED : +** SEE ALSO : +** LAST MODIFIED : Sep 16, 2002 +**========================================================================= +*/ + +String gnucomo_database::find_host(const String hostname) +{ + String objectid(""); + String check_host("select objectid from object where "); + + check_host += "objectname = '"; + check_host += hostname; + check_host += "'"; + + if (Query(check_host) > 0) + { + objectid = String(db->GetValue(0, "objectid")); + } + + return objectid; +} diff --git a/src/lib/gnucomo_config.cpp b/src/lib/gnucomo_config.cpp new file mode 100644 index 0000000..794241e --- /dev/null +++ b/src/lib/gnucomo_config.cpp @@ -0,0 +1,91 @@ + +/************************************************************************** +** (c) Copyright 2002, Andromeda Technology & Automation +*************************************************************************** +** MODULE INFORMATION * +*********************** +** FILE NAME : gnucomo_config.cpp +** SYSTEM NAME : Gnucomo - Gnu Computer Monitoring +** VERSION NUMBER : $Revision: 1.1 $ +** +** DESCRIPTION : Implementation of the gnucomo_config class. +** +** EXPORTED OBJECTS : +** LOCAL OBJECTS : +** MODULES USED : +*************************************************************************** +** ADMINISTRATIVE INFORMATION * +******************************** +** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl +** CREATION DATE : Jul 24, 2002 +** LAST UPDATE : Jul 24, 2002 +** MODIFICATIONS : +**************************************************************************/ + +/***************************** + $Log: gnucomo_config.cpp,v $ + Revision 1.1 2002-10-05 10:25:49 arjen + Creation of gcm_input and a first approach to a web interface + +*****************************/ + +static const char *RCSID = "$Id: gnucomo_config.cpp,v 1.1 2002-10-05 10:25:49 arjen Exp $"; + +#include "gnucomo_config.h" + + + +/*========================================================================= +** NAME : Database +** SYNOPSIS : String gnucomo_config::Database() +** PARAMETERS : +** RETURN VALUE : The database access string +** +** DESCRIPTION : +** +** VARS USED : +** VARS CHANGED : +** FUNCTIONS USED : +** SEE ALSO : +** LAST MODIFIED : +**========================================================================= +*/ + +String gnucomo_config::Database() +{ + String param; + String access_string(""); + + param = find_parameter("database", "name"); + if (param != "") + { + access_string += "dbname=" + param; + } + + param = find_parameter("database", "user"); + if (param != "") + { + access_string += " user=" + param; + } + param = find_parameter("database", "password"); + if (param != "") + { + access_string += " password=" + param; + } + + /* FIXME: This needs a fix in the AXE library first */ + + /* + param = find_parameter("database", "host"); + if (param != "") + { + access_string += " host=" + param; + } + param = find_parameter("database", "port"); + if (param != "") + { + access_string += " port=" + param; + } +*/ + return access_string; +} diff --git a/src/phpclasses/configuration.class.php b/src/phpclasses/configuration.class.php new file mode 100644 index 0000000..5d5968e --- /dev/null +++ b/src/phpclasses/configuration.class.php @@ -0,0 +1,109 @@ +type == XML_ELEMENT_NODE && $node[$i]->tagname == $tag) + { + $element = $node[$i]; + } + $i++; + } + + return $element; + } + + function read($app_name) + { + $filename = "/etc/" . $app_name . ".conf"; + $this->system = xmldocfile($filename); + + if (!$this->system) + { + $filename = "/usr/local/etc/" . $app_name . ".conf"; + $this->system = xmldocfile($filename); + } + + if ($this->system) + { + $root = $this->system->root(); + + if ($root->tagname != $app_name) + { + print("Configuration error: Wrong configuration file.
"); + $this->system = false; + } + } + else + { + print("Configuration error: Configuration file for $app_name not found.
"); + } + } + + function find_parameter($section, $parameter) + { + $param_value = ""; + + if ($this->system) + { + $root_node = $this->system->root(); + $section_node = $this->xmlFindTag($root_node->children(), $section); + if ($section_node) + { + $param_node = $this->xmlFindTag($section_node->children(), $parameter); + if ($param_node) + { + $param_node = $param_node->children(); + } + if ($param_node && $param_node[0]->type == XML_TEXT_NODE) + { + $param_value = $param_node[0]->content; + } + } + } + + return $param_value; + } +} + +?> diff --git a/src/phpclasses/gnucomo_config.php b/src/phpclasses/gnucomo_config.php new file mode 100644 index 0000000..ea57c2f --- /dev/null +++ b/src/phpclasses/gnucomo_config.php @@ -0,0 +1,62 @@ +find_parameter("database", "name"); + if ($param != "") + { + $access_string .= "dbname=" . $param; + } + + $param = $this->find_parameter("database", "user"); + if ($param != "") + { + $access_string .= " user=" . $param; + } + + $param = $this->find_parameter("database", "password"); + if ($param != "") + { + $access_string .= " password=" . $param; + } + + $param = $this->find_parameter("database", "host"); + if ($param != "") + { + $access_string .= " host=" . $param; + } + + $param = $this->find_parameter("database", "port"); + if ($param != "") + { + $access_string .= " port=" . $param; + } + return $access_string; + } +}; +?> diff --git a/src/web/change.png b/src/web/change.png new file mode 100644 index 0000000..d413512 Binary files /dev/null and b/src/web/change.png differ diff --git a/src/web/classes/configuration.class.php b/src/web/classes/configuration.class.php new file mode 100644 index 0000000..5d5968e --- /dev/null +++ b/src/web/classes/configuration.class.php @@ -0,0 +1,109 @@ +type == XML_ELEMENT_NODE && $node[$i]->tagname == $tag) + { + $element = $node[$i]; + } + $i++; + } + + return $element; + } + + function read($app_name) + { + $filename = "/etc/" . $app_name . ".conf"; + $this->system = xmldocfile($filename); + + if (!$this->system) + { + $filename = "/usr/local/etc/" . $app_name . ".conf"; + $this->system = xmldocfile($filename); + } + + if ($this->system) + { + $root = $this->system->root(); + + if ($root->tagname != $app_name) + { + print("Configuration error: Wrong configuration file.
"); + $this->system = false; + } + } + else + { + print("Configuration error: Configuration file for $app_name not found.
"); + } + } + + function find_parameter($section, $parameter) + { + $param_value = ""; + + if ($this->system) + { + $root_node = $this->system->root(); + $section_node = $this->xmlFindTag($root_node->children(), $section); + if ($section_node) + { + $param_node = $this->xmlFindTag($section_node->children(), $parameter); + if ($param_node) + { + $param_node = $param_node->children(); + } + if ($param_node && $param_node[0]->type == XML_TEXT_NODE) + { + $param_value = $param_node[0]->content; + } + } + } + + return $param_value; + } +} + +?> diff --git a/src/web/classes/gnucomo_config.php b/src/web/classes/gnucomo_config.php new file mode 100644 index 0000000..ea57c2f --- /dev/null +++ b/src/web/classes/gnucomo_config.php @@ -0,0 +1,62 @@ +find_parameter("database", "name"); + if ($param != "") + { + $access_string .= "dbname=" . $param; + } + + $param = $this->find_parameter("database", "user"); + if ($param != "") + { + $access_string .= " user=" . $param; + } + + $param = $this->find_parameter("database", "password"); + if ($param != "") + { + $access_string .= " password=" . $param; + } + + $param = $this->find_parameter("database", "host"); + if ($param != "") + { + $access_string .= " host=" . $param; + } + + $param = $this->find_parameter("database", "port"); + if ($param != "") + { + $access_string .= " port=" . $param; + } + return $access_string; + } +}; +?> diff --git a/src/web/closed_package.png b/src/web/closed_package.png new file mode 100644 index 0000000..d786cca Binary files /dev/null and b/src/web/closed_package.png differ diff --git a/src/web/exit.png b/src/web/exit.png new file mode 100644 index 0000000..86d9c47 Binary files /dev/null and b/src/web/exit.png differ diff --git a/src/web/functions.php b/src/web/functions.php new file mode 100755 index 0000000..61e64a8 --- /dev/null +++ b/src/web/functions.php @@ -0,0 +1,77 @@ +"; + $login .= "

GNU Computer Monitoring

"; + $login .= "
"; + $login .= ""; + $login .= ""; + $login .= ""; + $login .= ""; + $login .= "
GnuCoMo logo
"; + $login .= " "; + $login .= " "; + $login .= " "; + $login .= " "; + $login .= " "; + $login .= " "; + $login .= " "; + $login .= " "; + $login .= " "; + $login .= " "; + $login .= " "; + $login .= " "; + $login .= " "; + $login .= "
Username
Password
 
"; + $login .= "
"; + $login .= "
"; + $login .= ""; + + return $login; +} + +/******************************************************************************************/ +/* array function query( resource connection, string sqlquery ) */ +/* */ +/* gives an array return. */ +/* arr[0] = boolean if action completed whitout error, return true otherwise false */ +/* arr[1] = result sql query result */ +/* arr[2] = int number of rows */ +/* arr[3] = string error information */ +/******************************************************************************************/ +function query( $conn, $sql ) { + + $query_result = pg_exec( $conn, $sql ); + + if( $query_result != FALSE ) { + $query_nRows = pg_NumRows($query_result); + $query_error = pg_errormessage( $conn ); + return array( TRUE, $query_result, $query_nRows, "" ); + } else { + $query_error = @pg_errormessage( $conn ); + return array( FALSE, $query_result, 0, $query_error ); + } +} + +/******************************************************************************************/ +/* void function pgsql_error( string error ) */ +/* */ +/* prints an error message */ +/******************************************************************************************/ +function pgsql_error( $err ) { + echo "An error occured. Please contact your systemadministrator.
"; + echo "Error: $err"; +} +?> diff --git a/src/web/gnucomo.css b/src/web/gnucomo.css new file mode 100644 index 0000000..f4a27fb --- /dev/null +++ b/src/web/gnucomo.css @@ -0,0 +1,47 @@ + +body +{ + background-color : rgb(80, 120, 100); +} + +h1 +{ + font-family : sans-serif ; + text-align : center ; +} + +h2 +{ + font-family : sans-serif ; +} + +div.login +{ + background : rgb(80, 120, 150) ; + border: solid; + border-width: thick; + border-color : cyan ; + padding : 1em; + margin : 10% ; + width: 80%; + text-align : center ; +} +table +{ + width : 80% ; + border-width : medium ; + border-style : none ; + border-collapse : collapse; + padding : 1px ; +} + +td +{ + font-family : sans-serif ; +} + +th +{ + border-width : thin ; + border-style : solid ; +} diff --git a/src/web/harddisk.png b/src/web/harddisk.png new file mode 100644 index 0000000..981b148 Binary files /dev/null and b/src/web/harddisk.png differ diff --git a/src/web/index.html b/src/web/index.html new file mode 100644 index 0000000..b7a4b12 --- /dev/null +++ b/src/web/index.html @@ -0,0 +1,12 @@ + + + + + +GnuCoMo Web Interface + + + + + + diff --git a/src/web/log.png b/src/web/log.png new file mode 100644 index 0000000..b0783b0 Binary files /dev/null and b/src/web/log.png differ diff --git a/src/web/login.php b/src/web/login.php new file mode 100755 index 0000000..871bd10 --- /dev/null +++ b/src/web/login.php @@ -0,0 +1,59 @@ + + + + + + +GNUCoMo login + + +read("gnucomo"); + //echo "Database Access string = " . $config->Database(); + + $conn = pg_connect($config->Database()); + + // connect to the database + //$conn = pg_Connect( "host=$pgsqlhost port=$pgsqlport dbname=$dbname user=$name password=$passw" ); + if( !$conn ) { + echo "Error connecting, try again."; + echo login_form(); + $_SESSION["login"] = true; + } else { + $sql = "SELECT * FROM user_gnucomo WHERE username='$name' and password='$passw'"; + $res = query( $conn, $sql ); + + if( $res[0] ) { + if ($res[2] == 1) + { + $arr = pg_fetch_array( $res[1], 0 ); + $_SESSION["login.ini"] = $arr; + } + else + { + echo "Login incorrect.
"; + } + + // user is authorised, step to next page. + echo "Ok!"; + } else { + pgsql_error( "SQL: error.
" . $res[3] ); + } + } +} else { + echo login_form(); + $_SESSION["login"] = true; +} +?> + + diff --git a/src/web/menu.html b/src/web/menu.html new file mode 100644 index 0000000..64a9019 --- /dev/null +++ b/src/web/menu.html @@ -0,0 +1,17 @@ + + + + + +GnuCoMo Web Interface + + + Objects + Users + Packages + Change Password + Logout +
+ + + diff --git a/src/web/open_package.png b/src/web/open_package.png new file mode 100644 index 0000000..62500ad Binary files /dev/null and b/src/web/open_package.png differ diff --git a/src/web/password.png b/src/web/password.png new file mode 100644 index 0000000..b14045b Binary files /dev/null and b/src/web/password.png differ diff --git a/src/web/server.png b/src/web/server.png new file mode 100644 index 0000000..d1ade39 Binary files /dev/null and b/src/web/server.png differ diff --git a/src/web/service.png b/src/web/service.png new file mode 100644 index 0000000..41e5f6b Binary files /dev/null and b/src/web/service.png differ diff --git a/src/web/user.png b/src/web/user.png new file mode 100644 index 0000000..40ac51e Binary files /dev/null and b/src/web/user.png differ