/* ** 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; }
/* 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); }
/* ** 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; }
/* ** 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; }
PUBLIC void HTChunk_terminate (HTChunk * ch) { HTChunk_putc(ch, '\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; }
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; }
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); }