transformed into an XML document for further processing.
A collection of polymorphic classes handle the transformation of various
input formats into XML.
Classifying input data is done with a finite improbability calculation.
LDADD = ../lib/libgnucomo.a
gcm_input_SOURCES = gcm_input.cpp message.cpp string_utils.cpp syslog_cooker.cpp \
- irix_syslog_cooker.cpp access_cooker.cpp error_cooker.cpp
+ irix_syslog_cooker.cpp access_cooker.cpp error_cooker.cpp \
+ xml_cooker.cpp \
+ message_filter.cpp log_filter.cpp rpm_filter.cpp
logrunner_SOURCES = logrunner.cpp string_utils.cpp
-# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
+# Makefile.in generated by automake 1.6.3 from Makefile.am.
+# @configure_input@
-# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
-
+@SET_MAKE@
SHELL = @SHELL@
srcdir = @srcdir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
-
-DESTDIR =
-
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
-
top_builddir = ../..
ACLOCAL = @ACLOCAL@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
transform = @program_transform_name@
-
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
+
+EXEEXT = @EXEEXT@
+OBJEXT = @OBJEXT@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+AMTAR = @AMTAR@
AWK = @AWK@
CC = @CC@
CPP = @CPP@
CXX = @CXX@
+DEPDIR = @DEPDIR@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LN_S = @LN_S@
-MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
+STRIP = @STRIP@
VERSION = @VERSION@
XML_CONFIG = @XML_CONFIG@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
YACC = @YACC@
+am__include = @am__include@
+am__quote = @am__quote@
+install_sh = @install_sh@
bin_PROGRAMS = gcm_input logrunner
LDADD = ../lib/libgnucomo.a
gcm_input_SOURCES = gcm_input.cpp message.cpp string_utils.cpp syslog_cooker.cpp \
- irix_syslog_cooker.cpp access_cooker.cpp error_cooker.cpp
+ irix_syslog_cooker.cpp access_cooker.cpp error_cooker.cpp \
+ xml_cooker.cpp \
+ message_filter.cpp log_filter.cpp rpm_filter.cpp
logrunner_SOURCES = logrunner.cpp string_utils.cpp
+subdir = src/gcm_input
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_CLEAN_FILES =
-PROGRAMS = $(bin_PROGRAMS)
-
+CONFIG_CLEAN_FILES =
+bin_PROGRAMS = gcm_input$(EXEEXT) logrunner$(EXEEXT)
+PROGRAMS = $(bin_PROGRAMS)
+
+am_gcm_input_OBJECTS = gcm_input.$(OBJEXT) message.$(OBJEXT) \
+ string_utils.$(OBJEXT) syslog_cooker.$(OBJEXT) \
+ irix_syslog_cooker.$(OBJEXT) access_cooker.$(OBJEXT) \
+ error_cooker.$(OBJEXT) xml_cooker.$(OBJEXT) \
+ message_filter.$(OBJEXT) log_filter.$(OBJEXT) \
+ rpm_filter.$(OBJEXT)
+gcm_input_OBJECTS = $(am_gcm_input_OBJECTS)
+gcm_input_LDADD = $(LDADD)
+gcm_input_DEPENDENCIES = ../lib/libgnucomo.a
+gcm_input_LDFLAGS =
+am_logrunner_OBJECTS = logrunner.$(OBJEXT) string_utils.$(OBJEXT)
+logrunner_OBJECTS = $(am_logrunner_OBJECTS)
+logrunner_LDADD = $(LDADD)
+logrunner_DEPENDENCIES = ../lib/libgnucomo.a
+logrunner_LDFLAGS =
-DEFS = @DEFS@ -I. -I$(srcdir)
+DEFS = @DEFS@
+DEFAULT_INCLUDES = -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
-X_CFLAGS = @X_CFLAGS@
-X_LIBS = @X_LIBS@
-X_EXTRA_LIBS = @X_EXTRA_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
-gcm_input_OBJECTS = gcm_input.o message.o string_utils.o \
-syslog_cooker.o irix_syslog_cooker.o access_cooker.o error_cooker.o
-gcm_input_LDADD = $(LDADD)
-gcm_input_DEPENDENCIES = ../lib/libgnucomo.a
-gcm_input_LDFLAGS =
-logrunner_OBJECTS = logrunner.o string_utils.o
-logrunner_LDADD = $(LDADD)
-logrunner_DEPENDENCIES = ../lib/libgnucomo.a
-logrunner_LDFLAGS =
-CXXFLAGS = @CXXFLAGS@
-CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/access_cooker.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/error_cooker.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/gcm_input.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/irix_syslog_cooker.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/log_filter.Po ./$(DEPDIR)/logrunner.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/message.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/message_filter.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/rpm_filter.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/string_utils.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/syslog_cooker.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/xml_cooker.Po
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
-CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON = Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-
-TAR = gtar
-GZIP_ENV = --best
-DEP_FILES = .deps/access_cooker.P .deps/error_cooker.P \
-.deps/gcm_input.P .deps/irix_syslog_cooker.P .deps/logrunner.P \
-.deps/message.P .deps/string_utils.P .deps/syslog_cooker.P
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+CXXFLAGS = @CXXFLAGS@
+DIST_SOURCES = $(gcm_input_SOURCES) $(logrunner_SOURCES)
+DIST_COMMON = Makefile.am Makefile.in
SOURCES = $(gcm_input_SOURCES) $(logrunner_SOURCES)
-OBJECTS = $(gcm_input_OBJECTS) $(logrunner_OBJECTS)
-
-all: all-redirect
-.SUFFIXES:
-.SUFFIXES: .S .c .cpp .o .s
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu src/gcm_input/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
- cd $(top_builddir) \
- && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-
-mostlyclean-binPROGRAMS:
-
-clean-binPROGRAMS:
- -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-distclean-binPROGRAMS:
-
-maintainer-clean-binPROGRAMS:
+all: all-am
+.SUFFIXES:
+.SUFFIXES: .cpp .o .obj
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/gcm_input/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
- if test -f $$p; then \
- echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
- $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \
+ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
- list='$(bin_PROGRAMS)'; for p in $$list; do \
- rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
+ rm -f $(DESTDIR)$(bindir)/$$f; \
done
-.s.o:
- $(COMPILE) -c $<
-
-.S.o:
- $(COMPILE) -c $<
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+gcm_input$(EXEEXT): $(gcm_input_OBJECTS) $(gcm_input_DEPENDENCIES)
+ @rm -f gcm_input$(EXEEXT)
+ $(CXXLINK) $(gcm_input_LDFLAGS) $(gcm_input_OBJECTS) $(gcm_input_LDADD) $(LIBS)
+logrunner$(EXEEXT): $(logrunner_OBJECTS) $(logrunner_DEPENDENCIES)
+ @rm -f logrunner$(EXEEXT)
+ $(CXXLINK) $(logrunner_LDFLAGS) $(logrunner_OBJECTS) $(logrunner_LDADD) $(LIBS)
mostlyclean-compile:
- -rm -f *.o core *.core
-
-clean-compile:
+ -rm -f *.$(OBJEXT) core *.core
distclean-compile:
-rm -f *.tab.c
-maintainer-clean-compile:
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/access_cooker.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error_cooker.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gcm_input.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/irix_syslog_cooker.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_filter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logrunner.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message_filter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpm_filter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_utils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syslog_cooker.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_cooker.Po@am__quote@
-gcm_input: $(gcm_input_OBJECTS) $(gcm_input_DEPENDENCIES)
- @rm -f gcm_input
- $(CXXLINK) $(gcm_input_LDFLAGS) $(gcm_input_OBJECTS) $(gcm_input_LDADD) $(LIBS)
+distclean-depend:
+ -rm -rf ./$(DEPDIR)
-logrunner: $(logrunner_OBJECTS) $(logrunner_DEPENDENCIES)
- @rm -f logrunner
- $(CXXLINK) $(logrunner_LDFLAGS) $(logrunner_OBJECTS) $(logrunner_LDADD) $(LIBS)
.cpp.o:
- $(CXXCOMPILE) -c $<
+@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
+
+.cpp.obj:
+@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(CXXCOMPILE) -c -o $@ `cygpath -w $<`
+CXXDEPMODE = @CXXDEPMODE@
+uninstall-info-am:
+
+ETAGS = etags
+ETAGSFLAGS =
tags: TAGS
-ID: $(HEADERS) $(SOURCES) $(LISP)
- list='$(SOURCES) $(HEADERS)'; \
- unique=`for i in $$list; do echo $$i; done | \
- awk ' { files[$$0] = 1; } \
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
- here=`pwd` && cd $(srcdir) \
- && mkid -f$$here/ID $$unique $(LISP)
+ mkid -fID $$unique
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
- list='$(SOURCES) $(HEADERS)'; \
- unique=`for i in $$list; do echo $$i; done | \
- awk ' { files[$$0] = 1; } \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
- test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
-
-mostlyclean-tags:
+ test -z "$(ETAGS_ARGS)$$tags$$unique" \
+ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique
-clean-tags:
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
- -rm -f TAGS ID
-
-maintainer-clean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-subdir = src/gcm_input
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
- here=`cd $(top_builddir) && pwd`; \
- top_distdir=`cd $(top_distdir) && pwd`; \
- distdir=`cd $(distdir) && pwd`; \
- cd $(top_srcdir) \
- && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/gcm_input/Makefile
- @for file in $(DISTFILES); do \
- d=$(srcdir); \
+ @list='$(DISTFILES)'; for file in $$list; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkinstalldirs) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
if test -d $$d/$$file; then \
- cp -pr $$d/$$file $(distdir)/$$file; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
fi; \
done
-
-DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-
--include $(DEP_FILES)
-
-mostlyclean-depend:
-
-clean-depend:
-
-distclean-depend:
- -rm -rf .deps
-
-maintainer-clean-depend:
-
-%.o: %.c
- @echo '$(COMPILE) -c $<'; \
- $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
- @-cp .deps/$(*F).pp .deps/$(*F).P; \
- tr ' ' '\012' < .deps/$(*F).pp \
- | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
- >> .deps/$(*F).P; \
- rm .deps/$(*F).pp
-
-%.lo: %.c
- @echo '$(LTCOMPILE) -c $<'; \
- $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
- @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
- < .deps/$(*F).pp > .deps/$(*F).P; \
- tr ' ' '\012' < .deps/$(*F).pp \
- | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
- >> .deps/$(*F).P; \
- rm -f .deps/$(*F).pp
-
-%.o: %.cpp
- @echo '$(CXXCOMPILE) -c $<'; \
- $(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
- @-cp .deps/$(*F).pp .deps/$(*F).P; \
- tr ' ' '\012' < .deps/$(*F).pp \
- | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
- >> .deps/$(*F).P; \
- rm .deps/$(*F).pp
-
-%.lo: %.cpp
- @echo '$(LTCXXCOMPILE) -c $<'; \
- $(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
- @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
- < .deps/$(*F).pp > .deps/$(*F).P; \
- tr ' ' '\012' < .deps/$(*F).pp \
- | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
- >> .deps/$(*F).P; \
- rm -f .deps/$(*F).pp
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
check-am: all-am
check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am: install-binPROGRAMS
-install-exec: install-exec-am
+all-am: Makefile $(PROGRAMS)
-install-data-am:
-install-data: install-data-am
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
-uninstall-am: uninstall-binPROGRAMS
+install-exec: install-exec-am
+install-data: install-data-am
uninstall: uninstall-am
-all-am: Makefile $(PROGRAMS)
-all-redirect: all-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
-installdirs:
- $(mkinstalldirs) $(DESTDIR)$(bindir)
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
- -rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \
- mostlyclean-tags mostlyclean-depend mostlyclean-generic
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
-mostlyclean: mostlyclean-am
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
-clean-am: clean-binPROGRAMS clean-compile clean-tags clean-depend \
- clean-generic mostlyclean-am
+distclean: distclean-am
-clean: clean-am
+distclean-am: clean-am distclean-compile distclean-depend \
+ distclean-generic distclean-tags
-distclean-am: distclean-binPROGRAMS distclean-compile distclean-tags \
- distclean-depend distclean-generic clean-am
+dvi: dvi-am
-distclean: distclean-am
+dvi-am:
-maintainer-clean-am: maintainer-clean-binPROGRAMS \
- maintainer-clean-compile maintainer-clean-tags \
- maintainer-clean-depend maintainer-clean-generic \
- distclean-am
- @echo "This command is intended for maintainers to use;"
- @echo "it deletes files that may require special tools to rebuild."
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
maintainer-clean: maintainer-clean-am
-.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
-maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
-mostlyclean-compile distclean-compile clean-compile \
-maintainer-clean-compile tags mostlyclean-tags distclean-tags \
-clean-tags maintainer-clean-tags distdir mostlyclean-depend \
-distclean-depend clean-depend maintainer-clean-depend info-am info \
-dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
-install-exec install-data-am install-data install-am install \
-uninstall-am uninstall all-redirect all-am all installdirs \
-mostlyclean-generic distclean-generic clean-generic \
-maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am
+.PHONY: GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic distclean distclean-compile distclean-depend \
+ distclean-generic distclean-tags distdir dvi dvi-am info \
+ info-am install install-am install-binPROGRAMS install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-man install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic tags uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
***********************
** FILE NAME : access_cooker.cpp
** SYSTEM NAME :
-** VERSION NUMBER : $Revision: 1.1 $
+** VERSION NUMBER : $Revision: 1.2 $
**
** DESCRIPTION : Cooks Apache http daemon access log lines
**
/*****************************
$Log: access_cooker.cpp,v $
- Revision 1.1 2003-08-11 16:56:15 arjen
+ Revision 1.2 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+ Revision 1.1 2003/08/11 16:56:15 arjen
Different kinds of log files are parsed by a collection of objects
of different classes, derived from the base class line_cooker
Depending on the message content or the message_type element in
*****************************/
-/* static const char *RCSID = "$Id: access_cooker.cpp,v 1.1 2003-08-11 16:56:15 arjen Exp $"; */
+/* static const char *RCSID = "$Id: access_cooker.cpp,v 1.2 2003-12-04 10:38:09 arjen Exp $"; */
#include <ctype.h>
#include "access_cooker.h"
-static const regex re_accesslog("(GET|POST) .+ HTTP");
+static const regex re_accesslog("(GET|POST|HEAD) .+ HTTP");
bool access_cooker::check_pattern(String logline)
{
***********************
** FILE NAME : gcm_input.cpp
** SYSTEM NAME : Gnucomo - Gnu Computer Monitoring
-** VERSION NUMBER : $Revision: 1.11 $
+** VERSION NUMBER : $Revision: 1.12 $
**
** DESCRIPTION : Application to store client messages into the database
** The client message contains a log file from one of the
********************************
** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
** CREATION DATE : Aug 29, 2002
-** LAST UPDATE : Aug 11, 2003
+** LAST UPDATE : Nov 26, 2003
** MODIFICATIONS :
**************************************************************************/
/*****************************
$Log: gcm_input.cpp,v $
- Revision 1.11 2003-10-27 13:00:15 arjen
+ Revision 1.12 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+ Revision 1.11 2003/10/27 13:00:15 arjen
Catch exceptions from the database library
Revision 1.10 2003/09/03 06:58:31 arjen
*****************************/
-static const char *RCSID = "$Id: gcm_input.cpp,v 1.11 2003-10-27 13:00:15 arjen Exp $";
+static const char *RCSID = "$Id: gcm_input.cpp,v 1.12 2003-12-04 10:38:09 arjen Exp $";
#include <fstream>
#include <getopt.h>
#include "message.h"
+#include "log_filter.h"
+#include "rpm_filter.h"
+
+#include "xml_cooker.h"
#include "syslog_cooker.h"
#include "irix_syslog_cooker.h"
#include "access_cooker.h"
bool verbose = false;
bool testmode = false;
bool incremental = false;
-std::ostream *log = &std::cerr;
+std::ostream *Log = &std::cerr;
static char *Version = "gcm_input version 0.0.8 - Sep 04, 2003";
}
else
{
- log = &logfile;
+ Log = &logfile;
}
}
verbose = verbose || level > 0;
if (verbose)
{
- *log << "Hostname = " << hostname;
- *log << " Arrival = " << arrival;
- *log << " Service = " << service << "\n";
- *log << "Config OK.\n";
+ *Log << "Hostname = " << hostname;
+ *Log << " Arrival = " << arrival;
+ *Log << " Service = " << service << "\n";
+ *Log << "Config OK.\n";
}
/* Try to connect to the database */
{
client_message msg(&std::cin, db);
+
+ message_filter shortcircuit(hostname, arrival, service);
+ log_filter lf(hostname, arrival, service);
+ rpm_filter rf(hostname, arrival, service);
+
syslog_cooker slc;
irix_syslog_cooker islc;
access_cooker alc;
error_cooker elc;
+ xml_cooker xlc;
+ rpm_cooker rlc;
- msg.add_cooker(&slc);
- msg.add_cooker(&islc);
- msg.add_cooker(&alc);
- msg.add_cooker(&elc);
+ msg.add_cooker(&xlc, &shortcircuit);
+ msg.add_cooker(&slc, &lf);
+ msg.add_cooker(&islc, &lf);
+ msg.add_cooker(&alc, &lf);
+ msg.add_cooker(&elc, &lf);
+ msg.add_cooker(&rlc, &rf);
if (msg.classify(hostname, arrival, service) > 0.9)
{
{
msg.enter();
}
- catch (exception &e)
+ catch (std::exception &e)
{
- *log << "Caught an exception: " << e.what() << "\n";
+ *Log << "Caught an exception: " << e.what() << "\n";
}
}
return 0;
}
else
{
- *log << "gcm_input: Can not connect to database.\n";
- *log << "Gcm_input finished at " << Now() << ".\n";
+ *Log << "gcm_input: Can not connect to database.\n";
+ *Log << "Gcm_input finished at " << Now() << ".\n";
return 1;
}
}
--- /dev/null
+
+/**************************************************************************
+** (c) Copyright 2003, Andromeda Technology & Automation
+** This is free software; you can redistribute it and/or modify it under the
+** terms of the GNU General Public License, see the file COPYING.
+***************************************************************************
+** MODULE INFORMATION *
+***********************
+** FILE NAME : log_filter.cpp
+** SYSTEM NAME :
+** VERSION NUMBER : $Revision: 1.1 $
+**
+** DESCRIPTION : Implementation of the log_filter class
+**
+** EXPORTED OBJECTS :
+** LOCAL OBJECTS :
+** MODULES USED :
+***************************************************************************
+** ADMINISTRATIVE INFORMATION *
+********************************
+** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
+** CREATION DATE : Nov 26, 2003
+** LAST UPDATE : Nov 26, 2003
+** MODIFICATIONS :
+**************************************************************************/
+
+/*****************************
+ $Log: log_filter.cpp,v $
+ Revision 1.1 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+*****************************/
+
+/* static const char *RCSID = "$Id: log_filter.cpp,v 1.1 2003-12-04 10:38:09 arjen Exp $"; */
+
+#include "log_filter.h"
+
+extern String XML_Entities(String s);
+
+/*=========================================================================
+** NAME : constructXML
+** SYNOPSIS : int constructXML(message_buffer &in, strstream &xml)
+** PARAMETERS :
+** RETURN VALUE : None
+**
+** DESCRIPTION : Create the body for a Gnucomo XML document. Each line
+** of input from the log file is put in a <raw> XML element.
+**
+** VARS USED :
+** VARS CHANGED :
+** FUNCTIONS USED :
+** SEE ALSO :
+** LAST MODIFIED : Nov 26, 2003
+**=========================================================================
+*/
+
+void log_filter::construct_XML(message_buffer &in, std::strstream &xml)
+{
+ String line;
+
+ scan_email_header(in);
+ construct_header(xml);
+
+ xml << " <gcmt:data>\n";
+ xml << " <gcmt:log>\n";
+ while (in >> line)
+ {
+ xml << " <gcmt:raw>" << XML_Entities(line) << "</gcmt:raw>\n";
+ }
+ xml << " </gcmt:log>\n";
+ xml << " </gcmt:data>\n";
+ xml << "</gcmt:message>\n";
+}
+
--- /dev/null
+
+/**************************************************************************
+** (c) Copyright 2003, Andromeda Technology & Automation
+** This is free software; you can redistribute it and/or modify it under the
+** terms of the GNU General Public License, see the file COPYING.
+***************************************************************************
+** MODULE INFORMATION *
+***********************
+** FILE NAME : log_filter.h
+** SYSTEM NAME :
+** VERSION NUMBER : $Revision: 1.1 $
+**
+** DESCRIPTION : Message filter for various kinds of log files.
+**
+** EXPORTED OBJECTS :
+** LOCAL OBJECTS :
+** MODULES USED :
+***************************************************************************
+** ADMINISTRATIVE INFORMATION *
+********************************
+** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
+** CREATION DATE : Nov 26, 2003
+** LAST UPDATE : Nov 26, 2003
+** MODIFICATIONS :
+**************************************************************************/
+
+/*****************************
+ $Log: log_filter.h,v $
+ Revision 1.1 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+*****************************/
+
+/* static const char *RCSID = "$Id: log_filter.h,v 1.1 2003-12-04 10:38:09 arjen Exp $"; */
+
+#ifndef LOG_FILTER_H
+#define LOG_FILTER_H
+
+#include "message_filter.h"
+
+/*
+///////////////////////////////////////////////////////////////////////////
+// NAME : log_filter
+// BASECLASS : message_filter
+// MEMBERS :
+// OPERATORS :
+// METHODS : construct_XML
+//
+// DESCRIPTION : Transforms a log file into an XML document by putting
+// each line of input into a <gcmt:raw> XML element.
+//
+// RELATIONS :
+// SEE ALSO :
+// LAST MODIFIED : Nov 26, 2003
+///////////////////////////////////////////////////////////////////////////
+*/
+
+class log_filter : public message_filter
+{
+
+protected:
+
+public:
+
+ log_filter(String host, UTC arriv, String service) : message_filter(host, arriv, service)
+ {
+ }
+
+ virtual void construct_XML(message_buffer &in, std::strstream &xml);
+};
+
+#endif // LOG_FILTER_H
***********************
** FILE NAME : message.cpp
** SYSTEM NAME : Gnucomo - Gnu Computer Monitoring
-** VERSION NUMBER : $Revision: 1.15 $
+** VERSION NUMBER : $Revision: 1.16 $
**
** DESCRIPTION : Implementation of the message handling classes
**
********************************
** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
** CREATION DATE : Sep 16, 2002
-** LAST UPDATE : Jul 24, 2003
+** LAST UPDATE : Nov 28, 2003
** MODIFICATIONS :
**************************************************************************/
/*****************************
$Log: message.cpp,v $
- Revision 1.15 2003-10-27 11:28:27 arjen
+ Revision 1.16 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+ Revision 1.15 2003/10/27 11:28:27 arjen
Do not add another parameter_notification record is the notification
already exists for that parameter.
*****************************/
-static const char *RCSID = "$Id: message.cpp,v 1.15 2003-10-27 11:28:27 arjen Exp $";
+static const char *RCSID = "$Id: message.cpp,v 1.16 2003-12-04 10:38:09 arjen Exp $";
#include <algorithm>
#include <libxml/xpath.h>
extern bool verbose; /* Defined in the main application */
extern bool testmode;
extern bool incremental;
-extern std::ostream *log;
+extern std::ostream *Log;
/* Utility functions */
return input_ok;
}
+/*=========================================================================
+** NAME : client_message
+** SYNOPSIS : client_message(std::istream *in, gnucomo_database db)
+** PARAMETERS :
+** RETURN VALUE : None
+**
+** DESCRIPTION : Client message constructor.
+**
+** VARS USED :
+** VARS CHANGED :
+** FUNCTIONS USED :
+** SEE ALSO :
+** LAST MODIFIED : Nov 04, 2002
+**=========================================================================
+*/
+
client_message::client_message(std::istream *in, gnucomo_database db)
{
input.from(in);
certainty = 0.0;
}
-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_PGP("-----BEGIN PGP MESSAGE-----");
static const regex re_rpm("[[:alnum:]+-]+-[0-9][[:alnum:].-]");
static const regex re_uxmail_from("^From [^ \t]+[ ]+" + 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_mail_MsId("^Message-Id:[[:blank:]]+");
-static const regex re_email_address("[[:alnum:]_.-]+@[[:alnum:]_.-]+");
-static const regex re_email_user("[[:alnum:]_.-]+@");
static const regex re_xml_header("xml .*\?>$");
/*=========================================================================
-** NAME : readXMLinput
-** SYNOPSIS : int readXMLinput(String first_line)
+** NAME : extractHeader
+** SYNOPSIS : void extractHeader()
** PARAMETERS :
-** RETURN VALUE : Parse the XML input and extract the header information
+** RETURN VALUE : True if the mandatory header elements are available.
**
-** DESCRIPTION :
+** DESCRIPTION : Extract the header information from the XML DOM tree.
**
** VARS USED :
** VARS CHANGED :
** FUNCTIONS USED :
** SEE ALSO :
-** LAST MODIFIED : Jul 24, 2003
+** LAST MODIFIED : Nov 26, 2003
**=========================================================================
*/
-int client_message::readXMLinput(String first_line)
+bool client_message::extractHeader()
{
- xmlParserCtxtPtr ctxt;
- String line;
xmlNodePtr root, item;
xmlNsPtr namespaces[1];
xmlXPathObjectPtr res;
xmlXPathContextPtr pathcontext;
-
- ctxt = xmlCreatePushParserCtxt(NULL, NULL, first_line, ~first_line, NULL);
- while (input >> line)
- {
- xmlParseChunk(ctxt, line, ~line, 0);
- }
- xmlParseChunk(ctxt, "", 0, 1);
- xmlDom = ctxt->myDoc;
- xmlFreeParserCtxt(ctxt);
+ bool header_OK = true;
root = xmlDocGetRootElement(xmlDom);
namespaces[0] = root->ns;
#endif
res = xmlXPathEval((const xmlChar *)"gcmt:header/gcmt:messagetype/text()", pathcontext);
- if (res->nodesetval != NULL)
+ if (res->nodesetval != NULL && res->nodesetval->nodeTab != NULL)
{
-#ifdef DEBUG
- xmlDebugDumpNodeList(stdout, *res->nodesetval->nodeTab, 0);
-#endif
item = *res->nodesetval->nodeTab;
// Select a line cooker based on the message type.
#ifdef DEBUG
- std::cout << "Looking for a line cooker for " << item->content << "\n";
+ *Log << "Looking for a line cooker for " << item->content << "\n";
#endif
- std::list<line_cooker *>::iterator lci = kitchen.begin();
- pan = 0;
- while (pan == 0 && lci != kitchen.end())
+ pan.lc = 0;
+ std::list<xform>::iterator lci = kitchen.begin();
+ while (pan.lc == 0 && lci != kitchen.end())
{
- pan = *lci;
- if (pan->message_type() != (const char *)(item->content))
+ if (lci->lc->message_type() == (const char *)(item->content))
{
- pan = 0;
+ pan.lc = lci->lc;
}
lci++;
}
- if (pan == 0)
+ if (pan.lc == 0)
{
- *log << "Can not find a line cooker for message type " << item->content << "\n";
+ *Log << "Can not find a line cooker for message type " << item->content << "\n";
+ header_OK = false;
}
}
else
{
- *log << "Message type not found in XML header.\n";
+ *Log << "Message type not found in XML header.\n";
+ header_OK = false;
}
res = xmlXPathEval((const xmlChar *)"gcmt:header/gcmt:hostname/text()", pathcontext);
- if (res->nodesetval != NULL)
+ if (res->nodesetval != NULL && res->nodesetval->nodeTab != NULL)
{
-#ifdef DEBUG
- xmlDebugDumpNodeList(stdout, *res->nodesetval->nodeTab, 0);
-#endif
item = *res->nodesetval->nodeTab;
hostname = (const char *)item->content;
}
else
{
- *log << "Hostname not found in XML header.\n";
+ *Log << "Can not determine the hostname where the message came from.\n";
+ header_OK = false;
}
res = xmlXPathEval((const xmlChar *)"gcmt:header/gcmt:service/text()", pathcontext);
- if (res->nodesetval != NULL)
+ if (res->nodesetval != NULL && res->nodesetval->nodeTab != NULL)
{
item = *res->nodesetval->nodeTab;
service = (const char *)item->content;
}
res = xmlXPathEval((const xmlChar *)"gcmt:header/gcmt:time/text()", pathcontext);
- if (res->nodesetval != NULL)
+ if (res->nodesetval != NULL && res->nodesetval->nodeTab != NULL)
{
item = *res->nodesetval->nodeTab;
arrival = String((char *)item->content);
+ if (!arrival.proper())
+ {
+ *Log << "Arrival time is not properly stated.\n";
+ header_OK = false;
+ }
}
//xmlDebugDumpNodeList(stdout, *res->nodesetval->nodeTab, 0);
+ return header_OK;
}
+
/*=========================================================================
** NAME : classify
** SYNOPSIS : double classify(String host, date arriv_d, hour arriv_t, String serv)
** VARS CHANGED :
** FUNCTIONS USED :
** SEE ALSO :
-** LAST MODIFIED : Aug 11, 2003
+** LAST MODIFIED : Nov 27, 2003
**=========================================================================
*/
arrival = arriv;
service = serv;
+ const double epsilon = 0.1; // Threshold for uncertainty
+ const double P = 0.5; // Probability of a wrong match
+
+ double uncertainty;
+
/* First, check if the message has a mail header. */
if (input >> line && line == re_uxmail_from)
mail_header = true;
- /* Scan ahead for the hostname and date of arrival. */
+ /* Skip the mail header until the first empty line. */
while (input >> line && line != "")
{
- if (line == re_mail_From)
- {
- from_address = line(re_email_address);
- from_address(re_email_user) = ""; // Remove the user part;
- if (from_address != "" && ~hostname < ~from_address)
- {
- *log << "Detected hostname " << from_address << "\n";
- hostname = from_address;
- }
- }
- if (line == re_mail_MsId)
- {
- from_address = line(re_email_address);
- from_address(re_email_user) = ""; // Remove the user part;
- if (from_address != "" && ~hostname < ~from_address)
- {
- *log << "Detected hostname " << from_address << "\n";
- hostname = from_address;
- }
- }
- if (line == re_mail_Date)
- {
- arrival = UTC(line(regex(mail_date_re)));
- }
}
}
else
}
- pan = 0;
-
/*
* 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)
+ uncertainty = 1.0;
+
+ while (input >> line && uncertainty > 0.1)
{
if (verbose)
{
- *log << " testing: " << line << "\n";
+ *Log << " testing: " << line << "\n";
}
- if (line == re_xml_header)
+ if (line == re_PGP)
{
- certainty = 1.0;
- classification = XML;
- if (verbose)
- {
- *log << "XML input detected.\n";
- }
- readXMLinput(line);
- }
- else if (line == re_PGP)
- {
- certainty = 1.0;
+ uncertainty = 0.0;
gpg_encrypted = true;
- *log << "The message is PGP/GnuPG encrypted.\n";
- }
- else if (line == re_dump)
- {
- certainty = 1.0;
- if (verbose)
- {
- *log << "DUMP output detected.\n";
- }
- }
- else if (line == re_rpm)
- {
- certainty = 1.0;
- classification = RPMLIST;
- service = "";
- if (verbose)
- {
- *log << "RPM package list detected.\n";
- }
+ *Log << "The message is PGP/GnuPG encrypted.\n";
}
else
{
// Scan the list of line cookers if there is anything familiar.
- std::list<line_cooker *>::iterator lci = kitchen.begin();
- pan = 0;
- while (pan == 0 && lci != kitchen.end())
+ std::list<xform>::iterator lci = kitchen.begin();
+ uncertainty = 1.0;
+ while (lci != kitchen.end())
{
- pan = *lci;
- if (!pan->check_pattern(line))
+ if (lci->lc->check_pattern(line))
{
- pan = 0;
+ // We have a match; decrease the uncertainty
+
+ lci->uncertainty *= P;
+ if (uncertainty > lci->uncertainty)
+ {
+ uncertainty = lci->uncertainty;
+ pan = *lci;
+ }
+ if (verbose)
+ {
+ *Log << lci->lc->message_type() << " detected with "
+ << lci->uncertainty << " uncertainty.\n";
+ }
}
lci++;
}
- if (pan != 0)
- {
- certainty = 1.0;
- classification = COOKER_OBJECT;
- if (verbose)
- {
- *log << "Detected message type " << pan->message_type() << "\n";
- }
- }
+ classification = COOKER_OBJECT;
}
}
input.rewind();
- if (hostname == "")
- {
- *log << "Can not determine the hostname where the message came from.\n";
- certainty = 0.0;
- }
- else if (!arrival.proper())
- {
- *log << "Arrival time is not known.\n";
- certainty = 0.0;
- }
- else
- {
- certainty = 1.0;
- }
+ certainty = 1.0 - uncertainty;
return certainty;
}
** VARS CHANGED :
** FUNCTIONS USED :
** SEE ALSO :
-** LAST MODIFIED : Jul 24, 2003
+** LAST MODIFIED : Nov 28, 2003
**=========================================================================
*/
+struct param_property
+{
+ String name;
+ String value;
+};
+
void client_message::enterXML()
{
+ //TODO : return the number of elements that are handled.
+
xmlXPathObjectPtr res;
xmlXPathContextPtr pathcontext;
xmlNsPtr namespaces[1];
/* Try to find the host in the database */
String objectid;
+ String remark; // For notifications
objectid = database.find_host(hostname);
if (objectid == "")
{
- *log << "Please define the host " << hostname << " in the database.\n";
+ *Log << "Please define the host " << hostname << " in the database.\n";
return;
}
if (verbose)
{
- *log << "Object id for " << hostname << " is " << objectid << "\n";
+ *Log << "Object id for " << hostname << " is " << objectid << "\n";
}
pathcontext = xmlXPathNewContext(xmlDom);
String raw("");;
String log_service;
- if (strcmp((char *)node->name, "raw") == 0)
+ if (strcmp((char *)node->name, "raw") == 0 && node->children != NULL)
{
item = node->children;
- if (pan == 0)
+ if (pan.lc == 0)
{
- *log << "Can not cook this type of <raw> log element.\n";
+ *Log << "Can not cook this type of <raw> log element.\n";
}
else
{
raw = String((const char *)item->content);
- if (pan->cook_this(raw, arrival))
+ if (pan.lc->cook_this(raw, arrival))
{
- log_hostname = pan->hostname();
+ log_hostname = pan.lc->hostname();
if (log_hostname == "")
{
log_hostname = hostname;
}
- log_service = pan->service();
- log_date = pan->timestamp();
+ log_service = pan.lc->service();
+ log_date = pan.lc->timestamp();
}
else
{
- *log << "Log line " << raw << " does not match.\n";
+ *Log << "gcm_input WARNING: Not a valid line: " << raw << "\n";
raw = "";
}
}
if (verbose)
{
- *log << "Analyzing cooked element.\n";
+ *Log << "Analyzing cooked element.\n";
}
pathcontext->node = node;
log_hostname = (const char *)item->content;
if (log_hostname != hostname(0, ~log_hostname))
{
- *log << "Hostname " << log_hostname << " does not match.\n";
+ *Log << "Hostname " << log_hostname << " does not match.\n";
log_hostname = "";
}
}
}
else
{
- *log << "<timestamp> missing from cooked log element.\n";
+ *Log << "<timestamp> missing from cooked log element.\n";
}
res = xmlXPathEval((const xmlChar *)"raw/text()", pathcontext);
}
else
{
- *log << "<raw> missing from cooked log element.\n";
+ *Log << "<raw> missing from cooked log element.\n";
}
}
if (testmode)
{
- *log << insertion << "\n";
+ *Log << insertion << "\n";
}
else
{
database.Query(insertion);
}
- if (verbose)
- {
- *log << "\n\n";
- }
}
}
node = node->next;
}
}
- else
+ else if (strcmp((char *)node->name, "parameters") == 0)
{
- *log << "Data element " << node->name << " is not supported.\n";
- }
- }
- else
- {
- *log << "Data node not found.\n";
- }
-}
+ // Each child contains a parameter entry, with at least one property
-/*=========================================================================
-** 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 : Jul 24, 2003
-**=========================================================================
-*/
-
-int client_message::enter()
-{
- if (classification == XML)
- {
- enterXML();
- return 1;
- }
-
- long nr_lines = 0;
- String line;
- String qry;
-
- String change_notification("");
- String create_notification("");
- bool initial_entry = false;
-
- std::list<String> packages;
-
-
- /* Double-check the classification of the message */
-
- if (classification == UNKNOWN || certainty < 0.9 || gpg_encrypted)
- {
- return 0;
- }
+ String qry;
+ String insertion;
+ String change_notification("");
+ String create_notification("");
+ String remove_notification("");
+ bool initial_entry = false;
+ String param_class((const char *)xmlGetProp(node, (const xmlChar *)"class"));
- if (mail_header)
- {
- // Skip the mail header.
+ pathcontext->node = node;
- while (input >> line && line != "");
- }
+ // If we don;t have any parameters of this class, this will be
+ // an initial entry.
- /* Try to find the host in the database */
-
- String objectid;
-
- objectid = database.find_host(hostname);
- if (objectid == "")
- {
- *log << "Please define the host " << hostname << " in the database.\n";
- return 0;
- }
- if (verbose)
- {
- *log << "Object id for " << hostname << " is " << objectid << "\n";
- }
-
- if (classification == RPMLIST)
- {
-
- int n_packages;
-
- /* Read all packages, so we will know which ones are */
- /* missing at the end. */
-
- qry = "select name from parameter where objectid='";
- qry += objectid + "' and class='package'";
- n_packages = database.Query(qry);
- initial_entry = n_packages == 0;
-
-#ifdef DEBUG
- *log << n_packages << " packages in database.\n";
-#endif
- for (int t = 0; t < n_packages; t++)
- {
- packages.push_back(database.Field(t, "name"));
- }
-#ifdef DEBUG
- *log << "Package list built: " << packages.size() << ".\n";
-#endif
- }
-
- /* Scan the input line by line, entring records into the database */
-
- String rest; // Rest of the line to be parsed
- regex re_any(".*");
-
- while (input >> line)
- {
- if (verbose)
- {
- *log << line << "\n";
- }
+ qry = "select name from parameter where objectid='";
+ qry += objectid + "' and class='" + param_class + "'";
+ initial_entry = database.Query(qry) == 0;
+ node = node->children;
+ while (node != NULL)
+ {
+ if (node->type == XML_ELEMENT_NODE &&
+ strcmp((char *)node->name, "parameter") == 0)
+ {
+ String param_name((const char *)xmlGetProp(node, (const xmlChar *)"name"));
- /* Check each line if it contains valid information */
+ std::list<param_property> properties;
+ param_property prop;
+ xmlNodePtr item;
- const regex *check;
+ String paramid;
- switch (classification)
- {
- case RPMLIST:
- check = &re_rpm;
- break;
- case COOKER_OBJECT:
- check = &re_any;
- break;
- }
- if (line == *check)
- {
- date log_date;
- hour log_time;
- int i;
+ // Collect the parameter's properties.
- String insertion("insert into log (objectid, servicecode,"
- " object_timestamp, timestamp, rawdata, processed) values (");
- String datestring;
-
- switch (classification)
- {
- case COOKER_OBJECT:
-#ifdef DEBUG
- std::cerr << "\ncooker check: " << pan->check_pattern(line) << "\n";
-#endif
- if (pan->cook_this(line, arrival))
- {
- if (pan->hostname() == hostname(0,~pan->hostname()))
+ item = node->children;
+ while (item != NULL)
{
-
-#ifdef DEBUG
- std::cerr << " Information from cooker:\n";
- std::cerr << " timestamp = " << pan->timestamp() << "\n";
- std::cerr << " hostname = " << pan->hostname() << "\n";
- std::cerr << " service = " << pan->service() << "\n";
-#endif
- /* Insert a new record into the log table */
-
- insertion += "'" + objectid + "',";
- insertion += "'" + pan->service() + "',";
- insertion += "'" + pan->timestamp().format("%Y-%m-%d %T") + "',";
- insertion += "'" + arrival.format("%Y-%m-%d %T") + "',";
- insertion += "'" + SQL_Escape(line) + "',FALSE";
- insertion += ")";
-
- if (testmode)
+ if (item->type == XML_ELEMENT_NODE &&
+ strcmp((char *)item->name, "property") == 0)
{
- *log << insertion << "\n";
- }
- else
- {
- database.Query(insertion);
+ prop.name = (const char *)xmlGetProp(item, (const xmlChar *)"name");
+ if (item->children != NULL)
+ {
+ prop.value = (const char *)item->children->content;
+ properties.push_back(prop);
+ }
+ else
+ {
+ *Log << "WARNING: Property " << prop.name << " has no value.\n";
+ }
}
- if (verbose)
- {
- *log << "\n\n";
- }
+ // TODO: Hanlde description element
- nr_lines++;
+ item = item->next;
}
- else
- {
- *log << " Hostname " << pan->hostname() << " does not match.\n";
- }
- }
- else
- {
- *log << "gcm_input WARNING: Not a valid line: " << line << "\n";
- }
- break;
-
- case RPMLIST:
- // Scan a list of packages and versions from "rpm -a".
- // A similar listing can be created on IRIX 6.5 by using the
- // command "showprods -3 -n|awk '{printf "%s-%s\n",$2,$3}'|grep -v '^[-=]' \
- // |grep -v Version-Description".
- //
- // We have to separate the package name and the version.
- // The separation is marked by a '-', followed by a digit.
- // However, there may be other sequences of '-'digit in the package name,
- // do we have to scan ahead until there is at most one such sequence
- // left in the version string. The '-'digit seqeunce inside the
- // version usually separates the version and the release number.
+ // Check the parameter in the database.
- int version_start, next_version_start;
+ std::list<param_property>::iterator pi = properties.begin();
- i = line.index('-');
- version_start = i;
- next_version_start = i;
+ qry = "select paramid from parameter where objectid='";
+ qry += objectid + "' and class='";
+ qry += param_class + "' and name='";
+ qry += param_name + "'";
- while (i < ~line - 1)
- {
- while (i < ~line - 1 && !(line[i] == '-' && isdigit(line[i + 1])))
- {
- i++;
- }
- if (i < ~line - 1)
+ if (database.Query(qry) == 1)
{
- version_start = next_version_start;
- next_version_start = i;
- }
- i++;
- }
-
- if (!isdigit(line[version_start + 1]))
- {
- version_start = next_version_start;
- }
- String package(line(0,version_start));
- String version(line(version_start + 1, ~line));
- String paramid;
- String remark;
- String insert_h;
+ // The parameter exists in the database; check all properties.
- if (verbose)
- {
- *log << "Package is " << package;
- *log << ", version is " << version << "\n";
- }
+ bool param_changed = false;
- // Construct a qry to check the package's existance
+ paramid = database.Field(0, "paramid");
+ while (pi != properties.end())
+ {
+ qry = "select value from property where paramid='";
+ qry += paramid + "' and name='";
+ qry += pi->name + "'";
+ if (database.Query(qry) == 0)
+ {
+ *Log << "Property " << pi->name << " of "
+ << param_name << " does not exist.\n";
+ }
+ else if (database.Field(0, "value") != pi->value)
+ {
+ *Log << "Property " << pi->name << " of "
+ << param_name << " is different.\n";
- qry = "select paramid from parameter where objectid='";
- qry += objectid + "' and class='package' and name='";
- qry += package + "'";
+ insertion = "update property set value='";
+ insertion += pi->value + "' where paramid='";
+ insertion += paramid + "' and name='";
+ insertion += pi->name + "'";
- if (database.Query(qry) == 1)
- {
- std::list<String>::iterator lp;
+ database.Query(insertion);
- lp = find(packages.begin(), packages.end(), package);
- if (lp != packages.end())
- {
- packages.erase(lp);
- }
- else
- {
- *log << "Could NOT find " << package << " in list.\n";
- }
+ insertion = "insert into history (paramid, modified,";
+ insertion += " change_nature, changed_property, new_value)";
+ insertion += " values ('";
+ insertion += paramid + "', '" + arrival.format("%Y-%m-%d %T")
+ + "', 'MODIFIED', '";
+ insertion += pi->name + "', '";
+ insertion += pi->value + "')";
- paramid = database.Field(0, "paramid");
- qry = "select value from property where paramid='";
- qry += paramid + "' and name='version'";
- if (database.Query(qry) == 0)
- {
- *log << "Database corruption: Package " << package;
- *log << " does not have a 'version' property.\n";
- }
- else if (database.Field(0, "value") != version)
- {
- if (verbose)
- {
- *log << " Parameter " << package << " has different version\n";
- }
- insertion = "update property set value='";
- insertion += version + "' where paramid='";
- insertion += paramid + "' and name='version'";
+ database.Query(insertion);
- insert_h = "insert into history (paramid, modified, change_nature, changed_property, new_value)";
- insert_h += " values ('";
- insert_h += paramid + "', '" + arrival.format("%Y-%m-%d %T") + "', 'MODIFIED', 'version', '";
- insert_h += version + "')";
+ param_changed = true;
- database.Query(insertion);
- database.Query(insert_h);
- if (change_notification == "")
- {
- remark = "Gnucomo detected a different version for package parameter(s) ";
- change_notification = database.new_notification(objectid, "property modified", remark);
- change_notification = database.new_notification(objectid, "property modified", remark);
+ }
+ pi++;
}
- if (change_notification != "")
+ if (param_changed)
{
- qry = "select * from parameter_notification where notificationid='";
- qry += change_notification + "' and paramid='";
- qry += paramid + "'";
+ if (change_notification == "")
+ {
+ remark = "Gnucomo detected a different version for package parameter(s) ";
+ change_notification = database.new_notification(objectid,
+ "property modified", remark);
+ }
- if (database.Query(qry) == 0)
+ if (change_notification != "")
{
- insertion = "insert into parameter_notification (notificationid, paramid) values ('";
- insertion += change_notification + "', '";
- insertion += paramid + "')";
+ qry = "select * from parameter_notification where notificationid='";
+ qry += change_notification + "' and paramid='";
+ qry += paramid + "'";
- database.Query(insertion);
+ if (database.Query(qry) == 0)
+ {
+ insertion = "insert into parameter_notification";
+ insertion += " (notificationid, paramid) values ('";
+ insertion += change_notification + "', '";
+ insertion += paramid + "')";
+
+ database.Query(insertion);
+ }
+ }
+ else
+ {
+ *Log << "gcm_input ERROR: Cannot create 'property modified' notification.\n";
}
- }
- else
- {
- *log << "gcm_input ERROR: Cannot create 'property modified' notification.\n";
}
}
else
{
- if (verbose)
- {
- *log << " Parameter " << package << " has not changed.\n";
- }
- }
- }
- else
- {
+ // The parameter does not exist; create anew.
- if (verbose)
- {
- *log << " Parameter " << package << " does not exist.\n";
- }
- // Create a new package parameter, including version property and history record
+ // TODO: Insert description
- insertion = "insert into parameter (objectid, name, class, description) values ('";
- insertion += objectid + "', '" + package + "', 'package', 'RPM package " + package + "')";
- if (testmode)
- {
- paramid = "0";
- *log << insertion << "\n";
- }
- else
- {
+ insertion = "insert into parameter (objectid, name, class, description) values ('";
+ insertion += objectid + "', '" + param_name + "', '" + param_class + "', '')";
database.Query(insertion);
+
qry = "select paramid from parameter where objectid='";
- qry += objectid + "' and class='package' and name='";
- qry += package + "'";
+ qry += objectid + "' and class='";
+ qry += param_class + "' and name='";
+ qry += param_name + "'";
database.Query(qry);
paramid = database.Field(0, "paramid");
- }
- insertion = "insert into property (paramid, name, value, type) values ('";
- insertion += paramid + "', 'version', '";
- insertion += version + "', 'STATIC')";
- insert_h = "insert into history (paramid, modified, change_nature, changed_property, new_value)";
- insert_h += " values ('";
- insert_h += paramid + "', '" + arrival.format("%Y-%m-%d %T") + "', 'CREATED', 'version', '";
- insert_h += version + "')";
+ while (pi != properties.end())
+ {
+ insertion = "insert into property (paramid, name, value, type) values ('";
+ insertion += paramid + "', '";
+ insertion += pi->name + "', '";
+ insertion += pi->value + "', 'STATIC')";
+ database.Query(insertion);
+
+ insertion = "insert into history (paramid, modified,";
+ insertion += " change_nature, changed_property, new_value)";
+ insertion += " values ('";
+ insertion += paramid + "', '" + arrival.format("%Y-%m-%d %T")
+ + "', 'CREATED', '";
+ insertion += pi->name + "', '";
+ insertion += pi->value + "')";
+ database.Query(insertion);
+
+ pi++;
+ }
- if (testmode)
- {
- *log << insertion << "\n" << insert_h << "\n";
- }
- else
- {
- database.Query(insertion);
- database.Query(insert_h);
if (!initial_entry)
{
if (create_notification == "")
{
remark = "Gnucomo detected new parameter(s) of class package";
- create_notification = database.new_notification(objectid, "parameter created", remark);
+ create_notification = database.new_notification(objectid,
+ "parameter created", remark);
}
if (create_notification != "")
{
- insertion = "insert into parameter_notification (notificationid, paramid) values ('";
+ insertion = "insert into parameter_notification";
+ insertion += " (notificationid, paramid) values ('";
insertion += create_notification + "', '";
insertion += paramid + "')";
}
else
{
- *log << "gcm_input ERROR: Cannot create 'parameter created' notification.\n";
+ *Log << "gcm_input ERROR: Cannot create 'parameter created' notification.\n";
}
}
}
}
- if (verbose)
- {
- *log << "\n";
- }
-
- nr_lines++;
- break;
-
+ node = node->next;
}
- }
- else
- {
- *log << "gcm_input WARNING: Not a valid line: " << line << "\n";
- }
- }
- if (classification == RPMLIST && !incremental)
- {
- std::list<String>::iterator lp;
- String remove_notification("");
+ if (!incremental)
+ {
+ // Check if any parameters in this class have disappeared.
- /*
- * If there are any packages left in the list, they seem to have
- * disappeared from the system.
- */
+ qry = "select name, paramid from parameter where objectid='";
+ qry += objectid + "' and class='" + param_class + "'";
- for (lp = packages.begin(); lp != packages.end(); lp++)
- {
- String paramid;
- String remark;
- String insert;
+ int nr_parameters = database.Query(qry);
+ pqxx::Result parameter_set = database.Result();
- // Construct a qry to check the package's existance
+ for (int i = 0; i < nr_parameters; i++)
+ {
+ String XPath;
+ String param_name, paramid;
- qry = "select paramid from parameter where objectid='";
- qry += objectid + "' and class='package' and name='";
- qry += *lp + "'";
+ param_name = database.Field(parameter_set, i, "name");
+ XPath = "gcmt:parameter[@name='" + param_name + "']";
- if (database.Query(qry) == 1)
- {
- paramid = database.Field(0, "paramid");
- qry ="select change_nature from history where paramid='";
- qry += paramid + "' order by modified desc";
- if (database.Query(qry) <= 0)
- {
- *log << "Database ERROR: no history record for parameter " << *lp << ".\n";
- }
- else if (database.Field(0, "change_nature") != "REMOVED")
- {
- if (verbose)
+ res = xmlXPathEval((const xmlChar *)(const char *)XPath, pathcontext);
+ if (res->nodesetval->nodeTab == NULL)
{
- *log << "Removing parameter " << *lp << ".\n";
- }
+ // The parameter is in the database but not in the report
- insert = "insert into history (paramid, modified, change_nature)";
- insert += " values ('";
- insert += paramid + "', '" + arrival.format("%Y-%m-%d %T") + "', 'REMOVED')";
+ paramid = database.Field(parameter_set, i, "paramid");
+ qry ="select change_nature from history where paramid='";
+ qry += paramid + "' order by modified desc";
+ if (database.Query(qry) <= 0)
+ {
+ *Log << "Database ERROR: no history record for parameter "
+ << param_name << ".\n";
+ }
+ else if (database.Field(0, "change_nature") != "REMOVED")
+ {
+ if (verbose)
+ {
+ *Log << "Removing parameter " << param_name << ".\n";
+ }
- database.Query(insert);
+ insertion = "insert into history (paramid, modified, change_nature)";
+ insertion += " values ('";
+ insertion += paramid + "', '" + arrival.format("%Y-%m-%d %T")
+ + "', 'REMOVED')";
- if (remove_notification == "")
- {
- remark = "Gnucomo detected that package(s) have disappeared ";
- remove_notification = database.new_notification(objectid, "parameter removed", remark);
- }
+ database.Query(insertion);
- if (remove_notification != "")
- {
- insert = "insert into parameter_notification (notificationid, paramid) values ('";
- insert += remove_notification + "', '";
- insert += paramid + "')";
+ if (remove_notification == "")
+ {
+ remark = "Gnucomo detected that package(s) have disappeared ";
+ remove_notification = database.new_notification(objectid,
+ "parameter removed", remark);
+ }
- database.Query(insert);
- }
- else
- {
- *log << "gcm_input ERROR: Cannot create 'parameter removed' notification.\n";
+ if (remove_notification != "")
+ {
+ insertion = "insert into parameter_notification";
+ insertion += " (notificationid, paramid) values ('";
+ insertion += remove_notification + "', '";
+ insertion += paramid + "')";
+
+ database.Query(insertion);
+ }
+ else
+ {
+ *Log << "gcm_input ERROR: Cannot create 'parameter removed' notification.\n";
+ }
+ }
}
}
}
}
+ else
+ {
+ *Log << "Data element " << node->name << " is not supported.\n";
+ }
}
+ else
+ {
+ *Log << "Data node not found.\n";
+ }
+}
- if (verbose)
+/*=========================================================================
+** 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 : Nov 26, 2003
+**=========================================================================
+*/
+
+int client_message::enter()
+{
+ pan.mf->set_message_type(pan.lc->message_type());
+
+ pan.mf->construct_XML(input, xmlBuffer);
+
+#ifdef DEBUG
+ *Log << "Constructed XML document:\n\n";
+ *Log << xmlBuffer.str();
+ *Log << "\n";
+#endif
+
+ xmlDom = xmlParseMemory(xmlBuffer.str(), xmlBuffer.pcount());
+
+ if (xmlDom)
+ {
+ if (extractHeader())
+ {
+ enterXML();
+ }
+ }
+ else
{
- *log << nr_lines << " lines parsed from the log file.\n";
+ *Log << "XML parser FAILED.\n";
}
- return nr_lines;
+
+ return 0;
+
}
***********************
** FILE NAME : message.h
** SYSTEM NAME :
-** VERSION NUMBER : $Revision: 1.7 $
+** VERSION NUMBER : $Revision: 1.8 $
**
** DESCRIPTION : Classes to for handling client messages
**
/*****************************
$Log: message.h,v $
- Revision 1.7 2003-08-11 16:56:16 arjen
+ Revision 1.8 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+ Revision 1.7 2003/08/11 16:56:16 arjen
Different kinds of log files are parsed by a collection of objects
of different classes, derived from the base class line_cooker
Depending on the message content or the message_type element in
*****************************/
-/* static const char *RCSID = "$Id: message.h,v 1.7 2003-08-11 16:56:16 arjen Exp $"; */
+/* static const char *RCSID = "$Id: message.h,v 1.8 2003-12-04 10:38:09 arjen Exp $"; */
#include <iostream>
#include <list>
#include <libxml/parser.h>
+#include "message_filter.h"
#include "line_cooker.h"
#include "database.h"
-/*
-///////////////////////////////////////////////////////////////////////////
-// NAME : message_buffer
-// BASECLASS :
-// MEMBERS :
-// OPERATORS :
-// METHODS : rewind()
-//
-// DESCRIPTION :
-//
-// RELATIONS :
-// SEE ALSO :
-// LAST MODIFIED : Nov 04, 2002
-///////////////////////////////////////////////////////////////////////////
-*/
+// Associates line cookers and message filters
-class message_buffer
+struct xform
{
- std::istream *input;
- std::list<String> buffer;
-
- std::list<String>::iterator next_line;
-
-public:
+ message_filter *mf;
+ line_cooker *lc;
+ double uncertainty;
- message_buffer()
+ xform()
{
- input = 0;
- next_line = buffer.begin();
+ mf = NULL;
+ lc = NULL;
+ uncertainty = 1.0;
}
- message_buffer(std::istream *in)
+ xform(message_filter *m, line_cooker *l)
{
- input = in;
- next_line = buffer.begin();
- }
-
- void from(std::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--;
- }
+ mf = m;
+ lc = l;
+ uncertainty = 1.0;
}
};
UTC arrival; // When we got the message.
String service; // Service that created the message
- std::list<line_cooker *> kitchen; // The collection of line cookers
- line_cooker * pan; // The one we cook this log with
+ std::list<xform> kitchen; // The collection of message filters and line cookers
+ xform pan; // The one we cook this log with
bool mail_header; // Does the message contain a mail header ?
bool gpg_encrypted; // Is the message encrypted ?
- xmlDocPtr xmlDom;
+ std::strstream xmlBuffer;
+ xmlDocPtr xmlDom;
double certainty; // How certain are we about the message
enum
message_buffer input;
gnucomo_database database;
- int readXMLinput(String first_line);
void enterXML();
+ bool extractHeader();
public:
client_message(std::istream *in, gnucomo_database db);
- void add_cooker(line_cooker *lc)
+ void add_cooker(line_cooker *lc, message_filter *mf)
{
- kitchen.push_back(lc);
+ xform x(mf, lc);
+
+ kitchen.push_back(x);
}
double classify(String host, UTC arrival = Now(), String serv = "");
--- /dev/null
+
+/**************************************************************************
+** (c) Copyright 2002, Andromeda Technology & Automation
+** This is free software; you can redistribute it and/or modify it under the
+** terms of the GNU General Public License, see the file COPYING.
+***************************************************************************
+** MODULE INFORMATION *
+***********************
+** FILE NAME : message_buffer.h
+** SYSTEM NAME :
+** VERSION NUMBER : $Revision: 1.1 $
+**
+** DESCRIPTION : Classes to for buffering the input stream
+**
+** EXPORTED OBJECTS :
+** LOCAL OBJECTS :
+** MODULES USED :
+***************************************************************************
+** ADMINISTRATIVE INFORMATION *
+********************************
+** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
+** CREATION DATE : Sep 16, 2002
+** LAST UPDATE : Aug 06, 2003
+** MODIFICATIONS :
+**************************************************************************/
+
+/*****************************
+ $Log: message_buffer.h,v $
+ Revision 1.1 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+*****************************/
+
+/* static const char *RCSID = "$Id: message_buffer.h,v 1.1 2003-12-04 10:38:09 arjen Exp $"; */
+
+#include <iostream>
+#include <list>
+#include <AXE/String.h>
+
+
+/*
+///////////////////////////////////////////////////////////////////////////
+// NAME : message_buffer
+// BASECLASS :
+// MEMBERS :
+// OPERATORS :
+// METHODS : from()
+// rewind()
+//
+// DESCRIPTION :
+//
+// RELATIONS :
+// SEE ALSO :
+// LAST MODIFIED : Nov 04, 2002
+///////////////////////////////////////////////////////////////////////////
+*/
+
+class message_buffer
+{
+ std::istream *input;
+ std::list<String> buffer;
+
+ std::list<String>::iterator next_line;
+
+public:
+
+ message_buffer()
+ {
+ input = 0;
+ next_line = buffer.begin();
+ }
+
+ message_buffer(std::istream *in)
+ {
+ input = in;
+ next_line = buffer.begin();
+ }
+
+ void from(std::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--;
+ }
+ }
+};
+
--- /dev/null
+
+/**************************************************************************
+** (c) Copyright 2003, Andromeda Technology & Automation
+** This is free software; you can redistribute it and/or modify it under the
+** terms of the GNU General Public License, see the file COPYING.
+***************************************************************************
+** MODULE INFORMATION *
+***********************
+** FILE NAME : message_filter.cpp
+** 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 : Nov 26, 2003
+** LAST UPDATE : Nov 26, 2003
+** MODIFICATIONS :
+**************************************************************************/
+
+/*****************************
+ $Log: message_filter.cpp,v $
+ Revision 1.1 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+*****************************/
+
+/* static const char *RCSID = "$Id: message_filter.cpp,v 1.1 2003-12-04 10:38:09 arjen Exp $"; */
+
+#include "message_filter.h"
+
+extern std::ostream *Log;
+
+/*=========================================================================
+** NAME : constructXML
+** SYNOPSIS : int constructXML(message_buffer &in, std::strstream &xml)
+** PARAMETERS :
+** RETURN VALUE :
+**
+** DESCRIPTION : Copy the input stream into the internal XML buffer
+** The input is already in XML format, so no real transformation
+** is needed.
+**
+** VARS USED :
+** VARS CHANGED :
+** FUNCTIONS USED :
+** SEE ALSO :
+** LAST MODIFIED : Nov 26, 2003
+**=========================================================================
+*/
+
+void message_filter::construct_XML(message_buffer &in, std::strstream &xml)
+{
+ String line;
+
+ while (in >> line)
+ {
+ xml << line << "\n";
+ }
+}
+
+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_uxmail_from("^From [^ \t]+[ ]+" + 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_mail_MsId("^Message-Id:[[:blank:]]+");
+static const regex re_email_address("[[:alnum:]_.-]+@[[:alnum:]_.-]+");
+static const regex re_email_user("[[:alnum:]_.-]+@");
+
+/*=========================================================================
+** NAME : scan_email_header
+** SYNOPSIS : void scan_email_header(message_buffer &in)
+** PARAMETERS :
+** RETURN VALUE :
+**
+** DESCRIPTION :
+**
+** VARS USED :
+** VARS CHANGED :
+** FUNCTIONS USED :
+** SEE ALSO :
+** LAST MODIFIED : Nov 26, 2003
+**=========================================================================
+*/
+
+void message_filter::scan_email_header(message_buffer &in)
+{
+ String line;
+
+ /* First, check if the message has a mail header. */
+
+ if (in >> line && line == re_uxmail_from)
+ {
+ String from_address;
+
+ /* Scan ahead for the hostname and date of arrival. */
+
+ while (in >> line && line != "")
+ {
+
+ if (line == re_mail_From)
+ {
+ from_address = line(re_email_address);
+ from_address(re_email_user) = ""; // Remove the user part;
+ if (from_address != "" && ~hn < ~from_address)
+ {
+ *Log << "Detected hostname " << from_address << "\n";
+ hn = from_address;
+ }
+ }
+ if (line == re_mail_MsId)
+ {
+ from_address = line(re_email_address);
+ from_address(re_email_user) = ""; // Remove the user part;
+ if (from_address != "" && ~hn < ~from_address)
+ {
+ *Log << "Detected hostname " << from_address << "\n";
+ hn = from_address;
+ }
+ }
+ if (line == re_mail_Date)
+ {
+ ts = UTC(line(regex(mail_date_re)));
+ }
+ }
+ }
+ else
+ {
+ // Push the first line back, we need to read it again.
+ --in;
+
+ }
+
+}
+
+/*=========================================================================
+** NAME : construct_header
+** SYNOPSIS : void construct_header(std::strstream &xml)
+** PARAMETERS :
+** RETURN VALUE :
+**
+** DESCRIPTION : Create the header for a Gnucomo XML document.
+**
+** VARS USED :
+** VARS CHANGED :
+** FUNCTIONS USED :
+** SEE ALSO :
+** LAST MODIFIED : Nov 26, 2003
+**=========================================================================
+*/
+
+void message_filter::construct_header(std::strstream &xml)
+{
+ //xml << "<?xml version='1.0' encoding='utf-8'?>\n";
+ xml << "<?xml version='1.0' encoding='ISO-8859-1'?>\n";
+ xml << "<gcmt:message xmlns:gcmt='http://gnucomo.org/transport/'>\n";
+ xml << " <gcmt:header>\n";
+ xml << " <gcmt:messagetype>" << mt << "</gcmt:messagetype>\n";
+ xml << " <gcmt:hostname>" << hn << "</gcmt:hostname>\n";
+ xml << " <gcmt:service>" << srv << "</gcmt:service>\n";
+ xml << " <gcmt:time>" << ts << "</gcmt:time>\n";
+ xml << " </gcmt:header>\n";
+}
--- /dev/null
+
+/**************************************************************************
+** (c) Copyright 2003, Andromeda Technology & Automation
+** This is free software; you can redistribute it and/or modify it under the
+** terms of the GNU General Public License, see the file COPYING.
+***************************************************************************
+** MODULE INFORMATION *
+***********************
+** FILE NAME : message_filter.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 : Nov 26, 2003
+** LAST UPDATE : Nov 26, 2003
+** MODIFICATIONS :
+**************************************************************************/
+
+/*****************************
+ $Log: message_filter.h,v $
+ Revision 1.1 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+*****************************/
+
+/* static const char *RCSID = "$Id: message_filter.h,v 1.1 2003-12-04 10:38:09 arjen Exp $"; */
+
+#ifndef MESSAGE_FILTER_H
+#define MESSAGE_FILTER_H
+
+#include <strstream>
+
+#include <AXE/String.h>
+#include <AXE/date.h>
+
+#include "message_buffer.h"
+
+/*
+///////////////////////////////////////////////////////////////////////////
+// NAME : message_filter
+// BASECLASS :
+// MEMBERS :
+// OPERATORS :
+// METHODS : contruct_XML
+// set_message_type
+//
+// DESCRIPTION : Transform any kind of input into an XML document
+// for Gnucomo
+//
+// RELATIONS :
+// SEE ALSO :
+// LAST MODIFIED : Nov 26, 2003
+///////////////////////////////////////////////////////////////////////////
+*/
+
+class message_filter
+{
+
+protected:
+
+ UTC ts; // the timestamp.
+ String hn; // the hostname
+ String srv; // the service
+ String mt; // the message type
+
+ void scan_email_header(message_buffer &in);
+ void construct_header(std::strstream &xml);
+
+public:
+
+ message_filter(String host, UTC arriv, String service)
+ {
+ hn = host;
+ ts = arriv;
+ srv = service;
+ }
+
+ virtual void construct_XML(message_buffer &in, std::strstream &xml);
+
+ void set_message_type(String msgt)
+ {
+ mt = msgt;
+ }
+};
+
+#endif // MESSAGE_FILTER_H
--- /dev/null
+
+/**************************************************************************
+** (c) Copyright 2003, Andromeda Technology & Automation
+** This is free software; you can redistribute it and/or modify it under the
+** terms of the GNU General Public License, see the file COPYING.
+***************************************************************************
+** MODULE INFORMATION *
+***********************
+** FILE NAME : rpm_filter.cpp
+** SYSTEM NAME :
+** VERSION NUMBER : $Revision: 1.1 $
+**
+** DESCRIPTION : Transform a list of packages into a Gnucomo XML document
+**
+** EXPORTED OBJECTS :
+** LOCAL OBJECTS :
+** MODULES USED :
+***************************************************************************
+** ADMINISTRATIVE INFORMATION *
+********************************
+** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
+** CREATION DATE : Nov 27, 2003
+** LAST UPDATE : Nov 27, 2003
+** MODIFICATIONS :
+**************************************************************************/
+
+/*****************************
+ $Log: rpm_filter.cpp,v $
+ Revision 1.1 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+*****************************/
+
+/* static const char *RCSID = "$Id: rpm_filter.cpp,v 1.1 2003-12-04 10:38:09 arjen Exp $"; */
+
+#include <ctype.h>
+
+#include "rpm_filter.h"
+
+/*=========================================================================
+** NAME : constructXML
+** SYNOPSIS : int constructXML(message_buffer &in, strstream &xml)
+** PARAMETERS :
+** RETURN VALUE : Create an XML document from a list of RPMs
+**
+** DESCRIPTION :
+** Scan a list of packages and versions from "rpm -a".
+** A similar listing can be created on IRIX 6.5 by using the
+** command "showprods -3 -n|awk '{printf "%s-%s\n",$2,$3}'|grep -v '^[-=]' \
+** |grep -v Version-Description".
+**
+** We have to separate the package name and the version.
+** The separation is marked by a '-', followed by a digit.
+** However, there may be other sequences of '-'digit in the package name,
+** do we have to scan ahead until there is at most one such sequence
+** left in the version string. The '-'digit seqeunce inside the
+** version usually separates the version and the release number.
+**
+** VARS USED :
+** VARS CHANGED :
+** FUNCTIONS USED :
+** SEE ALSO :
+** LAST MODIFIED : Nov 27, 2003
+**=========================================================================
+*/
+
+void rpm_filter::construct_XML(message_buffer &in, std::strstream &xml)
+{
+ String line;
+
+ scan_email_header(in);
+ construct_header(xml);
+
+ xml << " <gcmt:data>\n";
+ xml << " <gcmt:parameters class='package'>\n";
+
+ while (in >> line)
+ {
+ int version_start, next_version_start;
+ int i;
+
+ // Separate the package name from the version number
+
+ i = line.index('-');
+ version_start = i;
+ next_version_start = i;
+
+ while (i < ~line - 1)
+ {
+ while (i < ~line - 1 && !(line[i] == '-' && isdigit(line[i + 1])))
+ {
+ i++;
+ }
+ if (i < ~line - 1)
+ {
+ version_start = next_version_start;
+ next_version_start = i;
+ }
+ i++;
+ }
+
+ if (!isdigit(line[version_start + 1]))
+ {
+ version_start = next_version_start;
+ }
+ String package(line(0,version_start));
+ String version(line(version_start + 1, ~line));
+
+ // Create the XML element.
+
+ xml << " <gcmt:parameter name='" << package << "'>\n";
+ xml << " <gcmt:property name='version'>" << version << "</gcmt:property>\n";
+ xml << " </gcmt:parameter>\n";
+ }
+ xml << " </gcmt:parameters>\n";
+ xml << " </gcmt:data>\n";
+ xml << "</gcmt:message>\n";
+}
+
+static const regex re_rpm("[[:alnum:]+-]+-[0-9][[:alnum:].-]");
+
+bool rpm_cooker::check_pattern(String logline)
+{
+ return logline == re_rpm;
+}
+
+bool rpm_cooker::cook_this(String logline, UTC arrival)
+{
+ return true;
+}
--- /dev/null
+
+/**************************************************************************
+** (c) Copyright 2003, Andromeda Technology & Automation
+** This is free software; you can redistribute it and/or modify it under the
+** terms of the GNU General Public License, see the file COPYING.
+***************************************************************************
+** MODULE INFORMATION *
+***********************
+** FILE NAME : rpm_filter.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 : Nov 27, 2003
+** LAST UPDATE : Nov 27, 2003
+** MODIFICATIONS :
+**************************************************************************/
+
+/*****************************
+ $Log: rpm_filter.h,v $
+ Revision 1.1 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+*****************************/
+
+/* static const char *RCSID = "$Id: rpm_filter.h,v 1.1 2003-12-04 10:38:09 arjen Exp $"; */
+
+#include "message_filter.h"
+#include "line_cooker.h"
+
+/*
+///////////////////////////////////////////////////////////////////////////
+// NAME : rpm_filter
+// BASECLASS :
+// MEMBERS :
+// OPERATORS :
+// METHODS :
+//
+// DESCRIPTION :
+//
+// RELATIONS :
+// SEE ALSO :
+// LAST MODIFIED : Nov 27, 2003
+///////////////////////////////////////////////////////////////////////////
+*/
+
+class rpm_filter : public message_filter
+{
+
+protected:
+
+public:
+
+ rpm_filter(String host, UTC arriv, String service) : message_filter(host, arriv, service)
+ {
+ }
+
+ virtual void construct_XML(message_buffer &in, std::strstream &xml);
+};
+
+/*
+///////////////////////////////////////////////////////////////////////////
+// NAME : rpm_cooker
+// BASECLASS :
+// MEMBERS :
+// OPERATORS :
+// METHODS :
+//
+// DESCRIPTION :
+//
+// RELATIONS :
+// SEE ALSO :
+// LAST MODIFIED : Nov 27, 2003
+///////////////////////////////////////////////////////////////////////////
+*/
+
+class rpm_cooker : public line_cooker
+{
+
+protected:
+
+
+public:
+
+ rpm_cooker()
+ {
+ }
+
+ bool check_pattern(String logline);
+ bool cook_this(String logline, UTC arrival);
+
+ String message_type()
+ {
+ return "package list";
+ }
+
+};
--- /dev/null
+
+/**************************************************************************
+** (c) Copyright 2002, Andromeda Technology & Automation
+** This is free software; you can redistribute it and/or modify it under the
+** terms of the GNU General Public License, see the file COPYING.
+***************************************************************************
+** MODULE INFORMATION *
+***********************
+** FILE NAME : xml_cooker.cpp
+** SYSTEM NAME :
+** VERSION NUMBER : $Revision: 1.1 $
+**
+** DESCRIPTION : Detect whether the input stream is in XML format
+**
+** EXPORTED OBJECTS :
+** LOCAL OBJECTS :
+** MODULES USED :
+***************************************************************************
+** ADMINISTRATIVE INFORMATION *
+********************************
+** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
+** CREATION DATE : Aug 06, 2003
+** LAST UPDATE : Aug 06, 2003
+** MODIFICATIONS :
+**************************************************************************/
+
+/*****************************
+ $Log: xml_cooker.cpp,v $
+ Revision 1.1 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+*****************************/
+
+/* static const char *RCSID = "$Id: xml_cooker.cpp,v 1.1 2003-12-04 10:38:09 arjen Exp $"; */
+
+#include <ctype.h>
+
+#include "xml_cooker.h"
+
+static const regex re_xml_header("xml .*\?>$");
+
+bool xml_cooker::check_pattern(String logline)
+{
+ if (XML_detected)
+ {
+ return true;
+ }
+ else if (logline == re_xml_header)
+ {
+ XML_detected = true;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool xml_cooker::cook_this(String logline, UTC arrival)
+{
+
+ return true;
+}
+
+
--- /dev/null
+
+/**************************************************************************
+** (c) Copyright 2003, Andromeda Technology & Automation
+** This is free software; you can redistribute it and/or modify it under the
+** terms of the GNU General Public License, see the file COPYING.
+***************************************************************************
+** MODULE INFORMATION *
+***********************
+** FILE NAME : xml_cooker.h
+** SYSTEM NAME :
+** VERSION NUMBER : $Revision: 1.1 $
+**
+** DESCRIPTION : The XML cooker does not cook anything. It is here to
+** match the XML header.
+**
+** EXPORTED OBJECTS :
+** LOCAL OBJECTS :
+** MODULES USED :
+***************************************************************************
+** ADMINISTRATIVE INFORMATION *
+********************************
+** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
+** CREATION DATE : Nov 26, 2003
+** LAST UPDATE : Nov 26, 2003
+** MODIFICATIONS :
+**************************************************************************/
+
+/*****************************
+ $Log: xml_cooker.h,v $
+ Revision 1.1 2003-12-04 10:38:09 arjen
+ Major redesign. All input is handled through XML. Raw input data is first
+ transformed into an XML document for further processing.
+ A collection of polymorphic classes handle the transformation of various
+ input formats into XML.
+ Classifying input data is done with a finite improbability calculation.
+
+*****************************/
+
+/* static const char *RCSID = "$Id: xml_cooker.h,v 1.1 2003-12-04 10:38:09 arjen Exp $"; */
+
+#include "line_cooker.h"
+
+/*
+///////////////////////////////////////////////////////////////////////////
+// NAME : xml_cooker
+// BASECLASS : line_cooker
+// MEMBERS :
+// OPERATORS :
+// METHODS :
+//
+// DESCRIPTION :
+//
+// RELATIONS :
+// SEE ALSO :
+// LAST MODIFIED : Nov 26, 2003
+///////////////////////////////////////////////////////////////////////////
+*/
+
+class xml_cooker : public line_cooker
+{
+
+ bool XML_detected;
+
+public:
+
+ xml_cooker()
+ {
+ XML_detected = false;
+ }
+
+ bool check_pattern(String logline);
+ bool cook_this(String logline, UTC arrival);
+
+ String message_type()
+ {
+ return "XML";
+ }
+
+};