/* ** Modular Logfile Analyzer ** Copyright 2000 Jan Kneschke ** ** Homepage: http://www.modlogan.org ** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version, and provided that the above copyright and permission notice is included with all distributed copies of this or derived software. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ** ** $Id: mhistory.c,v 1.9 2004/08/27 20:07:37 ostborn Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #ifdef HAVE_LIBXML #include #include #endif #include "mlocale.h" #include "mhistory.h" #include "mlist.h" #include "datatypes/webhist/datatype.h" #include "datatypes/state/datatype.h" #define HISTORY_FILE_VERSION "0.2" #define MSTATE_WRITE 1 int history_write(mconfig *conf, mlist *l, char *subpath) { char filename[255]; gzFile *fd; /* protect buffer */ if (subpath) { if (strlen(conf->statedir) + strlen(subpath) + strlen("//mla.history.xml") > sizeof(filename) - 1) { fprintf(stderr, "%s.%d: filename is too long\n", __FILE__, __LINE__); return -1; } sprintf(filename, "%s/%s/mla.history.xml", conf->statedir, subpath); } else { sprintf(filename, "%s/mla.history.xml", conf->statedir); } if ((fd = gzopen(filename, "wb")) == NULL) { fprintf(stderr, "%s.%d: can't open %s: %s\n", __FILE__, __LINE__, filename, strerror(errno)); return -1; } gzprintf(fd, "\n"); gzprintf(fd, "\n"); gzprintf(fd, "\n", HISTORY_FILE_VERSION, PACKAGE); mlist_write(fd, l); gzprintf(fd, "\n"); gzclose(fd); return 0; } #ifdef HAVE_LIBXML static xmlSAXHandler mlaSAXHandler = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #endif void history_startElement(void *user_data, const xmlChar *name, const xmlChar **attrs) { mstate_stack *m = user_data; // M_WP(); #if 0 for (i = 0; i < m->st_depth; i++) { fprintf(stderr, " "); } fprintf(stderr, "> %s ", name); if (attrs) { for (i = 0; attrs[i]; i += 2) { fprintf(stderr, "%s=%s ", attrs[i], attrs[i+1]); } } fprintf(stderr, "\n"); #endif #if 0 fprintf(stderr, "stack: "); for (i = 0; i < m->st_depth+1; i++) { fprintf(stderr, "%p ", m->st[i].data); } fprintf(stderr, "\n"); #endif if (m->st_depth == 0) { /* state */ m->st[m->st_depth].function = mdata_insert_value; m->st[m->st_depth].data = m->state; m->st[m->st_depth].type = M_DATA_FIELDTYPE_LIST; } else { (*(m->st[m->st_depth-1].function))(m, M_TAG_BEGIN, name, attrs); } m->st_depth++; } void history_endElement(void *user_data, const xmlChar *name) { mstate_stack *m = user_data; // M_WP(); #if 0 for (i = 0; i < m->st_depth-1; i++) { fprintf(stderr, " "); } fprintf(stderr, "< %s\n", name); #endif if (m->st_depth > 1) { (*(m->st[m->st_depth-1].function))(m, M_TAG_END, name, NULL); } else if (m->st_depth == 1) { /* all done */ } m->st_depth--; } void history_characters(void *user_data, const xmlChar *name, int len) { mstate_stack *m = user_data; xmlChar *s; if (*name == '\n') return; s = malloc((len + 1) * sizeof(xmlChar)); strncpy(s, name, len); s[len] = '\0'; // M_WP(); #if 0 for (i = 0; i < m->st_depth; i++) { fprintf(stderr, " "); } fprintf(stderr, "(%s)\n", s); #endif if (m->st_depth > 0) { (*(m->st[m->st_depth-1].function))(m, M_TAG_TEXT, s, NULL); } free(s); } int history_read(mconfig *conf, mlist *l, char *subpath) { char filename[255]; mstate_stack m; struct stat s; int i; #ifdef HAVE_EXPAT XML_Parser p; gzFile f; #endif sprintf(filename, "%s%s%s/mla.history.xml", conf->statedir ? conf->statedir : ".", subpath ? "/" : "", subpath ? subpath : ""); m.ext_conf = conf; m.state = l; m.st_depth = 0; for (i = 0; i < M_STATE_ST_ELEM; i++) { m.st[i].function = NULL; m.st[i].data = NULL; m.st[i].type = -1; } #ifdef HAVE_LIBXML mlaSAXHandler.startElement = history_startElement; mlaSAXHandler.endElement = history_endElement; mlaSAXHandler.characters = history_characters; mlaSAXHandler.warning = xmlParserWarning; mlaSAXHandler.error = xmlParserError; mlaSAXHandler.fatalError = xmlParserError; if (0 == stat(filename, &s)) { xmlSAXUserParseFile(&mlaSAXHandler, &m, filename); } else { M_DEBUG1(M_DEBUG_LEVEL_ERRORS, M_DEBUG_SECTION_INIT, M_DEBUG_LEVEL_ERRORS, "stating history-file '%s' failed\n", filename); } #elif HAVE_EXPAT # define BUFF_SIZE 256 p = XML_ParserCreate(NULL); XML_SetElementHandler(p, history_startElement, history_endElement); XML_SetCharacterDataHandler(p, history_characters); XML_SetUserData(p, &m); if (0 != stat(filename, &s)) { M_DEBUG1(M_DEBUG_LEVEL_ERRORS, M_DEBUG_SECTION_INIT, M_DEBUG_LEVEL_ERRORS, "stating history-file '%s' failed\n", filename); return -1; } if (NULL == (f = gzopen(filename, "rb"))) { return -1; } for (;;) { int bytes_read; void *buff = XML_GetBuffer(p, BUFF_SIZE); if (buff == NULL) { /* handle error */ M_DEBUG0(M_DEBUG_LEVEL_ERRORS, M_DEBUG_SECTION_INIT, M_DEBUG_LEVEL_ERRORS, "can't get buff\n" ); return -1; } bytes_read = gzread(f, buff, BUFF_SIZE); if (bytes_read < 0) { /* handle error */ M_DEBUG0(M_DEBUG_LEVEL_ERRORS, M_DEBUG_SECTION_INIT, M_DEBUG_LEVEL_ERRORS, "gzread() failed\n" ); } if (! XML_ParseBuffer(p, bytes_read, bytes_read == 0)) { /* handle parse error */ M_DEBUG3(M_DEBUG_LEVEL_ERRORS, M_DEBUG_SECTION_INIT, M_DEBUG_LEVEL_ERRORS, "XML: Line %d (Char %d): %s\n", XML_GetCurrentLineNumber(p), XML_GetCurrentColumnNumber(p), XML_ErrorString(XML_GetErrorCode(p))); } if (bytes_read == 0) break; } gzclose(f); XML_ParserFree(p); #else #error no XML parser #endif return 0; }