Example #1
0
/*
**  Check whether the application provides us with a cookie or more.
*/
PRIVATE int HTCookie_beforeFilter (HTRequest * request, void * param, int mode)
{
    if ((CookieMode & HT_COOKIE_SEND) && FindCookie) {
        HTAssocList * cookies = (*FindCookie)(request, FindCookieContext);
        if (cookies) {
            HTChunk * cookie_header = HTChunk_new(64);
            HTAssocList * cur = cookies;
            HTAssoc * pres;
            BOOL first=YES;
            while ((pres = (HTAssoc *) HTAssocList_nextObject(cur))) {
                if (!first) HTChunk_putc(cookie_header, ';');
                HTChunk_puts(cookie_header, HTAssoc_name(pres));
                HTChunk_putc(cookie_header, '=');
                HTChunk_puts(cookie_header, HTAssoc_value(pres));
                first = NO;
            }
            HTRequest_addExtraHeader(request, "Cookie", HTChunk_data(cookie_header));
            HTChunk_delete(cookie_header);

            /* Also delete the association list */
            HTAssocList_delete(cookies);
        }
    }
    return HT_OK;
}
Example #2
0
/*	Determine a suitable suffix
**	---------------------------
**  Use the set of bindings to find a suitable suffix (or index)
**  for a certain combination of language, media type and encoding
**  given in the anchor.
**
**  Returns a pointer to a suitable suffix string that must be freed 
**  by the caller. If more than one suffix is found they are all
**  concatenated using the first delimiter in HTDelimiters.
**  If no suffix is found, NULL is returned.
*/
PUBLIC char * HTBind_getSuffix (HTParentAnchor * anchor)
{
    int cnt;
    HTList * cur;
    HTChunk * suffix = HTChunk_new(48);
    char delimiter = *HTDelimiters;
    char * ct=NULL, * ce=NULL, * cl=NULL;
    HTFormat format = HTAnchor_format(anchor);
    HTList * encoding = HTAnchor_encoding(anchor);
    HTList * language = HTAnchor_language(anchor);
    if (!HTBindings) HTBind_init();
    if (anchor) {
	for (cnt=0; cnt<HT_L_HASH_SIZE; cnt++) {
	    if ((cur = HTBindings[cnt])) { 
		HTBind *pres;
		while ((pres = (HTBind *) HTList_nextObject(cur))) {
		    if (!ct && (pres->type && pres->type == format)){
			ct = pres->suffix;
		    } else if (!ce && pres->encoding && encoding) {
			HTList * cur_enc = encoding;
			HTEncoding pres_enc;
			while ((pres_enc = (HTEncoding) HTList_nextObject(cur_enc))) {
			    if (pres_enc == pres->encoding) {
				ce = pres->suffix;
				break;
			    }
			}
		    } else if (!cl && pres->language && language) {
			HTList * cur_lang = language;
			HTLanguage pres_lang;
			while ((pres_lang = (HTLanguage) HTList_nextObject(cur_lang))) {
			    if (pres_lang == pres->language) {
				cl = pres->suffix;
				break;
			    }
			}
		    }
		}
	    }
	}

	/* Put the found suffixes together */
	if (ct) {
	    HTChunk_putc(suffix, delimiter);
	    HTChunk_puts(suffix, ct);
	}
	if (ce) {
	    HTChunk_putc(suffix, delimiter);
	    HTChunk_puts(suffix, ce);
	}
	if (cl) {
	    HTChunk_putc(suffix, delimiter);
	    HTChunk_puts(suffix, cl);
	}
    }
    return HTChunk_toCString(suffix);
}
Example #3
0
/*
**	Folding is either of CF LWS, LF LWS, CRLF LWS
*/
PRIVATE int HTRule_put_block (HTStream * me, const char * b, int l)
{
    while (l > 0) {
	if (me->EOLstate == EOL_FCR) {
	    if (*b == LF)				   	     /* CRLF */
		me->EOLstate = EOL_FLF;
	    else if (isspace((int) *b))				   /* Folding: CR SP */
		me->EOLstate = EOL_DOT;
	    else {						 /* New line */
		HTRule_parseLine(rules, HTChunk_data(me->buffer));
		me->EOLstate = EOL_BEGIN;
		HTChunk_clear(me->buffer);
		continue;
	    }
	} else if (me->EOLstate == EOL_FLF) {
	    if (isspace((int) *b))		       /* Folding: LF SP or CR LF SP */
		me->EOLstate = EOL_DOT;
	    else {						/* New line */
		HTRule_parseLine(rules, HTChunk_data(me->buffer));
		me->EOLstate = EOL_BEGIN;
		HTChunk_clear(me->buffer);
		continue;
	    }
	} else if (me->EOLstate == EOL_DOT) {
	    if (isspace((int) *b)) {
		me->EOLstate = EOL_BEGIN;
		HTChunk_putc(me->buffer, ' ');
	    } else {
		HTRule_parseLine(rules, HTChunk_data(me->buffer));
		me->EOLstate = EOL_BEGIN;
		HTChunk_clear(me->buffer);
		continue;
	    }
	} else if (*b == CR) {
	    me->EOLstate = EOL_FCR;
	} else if (*b == LF) {
	    me->EOLstate = EOL_FLF;			       /* Line found */
	} else
	    HTChunk_putc(me->buffer, *b);
	l--; b++;
    }
    return HT_OK;
}
Example #4
0
/*
**	Header is terminated by CRCR, LFLF, CRLFLF, CRLFCRLF
**	Folding is either of CF LWS, LF LWS, CRLF LWS
*/
PRIVATE int HTMIME_put_block (HTStream * me, const char * b, int l)
{
    const char * start = b;
    const char * end = start;
    const char * value = HTChunk_size(me->value) > 0 ? b : NULL;
    int length = l;
    int status;

    while (!me->transparent) {
	if (me->EOLstate == EOL_FCR) {
	    if (*b == CR)				    /* End of header */
	        me->EOLstate = EOL_END;
	    else if (*b == LF)			   	     /* CRLF */
		me->EOLstate = EOL_FLF;
	    else if (isspace((int) *b))			   /* Folding: CR SP */
	        me->EOLstate = EOL_FOLD;
	    else						 /* New line */
	        me->EOLstate = EOL_LINE;
	} else if (me->EOLstate == EOL_FLF) {
	    if (*b == CR)				/* LF CR or CR LF CR */
		me->EOLstate = EOL_SCR;
	    else if (*b == LF)				    /* End of header */
	        me->EOLstate = EOL_END;
	    else if (isspace((int) *b))	       /* Folding: LF SP or CR LF SP */
		me->EOLstate = EOL_FOLD;
	    else						/* New line */
		me->EOLstate = EOL_LINE;
	} else if (me->EOLstate == EOL_SCR) {
	    if (*b==CR || *b==LF)			    /* End of header */
	        me->EOLstate = EOL_END;
	    else if (isspace((int) *b))	 /* Folding: LF CR SP or CR LF CR SP */
		me->EOLstate = EOL_FOLD;
	    else						/* New line */
		me->EOLstate = EOL_LINE;
	} else if (*b == CR)
	    me->EOLstate = EOL_FCR;
	else if (*b == LF)
	    me->EOLstate = EOL_FLF;			       /* Line found */
	else {
	    if (!me->haveToken) {
	        if (*b == ':' || isspace((int) *b)) {
		    HTChunk_putb(me->token, start, end-start);
		    HTChunk_putc(me->token, '\0');
		    me->haveToken = YES;
		} else {
		    unsigned char ch = *(unsigned char *) b;
		    ch = TOLOWER(ch);
		    me->hash = (me->hash * 3 + ch) % MIME_HASH_SIZE;
		}
	    } else if (value == NULL && *b != ':' && !isspace((int) *b))
	        value = b;
	    end++;
	}
	switch (me->EOLstate) {
	    case EOL_LINE:
	    case EOL_END:
	    {
		int ret = HT_ERROR;
		HTChunk_putb(me->value, value, end-value);
		HTChunk_putc(me->value, '\0');
		ret =  _stream2dispatchParsers(me);
		HTNet_addBytesRead(me->net, b-start);
		start=b, end=b;
		if (me->EOLstate == EOL_END) {		/* EOL_END */
		    if (ret == HT_OK) {
			b++, l--;
			ret = pumpData(me);
			HTNet_addBytesRead(me->net, 1);
			if (me->mode & (HT_MIME_FOOTER | HT_MIME_CONT)) {
			    HTHost_setConsumed(HTNet_host(me->net), length - l);
			    return ret;
                        } else {
                            HTNet_setHeaderBytesRead(me->net, HTNet_bytesRead(me->net));
                        }
		    }
	        } else {				/* EOL_LINE */
		    HTChunk_truncate(me->token,0);
		    HTChunk_truncate(me->value,0);
		    me->haveToken = NO;
		    me->hash = 0;
		    value = NULL;
		}
		me->EOLstate = EOL_BEGIN;
		if (ret != HT_OK && ret != HT_LOADED) return ret;
		break;
	    }
	    case EOL_FOLD:
		me->EOLstate = EOL_BEGIN;
	        if (!me->haveToken) {
		    HTChunk_putb(me->token, start, end-start);
		    HTChunk_putc(me->token, '\0');
		    me->haveToken = YES;
	        } else if (value) {
		    HTChunk_putb(me->value, value, end-value);
		    HTChunk_putc(me->value, ' ');
		}
		start=b, end=b;
		break;
	    default: 
	        b++, l--;
	        if (!l) {
		    BOOL stop = NO;
		    if (!me->haveToken) {
			/* If empty header then prepare to stop */
			if (end-start)
			    HTChunk_putb(me->token, start, end-start);
			else
			    stop = YES;
		    } else if (value)
		        HTChunk_putb(me->value, value, end-value);
		    HTHost_setConsumed(HTNet_host(me->net), length - l);
		    return stop ? pumpData(me) : HT_OK;
		}
	}
    }

    if (length != l) HTHost_setConsumed(HTNet_host(me->net), length - l);

    /* 
    ** Put the rest down the stream without touching the data but make sure
    ** that we get the correct content length of data. If we have a CL in
    ** the headers then this stream is responsible for the accountance.
    */
    if (me->hasBody) {
	HTNet * net = me->net;
	/* Check if CL at all - thanks to [email protected] (John Wei) */
	long cl = HTResponse_length(me->response);
	if (cl >= 0) {
	    long bodyRead = HTNet_bytesRead(net) - HTNet_headerBytesRead(net);

	    /*
	    **  If we have more than we need then just take what belongs to us.
	    */
	    if (bodyRead + l >= cl) {
		int consume = cl - bodyRead;
		if ((status = (*me->target->isa->put_block)(me->target, b, consume)) < 0)
		    return status;	    
                else {
                    HTAlertCallback * cbf = HTAlert_find(HT_PROG_DONE);
                    HTNet_addBytesRead(net, consume);
                    HTHost_setConsumed(HTNet_host(net), consume);
                    if (cbf) (*cbf)(me->request, HT_PROG_DONE, HT_MSG_NULL, NULL, NULL, NULL);
                    return HT_LOADED;
                }
            } else {
		if ((status = (*me->target->isa->put_block)(me->target, b, l)) < 0)
		    return status;
		HTNet_addBytesRead(net, l);
		HTHost_setConsumed(HTNet_host(net), l);
		return status;
	    }
	}
	return (*me->target->isa->put_block)(me->target, b, l);
    } else {
        HTAlertCallback * cbf = HTAlert_find(HT_PROG_DONE);
        if (cbf) (*cbf)(me->request, HT_PROG_DONE, HT_MSG_NULL, NULL, NULL, NULL);
    }
    return HT_LOADED;
}
Example #5
0
PUBLIC void HTChunk_terminate (HTChunk * ch)
{
    HTChunk_putc(ch, '\0');
}
Example #6
0
PRIVATE int SGML_write (HTStream * context, const char * b, int l)
    {
	const SGML_dtd	*dtd = context->dtd;
	HTChunk	*string = context->string;
	const char *text = b;
	int count = 0;
	
	while (l-- > 0)
	    {
		char c = *b++;
		switch(context->state)
		    {
		    got_element_open:
			/*
			** The label is jumped when the '>' of a the element
			** start tag has been detected. This DOES NOT FALL TO
			** THE CODE S_after_open, only processes the tag and
			** sets the state (c should still contain the
			** terminating character of the tag ('>'))
			*/
			if (context->current_tag && context->current_tag->name)
				start_element(context);
			context->state = S_after_open;
			break;

		    case S_after_open:
			/*
			** State S_after_open is entered only for single
			** character after the element opening tag to test
			** against newline. Strip one trainling newline only
			** after opening nonempty element.  - SGML: Ugh!
			*/
			text = b;
			count = 0;
			if (c == '\n' && (context->contents != SGML_EMPTY))
			    {
				context->state = S_text;
				break;
			    }
			--text;
			goto S_text;

		    S_text:
			context->state = S_text;
		    case S_text:
#ifdef ISO_2022_JP
			if (c == '\033')
			    {
				context->state = S_esc;
				++count;
				break;
			    }
#endif /* ISO_2022_JP */
			if (c == '&')
			    {
				if (count > 0)
					PUTB(text, count);
				count = 0;
				HTChunk_clear(string);
				context->state = S_ero;
			    }
			else if (c == '<')
			    {
				if (count > 0)
					PUTB(text, count);
				count = 0;
				HTChunk_clear(string);
				/* should scrap LITERAL, and use CDATA and
				   RCDATA -- msa */
				context->state =
					(context->contents == SGML_LITERAL) ?
						S_literal : S_tag;
			    }
			else if (c == '\n')
			    	/* Newline - ignore if before end tag! */
				context->state = S_nl;
			else
				++count;
			break;

		    case S_nl:
			if (c == '<')
			    {
				if (count > 0)
					PUTB(text, count);
				count = 0;
				HTChunk_clear(string);
				context->state =
					(context->contents == SGML_LITERAL) ?
						S_literal : S_nl_tago;
			    }
			else
			    {
				++count;
				goto S_text;
			    }
			break;

		    case S_nl_tago:	/* Had newline and tag opener */
			if (c != '/')
				PUTC('\n'); /* Only ignore newline before </ */
			context->state = S_tag;
			goto handle_S_tag;

#ifdef ISO_2022_JP
		    case S_esc:
			if (c=='$')
				context->state = S_dollar;
			else if (c=='(')
				context->state = S_paren;
			else
				context->state = S_text;
			++count;
			break;

		    case S_dollar:
			if (c=='@' || c=='B')
				context->state = S_nonascii_text;
			else
				context->state = S_text;
			++count;
			break;

		    case S_paren:
			if (c=='B' || c=='J')
				context->state = S_text;
			else
				context->state = S_text;
			++count;
			break;

		    case S_nonascii_text:
			if (c == '\033')
				context->state = S_esc;
			++count;
			break;
#endif /* ISO_2022_JP */

			/* In literal mode, waits only for specific end tag!
			** Only foir compatibility with old servers.
			*/
		    case S_literal:
			HTChunk_putc(string, c);
			if ( TOUPPER(c) !=
			    ((HTChunk_size(string) == 1) ? '/'
			     : context->current_tag->name[HTChunk_size(string)-2]))
			    {

				/* If complete match, end literal */
				if ((c == '>') &&
				    (!context->current_tag->name[HTChunk_size(string)-2]))
				    {
					end_element
						(context,context->current_tag);
					/*
					  ...setting SGML_MIXED below is a
					  bit of kludge, but a good guess that
					  currently works, anything other than
					  SGML_LITERAL would work... -- msa */
					context->contents = SGML_MIXED;
				    }
				else
				    {
					/* If Mismatch: recover string. */
					PUTC( '<');
					PUTB(HTChunk_data(string), HTChunk_size(string));
				    }
				context->state = S_text;
				text = b;
				count = 0;
			    }
			break;

			/*
			** Character reference or Entity
			*/
		    case S_ero:
			if (c == '#')
			    {
				/*   &# is Char Ref Open */ 
				context->state = S_cro;
				break;
			    }
			context->state = S_entity;

			/** FALL THROUGH TO S_entity !! ***/

			/*
			** Handle Entities
			*/
		    case S_entity:
			if (isalnum((int) c))
				HTChunk_putc(string, c);
			else
			    {
				HTChunk_terminate(string);
				handle_entity(context);
				text = b;
				count = 0;
				if (c != ';')
				    {
					--text;
					goto S_text;
				    }
				context->state = S_text;
			    }
			break;

			/*	Character reference
			 */
		    case S_cro:
			if (isalnum((int)c))
				/* accumulate a character NUMBER */
				HTChunk_putc(string, c);
			else
			    {
				int value;
				HTChunk_terminate(string);
				if (sscanf(HTChunk_data(string), "%d", &value)==1)
					PUTC((char)value);
				else
				    {
					PUTB("&#", 2);
					PUTB(HTChunk_data(string), HTChunk_size(string)-1);
				    }
				text = b;
				count = 0;
				if (c != ';')
				    {
					--text;
					goto S_text;
				    }
				context->state = S_text;
			    }
			break;

		    case S_tag:		/* new tag */
		    handle_S_tag:
			if (isalnum((int)c))
				HTChunk_putc(string, c);
			else { /* End of tag name */
			    int i;
			    if (c == '/') {
				if (HTChunk_size(string) > 0)
				    HTTRACE(SGML_TRACE, "`<%s/' found!\n" _ HTChunk_data(string));
				context->state = S_end;
				break;
			    } else if (c == '!') {
				if (HTChunk_size(string) > 0)
				    HTTRACE(SGML_TRACE, " `<%s!' found!\n" _ HTChunk_data(string));
				context->state = S_md;
				break;
			    }
			    HTChunk_terminate(string);
			    context->current_tag  = SGMLFindTag(dtd, HTChunk_data(string));
			    if (context->current_tag == NULL) {
				HTTRACE(SGML_TRACE, "*** Unknown element %s\n" _ HTChunk_data(string));
				(*context->actions->unparsed_begin_element)
				    (context->target, HTChunk_data(string), HTChunk_size(string));
			    } else {
				for (i=0; i<context->current_tag->number_of_attributes; i++) {
				    context->present[i] = NO;
				    context->value[i] = -1;
				}
			    }
			    context->token = 0;
			    HTChunk_clear(string);
			    context->current_attribute_number = INVALID;
			    goto S_tag_gap;
			}
			break;

		    S_tag_gap:
			context->state = S_tag_gap;
		    case S_tag_gap:		/* Expecting attribute or > */
			if (isspace((int) c))
				break;	/* Gap between attributes */

			if (c == '>')
				goto got_element_open;
			else
				goto S_attr;

		    S_attr:
			/*
			** Start collecting the attribute name and collect
			** it in S_attr.
			*/
			context->state = S_attr;
			HTChunk_truncate(string, context->token);
		    case S_attr:
			if (isspace((int) c) || c == '>' || c == '=')
				goto got_attribute_name;
			else
				HTChunk_putc(string, c);
			break;

		    got_attribute_name:
			/*
			** This label is entered when attribute name has been
			** collected. Process it and enter S_attr_gap for
			** potential value or start of the next attribute.
			*/
			HTChunk_terminate(string) ;
			handle_attribute_name
				(context, HTChunk_data(string) + context->token);
			HTChunk_truncate(string, context->token);
			context->state = S_attr_gap;
		    case S_attr_gap:	/* Expecting attribute or = or > */
			if (isspace((int) c))
				break;	/* Gap after attribute */

			if (c == '>')
				goto got_element_open;
			else if (c == '=')
				context->state = S_equals;
			else
				goto S_attr; /* Get next attribute */
			break;

		    case S_equals:	/* After attr = */ 
			if (isspace((int) c))
				break;	/* Before attribute value */

			if (c == '>')
			    {		/* End of tag */
				HTTRACE(SGML_TRACE, "found = but no value\n");
				goto got_element_open;
			    }
			else if (c == '\'')
				context->state = S_squoted;
			else if (c == '"')
				context->state = S_dquoted;
			else
				goto S_value;
			break;

		    S_value:
			context->state = S_value;
			HTChunk_truncate(string, context->token);
		    case S_value:
			if (isspace((int) c) || c == '>')
			    {
				HTChunk_terminate(string);
				handle_attribute_value(context);
				context->token = HTChunk_size(string);
				goto S_tag_gap;
			    }
			else
				HTChunk_putc(string, c);
			break;
		
		    case S_squoted:	/* Quoted attribute value */
			if (c == '\'')
			    {
				HTChunk_terminate(string);
				handle_attribute_value(context);
				context->token = HTChunk_size(string);
				context->state = S_tag_gap;
			    }
			else if (c && c != '\n' && c != '\r')
				HTChunk_putc(string, c);
			break;
	
		    case S_dquoted:	/* Quoted attribute value */
			if (c == '"')
			    {
				HTChunk_terminate(string);
				handle_attribute_value(context);
				context->token = HTChunk_size(string);
				context->state = S_tag_gap;
			    }
			else if (c && c != '\n' && c != '\r')
				HTChunk_putc(string, c);
			break;

		    case S_end:	/* </ */
			if (isalnum((int) c))
				HTChunk_putc(string, c);
			else
			    {		/* End of end tag name */
				HTTag *t;
				char * first;
				HTChunk_terminate(string);
				if ((first=HTChunk_data(string))!=NULL && *first != '\0')
				        t = SGMLFindTag(dtd, HTChunk_data(string));
				else
				    	/* Empty end tag */
					/* Original code popped here one
					   from the stack. If this feature
					   is required, I have to put the
					   stack back... -- msa */
					t = NULL;
				if (!t) {
				    HTTRACE(SGML_TRACE, "Unknown end tag </%s>\n" _ HTChunk_data(string));
				    (*context->actions->unparsed_end_element)
					(context->target, HTChunk_data(string), HTChunk_size(string));
				} else {
				    context->current_tag = NULL;
				    end_element(context, t);
				}
				HTChunk_clear(string);
				context->current_attribute_number = INVALID;
				if (c != '>')
				    {
					if (!isspace((int) c))
					    HTTRACE(SGML_TRACE, "`</%s%c' found!\n" _ HTChunk_data(string) _ c);
					context->state = S_junk_tag;
				    }
				else
				    {
					text = b;
					count = 0;
					context->state = S_text;
				    }
			    }
			break;

		    case S_junk_tag:
			if (c == '>')
			    {
				text = b;
				count = 0;
				context->state = S_text;
			    }
			break;

			/*
			** Scanning (actually skipping) declarations
			*/
		    case S_md:
			if (c == '-')
				context->state = S_com_1;
			else if (c == '"')
				context->state = S_md_dqs;
			else if (c == '\'')
				context->state = S_md_sqs;
			else if (c == '>')
			    {
				text = b;
				count = 0;
				context->state = S_text;
			    }
			break;

		    case S_md_dqs: /* Skip double quoted string */
			if (c == '"')
				context->state = S_md;
			else if (c == '>')
			    {
				text = b;
				count = 0;
				context->state = S_text;
			    }
			break;

		    case S_md_sqs: /* Skip single quoted string */
			if (c == '\'')
				context->state = S_md;
			else if (c == '>')
			    {
				text = b;
				count = 0;
				context->state = S_text;
			    }
			break;

		    case S_com_1: /* Starting a comment? */
			context->state = (c == '-') ? S_com : S_md;
			if (c == '>')
			    {
				text = b;
				count = 0;
				context->state = S_text;
			    }
			break;

		    case S_com: /* ..within comment */
			if (c == '-')
				context->state = S_com_2;
			break;

		    case S_com_2: /* Ending a comment ? */
			context->state = (c == '-') ? S_com_2a : S_com;
			break;
		    
		    case S_com_2a:
			if (c == '>') {
			    text = b;
			    count = 0;
			    context->state = S_text;
			} else if (c == '-') {
			    context->state = S_com_2a;
			} else
			    context->state = S_com;
			break;
		    }
	    }
	if (count > 0)
		PUTB(text, count);
	return HT_OK;
    }
