diff -urN ossec-hids-2.6.orig/src/config/localfile-config.c ossec-hids-2.6/src/config/localfile-config.c
--- ossec-hids-2.6.orig/src/config/localfile-config.c	2011-07-11 21:36:58.000000000 +0200
+++ ossec-hids-2.6/src/config/localfile-config.c	2012-08-12 08:05:41.648681721 +0200
@@ -26,7 +26,6 @@
     int glob_offset = 0;
     #endif
 
-
     /* XML Definitions */
     char *xml_localfile_location = "location";
     char *xml_localfile_command = "command";
@@ -45,14 +44,8 @@
     {
         os_calloc(2, sizeof(logreader), log_config->config);
         logf = log_config->config;
-        logf[0].file = NULL;
-        logf[0].command = NULL;
-        logf[0].alias = NULL;
-        logf[0].logformat = NULL;
-        logf[1].file = NULL;
-        logf[1].command = NULL;
-        logf[1].alias = NULL;
-        logf[1].logformat = NULL;
+        // @sgros Is this really necessary? Doesn't calloc already do that?
+        memset(logf, 2 * sizeof(logreader), 0);
     }
     else
     {
@@ -65,21 +58,13 @@
         /* Allocating more memory */
         os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config);
         logf = log_config->config;
-        logf[pl +1].file = NULL;
-        logf[pl +1].command = NULL;
-        logf[pl +1].alias = NULL;
-        logf[pl +1].logformat = NULL;
+        // @sgros Is this really necessary? Doesn't calloc already do that?
+        memset(logf + pl + 1, sizeof(logreader), 0);
     }
     
-    logf[pl].file = NULL;
-    logf[pl].command = NULL;
-    logf[pl].alias = NULL;
-    logf[pl].logformat = NULL;
-    logf[pl].fp = NULL;
-    logf[pl].ffile = NULL;
-    logf[pl].djb_program_name = NULL;
+    // @sgros Is this really necessary? Doesn't calloc already do that?
+    memset(logf + pl, sizeof(logreader), 0);
     logf[pl].ign = 360;
-
     
     /* Searching for entries related to files */
     i = 0;
@@ -103,12 +88,8 @@
                 merror("%s: Remote commands are not accepted from the manager. "
                        "Ignoring it on the agent.conf", ARGV0);
 
-                logf[pl].file = NULL;
-                logf[pl].ffile = NULL;
-                logf[pl].command = NULL;
-                logf[pl].alias = NULL;
-                logf[pl].logformat = NULL;
-                logf[pl].fp = NULL;
+                // @sgros Is this really necessary? Doesn't calloc already do that?
+                memset(logf + pl, sizeof(logreader), 0);
                 return(OS_INVALID);
             }
 
@@ -220,6 +201,8 @@
                 os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config);
                 logf = log_config->config;
                 
+                // @sgros Is this really necessary? Doesn't calloc already do that?
+                memset(logf + pl, 2 * sizeof(logreader), 0);
                 logf[pl].file = NULL;
                 logf[pl].alias = NULL;
                 logf[pl].logformat = NULL;
@@ -317,35 +300,81 @@
             else if(strcmp(logf[pl].logformat, "full_command") == 0)
             {
             }
