/*---[ parse.c ]------------------------------------------------------
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * The text file parse functions.
 * TODO: Maybe rewrite using GStrings and properly modular functions.
 *
 * Based on firestarter code by Tomas Junnonen (majix@sci.fi)
 *--------------------------------------------------------------------*/

#include "razorback.h"
#include "parse.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

// Remove trailing newline and whitespace.
void chomp (char *string)
{
	char * pointer=0;

	pointer=&string[strlen(string)-1];
	while(pointer >= string)
	{
		if(*pointer==' ' || *pointer=='	' || *pointer==10)
		{
			*pointer='\0';
		} else {
			break;
		}
		pointer--;
	}
}


/* [ get_text_between ]
 * Give a string and two text markers in the string the function returns the
 * text between the markers.
 */
void
get_text_between (const char *string, const char *marker1, const char *marker2, char *result)
{
	char *start,*end;

	start = strstr (string, marker1);
	if(start == NULL) { return; }
	start += strlen(marker1);
	end = strstr (start, marker2);
	if(end == NULL) { return; }

	if(end-start > 0)
	{
		strncpy(result,start,end-start);
		result[end-start]='\0';
	}
	else
		strcpy(result,"");
	
}

/* [ parse_hit_log ]
 * Parses *line. Extracts port, remoteip, service, time and protocol
 */
