/******************************************************************************
* $Id: lstringhack.c,v 1.10 2005/09/25 11:55:53 gareuselesinge Exp $
* This file is part of FreePOPs (http://www.freepops.org) *
* This file is distributed under the terms of GNU GPL license. *
******************************************************************************/
/******************************************************************************
* File description:
* some hacks
* Notes:
*
* Authors:
* Name <gareuselesinge@users.sourceforge.net>
******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#if defined(BEOS)
# include <bsd_mem.h>
#endif
#ifdef __sun
# include <strings.h>
#endif
#include "lstringhack.h"
#include "regularexp.h"
#include "win32_compatibility.h"
#include "log.h"
#define LOG_ZONE "STRINGHACK"
struct strhack_t
{
int header_done;
long int current_lines;
char last3[4];
char last4[4];
// char* to_free_top;
// char* to_free_dot;
};
struct strhack_t* new_str_hack()
{
struct strhack_t* tmp;
tmp = malloc(sizeof(struct strhack_t));
MALLOC_CHECK(tmp);
tmp->header_done = 0;
tmp->current_lines = 0;
memset(tmp->last3,'\0',4);
memset(tmp->last4,'\0',4);
//tmp->to_free_top = NULL;
//tmp->to_free_dot = NULL;
return tmp ;
}
void delete_str_hack(struct strhack_t* x)
{
//free(x->to_free_top);
//free(x->to_free_dot);
free(x);
}
/*! gets a string, plus a static buffer char last [4]
* and return a buffer with all the \n\r.\n replaced
* with \n\r..\n even if fragmented between two subsequest
* calls. buff must be dynamic memory, and the result should be free
* by the client, while buff is eventually freed by this function.
*
*/
char * dothack(struct strhack_t*a,const char *buff)
{
char defrag[7];
int p;
int n;
char* rc;
char* last = a->last4;
if(buff == NULL)
return NULL;
//buff = strdup(buff);
memset(defrag,'\0',7);
strcpy(defrag,last);
strncpy(&defrag[strlen(last)],buff,3);
defrag[strlen(last)+3]='\0';
p = regfind_start(defrag,"\r\n\\.\r");
if(p != -1)
{
//fragmented!
char* idx;
int d;
//printf("!!FRAG ->%s<-!!\n",defrag);
idx = index(defrag,'.');
if(idx == NULL)
{
//printf("!!ERROR\n");
ERROR_PRINT("not a '.'\n");
}
d = idx - defrag;
//printf("!!d=%d\n",d);
switch(d)
{
case 0:
case 1:
case 5:
//printf("!!skip\n");
break;
case 2:
case 3:
case 4:
{
char * rc = calloc(strlen(buff)+ 2,sizeof(char));
memcpy(rc,&("\n.."[4-d]),d);
strcpy(&rc[d-1],&buff[d-2]);
//free(buff);
buff = (const char*)rc;
/*
if (a->to_free_dot != NULL)
free(a->to_free_dot);
a->to_free_dot = buff;
*/
}
break;
default:
//printf("!!ERROR\n");
ERROR_PRINT("not in case!\n");
break;
}
}
n = regfind_count(buff,"\r\n\\.\r",1);
//printf("!!%d!!\n",n);
if(n>0)
{
int i,o;
int len = strlen(buff);
//int n1=n; //DELETE ME!!!!
rc = calloc(len + 1 + n,sizeof(char));
for(i=0,o=0;n>0;i++,o++)
{
//printf("!!comparing %s!!\n",&buff[i]);
if(!strncmp(&buff[i],"\r\n.\r",4))
{
memcpy(&rc[o],"\r\n..\r",5);
o+=5-2;
i+=4-2;
n--;
//printf("!!GOT!!\n");
}
else
{
rc[o] = buff[i];
}
}
if( i < len)
{
//printf("i=%d, o=%d, len_buff=%d, lenrc=%d\n",
// i,o, strlen(&buff[i]), len + 1 + n1);
strcpy(&rc[o],&buff[i]);
}
//free(buff);
// this if should be always true
/*
if (a->to_free_dot != NULL)
free(a->to_free_dot);
a->to_free_dot = rc;
*/
}
else
{
rc = (char *)buff;
}
memcpy(last,&rc[strlen(rc) - 3],4);
return rc;
}
// returned value is tmp
char *tophack(struct strhack_t *a,const char* tmp,int lines)
{
char* buff = NULL;
if(!a->header_done)
{
regmatch_t pm;
char defrag[7];
// build the defrag
memset(defrag,'\0',7);
strncat(defrag, a->last3,3);
strncat(defrag,tmp,3);
//DBG("DEFRAG='%s'\n",defrag);
//search first here
pm = regfind(defrag,"\r\n\r\n");
if(pm.begin == -1)
{
//not fragmented :)
//DBG("NOT FRAGMENTED!!\n");
//search for the end of header
pm = regfind(tmp,"\r\n\r\n");
if( pm.begin != -1)
{
a->header_done = 1;
a->current_lines =
regfind_count(&tmp[pm.end],"\r\n",0);
}
}
else
{
//DBG("!! FRAGMENTED !!\n");
// the end of the header tag is fragmented
a->header_done = 1;
a->current_lines = regfind_count(tmp,"\r\n",0);
// if ..R|NRN or .RN|RN. current_lines--
pm = regfind(defrag,"..\r\n\r\n");
if(pm.begin != -1)
a->current_lines--;
pm = regfind(defrag,".\r\n\r\n.");
if(pm.begin != -1)
a->current_lines--;
}
//save last3
snprintf(a->last3,
4,"%s",&tmp[strlen(tmp)-3]);
}
else
{
a->current_lines += regfind_count(tmp,"\r\n",0);
}
/* have we received more than needed? */
if (a->current_lines > lines || (lines == 0 && a->header_done))
{
int i;
int l,l_old;
/*
if (a->to_free_top != NULL)
free(a->to_free_top);
*/
buff = strdup(tmp);
/*a->to_free_top = tmp;*/
//DBG("cutting %ld\n",a->current_lines - lines);
l = l_old = strlen(buff) - 2;
if(lines == 0)
i = -1; // we have t oremove the blank line!
else
i = 0;
//return back from the end of
while( i <= a->current_lines - lines && l >= 0)
{
if(!strncmp(&buff[l],"\r\n",2))
{
i++;
l--; //skip 2 == strlen("\r\n")
//DBG("CUT %d\n$\n%s\n$\n",i,&buff[l]);
}
l--;
}
if(l>=0)
l+=2;
// fix it putting a \0
if(l>=0)
{
//DBG("(%d)cutting from here:\n$\n%s\n$\n",l,&tmp[l]);
if(l_old - l >= 3)
{
buff[l+2]='\0';
buff[l+1]='\n';
buff[l+0]='\r';
}
else if(l_old - l >= 1)
{
buff[l]='\0';
}
}
}
else
buff= (char *)tmp;
return buff;
}
int check_stop(struct strhack_t *a,int lines)
{
if (a->current_lines > lines || (lines == 0 && a->header_done))
return 1;
else
return 0;
}
int current_lines(struct strhack_t *a)
{
return a->current_lines;
}
syntax highlighted by Code2HTML, v. 0.9.1