-            else if(strncmp(logf[pl].logformat, "multi-line", 10) == 0)
+            else if(strncmp(logf[pl].logformat, "multiline", 10) == 0)
             {
-                int x = 0;
-                logf[pl].logformat+=10;
+                if (node[i]->attributes == NULL || node[i]->values == NULL) {
+                    merror(XML_ATTRERR,ARGV0,node[i]->element,node[i]->content);
+                    return(OS_INVALID);
+                }
 
-                while(logf[pl].logformat[0] == ' ')
-                    logf[pl].logformat++;
-                
-                if(logf[pl].logformat[0] != ':')
-                {
-                    merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
+                int a = 0;
+
+                while (node[i]->attributes[a] && node[i]->values[a]) {
+                    if (strncmp(node[i]->attributes[a], "lines", 5) == 0)
+                        logf[pl].lines = atol(node[i]->values[a]);
+                    a++;
+                }
+
+            }
+            else if(strncmp(logf[pl].logformat, "modsec_audit", 10) == 0)
+            {
+            }
+            else if(strncmp(logf[pl].logformat, "regex", 10) == 0)
+            {
+                if (node[i]->attributes == NULL || node[i]->values == NULL) {
+                    merror(XML_ATTRERR,ARGV0,node[i]->element,node[i]->content);
                     return(OS_INVALID);
                 }
-                logf[pl].logformat++;
 
-                while(*logf[pl].logformat == ' ')
-                    logf[pl].logformat++;
-                
-                while(logf[pl].logformat[x] >= '0' && logf[pl].logformat[x] <= '9')    
-                    x++;
+                int a = 0;
 
-                while(logf[pl].logformat[x] == ' ')
-                    x++;
+                while (node[i]->attributes[a] && node[i]->values[a]) {
 
-                if(logf[pl].logformat[x] != '\0')
-                {
-                    merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
+                    if (strncmp(node[i]->attributes[a], "start_regex", 11) == 0) {
+                        if (logf[pl].start_regex != NULL)
+                            os_free(logf[pl].start_regex);
+                        logf[pl].start_regex = strndup(node[i]->values[a], OS_PATTERN_MAXSIZE);
+                        // @todo Maybe try to immediatelly compile regex so that user knows if it is OK?
+                    }
+
+                    if (strncmp(node[i]->attributes[a], "end_regex", 9) == 0) {
+                        if (logf[pl].start_regex != NULL)
+                            os_free(logf[pl].start_regex);
+                        logf[pl].start_regex = strndup(node[i]->values[a], OS_PATTERN_MAXSIZE);
+                        // @todo Maybe try to immediatelly compile regex so that user knows if it is OK?
+                    }
+
+                    a++;
+                }
+
+            }
+            else if(strncmp(logf[pl].logformat, "linux_audit", 11) == 0)
+            {
+                if (node[i]->attributes == NULL || node[i]->values == NULL) {
+                    merror(XML_ATTRERR,ARGV0,node[i]->element,node[i]->content);
                     return(OS_INVALID);
                 }
+
+                int a = 0;
+
+                while (node[i]->attributes[a] && node[i]->values[a]) {
+
+                    if (strncmp(node[i]->attributes[a], "window", 6) == 0) {
+                        logf[pl].window = atoi(node[i]->values[a]);
+                        // @todo Maybe try to immediatelly compile regex so that user knows if it is OK?
+                    } else if (strncmp(node[i]->attributes[a], "timeout", 7) == 0) {
+                        logf[pl].timeout = atoi(node[i]->values[a]);
+                    }
+
+                    a++;
+                }
+
+                if ((logf[pl].window == 0 && logf[pl].timeout == 0) ||
+                        (logf[pl].window != 0 && logf[pl].timeout != 0)) {
+                    merror(XML_ATTRERR,ARGV0,node[i]->element,node[i]->content);
+                    return(OS_INVALID);
+                }
+
             }
             else if(strcmp(logf[pl].logformat, EVENTLOG) == 0)
             {
diff -urN ossec-hids-2.6.orig/src/config/localfile-config.h ossec-hids-2.6/src/config/localfile-config.h
--- ossec-hids-2.6.orig/src/config/localfile-config.h	2011-07-11 21:36:58.000000000 +0200
+++ ossec-hids-2.6/src/config/localfile-config.h	2012-08-12 07:47:46.043394859 +0200
@@ -23,7 +23,6 @@
 /* For ino_t */
 #include <sys/types.h>
 
-
 /* Logreader config */
 typedef struct _logreader
 {
@@ -45,13 +44,47 @@
     char *ffile;        
     char *file;
     char *logformat;
-    char *djb_program_name;
-    char *command;
-	char *alias;
 	
     void (*read)(int i, int *rc, int drop_it);
 
     FILE *fp;
+
+    /* Semi-private configuration data specific to each log type */
+    union
+    {
+
+        /* For Linux audit log reader */
+        struct
+        {
+            // == 0 -> not used, != 0 used. Only one != 0!
+            int timeout;
+            int window;
+        };
+
+        /* Logreader config for regex configuration types */
+        struct
+        {
+            char *start_regex;
+            char *end_regex;
+        };
+
+        /* For read_command and read_fullcommand log readers */
+        struct
+        {
+            char *command;
+            char *alias;
+        };
+
+        /* For read_djb_program log reader */
+        char *djb_program_name;
+
+        /* For read_multiline, number of lines that have to be concatenated */
+        int lines;
+    };
+
+    /* Dynamic private data that can be used by each log reader */
+    void *private_data;
+
 }logreader;
 
 typedef struct _logreader_config
diff -urN ossec-hids-2.6.orig/src/error_messages/error_messages.h ossec-hids-2.6/src/error_messages/error_messages.h
--- ossec-hids-2.6.orig/src/error_messages/error_messages.h	2011-07-11 21:36:58.000000000 +0200
+++ ossec-hids-2.6/src/error_messages/error_messages.h	2012-08-12 06:09:10.918969109 +0200
@@ -92,6 +92,7 @@
 #define NO_CONFIG       "%s(1239): ERROR: Configuration file not found: '%s'."
 #define INVALID_TIME    "%s(1240): ERROR: Invalid time format: '%s'."
 #define INVALID_DAY     "%s(1241): ERROR: Invalid day format: '%s'."
+#define XML_ATTRERR     "%s(1242): ERROR: Attribute(s) error for element '%s': %s."
 
 #define MAILQ_ERROR	    "%s(1221): ERROR: No Mail queue at %s"
 #define IMSG_ERROR	    "%s(1222): ERROR: Invalid msg: %s"
Binary files ossec-hids-2.6.orig/src/isbigendian and ossec-hids-2.6/src/isbigendian differ
diff -urN ossec-hids-2.6.orig/src/logcollector/logcollector.c ossec-hids-2.6/src/logcollector/logcollector.c
--- ossec-hids-2.6.orig/src/logcollector/logcollector.c	2011-07-11 21:36:58.000000000 +0200
+++ ossec-hids-2.6/src/logcollector/logcollector.c	2012-08-12 07:45:19.083849769 +0200
@@ -221,10 +221,27 @@
                 }
                 logff[i].read = (void *)read_djbmultilog;
             }
-            else if(logff[i].logformat[0] >= '0' && logff[i].logformat[0] <= '9')
+            else if(strcmp("multitline", logff[i].logformat) == 0)
             {
                 logff[i].read = (void *)read_multiline;
             }
+            else if(strcmp("modsec_audit", logff[i].logformat) == 0)
+            {
+                logff[i].read = (void *)read_modsec_audit;
+            }
+            else if(strcmp("regex", logff[i].logformat) == 0)
+            {
+                if(!read_regex_init(i))
+                {
+                    if(logff[i].fp)
+                    {
+                        fclose(logff[i].fp);
+                        logff[i].fp = NULL;
+                    }
+                    logff[i].file = NULL;
+                }
+                logff[i].read = (void *)read_regex;
+            }
             else
             {
                 logff[i].read = (void *)read_syslog;
diff -urN ossec-hids-2.6.orig/src/logcollector/logcollector.h ossec-hids-2.6/src/logcollector/logcollector.h
--- ossec-hids-2.6.orig/src/logcollector/logcollector.h	2011-07-11 21:36:58.000000000 +0200
+++ ossec-hids-2.6/src/logcollector/logcollector.h	2012-08-12 08:08:53.706692797 +0200
@@ -60,6 +60,13 @@
 /* read multi line logs. */
 void *read_multiline(int pos, int *rc, int drop_it);
 
+/* read mod_security audit logs. */
+void *read_modsec_audit(int pos, int *rc, int drop_it);
+
+/* read regex delimited logs. */
+int read_regex_init(int i);
+void *read_regex(int pos, int *rc, int drop_it);
+
 /* Read DJB multilog format */
 /* Initializes multilog. */
 int init_djbmultilog(int pos);
diff -urN ossec-hids-2.6.orig/src/logcollector/Makefile ossec-hids-2.6/src/logcollector/Makefile
--- ossec-hids-2.6.orig/src/logcollector/Makefile	2011-07-11 21:36:58.000000000 +0200
+++ ossec-hids-2.6/src/logcollector/Makefile	2012-08-12 11:01:29.600294028 +0200
@@ -8,12 +8,18 @@
 include ../Config.Make
 
 
-logr_OBJS = *.c  ${OS_CONFIG} ${OS_SHARED} ${OS_XML} ${OS_REGEX} ${OS_NET} ${OS_CRYPTO} 
+logr_LIBS = ${OS_CONFIG} ${OS_SHARED} ${OS_XML} ${OS_REGEX} ${OS_NET} ${OS_CRYPTO} 
+logr_OBJS = *.c
 
 logcollector:
-		${CC} ${CFLAGS} ${OS_LINK} -DARGV0=\"${NAME}\" ${logr_OBJS} -o ${NAME}
+		${CC} ${CFLAGS} ${OS_LINK} -DARGV0=\"${NAME}\" ${logr_OBJS} ${logr_LIBS} -o ${NAME}
+
+test:
+		${CC} ${CFLAGS} read_linux_audit.c ${OS_LINK} ${logr_LIBS} -DBUILD_TEST_BINARY -o read_linux_audit
 
 clean:
 		${CLEAN}
+		rm -f test_linux_audit
+
 build:
 		${BUILD}
diff -urN ossec-hids-2.6.orig/src/logcollector/read_linux_audit.c ossec-hids-2.6/src/logcollector/read_linux_audit.c
--- ossec-hids-2.6.orig/src/logcollector/read_linux_audit.c	1970-01-01 01:00:00.000000000 +0100
+++ ossec-hids-2.6/src/logcollector/read_linux_audit.c	2012-08-12 11:55:12.264655681 +0200
@@ -0,0 +1,316 @@
+/* @(#) $Id$ */
+
+/* Copyright (C) 2010 Trend Micro Inc.
+ * All right reserved.
+ *
+ * This program is a free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General Public
+ * License (version 2) as published by the FSF - Free Software
+ * Foundation
+ */
+
+/* Read the Linux audit log files */
+
+#ifndef WIN32
+
+#include "shared.h"
+#include "logcollector.h"
+
+#ifdef BUILD_TEST_BINARY
+// #define SendMSG(q, b, f, Q)	printf("%s\n", b)
+#define SendMSG(q, b, f, Q)	1
+#define debug1(...)		{};
+#define debug2(...)		{};
+#define merror			printf
+#define ErrorExit(a,b,c)	exit(1)
+#undef ARGV0
+#define ARGV0			"test"
+#undef os_calloc
+#define os_calloc(n, s, p)	{ p = calloc(n, s); }
+#define TEST_LOG		"test_audit.log"
+#define MAX_COPY_LINES		20
+#endif /* BUILD_TEST_BINARY */
+
+typedef struct _log_record {
+    long lrid;
+    int is_timeout; // is counter timeout or window
+    int counter;
+    char buffer[OS_MAXSTR+1];
+} log_record;
+
+typedef struct _linux_audit_data {
+    OSList *log_records;
+} linux_audit_data;
+
+void _decrement_every_timeout_or_window(int pos)
+{
+    linux_audit_data *lad = (linux_audit_data *)(logff[pos].private_data);
+
+    OSListNode *n = OSList_GetFirstNode(lad->log_records);
+
+    while (n) {
+
+        log_record *lr = (log_record *)n->data;
+        lr->counter--;
+
+        n = OSList_GetNextNode(lad->log_records);
+    }
+}
+
+void _send_msg(int pos, log_record *lr)
+{
+    if(SendMSG(logr_queue, lr->buffer, logff[pos].file, LOCALFILE_MQ) < 0)
+    {
+        merror(QUEUE_SEND, ARGV0);
+        if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0)
+        {
+            ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
+        }
+    }
+}
+
+void _send_expired_items(int pos)
+{
+    linux_audit_data *lad = (linux_audit_data *)(logff[pos].private_data);
+
+    OSListNode *n = OSList_GetFirstNode(lad->log_records);
+
+    while (n) {
+
+        log_record *lr = (log_record *)n->data;
+
+        if (lr->counter == 0) {
+
+            _send_msg(pos, lr);
+            os_free(lr);
+            OSList_DeleteThisNode(lad->log_records, n);
+            n = OSList_GetCurrentlyNode(lad->log_records);
+        } else
+            n = OSList_GetNextNode(lad->log_records);
+    }
+}
+
+log_record *_get_or_create_lr_by_id(int pos, long lrid)
+{
+    linux_audit_data *lad = (linux_audit_data *)(logff[pos].private_data);
+    log_record *lr;
+
+    OSListNode *n = OSList_GetFirstNode(lad->log_records);
+
+    while (n) {
+
+        lr = (log_record *)n->data;
+
+        if (lr->lrid == lrid)
+            return lr;
+
+        n = OSList_GetNextNode(lad->log_records);
+    }
+
+    os_calloc(1, sizeof(log_record), lr);
+
+    lr->lrid = lrid;
+
+    // Just in case...
+    lr->buffer[0] = '\0';
+    lr->buffer[OS_MAXSTR] = '\0';
+
+    lr->is_timeout = (logff[pos].timeout != 0);
+    if (lr->is_timeout)
+        lr->counter = logff[pos].timeout;
+    else
+        lr->counter = logff[pos].window;
+
+    if (OSList_AddData(lad->log_records, lr) != 1)
+        // Fail miserably
+        exit(1);
+
+    return lr;
+}
+
+int read_linux_audit_init(int i)
+{
+    os_calloc(1, sizeof(linux_audit_data), logff[i].private_data);
+
+    linux_audit_data *lad = (linux_audit_data *)(logff[i].private_data);
+
+    if ((lad->log_records = OSList_Create()) == NULL)
+	exit(1);
+    
+
+    return 1;
+}
+
+/* Read Linux audit log file. */
+void *read_linux_audit(int pos, int *rc, int drop_it)
+{
+    int __ms = 0;
+    int buffer_size = 0;
+    char *p;
+    char str[OS_MAXSTR + 1];
+    str[OS_MAXSTR]= '\0';
+
+    fpos_t fp_pos;
+
+    *rc = 0;
+
+    // Start by decrementing all window/timeout values
+    _decrement_every_timeout_or_window(pos);
+
+    /* Getting initial file location */
+    fgetpos(logff[pos].fp, &fp_pos);
+
+    while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL)
+    {
+
+        /* Getting the last occurence of \n */
+        if ((p = strrchr(str, '\n')) != NULL) 
+        {
+            *p = '\0';
+        }
+
+        /* If we didn't get the new line, because the
+         * size is large, send what we got so far.
+         */
+        else if(strlen(str) >= (OS_MAXSTR - OS_LOG_HEADER - 2))
+        {
+            /* Message size > maximum allowed */
+            __ms = 1;
+        }
+        else
+        {
+            /* Message not complete. Return. */
+            debug1("%s: Message not complete. Trying again: '%s'", ARGV0,str);
+            fsetpos(logff[pos].fp, &fp_pos);
+            break;
+        }    
+
+        debug2("%s: DEBUG: Reading message: '%s'", ARGV0, str);
+        
+        // Extract log record ID.
+        // Search for first occurence of :, after that, up to the closing
+        // bracket is the ID.
+        char *s;
+        if ((s = strchr(str, ':')) == NULL) {
+            merror("%s: Ignoring line with no record ID: '%s'", ARGV0, str);
+            continue;
+        }
+
+        int lrid = atoi(++s);
+        if (lrid == 0) {
+            merror("%s: Ignoring line with no record ID: '%s'", ARGV0, str);
+            continue;
+        }
+
+	log_record *lr = _get_or_create_lr_by_id(pos, lrid);
+        if (lr == NULL) {
+            merror("%s: Unknown error: '%s'", ARGV0, str);
+            continue;
+        }
+
+        // We touched the record, refresh timeout if used...
+        if (lr->is_timeout)
+            lr->counter = logff[pos].timeout;
+
+        /* Adding to buffer. */
+        buffer_size = strlen(lr->buffer);
+        if(lr->buffer[0] != '\0')
+        {
+            // Convert NULL to space, we are not using strcat...
+            lr->buffer[buffer_size] = ' ';
+            buffer_size++;
+        }
+
+        // We don't treat specially buffer overflow but count on being
+        // properly handled as a side effect of regular processing (sic!)
+        strncpy(lr->buffer + buffer_size, str, OS_MAXSTR - buffer_size -2);
+
+        /* Incorrectly message size */
+        if(__ms)
+        {
+
+            merror("%s: Large message size: '%s'", ARGV0, str);
+            while(fgets(str, OS_MAXSTR - 2, logff[pos].fp) != NULL)
+            {
+                /* Getting the last occurence of \n */
+                if ((p = strrchr(str, '\n')) != NULL)
+                {
+                    break;
+                }
+            }
+            __ms = 0;
+        }
+        
+        fgetpos(logff[pos].fp, &fp_pos);
+    }
+
+    // Now look for all log records that have zero in counter and send them
+    // to the central location
+    if(drop_it == 0)
+        _send_expired_items(pos);
+
+    return(NULL); 
+}
+
+#ifdef BUILD_TEST_BINARY
+int main(int argc, char **argv)
+{
+    FILE *inf, *outf;
+    char buffer[OS_MAXSTR+1];
+    int timeout = 0, window = 0;
+
+    int rc;
+
+    if (argc != 4) {
+        fprintf(stderr, "Usage: %s timeout window <audit log file>\n", argv[0]);
+        return 1;
+    }
+
+    timeout = atoi(argv[1]);
+    window = atoi(argv[2]);
+
+    if ((inf = fopen(argv[3], "r")) == NULL) {
+        perror("fopen");
+        return 1;
+    }
+
+    if ((outf = fopen(TEST_LOG, "w")) == NULL) {
+        perror("fopen");
+        return 1;
+    }
+
+    os_calloc(1, sizeof(logreader), logff);
+
+    logff[0].file = TEST_LOG;
+    logff[0].fp = fopen(logff[0].file, "r");
+    logff[0].timeout = timeout;
+    logff[0].window = window;
+
+    read_linux_audit_init(0);
+    while (!feof(inf)) {
+
+        // First, copy a random number of lines from real log to test log
+        int n = rand() % MAX_COPY_LINES;
+        while(n-- > 0 && fgets(buffer, OS_MAXSTR, inf) != NULL)
+             fputs(buffer, outf);
+
+        // Now call routine to be tested
+        read_linux_audit(0, &rc, 0);
+
+//	sleep(1);
+    }
+
+    // To flush what's left waiting...
+    while (timeout > 0 && window > 0) {
+        if (timeout > 0) timeout--;
+        if (window > 0) window--;
+        read_linux_audit(0, &rc, 0);
+    }
+    
+    return 0;
+}
+#endif /* BUILD_TEST_BINARY */
+
+#endif /* !WIN32 */
+
+/* EOF */
diff -urN ossec-hids-2.6.orig/src/logcollector/read_modsec_audit.c ossec-hids-2.6/src/logcollector/read_modsec_audit.c
--- ossec-hids-2.6.orig/src/logcollector/read_modsec_audit.c	1970-01-01 01:00:00.000000000 +0100
+++ ossec-hids-2.6/src/logcollector/read_modsec_audit.c	2012-08-12 06:09:10.922969196 +0200
@@ -0,0 +1,158 @@
+/* @(#) $Id$ */
+
+/* Copyright (C) 2010 Trend Micro Inc.
+ * All right reserved.
+ *
+ * This program is a free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General Public
+ * License (version 2) as published by the FSF - Free Software
+ * Foundation
+ */
+
+/* Read the syslog */
+
+
+#include "shared.h"
+#include "logcollector.h"
+
+
+
+/* Read multiline logs. */
+void *read_modsec_audit(int pos, int *rc, int drop_it)
+{
+    int __ms = 0, __bs = 0;
+    int buffer_size = 0;
+    char *p;
+    char str[OS_MAXSTR + 1];
+    char buffer[OS_MAXSTR +1];
+
+    fpos_t fp_pos;
+
+    buffer[0] = '\0';
+    buffer[OS_MAXSTR] = '\0';
+    str[OS_MAXSTR]= '\0';
+    *rc = 0;
+
+    int in_block = 0;
+
+    /* Getting initial file location */
+    fgetpos(logff[pos].fp, &fp_pos);
+
+    while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL)
+    {
+
+        /* Getting the last occurence of \n */
+        if ((p = strrchr(str, '\n')) != NULL) 
+        {
+            *p = '\0';
+        }
+ 
+        /* If we didn't get the new line, because the
+         * size is large, send what we got so far.
+         */
+        else if(strlen(str) >= (OS_MAXSTR - OS_LOG_HEADER - 2))
+        {
+            /* Message size > maximum allowed */
+            __ms = 1;
+        }
+        else
+        {
+            /* Message not complete. Return. */
+            debug1("%s: Message not complete. Trying again: '%s'", ARGV0,str);
+            fsetpos(logff[pos].fp, &fp_pos);
+            break;
+        }    
+        
+        #ifdef WIN32
+        if ((p = strrchr(str, '\r')) != NULL)
+        {
+            *p = '\0';
+        }
+        #endif
+                      
+        debug2("%s: DEBUG: Reading message: '%s'", ARGV0, str);
+
+        // See if the line has the following form: --62a78a12-A--
+        // If so, than it is a start marker.
+        if (in_block == 0) {
+
+            if (str[0] == '-' && str[1] == '-' && isxdigit(str[2])
+                    && isxdigit(str[3]) && isxdigit(str[4])
+                    && isxdigit(str[5]) && isxdigit(str[6])
+                    && isxdigit(str[7]) && isxdigit(str[8])
+                    && isxdigit(str[9]) && str[10] == '-'
+                    && str[11] == 'A' && str[12] == '-'
+                    && str[13] == '-' && str[14] == '\n')
+                in_block = 1;
+            continue;
+        }
+
+        /* Adding to buffer. */
+        buffer_size = strlen(buffer);
+        if(buffer[0] != '\0')
+        {
+            buffer[buffer_size] = ' ';
+            buffer_size++;
+        }
+
+        if (buffer_size + strlen(str) > OS_MAXSTR - OS_LOG_HEADER - 2)
+            __bs = 1;
+        else
+            strncpy(buffer + buffer_size, str, OS_MAXSTR - buffer_size -2);
+
+        // If we don't have yet an end of the message and maximum size wasn't
+        // exceeded then go to the next line.
+        if (!__ms && !__bs &&
+            (str[0] != '-' || str[1] != '-' || !isxdigit(str[2])
+                    || !isxdigit(str[3]) || !isxdigit(str[4])
+                    || !isxdigit(str[5]) || !isxdigit(str[6])
+                    || !isxdigit(str[7]) || !isxdigit(str[8])
+                    || !isxdigit(str[9]) || str[10] != '-'
+                    || str[11] != 'Z' || str[12] != '-'
+                    || str[13] != '-' || str[14] != '\n'))
+            continue;
+
+        in_block = 0;
+
+        /* Sending message to queue */
+        if(drop_it == 0)
+        {
+            if(SendMSG(logr_queue, buffer, logff[pos].file,
+                        LOCALFILE_MQ) < 0)
+            {
+                merror(QUEUE_SEND, ARGV0);
+                if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0)
+                {
+                    ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
+                }
+            }
+        }
+
+        buffer[0] = '\0';
+
+        /* Incorrectly message size */
+        if(__ms || __bs)
+        {
+            merror("%s: Large message size: '%s'", ARGV0, str);
+
+            // The following isn't used if buffer size was exceeded. Upon return
+            // to this function we'll anyway discard anything that isn't a start
+            // marker.
+            while(__ms && fgets(str, OS_MAXSTR - 2, logff[pos].fp) != NULL)
+            {
+                /* Getting the last occurence of \n */
+                if ((p = strrchr(str, '\n')) != NULL)
+                {
+                    break;
+                }
+            }
+        }
+        
+        fgetpos(logff[pos].fp, &fp_pos);
+        continue;
+    }
+
+    return(NULL); 
+}
+
+/* EOF */
diff -urN ossec-hids-2.6.orig/src/logcollector/read_multiline.c ossec-hids-2.6/src/logcollector/read_multiline.c
--- ossec-hids-2.6.orig/src/logcollector/read_multiline.c	2011-07-11 21:36:58.000000000 +0200
+++ ossec-hids-2.6/src/logcollector/read_multiline.c	2012-08-12 07:26:00.339628138 +0200
@@ -21,7 +21,6 @@
 void *read_multiline(int pos, int *rc, int drop_it)
 {
     int __ms = 0;
-    int linecount;
     int linesgot = 0;
     int buffer_size = 0;
     char *p;
@@ -35,8 +34,6 @@
     str[OS_MAXSTR]= '\0';
     *rc = 0;
 
-    linecount = atoi(logff[pos].logformat);
-
     /* Getting initial file location */
     fgetpos(logff[pos].fp, &fp_pos);
 
@@ -86,13 +83,11 @@
 
         strncpy(buffer + buffer_size, str, OS_MAXSTR - buffer_size -2);
 
-        
-        if(linesgot < linecount)
+        if(linesgot < logff[pos].lines)
         {
             continue;
         }
                       
-
         /* Sending message to queue */
         if(drop_it == 0)
         {
diff -urN ossec-hids-2.6.orig/src/logcollector/read_mysql_log.c ossec-hids-2.6/src/logcollector/read_mysql_log.c
--- ossec-hids-2.6.orig/src/logcollector/read_mysql_log.c	2011-07-11 21:36:58.000000000 +0200
+++ ossec-hids-2.6/src/logcollector/read_mysql_log.c	2012-08-12 06:10:25.420792544 +0200
@@ -24,7 +24,7 @@
 
 
 
-/* Read syslog files/snort fast/apache files */
+/* Read mysql log */
 void *read_mysql_log(int pos, int *rc, int drop_it)
 {
     int str_len = 0;
diff -urN ossec-hids-2.6.orig/src/logcollector/read_regex.c ossec-hids-2.6/src/logcollector/read_regex.c
--- ossec-hids-2.6.orig/src/logcollector/read_regex.c	1970-01-01 01:00:00.000000000 +0100
+++ ossec-hids-2.6/src/logcollector/read_regex.c	2012-08-12 09:24:08.101733650 +0200
@@ -0,0 +1,171 @@
+/* @(#) $Id$ */
+
+/* Copyright (C) 2010 Trend Micro Inc.
+ * All right reserved.
+ *
+ * This program is a free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General Public
+ * License (version 2) as published by the FSF - Free Software
+ * Foundation
+ */
+
+/* Read the syslog */
+
+
+#include "shared.h"
+#include "logcollector.h"
+
+typedef struct _runtime_data {
+    OSRegex start, end;
+} runtime_data;
+
+int read_regex_init(int i)
+{
+    runtime_data *rd;
+
+    os_calloc(1, sizeof(runtime_data), rd);
+
+    if (!OSRegex_Compile(logff[i].start_regex, &(rd->start), 0)) {
+        debug1("%s: Error in start regex. Giving up from this log source.", ARGV0);
+        os_free(rd);
+        return 0;
+    }
+
+    if (logff[i].end_regex && !OSRegex_Compile(logff[i].start_regex, &(rd->start), 0)) {
+        debug1("%s: Error in end regex. Giving up from this log source.", ARGV0);
+        OSRegex_FreePattern(&(rd->start));
+        os_free(rd);
+        return 0;
+    }
+
+    return 1;
+}
+
+/* Read multiline logs. */
+void *read_regex(int pos, int *rc, int drop_it)
+{
+    int __ms = 0, __bs = 0;
+    int buffer_size = 0;
+    char *p;
+    char str[OS_MAXSTR + 1];
+    char buffer[OS_MAXSTR +1];
+
+    fpos_t fp_pos;
+
+    buffer[0] = '\0';
+    buffer[OS_MAXSTR] = '\0';
+    str[OS_MAXSTR]= '\0';
+    *rc = 0;
+
+    int in_block = 0;
+
+    runtime_data *rd = (runtime_data *)logff[pos].private_data;
+
+    /* Getting initial file location */
+    fgetpos(logff[pos].fp, &fp_pos);
+
+    while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL)
+    {
+
+        /* Getting the last occurence of \n */
+        if ((p = strrchr(str, '\n')) != NULL) 
+        {
+            *p = '\0';
+        }
+ 
+        /* If we didn't get the new line, because the
+         * size is large, send what we got so far.
+         */
+        else if(strlen(str) >= (OS_MAXSTR - OS_LOG_HEADER - 2))
+        {
+            /* Message size > maximum allowed */
+            __ms = 1;
+        }
+        else
+        {
+            /* Message not complete. Return. */
+            debug1("%s: Message not complete. Trying again: '%s'", ARGV0,str);
+            fsetpos(logff[pos].fp, &fp_pos);
+            break;
+        }    
+        
+        #ifdef WIN32
+        if ((p = strrchr(str, '\r')) != NULL)
+        {
+            *p = '\0';
+        }
+        #endif
+                      
+        debug2("%s: DEBUG: Reading message: '%s'", ARGV0, str);
+
+        // Check if starting regex matches...
+        if (in_block == 0) {
+            if (OSRegex_Execute(str, &(rd->start)))
+                in_block = 1;
+            continue;
+        }
+
+        /* Adding to buffer. */
+        buffer_size = strlen(buffer);
+        if(buffer[0] != '\0')
+        {
+            buffer[buffer_size] = ' ';
+            buffer_size++;
+        }
+
+        if (buffer_size + strlen(str) > OS_MAXSTR - OS_LOG_HEADER - 2)
+            __bs = 1;
+        else
+            strncpy(buffer + buffer_size, str, OS_MAXSTR - buffer_size -2);
+
+        // If we don't have yet an end of the message and maximum size wasn't
+        // exceeded then go to the next line.
+        if (!__ms && !__bs &&
+            (!(logff[pos].end_regex != NULL && OSRegex_Execute(str, &(rd->end))) ||
+             !(logff[pos].end_regex == NULL && OSRegex_Execute(str, &(rd->start)))))
+            continue;
+
+        in_block = 0;
+
+        /* Sending message to queue */
+        if(drop_it == 0)
+        {
+            if(SendMSG(logr_queue, buffer, logff[pos].file,
+                        LOCALFILE_MQ) < 0)
+            {
+                merror(QUEUE_SEND, ARGV0);
+                if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0)
+                {
+                    ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
+                }
+            }
+        }
+
+        buffer[0] = '\0';
+
+        /* Incorrectly message size */
+        if(__ms || __bs)
+        {
+            merror("%s: Large message size: '%s'", ARGV0, str);
+
+            // The following isn't used if buffer size was exceeded. Upon return
+            // to this function we'll anyway discard anything that isn't a start
+            // marker.
+            while(__ms && fgets(str, OS_MAXSTR - 2, logff[pos].fp) != NULL)
+            {
+                /* Getting the last occurence of \n */
+                if ((p = strrchr(str, '\n')) != NULL)
+                {
+                    break;
+                }
+            }
+        }
+        
+        fgetpos(logff[pos].fp, &fp_pos);
+        continue;
+    }
+
+    return(NULL); 
+}
+
+/* EOF */
