2010-03-08 04:55:21 -06:00
|
|
|
/* FILE WRITER HTWrite.c
|
|
|
|
** ===========
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
#include "../config.h"
|
|
|
|
#include "HTWriter.h"
|
|
|
|
|
|
|
|
#define BUFFER_SIZE 4096 /* Tradeoff */
|
|
|
|
|
|
|
|
#include "HTUtils.h"
|
|
|
|
#include "tcp.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
char adbuf[1024];
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
extern int httpTrace;
|
|
|
|
extern int www2Trace;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* HTML Object
|
|
|
|
** -----------
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct _HTStream {
|
|
|
|
WWW_CONST HTStreamClass * isa;
|
|
|
|
|
|
|
|
int soc;
|
|
|
|
char *write_pointer;
|
|
|
|
char buffer[BUFFER_SIZE];
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* Write the buffer out to the socket
|
|
|
|
** ----------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
PRIVATE void flush ARGS1(HTStream *, me)
|
|
|
|
{
|
|
|
|
char *read_pointer = me->buffer;
|
|
|
|
char *write_pointer = me->write_pointer;
|
|
|
|
|
|
|
|
while (read_pointer < write_pointer) {
|
|
|
|
int status;
|
|
|
|
status = NETWRITE(me->soc, me->buffer,
|
|
|
|
write_pointer - read_pointer);
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (httpTrace) {
|
|
|
|
strncpy(adbuf, me->buffer, write_pointer - read_pointer);
|
|
|
|
adbuf[write_pointer - read_pointer] = '\0';
|
|
|
|
fprintf(stderr,"%s",adbuf);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (status<0) {
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if(www2Trace) fprintf(stderr,
|
|
|
|
"HTWrite: Error on socket output stream!!!\n");
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
read_pointer = read_pointer + status;
|
|
|
|
}
|
|
|
|
me->write_pointer = me->buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*_________________________________________________________________________
|
|
|
|
**
|
|
|
|
** A C T I O N R O U T I N E S
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Character handling
|
|
|
|
** ------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
PRIVATE void HTWriter_put_character ARGS2(HTStream *, me, char, c)
|
|
|
|
{
|
|
|
|
if (me->write_pointer == &me->buffer[BUFFER_SIZE]) flush(me);
|
|
|
|
*me->write_pointer++ = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* String handling
|
|
|
|
** ---------------
|
|
|
|
**
|
|
|
|
** Strings must be smaller than this buffer size.
|
|
|
|
*/
|
|
|
|
PRIVATE void HTWriter_put_string ARGS2(HTStream *, me, WWW_CONST char*, s)
|
|
|
|
{
|
|
|
|
int l = strlen(s);
|
|
|
|
if (me->write_pointer + l > &me->buffer[BUFFER_SIZE]) flush(me);
|
|
|
|
strcpy(me->write_pointer, s);
|
|
|
|
me->write_pointer = me->write_pointer + l;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Buffer write. Buffers can (and should!) be big.
|
|
|
|
** ------------
|
|
|
|
*/
|
|
|
|
PRIVATE void HTWriter_write ARGS3(HTStream *, me, WWW_CONST char*, s, int, l)
|
|
|
|
{
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
WWW_CONST char *read_pointer = s;
|
|
|
|
WWW_CONST char *write_pointer = s+l;
|
|
|
|
|
|
|
|
flush(me); /* First get rid of our buffer */
|
|
|
|
|
|
|
|
while (read_pointer < write_pointer) {
|
|
|
|
int status = NETWRITE(me->soc, read_pointer,
|
|
|
|
write_pointer - read_pointer);
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (httpTrace) {
|
|
|
|
strncpy(adbuf, me->buffer, read_pointer - read_pointer);
|
|
|
|
adbuf[write_pointer - read_pointer] = '\0';
|
|
|
|
fprintf(stderr,"%s",adbuf);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (status<0) {
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if(www2Trace) fprintf(stderr,
|
|
|
|
"HTWriter_write: Error on socket output stream!!!\n");
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
read_pointer = read_pointer + status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Free an HTML object
|
|
|
|
** -------------------
|
|
|
|
**
|
|
|
|
** Note that the SGML parsing context is freed, but the created object is not,
|
|
|
|
** as it takes on an existence of its own unless explicitly freed.
|
|
|
|
*/
|
|
|
|
PRIVATE void HTWriter_free ARGS1(HTStream *, me)
|
|
|
|
{
|
|
|
|
NETCLOSE(me->soc);
|
|
|
|
flush(me);
|
|
|
|
free(me);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* End writing
|
|
|
|
*/
|
|
|
|
|
|
|
|
PRIVATE void HTWriter_end_document ARGS1(HTStream *, me)
|
|
|
|
{
|
|
|
|
flush(me);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRIVATE void HTWriter_handle_interrupt ARGS1(HTStream *, me)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Structured Object Class
|
|
|
|
** -----------------------
|
|
|
|
*/
|
|
|
|
PRIVATE WWW_CONST HTStreamClass HTWriter = /* As opposed to print etc */
|
2013-03-09 18:59:42 -06:00
|
|
|
{
|
2010-03-08 04:55:21 -06:00
|
|
|
"SocketWriter",
|
|
|
|
HTWriter_free,
|
|
|
|
HTWriter_end_document,
|
|
|
|
HTWriter_put_character, HTWriter_put_string,
|
|
|
|
HTWriter_write,
|
|
|
|
HTWriter_handle_interrupt
|
2013-03-09 18:59:42 -06:00
|
|
|
};
|
2010-03-08 04:55:21 -06:00
|
|
|
|
|
|
|
|
|
|
|
/* Subclass-specific Methods
|
|
|
|
** -------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
PUBLIC HTStream* HTWriter_new ARGS1(int, soc)
|
|
|
|
{
|
|
|
|
HTStream* me = (HTStream*)malloc(sizeof(*me));
|
|
|
|
if (me == NULL) outofmem(__FILE__, "HTWriter_new");
|
2013-03-09 18:59:42 -06:00
|
|
|
me->isa = &HTWriter;
|
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
me->soc = soc;
|
|
|
|
me->write_pointer = me->buffer;
|
|
|
|
return me;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Subclass-specific Methods
|
|
|
|
** -------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
PUBLIC HTStream* HTASCIIWriter ARGS1(int, soc)
|
|
|
|
{
|
|
|
|
HTStream* me = (HTStream*)malloc(sizeof(*me));
|
|
|
|
if (me == NULL) outofmem(__FILE__, "HTASCIIWriter");
|
2013-03-09 18:59:42 -06:00
|
|
|
me->isa = &HTWriter;
|
2010-03-08 04:55:21 -06:00
|
|
|
|
|
|
|
me->soc = soc;
|
|
|
|
me->write_pointer = me->buffer;
|
|
|
|
return me;
|
|
|
|
}
|
|
|
|
|