8
8
routine by line-buffering up first.
10
10
12/11/2002: Corrected input buffer termination with fgets where the last line
11
of the input file does not terminate with a \n or \r.
11
of the input file does not terminate with a \n or \r.
13
13
27/09/2001: Added SGI specific compile time changes from char -> short
14
14
contributed by Don Lafontaine <lafont02@cn.ca>
23
23
#include "logger.h"
26
#define FFGET_VERSION "1.0.0.4"
27
#define FFGET_LASTUPDATED "29/03/2006"
29
#define FFGET_DNORMAL ((FFGET_debug >= _FFGET_DEBUG_NORMAL ))
30
#define FFGET_DPEDANTIC ((FFGET_debug >= _FFGET_DEBUG_PEDANTIC))
27
#define FL __FILE__,__LINE__
30
#define FFGET_VERSION "1.0.0.7"
31
#define FFGET_LASTUPDATED "200707091500"
33
#define FFGET_DNORMAL ((FFGET_debug >= FFGET_DEBUG_NORMAL ))
34
#define FFGET_DPEDANTIC ((FFGET_debug >= FFGET_DEBUG_PEDANTIC))
33
37
int ffget_linesize=0;
35
39
int FFGET_SDL_MODE = 0; // Single Char Delimeter
37
41
int FFGET_SDL_WATCH = 0; // Set if we want to watch for double-CR exploits
42
int FFGET_ALLOW_NUL = 0; // Dont Convert \0's to spaces.
39
44
int FFGET_debug = 0;
41
static char SDL_MODE_DELIMITS[]="\n\r";
42
static char NORM_MODE_DELIMITS[]="\n";
43
static char *DELIMITERS=SDL_MODE_DELIMITS;
46
char SDL_MODE_DELIMITS[]="\n\r";
47
char NORM_MODE_DELIMITS[]="\n";
48
char *DELIMITERS=SDL_MODE_DELIMITS;
45
50
/*------------------------------------------------------------------------
46
51
Procedure: FFGET_set_watch_SDL ID:1
58
63
return FFGET_SDL_WATCH;
66
/*-----------------------------------------------------------------\
67
Function Name : FFGET_set_allow_nul
74
--------------------------------------------------------------------
76
This tells the FFGET_raw() if it needs to remove \0's or not
77
in the data it reads. This was added so as to ensure that \0
78
sequences were preserved in form-data from WWW pages.
80
--------------------------------------------------------------------
82
Added 2004-Aug-09 by PLD.
84
\------------------------------------------------------------------*/
85
int FFGET_set_allow_nul(int level )
87
FFGET_ALLOW_NUL = level;
89
return FFGET_ALLOW_NUL;
62
92
/*------------------------------------------------------------------------
63
93
Procedure: FFGET_set_debug ID:1
105
block_pos = ftell(f->f);
106
bs = fread( f->buffer, 1, _FFGET_BUFFER_MAX -2, f->f );
108
if (bs < (_FFGET_BUFFER_MAX -2)) {
135
block_pos = ftell(f->f); /** Get our current read position so we can use it in FFGET_ftell if required **/
137
bs = fread( f->buffer, 1, FFGET_BUFFER_MAX -FFGET_BUFFER_PADDING, f->f );
139
if (bs < (FFGET_BUFFER_MAX -FFGET_BUFFER_PADDING))
114
fprintf(stderr,"%s:%d: WARNING - File read failed with error:%s",__FILE__,__LINE__,strerror(errno));
147
LOGGER_log("%s:%d:FFGET_getnewblock:ERROR: File read failed with error:%s", FL, strerror(errno));
121
155
// If we read in some data, then adjust the buffer to deal with it
123
// First we set the start point back to the start of the buffer,
124
// then we set the end point to be the start +datasize we read, -1
125
// then we adjust the total bytes read (for the sake of record keeping
126
// though it has no /real/ purpose)
157
// First we set the start point back to the start of the buffer,
158
// then we set the end point to be the start +datasize we read, -1
159
// then we adjust the total bytes read (for the sake of record keeping
160
// though it has no /real/ purpose)
129
f->last_block_read_from = block_pos;
163
f->buffer[bs] = '\0'; //20040208-1703:PLD:JS
164
f->last_block_read_from = block_pos; // 200607150941:PLD
130
165
f->startpoint = f->buffer;
131
166
f->endpoint = f->startpoint +bs -1;
134
169
// Check the buffer for poisioning \0's
135
// As these routines are being used for 7-bit valid text data,
136
// we have to filter out any nasty \0's.
170
// As these routines are being used for 7-bit valid text data,
171
// we have to filter out any nasty \0's.
139
for (i = 0; i < bs; i++) {
140
if (*p == '\0') *p = ' ';
173
if (FFGET_ALLOW_NUL == 0)
176
for (i = 0; i < bs; i++) {
177
if (*p == '\0') *p = ' ';
145
if (FFGET_DPEDANTIC) LOGGER_log("Size: %ld bytes\n",f->bytes);
183
if (FFGET_DPEDANTIC) LOGGER_log("%s:%d:FFGET_getnewblock:DEBUG-PEDANTIC: Size: %ld bytes\n", FL, f->bytes);
167
205
------------------------------------------------------------------------*/
168
206
int FFGET_presetbuffer( FFGET_FILE *f, char *buffer, int size )
170
if (size > _FFGET_BUFFER_MAX) size = _FFGET_BUFFER_MAX;
208
if (size > FFGET_BUFFER_MAX) size = FFGET_BUFFER_MAX;
172
210
memcpy(f->buffer,buffer,size);
173
211
f->startpoint = buffer;
186
224
------------------------------------------------------------------------*/
187
225
int FFGET_setstream( FFGET_FILE *f, FILE *fi )
228
memset(f,0,sizeof(FFGET_FILE)); // be pedantic - clear the struct
191
232
f->linecount = 0;
192
233
f->endpoint = f->buffer;
193
234
f->startpoint = f->endpoint +1;
235
f->buffer_end = f->buffer +FFGET_BUFFER_MAX +FFGET_BUFFER_PADDING;
194
236
f->trueblank = 0;
195
237
f->ungetcset = 0;
196
238
f->lastchar = '\0';
197
memset(f->buffer,'\0',_FFGET_BUFFER_MAX +1);
239
memset(f->buffer,'\0',FFGET_BUFFER_MAX +FFGET_BUFFER_PADDING);
232
275
/*-----------------------------------------------------------------\
233
Function Name : FFGET_seek
241
--------------------------------------------------------------------
243
Seeks to 'offset' bytes from the first byte of the file.
244
Reloads the buffer block.
246
--------------------------------------------------------------------
276
Function Name : FFGET_seek
283
-1 = error, check logs for reason of failure.
286
--------------------------------------------------------------------
288
Seeks to 'offset' bytes from the first byte of the file.
289
Reloads the buffer block.
291
--------------------------------------------------------------------
249
294
\------------------------------------------------------------------*/
250
295
int FFGET_seek( FFGET_FILE *f, long offset, int whence )
253
fseek(f->f, offset, whence);
299
/** Move to the new block location **/
300
result = fseek(f->f, offset, whence);
302
LOGGER_log("%s:%d:FFGET_seek:ERROR: While attempting to seek to offset %ld from %d - [%s]", FL, offset, whence, strerror(errno));
306
/** Read a whole new block **/
254
307
result = FFGET_getnewblock(f);
259
314
/*-----------------------------------------------------------------\
260
Function Name : FFGET_tell
261
Returns Type : size_t
267
--------------------------------------------------------------------
269
Returns the position in the file that the current "file cursor"
273
--------------------------------------------------------------------
315
Function Name : FFGET_tell
316
Returns Type : size_t
322
--------------------------------------------------------------------
324
Returns the position in the file that the current "file cursor"
328
--------------------------------------------------------------------
276
331
\------------------------------------------------------------------*/
277
332
long FFGET_ftell( FFGET_FILE *f )
360
418
char *FFGET_fgets( char *linein, int maxsize, FFGET_FILE *f )
362
420
char *line = linein;
421
char *crlfpos = NULL;
367
425
int max_size = maxsize;
370
// We /ONLY/ return EOF -here-, because, even if during the process of
371
// reading through the bufffer we reach the end, we do still have data
372
// which we can send back to the caller. I'm surprised that more people
373
// didn't pick up on this, it's a glaring flaw.
426
int endpoint_tainted = 0;
427
int extra_char_kept=0;
375
430
f->trueblank = 0;
386
441
else DELIMITERS = NORM_MODE_DELIMITS;
389
// fprintf(stderr,"FFGET_called, SDLMODE = %d, Offset = %d, maxsize = %d, DATA left = %d, first char is '%02X'\n", FFGET_SDL_MODE, (f->startpoint -f->buffer), max_size, (f->endpoint -f->startpoint)+1, (int)(*f->startpoint));
444
// fprintf(stderr,"FFGET_called, SDLMODE = %d, Offset = %d, maxsize = %d, DATA left = %d, first char is '%02X'\n", FFGET_SDL_MODE, (f->startpoint -f->buffer), max_size, (f->endpoint -f->startpoint)+1, (int)(*f->startpoint));
391
446
max_size = maxsize = maxsize -2;
393
// memset(line, 0, max_size+1);
448
// memset(line, 0, max_size+1);
395
450
// If we dont have enough data in the buffer to fill up the fgets request
396
451
// we'll have to do a two step fill
398
//fprintf(stderr,"DATA Reminianing : %d\n", (int)(f->endpoint -f->startpoint)+1);
453
//fprintf(stderr,"DATA Reminianing : %d\n", (int)(f->endpoint -f->startpoint)+1);
400
455
if ((f->startpoint > f->endpoint))
417
472
crlfpos = strpbrk( f->startpoint, DELIMITERS);
476
endpoint_tainted = 0;
420
478
// if our next char is a CR or LF, then pick it up and
421
479
// return it with the line. NOTE - this is to deal with
422
480
// CRLF pairings which are common on DOS files. In fact,
423
481
// this is a case of where UNIX is actually -wrong-. It
424
482
// should have also used CRLF pairing to mark line ends, but
425
483
// someone obviously (and understandably, to save space)
426
// thought they'd leave make LF imply a CR as well.
484
// thought they'd leave make LF imply a CR as well.
427
485
// Well done... another bugger up in life.
460
517
if ((c > 0) && (c <= 255))
519
if (FFGET_DNORMAL) LOGGER_log("%s:%d:FFGET_fgets:DEBUG: Tainting endpoint +1 (%p -> %p, hard buffer end = %p, file read bytes = %ld)", FL, f->endpoint, f->endpoint+1, f->buffer_end, f->bytes);
463
521
*(f->endpoint) = c;
464
522
*(f->endpoint+1) = '\0';
523
endpoint_tainted = 1;
474
533
if ( ((crlfpos +1) <= f->endpoint))
477
// fprintf(stderr,"Found '%02X' [next is '%02X']\n",*crlfpos, *(crlfpos+1));
536
// fprintf(stderr,"Found '%02X' [next is '%02X']\n",*crlfpos, *(crlfpos+1));
479
538
if ( *crlfpos == '\n' )
481
540
if ( *(crlfpos +1) == '\r' )
501
561
FFGET_doubleCR=1;
502
562
FFGET_SDL_MODE=1;
506
if ( *(crlfpos +1) == '\n' )
566
} else if ( *(crlfpos +1) == '\n' ) {
508
567
// If we see a \n after our \r, then treat this as a single
509
568
// line delimeter if we are NOT in Single Delimeter mode
511
if (!FFGET_SDL_MODE) { crlfpos++; }
570
if (!FFGET_SDL_MODE) {
573
}// 20040208-1706:PLD
574
//crlfpos++;// 20040208-1706:PLD // 20040306-0003:PLD - this line causes a CRCR test to fail; mailpack.virus.badtrans
515
576
// If we saw a \r, but then there was no other EOL type char (\r or \n)
516
577
// then switch to SDL mode (Single delimeter).
552
615
if (( f->endpoint -f->startpoint) >= max_size)
554
if (max_size < 0) fprintf(stderr,"ERROR - Max size < 0\n");
617
if (max_size < 0) LOGGER_log("%s:%d:FFGET_fgets:ERROR: Max size < 0\n", FL);
555
618
memcpy(line, f->startpoint, max_size +1);//+1
556
619
f->startpoint += (max_size +1); //+1
557
620
*(line +max_size +1) = '\0'; //+1
563
625
// else, if the amount of data available is /LESS/ than what we can
564
// accept in the line buffer then copy what remains out to the line
565
// buffer and then tack on the results of a new read.
626
// accept in the line buffer then copy what remains out to the line
627
// buffer and then tack on the results of a new read.
567
629
chardiff = f->endpoint -f->startpoint;
569
// fprintf(stderr,"CHARDiff = %d, FFEOF = %d, FILEEND = %d\n",chardiff, f->FFEOF, f->FILEEND);
631
// fprintf(stderr,"CHARDiff = %d, FFEOF = %d, FILEEND = %d\n",chardiff, f->FFEOF, f->FILEEND);
571
633
if (chardiff >= 0)