Example #7
0
int main (int argc, char ** argv)
{
    int		status = 0;	
    int		arg;
    int		tokencount = 0;
    BOOL	formdata = NO;
    HTChunk *	keywords = NULL;			/* From command line */
    HTAssocList*formfields = NULL;
    HTMethod	method = METHOD_GET;			    /* Default value */
    ComLine *	cl = ComLine_new();
    BOOL	cache = NO;			     /* Use persistent cache */
    BOOL	flush = NO;		       /* flush the persistent cache */
    char *	cache_root = NULL;

    /* Starts Mac GUSI socket library */
#ifdef GUSI
    GUSISetup(GUSIwithSIOUXSockets);
    GUSISetup(GUSIwithInternetSockets);
#endif

#ifdef __MWERKS__ /* STR */
    InitGraf((Ptr) &qd.thePort); 
    InitFonts(); 
    InitWindows(); 
    InitMenus(); TEInit(); 
    InitDialogs(nil); 
    InitCursor();
    SIOUXSettings.asktosaveonclose = false;
    argc=ccommand(&argv);
#endif

    /* Initiate W3C Reference Library with a client profile */
    HTProfile_newNoCacheClient(APP_NAME, APP_VERSION);

    /* Need our own trace and print functions */
    HTPrint_setCallback(printer);
    HTTrace_setCallback(tracer);

    /*
    ** Delete the default Username/password handler so that we can handle
    ** parameters handed to us from the command line. The default is set
    ** by the profile.
    */
    HTAlert_deleteOpcode(HT_A_USER_PW);
    HTAlert_add(PromptUsernameAndPassword, HT_A_USER_PW);

    /*
    ** Add default content decoder. We insert a through line as it doesn't
    ** matter that we get an encoding that we don't know.
    */
    HTFormat_addCoding("*", HTIdentityCoding, HTIdentityCoding, 0.3);

    /* Scan command Line for parameters */
    for (arg=1; arg<argc; arg++) {
	if (*argv[arg] == '-') {
	    
	    /* - alone => filter */
	    if (argv[arg][1] == '\0') {
		cl->flags |= CL_FILTER;	   
	    
	    /* -? or -help: show the command line help page */
	    } else if (!strcmp(argv[arg],"-?") || !strcmp(argv[arg],"-help")) {
		cl->anchor = (HTParentAnchor *) HTAnchor_findAddress(W3C_HELP);
		tokencount = 1;

	    /* non-interactive */
	    } else if (!strcmp(argv[arg], "-n")) {
		HTAlert_setInteractive(NO);

	    /* Treat the keywords as form data with a <name> "=" <value> */
	    } else if (!strcmp(argv[arg], "-form")) {
		formdata = YES;

	    /* from -- Initial represntation (only with filter) */
	    } else if (!strcmp(argv[arg], "-from")) {
		cl->format = (arg+1 < argc && *argv[arg+1] != '-') ?
		    HTAtom_for(argv[++arg]) : WWW_HTML;

	    /* to -- Final representation */
	    } else if (!strcmp(argv[arg], "-to")) {
		HTFormat format = (arg+1 < argc && *argv[arg+1] != '-') ?
		    HTAtom_for(argv[++arg]) : DEFAULT_FORMAT;
		HTRequest_setOutputFormat(cl->request, format);

	    /* destination for PUT, POST etc. */
	    } else if (!strcmp(argv[arg], "-dest")) {
		if (arg+1 < argc && *argv[arg+1] != '-') {
		    char * dest = HTParse(argv[++arg], cl->cwd, PARSE_ALL);
		    cl->dest = (HTParentAnchor *) HTAnchor_findAddress(dest);
		    HT_FREE(dest);
		}

	    /* source please */
	    } else if (!strcmp(argv[arg], "-source")) {
		HTRequest_setOutputFormat(cl->request, WWW_RAW);

	    /* log file */
	    } else if (!strcmp(argv[arg], "-l")) {
		cl->logfile = (arg+1 < argc && *argv[arg+1] != '-') ?
		    argv[++arg] : DEFAULT_LOG_FILE;

	    /* Max forward hops in case of TRACE request */
	    } else if (!strcmp(argv[arg], "-hops") ||
		       !strcmp(argv[arg], "-maxforwards")) {
		int hops = (arg+1 < argc && *argv[arg+1] != '-') ?
		    atoi(argv[++arg]) : DEFAULT_HOPS;
		if (hops >= 0) HTRequest_setMaxForwards(cl->request, hops);

	    /* automated authentication of format user:password@realm */
	    } else if (!strncmp(argv[arg], "-auth", 5)) {
		char * credentials = (arg+1 < argc && *argv[arg+1] != '-') ?
		    argv[++arg] : NULL;
		if (credentials) ParseCredentials(cl, credentials);

	    /* rule file */
	    } else if (!strcmp(argv[arg], "-r")) {
		cl->rules = (arg+1 < argc && *argv[arg+1] != '-') ?
		    argv[++arg] : DEFAULT_RULE_FILE;

	    /* output filename */
	    } else if (!strcmp(argv[arg], "-o")) { 
		cl->outputfile = (arg+1 < argc && *argv[arg+1] != '-') ?
		    argv[++arg] : DEFAULT_OUTPUT_FILE;

	    /* timeout -- Change the default request timeout */
	    } else if (!strcmp(argv[arg], "-timeout")) {
		int timeout = (arg+1 < argc && *argv[arg+1] != '-') ?
		    atoi(argv[++arg]) : DEFAULT_TIMEOUT;
		if (timeout >= 1) cl->timer = timeout*MILLIES;

	    /* preemptive or non-preemptive access */
	    } else if (!strcmp(argv[arg], "-single")) {
		HTRequest_setPreemptive(cl->request, YES);

	    /* content Length Counter */
	    } else if (!strcmp(argv[arg], "-cl")) { 
		cl->flags |= CL_COUNT;

	    /* print version and exit */
	    } else if (!strcmp(argv[arg], "-version")) { 
		VersionInfo(argv[0]);
		Cleanup(cl, 0);

	    /* run in quiet mode */
	    } else if (!strcmp(argv[arg], "-q")) { 
		cl->flags |= CL_QUIET;

	    /* Start the persistent cache */
	    } else if (!strcmp(argv[arg], "-cache")) {
		cache = YES;

	    /* Determine the cache root */
	    } else if (!strcmp(argv[arg], "-cacheroot")) { 
		cache_root = (arg+1 < argc && *argv[arg+1] != '-') ?
		    argv[++arg] : NULL;

	    /* Persistent cache flush */
	    } else if (!strcmp(argv[arg], "-flush")) {
		flush = YES;

	    /* Do a cache validation */
	    } else if (!strcmp(argv[arg], "-validate")) {
		cl->flags |= CL_VALIDATE;

	    /* Do an end-to-end cache-validation */
	    } else if (!strcmp(argv[arg], "-endvalidate")) {
		cl->flags |= CL_END_VALIDATE;

	    /* Force complete reload */
	    } else if (!strcmp(argv[arg], "-nocache")) {
		cl->flags |= CL_CACHE_FLUSH;

#ifdef WWWTRACE
	    /* trace flags */
	    } else if (!strncmp(argv[arg], "-v", 2)) {
		HTSetTraceMessageMask(argv[arg]+2);
#endif

	    /* GET method */
	    } else if (!strcasecomp(argv[arg], "-get")) {
		method = METHOD_GET;

	    /* HEAD method */
	    } else if (!strcasecomp(argv[arg], "-head")) {
		method = METHOD_HEAD;

	    /* DELETE method */
	    } else if (!strcasecomp(argv[arg], "-delete")) {
		method = METHOD_DELETE;

	    /* POST Method */
	    } else if (!strcasecomp(argv[arg], "-post")) {
		method = METHOD_POST;

	    /* PUT Method */
	    } else if (!strcasecomp(argv[arg], "-put")) {
		method = METHOD_PUT;

	    /* OPTIONS Method */
	    } else if (!strcasecomp(argv[arg], "-options")) {
		method = METHOD_OPTIONS;

	    /* TRACE Method */
	    } else if (!strcasecomp(argv[arg], "-trace")) {
		method = METHOD_TRACE;

	    } else {
		if (SHOW_MSG) HTPrint("Bad Argument (%s)\n", argv[arg]);
	    }
	} else {	 /* If no leading `-' then check for URL or keywords */
    	    if (!tokencount) {
		char * ref = HTParse(argv[arg], cl->cwd, PARSE_ALL);
		cl->anchor = (HTParentAnchor *) HTAnchor_findAddress(ref);
		tokencount = 1;
		HT_FREE(ref);
	    } else if (formdata) {		   /* Keywords are form data */
		char * string = argv[arg];
		if (tokencount++ <= 1) formfields = HTAssocList_new();
		HTParseFormInput(formfields, string);
	    } else {		   	       /* keywords are search tokens */
		char * escaped = HTEscape(argv[arg], URL_XALPHAS);
		if (tokencount++ <= 1)
		    keywords = HTChunk_new(128);
		else
		    HTChunk_putc(keywords, ' ');
		HTChunk_puts(keywords, HTStrip(escaped));
		HT_FREE(escaped);
	    }
	}
    }

    if (!tokencount && !cl->flags & CL_FILTER) {
	VersionInfo(argv[0]);
	Cleanup(cl, 0);
    }

    /* Should we use persistent cache? */
    if (cache) {
	HTCacheInit(cache_root, 20);

	/* Should we start by flushing? */
	if (flush) HTCache_flushAll();
    }

    /*
    ** Check whether we should do some kind of cache validation on
    ** the load
    */
    if (cl->flags & CL_VALIDATE)
	HTRequest_setReloadMode(cl->request, HT_CACHE_VALIDATE);
    else if (cl->flags & CL_END_VALIDATE)
	HTRequest_setReloadMode(cl->request, HT_CACHE_END_VALIDATE);
    else if (cl->flags & CL_CACHE_FLUSH)
	HTRequest_setReloadMode(cl->request, HT_CACHE_FLUSH);

    /* Add progress notification */
    if (cl->flags & CL_QUIET) HTAlert_deleteOpcode(HT_A_PROGRESS);

    /* Output file specified? */
    if (cl->outputfile) {
	if ((cl->output = fopen(cl->outputfile, "wb")) == NULL) {
	    if (SHOW_MSG) HTPrint("Can't open `%s'\\n",cl->outputfile);
	    cl->output = OUTPUT;
	}
    }

    /*
    ** Set up the output. Even though we don't use this explicit, it is
    ** required in order to show the stream stack that we know that we are
    ** getting raw data output on the output stream of the request object.
    */
    HTRequest_setOutputStream(cl->request,
			      HTFWriter_new(cl->request, cl->output, YES));

    /* Setting event timeout */
    HTHost_setEventTimeout(cl->timer);

    /*
    ** Make sure that the first request is flushed immediately and not
    ** buffered in the output buffer
    */
    HTRequest_setFlush(cl->request, YES);

    /* Log file specifed? */
    if (cl->logfile) {
	cl->log = HTLog_open(cl->logfile, YES, YES);
        if (cl->log) HTNet_addAfter(HTLogFilter, NULL, cl->log, HT_ALL, HT_FILTER_LATE);
    }

    /* Just convert formats */
    if (cl->flags & CL_FILTER) {
#ifdef STDIN_FILENO
	HTRequest_setAnchor(cl->request, (HTAnchor *) cl->anchor);
	HTRequest_setPreemptive(cl->request, YES);
	HTLoadSocket(STDIN_FILENO, cl->request);
#endif
	Cleanup(cl, 0);
    }
    
    /* Content Length Counter */
    if (cl->flags & CL_COUNT) {
	HTRequest_setOutputStream(cl->request,
				  HTContentCounter(HTBlackHole(),
						   cl->request, 0x2000));
    }

    /* Rule file specified? */
    if (cl->rules) {
	char * rules = HTParse(cl->rules, cl->cwd, PARSE_ALL);
	if (!HTLoadRulesAutomatically(rules))
	    if (SHOW_MSG) HTPrint("Can't access rules\n");
	HT_FREE(rules);
    }

    /* Add our own filter to update the history list */
    HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);

    /* Start the request */
    switch (method) {
    case METHOD_GET:

	if (formdata)
	    status = HTGetFormAnchor(formfields, (HTAnchor *) cl->anchor,
				     cl->request);
	else if (keywords)
	    status = HTSearchAnchor(keywords, (HTAnchor *) cl->anchor,
				    cl->request);
	else
	    status = HTLoadAnchor((HTAnchor *) cl->anchor, cl->request);
	break;

    case METHOD_HEAD:
	if (formdata) {
	    HTRequest_setMethod(cl->request, METHOD_HEAD);
	    status = HTGetFormAnchor(formfields, (HTAnchor *) cl->anchor,
				     cl->request);
	} else if (keywords) {
	    HTRequest_setMethod(cl->request, METHOD_HEAD);
	    status = HTSearchAnchor(keywords, (HTAnchor *) cl->anchor,
				    cl->request);
	} else
	    status = HTHeadAnchor((HTAnchor *) cl->anchor, cl->request);
	break;

    case METHOD_DELETE:
	status = HTDeleteAnchor((HTAnchor *) cl->anchor, cl->request);
	break;

    case METHOD_POST:
	if (formdata) {
	    HTParentAnchor * posted = NULL;
#if 1
	    posted = HTPostFormAnchor(formfields, (HTAnchor *) cl->anchor,
				      cl->request);
	    status = posted ? YES : NO;
#else
	    /* If we want output to a chunk instead */
	    post_result = HTPostFormAnchorToChunk(formfields, (HTAnchor *) cl->anchor,
						  cl->request);
	    status = post_result ? YES : NO;
#endif
	} else {
	    if (SHOW_MSG) HTPrint("Nothing to post to this address\n");
	    status = NO;	    
	}
	break;

    case METHOD_PUT:
	status = HTPutDocumentAnchor(cl->anchor, (HTAnchor *) cl->dest,
				     cl->request);
	break;

    case METHOD_OPTIONS:
	status = HTOptionsAnchor((HTAnchor *) cl->anchor, cl->request);
	break;	

    case METHOD_TRACE:
	status = HTTraceAnchor((HTAnchor *) cl->anchor, cl->request);
	break;	

    default:
	if (SHOW_MSG) HTPrint("Don't know this method\n");
	break;
    }

    if (keywords) HTChunk_delete(keywords);
    if (formfields) HTAssocList_delete(formfields);
    if (status != YES) {
	if (SHOW_MSG) HTPrint("Sorry, can't access resource\n");
	Cleanup(cl, -1);
    }

    /* Go into the event loop... */
    HTEventList_loop(cl->request);

    /* Only gets here if event loop fails */
    Cleanup(cl, 0);
    return 0;
}
Example #8
0
PUBLIC char * HTDialog_errorMessage (HTRequest * request, HTAlertOpcode op,
			             int msgnum, const char * dfault,
				     void * input)
{
    HTList * cur = (HTList *) input;
    HTError * pres;
    HTErrorShow showmask = HTError_show();
    HTChunk * msg = NULL;
    int code;
    if (!request || !cur) return NULL;
    while ((pres = (HTError *) HTList_nextObject(cur))) {
	int index = HTError_index(pres);
	if (HTError_doShow(pres)) {
	    if (!msg) {
		HTSeverity severity = HTError_severity(pres);
		msg = HTChunk_new(128);
		if (severity == ERR_WARN)
		    HTChunk_puts(msg, "Warning: ");
		else if (severity == ERR_NON_FATAL)
		    HTChunk_puts(msg, "Non Fatal Error: ");
		else if (severity == ERR_FATAL)
		    HTChunk_puts(msg, "Fatal Error: ");
		else if (severity == ERR_INFO)
		    HTChunk_puts(msg, "Information: ");
		else {
		    HTChunk_puts(msg, "UNKNOWN ERROR TYPE");
		    return HTChunk_toCString(msg);
		}

		/* Error number */
		if ((code = HTErrors[index].code) > 0) {
		    char buf[10];
		    sprintf(buf, "%d ", code);
		    HTChunk_puts(msg, buf);
		}
	    } else
		HTChunk_puts(msg, "\nReason: ");

	    if (index == HTERR_SYSTEM) {
		int length = 0;
		char * pars = (char *) HTError_parameter(pres, &length);
		HTChunk_puts(msg, HTError_location(pres));
		HTChunk_puts(msg, " ");
		HTChunk_puts(msg, HTErrors[index].msg);
		if (length && pars) {
		    HTChunk_puts(msg, " (");
		    HTChunk_puts(msg, pars);
		    HTChunk_puts(msg, ")");
		}
		
	    } else {

		/* Error message */
		HTChunk_puts(msg, HTErrors[index].msg);

		/* Error parameters */
		if (showmask & HT_ERR_SHOW_PARS) {
		    int length;
		    int cnt;		
		    char *pars = (char *) HTError_parameter(pres, &length);
		    if (length && pars) {
			HTChunk_puts(msg, " (");
			for (cnt=0; cnt<length; cnt++) {
			    char ch = *(pars+cnt);
			    if (ch < 0x20 || ch >= 0x7F)
				HTChunk_putc(msg, '#');
			    else
				HTChunk_putc(msg, ch);
			}
			HTChunk_puts(msg, ") ");
		    }
		}
		
		/* Error Location */
		if (showmask & HT_ERR_SHOW_LOCATION) {
		    HTChunk_puts(msg, "This occured in ");
		    HTChunk_puts(msg, HTError_location(pres));
		    HTChunk_putc(msg, '\n');
		}
	    }

	    /*
	    ** Make sure that we don't get this error more than once even
	    ** if we are keeping the error stack from one request to another
	    */
	    HTError_setIgnore(pres);
	    
	    /* If we only are show the most recent entry then break here */
	    if (showmask & HT_ERR_SHOW_FIRST)
		break;
	}
    }
    return HTChunk_toCString(msg);
}