int
parse_hit_log (char *line)
{
	char buffer[512];
	char *bufferpointer, *bufferpointer2;
	gchar *olddata[3];
	char data[8][512];
	char proto[512];
	static char time[512], port[512], ip[512];
	static int datakey = 1;

	strncpy(data[0],line, 12);
	data[0][12]='\0';

	if ( (bufferpointer = (char *)strstr (line, "snort")) == (char *)NULL )
		return FALSE;

	bufferpointer = strstr (bufferpointer, ":");
	if (bufferpointer == NULL)
		return FALSE;

	if(strstr(bufferpointer,"Classification") == NULL)
	{
		// Old snort log format
		get_text_between (bufferpointer, ":", ":",data[1]);

		bufferpointer2=strstr(bufferpointer, "->");
		if(bufferpointer2 == NULL)
		{
			// Must a descriptive event. Grab the source IP first.
			bufferpointer2=strstr(bufferpointer,"from");
			if(bufferpointer2 == NULL)
			{
				// Hmm.. no from. Make it up.
				strcpy(data[4],"Unknown");
				strcpy(data[5],"Unknown");
				strcpy(data[6],"Unknown");
				strcpy(data[7],"Unknown");
			} else {
				// Grab the data between the spaces.
				//get_text_between(bufferpointer2," "," ",buffer3);
				get_text_between(bufferpointer2," "," ",buffer);

				// Trim off the tail colon if it is there.
				bufferpointer2 = buffer + strlen(buffer) - 1;
				if(!strncmp(bufferpointer2,":",1))
				{
					// Get rid of that colon.
					strncpy(data[4],buffer,strlen(buffer)-1);
					data[4][strlen(buffer)-1]='\0';
					strcpy(data[5],"Unknown");
					strcpy(data[6],"Unknown");
					strcpy(data[7],"Unknown");
				} else {
					strcpy(data[4],buffer);
					strcpy(data[5],"Unknown");
					strcpy(data[6],"Unknown");
					strcpy(data[7],"Unknown");
				}
			}
		} else {
			bufferpointer=strstr(bufferpointer," ");
			if(bufferpointer == NULL) return(FALSE);
			bufferpointer=strstr(bufferpointer,": ");
			if(bufferpointer == NULL) return(FALSE);

			get_text_between(bufferpointer,": "," ->",buffer);
			bufferpointer2=strstr(buffer,":");
			if(bufferpointer2 == NULL)
			{
				// No port number
				strcpy(data[6],"?");
				strcpy(data[4],buffer);
				chomp(data[4]);
				chomp(data[6]);
			} else {
				bufferpointer2++;
				strcpy(data[6],bufferpointer2);
				strncpy(data[4],buffer,bufferpointer2-buffer-1);
				data[4][bufferpointer2-buffer-1]='\0';
				chomp(data[4]);
				chomp(data[6]);
			}
			bufferpointer=strstr(bufferpointer,"->");
			if(bufferpointer==NULL) { return(FALSE); }
			bufferpointer+=3;
			bufferpointer2=strstr(bufferpointer,":");
			if(bufferpointer2 == NULL)
			{
				// No port number
				strcpy(data[7],"?");
				strcpy(data[5],bufferpointer);
				chomp(data[5]);
				chomp(data[7]);
			} else {
				bufferpointer2++;
				strcpy(data[7],bufferpointer2);
				// Get rid of any nasty end characters.
				chomp(data[7]);
				get_text_between(bufferpointer,"",":",data[5]);
				chomp(data[5]);
			}
		}
	} else {
	
		// 1.8 format is:
		// snort[blah]: Text [x:xxx:x]TAB Moretext [Classification: Something or otherTAB TAB  Priority: x]: 999.999.999.999 -> 888.888.888.888
		// snort[blah]: Text [x:xxx:x] Moretext [Classification: Something or other  Priority: x]: 999.999.999.999:xxx -> 888.888.888.888:xxx
		// eg:
		// Jun 27 16:41:48 server snort[3313]: [1:620:1]  SCAN Proxy attempt [Classification: Attempted Information Leak   Priority: 3]: 142.1.98.999:33262 -> 160.230.150.870:8080
		// Jun 27 17:34:08 server snort[3563]: MISC Large ICMP Packet [1:499:1]  [Classification: Potentially Bad Traffic   Priority: 2]: 142.1.98.888 -> 142.1.69.225 
		// Thus: information 1 = to first tab
		//       information 2 = from first tab to [
		//       classification = [ to tab
		//       (skip tab,spaces)
		//	 priority = priority: to ]
		//	 ip/port is : to ->
		//	 ip/port is -> to end
	
	
		get_text_between(bufferpointer,": ","[",data[1]);
	
		bufferpointer=strstr(bufferpointer,"]");
		if(bufferpointer==NULL) { return(FALSE); }
		get_text_between(bufferpointer,"]","[",buffer);
		bufferpointer2=buffer;
		while(*bufferpointer2==' ') { bufferpointer2++; }
		if(strlen(bufferpointer2)) {

			strcat(data[1],bufferpointer2);
		}
	
		get_text_between(bufferpointer,"[Classification: ","  Priority:",data[2]);
		data[2][strlen(data[2])-2] = '\0';

	
		bufferpointer=strstr(bufferpointer,"Priority:");
		if(bufferpointer==NULL) { return(FALSE); }
		get_text_between(bufferpointer,"Priority: ","]",data[3]);
		bufferpointer=strstr(bufferpointer,"]:");
		if(bufferpointer==NULL) { return(FALSE); }
		bufferpointer+=2;
	
		// IP/Port
		get_text_between(bufferpointer," "," ->",buffer);
		bufferpointer2=strstr(buffer,":");
		if(bufferpointer2 == NULL)
		{
			// No port number
			strcpy(data[6],"?");
			strcpy(data[4],buffer);
		} else {
			bufferpointer2++;
			strcpy(data[6],bufferpointer2);
			get_text_between(buffer,"",":",data[4]);
		}
		bufferpointer=strstr(bufferpointer,"->");
		if(bufferpointer==NULL) { return(FALSE); }
		bufferpointer+=3;
	
		bufferpointer2=strstr(bufferpointer,":");
		if(bufferpointer2 == NULL)
		{
			// No port number
			strcpy(data[7],"?");
			strcpy(data[5],bufferpointer);
			data[5][strlen(data[5])-2]='\0';;
		} else {
			bufferpointer2++;
			strcpy(data[7],bufferpointer2);
			data[7][strlen(data[7])-1]='\0';
			strncpy(data[5],bufferpointer,bufferpointer2-bufferpointer-1); //strlen(bufferpointer)-strlen(bufferpointer2)-1);
			data[5][bufferpointer2-bufferpointer-1]='\0';
		}
	
		/* Reset datakey if the clist is empty */
		if (!gtk_clist_get_text (GTK_CLIST (hitlogclist), 0, 0, NULL))
		datakey = 1;
	
	
		/* Remove identical lines */
		if (gnome_config_get_bool ("/razorback/Program/removedups=TRUE")) {
			if ((time != NULL) && (!strcmp (time, data[0]))) {
				if (!strcmp (port, data[5]))
					if (!strcmp (ip, data[4]))
						return FALSE;
			}
			strcpy(time,data[0]);
			strcpy(port,data[5]);
			strcpy(ip,data[4]);
		}

	}

	// For the moment, to get things working, shove some of the new data into the old format.
	olddata[0]=g_strdup(data[0]);
	olddata[1]=g_strdup(data[1]);
	olddata[2]=g_strdup_printf("%s:%s -> %s:%s",data[4],data[6],data[5],data[7]);
	
	gtk_clist_append (GTK_CLIST (hitlogclist), olddata);

	g_free(olddata[0]);
	g_free(olddata[1]);
	g_free(olddata[2]);

	{
		char datakeystring[10];
		sprintf(datakeystring,"%d",datakey);
		gtk_object_set_data (GTK_OBJECT (hitlogclist),
			     datakeystring, proto);
		gtk_object_set_data (GTK_OBJECT (hitlogclist),
			     "keys", GINT_TO_POINTER (datakey));
	}

	++datakey;

	return TRUE;
}
