/*
 *   strregrep - a regex based text replacing function for general purpose use
 *
 *   Copyright (C) 2003 A.L.Lambert
 *
 *   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, or (at your option)
 *   any later version.
 *
 *   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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


#include "includes.h"

/* our error handler */
void ipregex_resolv_err(short int status, short int func) {
	/* opps - couldn't even compile the regex - return error and optionally whine about it */
	char buffer[LSIZE];	/* where we place the error message */

	/* if we ain't in debug mode, why are we here?!?!?! */
	if(! cf.debug) return;
	
	/* go get us an error message */
	regerror(status, NULL, buffer, LSIZE);
	
	/* depending on what function created error (passed by calling prog), prefix error with text */
	if(func == 0) fprintf(stderr, "regex failure: ");
	if(func == 1) fprintf(stderr, "regcomp error: ");
	if(func == 2) fprintf(stderr, "regexec error: ");
	
	/* print out our error message */
	fprintf(stderr, "%s\n", buffer);
	return;
}

/* the main show */
int ipregex_resolv(char *string, long int stlen, short int recur) {
	long int i, j;			/* used for counters in loops */
	long int tmp_len;			/* temporairy string length storage */
	regex_t reg;			/* compiled regex variable */
	regmatch_t pmatch[1];		/* how many matches we got? */
	short int status;		/* return value of reg*(); */
	char *ptr;			/* a pointer for parsing */
	char *tmp_string;		/* a temp string storage space for parsing */
	char ip_regex[1024];		/* where we store the text for an IP search regex */
	char ip_addr[1024];		/* where we put the IP address as a string temporairly */

	strcpy(ip_regex, " ([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-5][0-5])\\.([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-5][0-5])\\.([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-5][0-5])\\.([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-5][0-5]) ");
	
	/* if we've been overly-recursive, get out of here without doing anything */
	if(recur == -1) return(-1);

	/* if we're in debug mode, tell the user the details of how we were called */
	if(cf.debug) fprintf(stderr, "ipregex_resolv(%s, %li, %i);\n", string, stlen, recur);

	/* make sure we can compile the patern - and if not return error */
	status = regcomp(&reg, ip_regex, REG_EXTENDED);
	if(status != 0)	{ ipregex_resolv_err(status, 1); return ERR; }
	
	/* malloc some space for our tmp_string */
	tmp_string = malloc(stlen);
	if(tmp_string == NULL) {
		perror("malloc");
		return ERR;
	}

	/* see if we have a match in the unprocessed part of string */
	status = regexec(&reg, string, (size_t) 1, pmatch, 0);
	if(status == REG_NOMATCH) {
		if(tmp_string != NULL) free(tmp_string);
		return 0;			/* we didn't match anything, return normally */
	}
	if(status != 0) { 
		ipregex_resolv_err(status, 2);
		if(tmp_string != NULL) free(tmp_string);
		return ERR;
	}	/* we mucked up, return error */
	
	/* recurse now instaed of later so we end up processing the line in reverse for matches */
	ptr = string;
	ptr = (ptr + pmatch[0].rm_eo);
	status = ipregex_resolv(ptr, (stlen - pmatch[0].rm_eo), (recur - 1));
	if(status == ERR) {
		if(tmp_string != NULL) free(tmp_string);
		return ERR;	/* if recursion returned error, back out of forest with error all the way */
	}
	
	/* copy off the first part of the string that doesn't match */
	for(i = 0; i < pmatch[0].rm_so ; ++i, ++j) {
		tmp_string[i] = string[i]; /* copy the character */
	}
	tmp_string[i] = '\0';	 	/* null terminate the tmp string */
	ptr = string;
	ptr = (ptr + pmatch[0].rm_so);
	sscanf(ptr, "%s", ip_addr);
	/* some quick sanity to make sure we're not about to overflow our tmp_string variable */
	tmp_len = (strlen(tmp_string) + strlen(tmp_string));
	if(tmp_len < stlen) { /* if the new length is shorter than possible length, then */
		strcat(tmp_string, " blahblah(");	/* add the 'new_text' text to buffer */
		strcat(tmp_string, ip_addr);	/* add the 'new_text' text to buffer */
		strcat(tmp_string, ") ");
	} else { /* new length is longer than possible length - we got a problem - error out */
		if(cf.debug) fprintf(stderr, "result (%li) too large for size of char *string (%li)\n", tmp_len, stlen);
		if(tmp_string != NULL) free(tmp_string);
		return ERR;
	}

	/* finish off adding the rest of the string to tmp_string */
	for(i = 0, j = strlen(tmp_string); string[i + pmatch[0].rm_eo] != '\0'; ++i, ++j) {
		if(j > stlen) {
			if(cf.debug) fprintf(stderr, "result too large for size of char *string[%li]\n", stlen);
			tmp_string[j] = '\0';	
			break;	/* just break out of here - we don't have to exit for this one - leave what's done done */
		}
		tmp_string[j] = string[i + pmatch[0].rm_eo];
	}
	tmp_string[j] = '\0';	/* null terminate always always always */
	
	/* put the tmp_string onto the end of string */
	strcpy(string, tmp_string);

	/* free our variables */
	if(tmp_string != NULL) free(tmp_string);
	regfree(&reg);
	return 0;	/* outta here */
}



syntax highlighted by Code2HTML, v. 0.9.1