/* 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 HTFWriter_free ARGS1(HTStream *, me) { if (me->cache) { time_t finish_time; time(&finish_time); me->cache->load_delay = finish_time - me->cache->load_time; /* Actually, ought to use draft ANSI-C difftime() */ /* But that I bet is more portable in real life (@@?) */ } if (me->leave_open != YES) fclose(me->fp); if (me->end_command) { /* Temp file */ HTProgress(me->end_command); /* Tell user what's happening */ system(me->end_command); /* @@ Beware of security hole */ free (me->end_command); if (me->remove_on_close) { unlink(me->filename); } } if (me->callback) { (*me->callback)(me->request, me->filename); } if (me->filename) free(me->filename); free(me); }
PUBLIC int HTSendMailTo ARGS4( WWW_CONST char *, arg, HTParentAnchor *, anAnchor, HTFormat, format_out, HTStream*, stream) { char *mailtoURL; char *mailtoSubject; #ifndef DISABLE_TRACE if (www2Trace) fprintf(stderr, "HTMailto: Mailing to %s\n", arg); #endif if (!initialized) initialized = initialize(); if (!initialized) { HTProgress ((char *) 0); return HT_NOT_LOADED; } { WWW_CONST char * p1=arg; /* We will ask for the document, omitting the host name & anchor. ** ** Syntax of address is ** xxx@yyy User xxx at site yyy (xxx is optional). */ if (!my_strncasecmp (arg, "mailto:", 7)) p1 = arg + 7; /* Skip "mailto:" prefix */ if (!*arg) { HTProgress ("Could not find email address"); return HT_NOT_LOADED; /* Ignore if no name */ } GetMailtoKludgeInfo(&mailtoURL,&mailtoSubject); (void) mo_post_mailto_win(p1,mailtoSubject); return HT_LOADED; } }
/* String handling ** --------------- ** ** Strings must be smaller than this buffer size. */ PRIVATE void HTFWriter_put_string ARGS2(HTStream *, me, WWW_CONST char*, s) { int rv; if (me->write_error) return; rv = fputs(s, me->fp); if (rv == EOF) { HTProgress ("Error writing to temporary file."); me->write_error = 1; } }
/* Buffer write. Buffers can (and should!) be big. ** ------------ */ PRIVATE void HTFWriter_write ARGS3(HTStream *, me, WWW_CONST char*, s, int, l) { int rv; if (me->write_error) return; rv = fwrite(s, 1, l, me->fp); if (rv != l) { HTProgress ("Error writing to temporary file."); me->write_error = 1; } }
PRIVATE void HTFWriter_put_character ARGS2(HTStream *, me, char, c) { int rv; if (me->write_error) return; /* Make sure argument to putc is in range 0-255, to avoid weirdness with rv == -1 == EOF when it's not supposed to. */ rv = putc ((int)(unsigned char)c, me->fp); if (rv == EOF) { HTProgress ("Error writing to temporary file."); me->write_error = 1; } }
/* Take action using a system command ** ---------------------------------- ** ** Creates temporary file, writes to it, executes system command ** on end-document. The suffix of the temp file can be given ** in case the application is fussy, or so that a generic opener can ** be used. ** ** WARNING: If force_dump_to_file is high, pres may be NULL ** (as we may get called directly from HTStreamStack). */ PUBLIC HTStream* HTSaveAndExecute ARGS5( HTPresentation *, pres, HTParentAnchor *, anchor, /* Not used */ HTStream *, sink, HTFormat, format_in, int, compressed) /* Not used */ { char *command; WWW_CONST char * suffix; HTStream* me; me = (HTStream*)malloc(sizeof(*me)); me->isa = &HTFWriter; me->interrupted = 0; me->write_error = 0; me->fnam = NULL; me->end_command = NULL; me->compressed = compressed; if (!format_in || !format_in->name || !*(format_in->name)) { me->mime_type=NULL; } else { if (!strncmp(format_in->name,"image",5)) { me->mime_type=strdup(format_in->name); } else { me->mime_type=NULL; } } #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "[HTSaveAndExecute] me->compressed is '%d'\n", me->compressed); #endif /* Save the file under a suitably suffixed name */ if (!force_dump_to_file) { extern char *mo_tmpnam (char *); suffix = HTFileSuffix(pres->rep); me->fnam = mo_tmpnam(anchor->address); if (suffix) { char *freeme = me->fnam; me->fnam = (char *)malloc (strlen (me->fnam) + strlen (suffix) + 8); strcpy(me->fnam, freeme); strcat(me->fnam, suffix); free (freeme); } } else { me->fnam = strdup (force_dump_filename); } me->fp = fopen (me->fnam, "w"); if (!me->fp) { HTProgress("Can't open temporary file -- serious problem."); me->write_error = 1; return me; } /* If force_dump_to_file is high, we're done here. */ if (!force_dump_to_file) { if (!strstr (pres->command, "mosaic-internal-reference")) { /* If there's a "%s" in the command, or if the command is magic... */ #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTFWriter: pres->command is '%s'\n", pres->command); #endif if (strstr (pres->command, "%s") || strstr (pres->command, "mosaic-internal")) { /* Make command to process file */ command = (char *)malloc ((strlen (pres->command) + 10 + 3*strlen(me->fnam)) * sizeof (char)); /* Cute. pres->command will be something like "xv %s"; me->fnam gets filled in as many times as appropriate. */ sprintf (command, pres->command, me->fnam, me->fnam, me->fnam); me->end_command = (char *)malloc ((strlen (command) + 32 + strlen(me->fnam)) * sizeof (char)); sprintf (me->end_command, "(%s ; /bin/rm -f %s) &", command, me->fnam); free (command); } else { /* Make command to process file -- but we have to cat to the viewer's stdin. */ me->end_command = (char *)malloc ((strlen (pres->command) + 64 + (2 * strlen(me->fnam))) * sizeof (char)); sprintf (me->end_command, "((cat %s | %s); /bin/rm -f %s) &", me->fnam, pres->command, me->fnam); } } else { /* Overload me->end_command to be what we should write out as text to communicate back to client code. */ me->end_command = (char *)malloc (strlen ("mosaic-internal-reference") + strlen (me->fnam) + 32); sprintf (me->end_command, "<%s \"%s\">\n", "mosaic-internal-reference", me->fnam); } } return me; }
/* 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 HTFWriter_free ARGS1(HTStream *, me) { HText *text; static char *envbuf1=NULL; static char *envbuf2=NULL; /* I dunno if this is necessary... */ if (me->interrupted) { free (me->fnam); free (me); return; } if (me->write_error) { /* char *cmd = (char *)malloc ((strlen (me->fnam) + 32)); sprintf (cmd, "/bin/rm -f %s &", me->fnam); system (cmd); free (cmd); */ /*ddt*/unlink(me->fnam); HTProgress ("Insufficient temporary disk space; could not transfer data."); free (me->fnam); free (me); return; } fflush (me->fp); fclose (me->fp); /* We do want to be able to handle compressed inlined images, but we don't want transparent uncompression to take place in binary transfer mode. */ if (!binary_transfer && me->compressed != COMPRESSED_NOT) { #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "[HTFWriter] Hi there; compressed is %d, fnam is '%s'\n", me->compressed, me->fnam); #endif HTCompressedFileToFile (me->fnam, me->compressed); } if (force_dump_to_file) { if (!binary_transfer) goto done; } /* Now, me->end_command can either be something starting with "<mosaic-internal-reference" or it can be a real command. Deal with appropriately. */ if (me->end_command) { /* Check for forced dump condition. The left paren comes from the construction of me->end_command as a compound shell command below. */ if (strstr (me->end_command, "mosaic-internal-dump")) { rename_binary_file (me->fnam); } else if (!strstr (me->end_command, "mosaic-internal-reference")) { if (imageViewInternal && supportedImageType(me->mime_type)) { char *newHTML="<html>\n<head>\n<title>Mosaic's Internal Image Display</title>\n</head>\n<body>\n<img align=center src=\"%s\">\n</body>\n</html>\n"; char *buf; buf=(char *)calloc((strlen(currentURL)+strlen(newHTML)+5),sizeof(char)); sprintf(buf,newHTML,currentURL); text=HText_new(); HText_beginAppend(text); HText_appendText(text,buf); HText_endAppend(text); free(buf); buf=(char *)calloc((strlen(currentURL)+strlen(me->fnam)+5),sizeof(char)); sprintf(buf,"%s\n%s",me->fnam,currentURL); ImageResolve(NULL,buf,0); free(buf); goto done; } HTProgress("Spawning external viewer."); /* * Have to dance around putenv since it makes "envbuf*" part * of the actual environment string...*sigh* What a mess! */ if (envbuf1) { envbuf2=(char *)calloc((strlen(currentURL)+ strlen("MOSAIC_CURRENT_URL=")+ 2), sizeof(char)); sprintf(envbuf2,"MOSAIC_CURRENT_URL=%s",currentURL); putenv(envbuf2); free(envbuf1); envbuf1=NULL; } else if (envbuf2) { envbuf1=(char *)calloc((strlen(currentURL)+ strlen("MOSAIC_CURRENT_URL=")+ 2), sizeof(char)); sprintf(envbuf1,"MOSAIC_CURRENT_URL=%s",currentURL); putenv(envbuf1); free(envbuf2); envbuf2=NULL; } else { /* Likely it is the first time */ envbuf1=(char *)calloc((strlen(currentURL)+ strlen("MOSAIC_CURRENT_URL=")+ 2), sizeof(char)); sprintf(envbuf1,"MOSAIC_CURRENT_URL=%s",currentURL); putenv(envbuf1); } system (me->end_command); if (envbuf1) { envbuf2=(char *)calloc((strlen("MOSAIC_CURRENT_URL=")+ 2), sizeof(char)); sprintf(envbuf2,"MOSAIC_CURRENT_URL="); putenv(envbuf2); free(envbuf1); envbuf1=NULL; } else if (envbuf2) { envbuf1=(char *)calloc((strlen("MOSAIC_CURRENT_URL=")+ 2), sizeof(char)); sprintf(envbuf1,"MOSAIC_CURRENT_URL="); putenv(envbuf1); free(envbuf2); envbuf2=NULL; } else { /* Likely it is the first time */ envbuf1=(char *)calloc((strlen("MOSAIC_CURRENT_URL=")+ 2), sizeof(char)); sprintf(envbuf1,"MOSAIC_CURRENT_URL="); putenv(envbuf1); } } else { /* Internal reference, aka HDF file. Just close output file. */ } } else { /* No me->end_command; just close the file. */ } /* Construct dummy HText thingie so Mosaic knows not to try to access this "document". */ text = HText_new (); HText_beginAppend (text); /* If it's a real internal reference, tell Mosaic. */ if (me->end_command) { if (strstr (me->end_command, "mosaic-internal-reference")) { HText_appendText (text, me->end_command); } else { HText_appendText (text, "<mosaic-access-override>\n"); } free (me->end_command); } else { /* No me->end_command; just override the access. */ HText_appendText (text, "<mosaic-access-override>\n"); } HText_endAppend (text); done: if (binary_transfer) rename_binary_file (me->fnam); really_done: free (me->fnam); if (me->mime_type) { free(me->mime_type); } free (me); return; }
PUBLIC int HTCopy ARGS3(int, file_number, HTStream*, sink, int, bytes_already_read) { HTStreamClass targetClass; char line[256]; char *msg; int bytes = bytes_already_read; extern int twirl_increment; int next_twirl = twirl_increment; int rv = 0; int left = -1, total_read = bytes_already_read, hdr_len = 0; /* if(loading_length != -1) left = loading_length;*/ HTClearActiveIcon(); /* Push the data down the stream ** */ targetClass = *(sink->isa); /* Copy pointers to procedures */ hdr_len = HTMIME_get_header_length(sink); /* Push binary from socket down sink */ for(;;) { int status, intr; if (bytes > next_twirl) { intr = HTCheckActiveIcon(1); next_twirl += twirl_increment; } else { intr = HTCheckActiveIcon(0); } if (intr) { #ifdef SWP_HACK loading_length=(-1); #endif HTProgress ("Data transfer interrupted."); noLength=0; HTMeter(100,NULL); noLength=1; (*targetClass.handle_interrupt)(sink); rv = -1; goto ready_to_leave; } if(loading_length == -1) { left = -1; status = NETREAD(file_number, input_buffer, INPUT_BUFFER_SIZE); } else { left = (loading_length+hdr_len)-total_read; if(left>0) status = NETREAD(file_number, input_buffer, (left>INPUT_BUFFER_SIZE? INPUT_BUFFER_SIZE:left)); else status=0; } if (status > 0) total_read += status; /* fprintf(stderr,"ll = %d status = %d left = %d hdr = %d tr = %d\n", loading_length,status,left,hdr_len,total_read); */ /* status = NETREAD(file_number, input_buffer, INPUT_BUFFER_SIZE); */ if (status <= 0) { if (status == 0) break; if (status == HT_INTERRUPTED) { #ifdef SWP_HACK loading_length=(-1); #endif HTProgress ("Data transfer interrupted."); noLength=0; HTMeter(100,NULL); noLength=1; (*targetClass.handle_interrupt)(sink); rv = -1; goto ready_to_leave; } if (errno == ENOTCONN || errno == ECONNRESET || errno == EPIPE) { /* Arrrrgh, HTTP 0/1 compability problem, maybe. */ rv = -2; goto ready_to_leave; } break; } #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTCopy: put_block on input_buffer '%s'\n", input_buffer); #endif (*targetClass.put_block)(sink, input_buffer, status); if (ftpKludge) { hdr_len=0; } else { hdr_len = HTMIME_get_header_length(sink); } /* left = loading_length - total_read;*/ bytes += status; /* moved msg stuff here as loading_length may change midstream -bjs*/ if (loading_length == -1){ msg = (loading_inlined_images ? "Read %d bytes of inlined image data." : "Read %d bytes of data."); sprintf (line, msg, bytes); /* HTMeter(0,NULL);*/ }else{ msg = (loading_inlined_images ? "Read %d of %d bytes of inlined image data." : "Read %d of %d bytes of data."); sprintf (line, msg, bytes, loading_length+hdr_len); HTMeter((bytes*100)/(loading_length+hdr_len),NULL); } HTProgress (line); if((loading_length != -1) && (total_read>=(loading_length+hdr_len))) { /* fprintf(stderr,"done\n");*/ break; } } /* next bufferload */ /* HTProgress (loading_inlined_images ? "Data transfer complete." : "Data transfer complete."); */ HTProgress("Data transfer complete."); noLength=0; HTMeter(100,NULL); noLength=1; /* fprintf(stderr,"HTFormat: KeepAlive Exit\n");*/ /* NETCLOSE (file_number); */ /* Success. */ rv = 0; ready_to_leave: /* Reset ourselves so we don't get confused. */ loading_length = -1; return rv; }
/* Load by name HTLoadFinger * ============ */ int HTLoadFinger(const char *arg, HTParentAnchor *anAnchor, HTFormat format_out, HTStream *stream) { static char empty[1]; char *username, *sitename; /* Fields extracted from URL */ char *slash, *at_sign; /* Fields extracted from URL */ char *command, *str, *param; /* Buffers */ int port; /* Port number from URL */ int status; /* tcp return */ int result = HT_LOADED; BOOL IsGopherURL = FALSE; const char *p1 = arg; CTRACE((tfp, "HTFinger: Looking for %s\n", (arg ? arg : "NULL"))); if (!(arg && *arg)) { HTAlert(COULD_NOT_LOAD_DATA); return HT_NOT_LOADED; /* Ignore if no name */ } if (!initialized) initialized = initialize(); if (!initialized) { HTAlert(gettext("Could not set up finger connection.")); return HT_NOT_LOADED; /* FAIL */ } /* Set up the host and command fields. */ if (!strncasecomp(arg, "finger://", 9)) { p1 = arg + 9; /* Skip "finger://" prefix */ } else if (!strncasecomp(arg, "gopher://", 9)) { p1 = arg + 9; /* Skip "gopher://" prefix */ IsGopherURL = TRUE; } param = 0; sitename = StrAllocCopy(param, p1); if (param == 0) { HTAlert(COULD_NOT_LOAD_DATA); return HT_NOT_LOADED; } else if ((slash = StrChr(sitename, '/')) != NULL) { *slash++ = '\0'; HTUnEscape(slash); if (IsGopherURL) { if (*slash != '0') { HTAlert(COULD_NOT_LOAD_DATA); return HT_NOT_LOADED; /* FAIL */ } *slash++ = '\0'; } } if ((at_sign = StrChr(sitename, '@')) != NULL) { if (IsGopherURL) { HTAlert(COULD_NOT_LOAD_DATA); return HT_NOT_LOADED; /* FAIL */ } else { *at_sign++ = '\0'; username = sitename; sitename = at_sign; HTUnEscape(username); } } else if (slash) { username = slash; } else { username = empty; } if (*sitename == '\0') { HTAlert(gettext("Could not load data (no sitename in finger URL)")); result = HT_NOT_LOADED; /* Ignore if no name */ } else if (HTParsePort(sitename, &port) != NULL) { if (port != 79) { HTAlert(gettext("Invalid port number - will only use port 79!")); result = HT_NOT_LOADED; /* Ignore if wrong port */ } } if (result == HT_LOADED) { /* Load the string for making a connection/ */ str = 0; HTSprintf0(&str, "lose://%s/", sitename); /* Load the command for the finger server. */ command = 0; if (at_sign && slash) { if (*slash == 'w' || *slash == 'W') { HTSprintf0(&command, "/w %s%c%c", username, CR, LF); } else { HTSprintf0(&command, "%s%c%c", username, CR, LF); } } else if (at_sign) { HTSprintf0(&command, "%s%c%c", username, CR, LF); } else if (*username == '/') { if ((slash = StrChr((username + 1), '/')) != NULL) { *slash = ' '; } HTSprintf0(&command, "%s%c%c", username, CR, LF); } else if ((*username == 'w' || *username == 'W') && *(username + 1) == '/') { if (*username + 2 != '\0') { *(username + 1) = ' '; } else { *(username + 1) = '\0'; } HTSprintf0(&command, "/%s%c%c", username, CR, LF); } else if ((*username == 'w' || *username == 'W') && *(username + 1) == '\0') { HTSprintf0(&command, "/%s%c%c", username, CR, LF); } else if ((slash = StrChr(username, '/')) != NULL) { *slash++ = '\0'; if (*slash == 'w' || *slash == 'W') { HTSprintf0(&command, "/w %s%c%c", username, CR, LF); } else { HTSprintf0(&command, "%s%c%c", username, CR, LF); } } else { HTSprintf0(&command, "%s%c%c", username, CR, LF); } /* Now, let's get a stream setup up from the FingerHost: * CONNECTING to finger host */ CTRACE((tfp, "HTFinger: doing HTDoConnect on '%s'\n", str)); status = HTDoConnect(str, "finger", FINGER_PORT, &finger_fd); CTRACE((tfp, "HTFinger: Done DoConnect; status %d\n", status)); if (status == HT_INTERRUPTED) { /* Interrupt cleanly */ CTRACE((tfp, "HTFinger: Interrupted on connect; recovering cleanly.\n")); HTProgress(CONNECTION_INTERRUPTED); result = HT_NOT_LOADED; } else if (status < 0) { NETCLOSE(finger_fd); finger_fd = -1; CTRACE((tfp, "HTFinger: Unable to connect to finger host.\n")); HTAlert(gettext("Could not access finger host.")); result = HT_NOT_LOADED; /* FAIL */ } else { CTRACE((tfp, "HTFinger: Connected to finger host '%s'.\n", str)); /* Send the command, and process response if successful. */ if (response(command, sitename, anAnchor, format_out, stream) != 0) { HTAlert(gettext("No response from finger server.")); result = HT_NOT_LOADED; } } FREE(str); FREE(command); } FREE(param); return result; }
/* Translate by rules HTTranslate() * ------------------ * * The most recently defined rules are applied first. * * On entry, * required points to a string whose equivalent value is needed * On exit, * returns the address of the equivalent string allocated from * the heap which the CALLER MUST FREE. If no translation * occurred, then it is a copy of the original. * NEW FEATURES: * When a "protect" or "defprot" rule is matched, * a call to HTAA_setCurrentProtection() or * HTAA_setDefaultProtection() is made to notify * the Access Authorization module that the file is * protected, and so it knows how to handle it. * -- AL */ char *HTTranslate(const char *required) { rule *r; char *current = NULL; char *msgtmp = NULL; const char *pMsg; int proxy_none_flag = 0; int permitredir_flag = 0; StrAllocCopy(current, required); HTAA_clearProtections(); /* Reset from previous call -- AL */ for (r = rules; r; r = r->next) { char *p = r->pattern; int m = 0; /* Number of characters matched against wildcard */ const char *q = current; for (; *p && *q; p++, q++) { /* Find first mismatch */ if (*p != *q) break; } if (*p == '*') { /* Match up to wildcard */ m = strlen(q) - strlen(p + 1); /* Amount to match to wildcard */ if (m < 0) continue; /* tail is too short to match */ if (0 != strcmp(q + m, p + 1)) continue; /* Tail mismatch */ } else /* Not wildcard */ if (*p != *q) continue; /* plain mismatch: go to next rule */ if (!rule_cond_ok(r)) /* check condition, next rule if false - kw */ continue; switch (r->op) { /* Perform operation */ #ifdef ACCESS_AUTH case HT_DefProt: case HT_Protect: { char *local_copy = NULL; char *p2; char *eff_ids = NULL; char *prot_file = NULL; CTRACE((tfp, "HTRule: `%s' matched %s %s: `%s'\n", current, (r->op == HT_Protect ? "Protect" : "DefProt"), "rule, setup", (r->equiv ? r->equiv : (r->op == HT_Protect ? "DEFAULT" : "NULL!!")))); if (r->equiv) { StrAllocCopy(local_copy, r->equiv); p2 = local_copy; prot_file = HTNextField(&p2); eff_ids = HTNextField(&p2); } if (r->op == HT_Protect) HTAA_setCurrentProtection(current, prot_file, eff_ids); else HTAA_setDefaultProtection(current, prot_file, eff_ids); FREE(local_copy); /* continue translating rules */ } break; #endif /* ACCESS_AUTH */ case HT_UserMsg: /* Produce message immediately */ LYFixCursesOn("show rule message:"); HTUserMsg2((r->equiv ? r->equiv : "Rule: %s"), current); break; case HT_InfoMsg: /* Produce messages immediately */ case HT_Progress: case HT_Alert: LYFixCursesOn("show rule message:"); /* and fall through */ case HT_AlwaysAlert: pMsg = r->equiv ? r->equiv : (r->op == HT_AlwaysAlert) ? "%s" : "Rule: %s"; if (strchr(pMsg, '%')) { HTSprintf0(&msgtmp, pMsg, current); pMsg = msgtmp; } switch (r->op) { /* Actually produce message */ case HT_InfoMsg: HTInfoMsg(pMsg); break; case HT_Progress: HTProgress(pMsg); break; case HT_Alert: HTAlert(pMsg); break; case HT_AlwaysAlert: HTAlwaysAlert("Rule alert:", pMsg); break; default: break; } FREE(msgtmp); break; case HT_PermitRedir: /* Set special flag */ permitredir_flag = 1; CTRACE((tfp, "HTRule: Mark for redirection permitted\n")); break; case HT_Pass: /* Authorised */ if (!r->equiv) { if (proxy_none_flag) { char *temp = NULL; StrAllocCopy(temp, "NoProxy="); StrAllocCat(temp, current); FREE(current); current = temp; } CTRACE((tfp, "HTRule: Pass `%s'\n", current)); return current; } /* Else fall through ...to map and pass */ case HT_Map: case HT_Redirect: case HT_RedirectPerm: if (*p == *q) { /* End of both strings, no wildcard */ CTRACE((tfp, "For `%s' using `%s'\n", current, r->equiv)); StrAllocCopy(current, r->equiv); /* use entire translation */ } else { char *ins = strchr(r->equiv, '*'); /* Insertion point */ if (ins) { /* Consistent rule!!! */ char *temp = NULL; HTSprintf0(&temp, "%.*s%.*s%s", (int) (ins - r->equiv), r->equiv, m, q, ins + 1); CTRACE((tfp, "For `%s' using `%s'\n", current, temp)); FREE(current); current = temp; /* Use this */ } else { /* No insertion point */ char *temp = NULL; StrAllocCopy(temp, r->equiv); CTRACE((tfp, "For `%s' using `%s'\n", current, temp)); FREE(current); current = temp; /* Use this */ } /* If no insertion point exists */ } if (r->op == HT_Pass) { if (proxy_none_flag) { char *temp = NULL; StrAllocCopy(temp, "NoProxy="); StrAllocCat(temp, current); FREE(current); current = temp; } CTRACE((tfp, "HTRule: ...and pass `%s'\n", current)); return current; } else if (r->op == HT_Redirect) { CTRACE((tfp, "HTRule: ...and redirect to `%s'\n", current)); redirecting_url = current; HTPermitRedir = (BOOL) (permitredir_flag == 1); return (char *) 0; } else if (r->op == HT_RedirectPerm) { CTRACE((tfp, "HTRule: ...and redirect like 301 to `%s'\n", current)); redirecting_url = current; permanent_redirection = TRUE; HTPermitRedir = (BOOL) (permitredir_flag == 1); return (char *) 0; } break; case HT_UseProxy: if (r->equiv && 0 == strcasecomp(r->equiv, "none")) { CTRACE((tfp, "For `%s' will not use proxy\n", current)); proxy_none_flag = 1; } else if (proxy_none_flag) { CTRACE((tfp, "For `%s' proxy server ignored: %s\n", current, NONNULL(r->equiv))); } else { char *temp = NULL; StrAllocCopy(temp, "Proxied="); StrAllocCat(temp, r->equiv); StrAllocCat(temp, current); CTRACE((tfp, "HTRule: proxy server found: %s\n", NONNULL(r->equiv))); FREE(current); return temp; } break; case HT_Invalid: case HT_Fail: /* Unauthorised */ CTRACE((tfp, "HTRule: *** FAIL `%s'\n", current)); FREE(current); return (char *) 0; } /* if tail matches ... switch operation */ } /* loop over rules */ if (proxy_none_flag) { char *temp = NULL; StrAllocCopy(temp, "NoProxy="); StrAllocCat(temp, current); FREE(current); return temp; } return current; }
void HTFWriter_free( HTStream *me ) { int len; char *path = 0; char *addr = 0; int status; BOOLEAN use_zread = 0; BOOLEAN found = 0; if ( me->fp ) fflush( &me->fp ); if ( me->end_command ) { LYCloseTempFP( &me->fp ); if ( me->input_format == HTAtom_for( "www/compressed" ) ) { if ( me->anchor->FileCache ) { BOOLEAN skip_loadfile = me->viewer_command != 0; HTSACopy( &path, &me->anchor->FileCache ); len = strlen( path ); if ( len > 3 && ( strcasecomp( &path[ len + -2 ], "gz" ) == 0 || strcasecomp( &path[ len + -2 ], "zz" ) == 0 ) ) { if ( skip_loadfile == 0 ) use_zread = 1; else { path[ len + -3 ] = 0; remove( path ); } } else if ( len > 4 && strcasecomp( &path[ len + -3 ], "bz2" ) == 0 ) { path[ len + -4 ] = 0; remove( path ); } else if ( len > 2 && strcasecomp( &path[ len + -1 ], "Z" ) == 0 ) { path[ len + -2 ] = 0; remove( path ); } if ( use_zread == 0 ) { if ( dump_output_immediately == 0 ) { mustshow = 1; HTProgress( &me->end_command ); } if ( me->end_command && me->end_command[0] ) LYSystem( &me->end_command ); found = LYCanReadFile( &me->anchor->FileCache ); } if ( found ) { if ( dump_output_immediately == 0 ) { lynx_force_repaint( ); LYrefresh( ); } HTAlert( gettext( "Error uncompressing temporary file!" ) ); LYRemoveTemp( &me->anchor->FileCache ); if ( me->anchor->FileCache ) { free( &me->anchor->FileCache ); me->anchor->FileCache = 0; } } else { LYLocalFileToURL( &addr, path ); if ( use_zread == 0 ) { LYRenamedTemp( &me->anchor->FileCache, path ); HTSACopy( &me->anchor->FileCache, path ); HTSACopy( &me->anchor->content_encoding, "binary" ); } if ( path ) { free( path ); path = 0; } if ( skip_loadfile == 0 ) { if ( HTAnchor_getUCLYhndl( &me->anchor, 1 ) < 0 ) HTAnchor_copyUCInfoStage( &me->anchor, 1, 0, 2 ); HTAnchor_copyUCInfoStage( &me->anchor, 1, 0, -1 ); } if ( dump_output_immediately == 0 ) { LYstore_message2( gettext( "Using %s" ), addr ); } if ( skip_loadfile ) { if ( me->end_command ) { free( &me->end_command ); *(int*)&me->end_command = 0; } HTAddParam( &me->end_command, &me->viewer_command, 1, &me->anchor->FileCache ); HTEndParam( &me->end_command, &me->viewer_command, 1 ); if ( dump_output_immediately == 0 ) { HTProgress( &me->end_command ); stop_curses( ); } LYSystem( &me->end_command ); if ( me->remove_command && me->remove_command ) { free( &me->remove_command ); *(int*)&me->remove_command = 0; } if ( dump_output_immediately == 0 ) start_curses( ); } else { status = HTLoadFile( addr, &me->anchor, &me->output_format, &me->sink ); } if ( dump_output_immediately && me->output_format == HTAtom_for( "www/present" ) ) { if ( addr ) { free( addr ); addr = 0; } remove( &me->anchor->FileCache ); if ( me->anchor->FileCache ) { free( &me->anchor->FileCache ); me->anchor->FileCache = 0; } if ( me->remove_command ) { free( &me->remove_command ); *(int*)&me->remove_command = 0; } if ( me->end_command ) { free( &me->end_command ); *(int*)&me->end_command = 0; } if ( me->viewer_command ) { free( &me->viewer_command ); *(int*)&me->viewer_command = 0; } if ( me == 0 ) { return; } free( me ); me = 0; return; } } if ( addr ) { free( addr ); addr = 0; } } if ( me->remove_command && me->remove_command ) { free( &me->remove_command ); *(int*)&me->remove_command = 0; } } else { if ( strcmp( &me->end_command, "SaveToFile" ) ) { if ( dump_output_immediately == 0 ) { mustshow = 1; HTProgress( &me->end_command ); stop_curses( ); } LYSystem( &me->end_command ); if ( me->remove_command && me->remove_command ) { free( &me->remove_command ); *(int*)&me->remove_command = 0; } if ( dump_output_immediately == 0 ) start_curses( ); } else { if ( me->remove_command && me->remove_command ) { free( &me->remove_command ); *(int*)&me->remove_command = 0; } if ( dump_output_immediately == 0 ) start_curses( ); } } if ( me->end_command ) { free( &me->end_command ); *(int*)&me->end_command = 0; } } if ( me->viewer_command ) { free( &me->viewer_command ); *(int*)&me->viewer_command = 0; } if ( dump_output_immediately ) { if ( me->anchor->FileCache ) remove( &me->anchor->FileCache ); if ( me ) { free( me ); me = 0; } if ( persistent_cookies ) LYStoreCookies( LYCookieSaveFile ); exit_immediately( 0 ); } if ( me == 0 ) { return; } free( me ); me = 0; return; }
PUBLIC int HTLoadHTTP ARGS4 ( char *, arg, HTParentAnchor *, anAnchor, HTFormat, format_out, HTStream*, sink) { int s; /* Socket number for returned data */ char *command; /* The whole command */ char *eol; /* End of line if found */ char *start_of_data; /* Start of body of reply */ int status; /* tcp return */ int bytes_already_read; char crlf[3]; /* A CR LF equivalent string */ HTStream *target; /* Unconverted data */ HTFormat format_in; /* Format arriving in the message */ char *line_buffer; char *line_kept_clean; BOOL extensions; /* Assume good HTTP server */ int compressed; char line[2048]; /* bumped up to cover Kerb huge headers */ int length, doing_redirect, rv; int already_retrying = 0; int return_nothing; int i; int keepingalive = 0; char *p; /*SWP*/ int statusError=0; if (!arg) { status = -3; HTProgress ("Bad request."); goto done; } if (!*arg) { status = -2; HTProgress ("Bad request."); goto done; } sprintf(crlf, "%c%c", CR, LF); /* At this point, we're talking HTTP/1.0. */ extensions = YES; try_again: /* All initializations are moved down here from up above, so we can start over here... */ eol = 0; bytes_already_read = 0; length = 0; doing_redirect = 0; compressed = 0; target = NULL; line_buffer = NULL; line_kept_clean = NULL; return_nothing = 0; /* okay... addr looks like http://hagbard.ncsa.uiuc.edu/blah/etc.html lets crop it at the 3rd '/' */ for(p = arg,i=0;*p && i!=3;p++) if(*p=='/') i++; if(i==3) i = p-arg; /* i = length not counting last '/' */ else i = 0; if((lsocket != -1) && i && addr && !strncmp(addr,arg,i)){ /* keepalive is active and addresses match -- try the old socket */ s = lsocket; keepingalive = 1; /* flag in case of network error due to server timeout*/ lsocket = -1; /* prevent looping on failure */ #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Keep-Alive reusing '%s'\n",addr); #endif /* if (addr && *addr) { sprintf(tmpbuf,"Reusing socket from %s.",addr); HTProgress(tmpbuf); } */ } else { if(addr) free(addr); /* save the address for next time around */ addr = malloc(i+1); strncpy(addr,arg,i); *(addr+i)=0; keepingalive = 0; /* just normal opening of the socket */ if(lsocket != -1) NETCLOSE(lsocket); /* no socket leaks here */ lsocket = -1; /*dont assign until we know the server says okay */ #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Keep-Alive saving '%s'\n",addr); #endif /* if (addr && *addr) { sprintf(tmpbuf,"Saving %s for possible socket reuse.",addr); HTProgress(tmpbuf); } */ } if (!keepingalive) { status = HTDoConnect (arg, "HTTP", TCP_PORT, &s); if (status == HT_INTERRUPTED){ /* Interrupt cleanly. */ #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Interrupted on connect; recovering cleanly.\n"); #endif HTProgress ("Connection interrupted."); /* status already == HT_INTERRUPTED */ goto done; } if (status < 0) { #ifndef DISABLE_TRACE if (www2Trace) fprintf(stderr, "HTTP: Unable to connect to remote host for `%s' (errno = %d).\n", arg, errno); #endif HTProgress ("Unable to connect to remote host."); status = HT_NO_DATA; goto done; } } /* Ask that node for the document, ** omitting the host name & anchor */ { char * p1 = HTParse(arg, "", PARSE_PATH|PARSE_PUNCTUATION); command = malloc(5 + strlen(p1)+ 2 + 31); if (do_post && !do_put) strcpy(command, "POST "); else if (do_post && do_put) strcpy(command, "PUT "); else if (do_head) strcpy(command, "HEAD "); else if (do_meta) strcpy(command, "META "); else strcpy(command, "GET "); /* * For a gateway, the beginning '/' on the request must * be stripped before appending to the gateway address. */ if ((using_gateway)||(using_proxy)) { strcat(command, p1+1); } else strcat(command, p1); free(p1); } if (extensions) { strcat(command, " "); strcat(command, HTTP_VERSION); } strcat(command, crlf); /* CR LF, as in rfc 977 */ if (extensions) { #ifdef SAM_NOT_YET /* SAM This produces an absolutely huge Accept: line. While there is probably a better way to turn this off, just compiling it out works for now. */ int n, i; if (!HTPresentations) HTFormatInit(); n = HTList_count(HTPresentations); begin_ptr=command+strlen(command); env_length=0; sprintf(line, "Accept:"); env_length+=strlen(line); StrAllocCat(command, line); /* KCMS Accept Header - swp */ if (KCMS_Return_Format==JPEG) { sprintf(line," image/x-pcd-jpeg,"); StrAllocCat(command, line); env_length+=strlen(line); } else if (KCMS_Return_Format==JYCC) { sprintf(line," image/x-pcd-jycc,"); StrAllocCat(command, line); env_length+=strlen(line); } else if (KCMS_Return_Format==GIF) { sprintf(line," image/x-pcd-gif,"); StrAllocCat(command, line); env_length+=strlen(line); } for(i=0; i<n; i++) { HTPresentation * pres = HTList_objectAt(HTPresentations, i); if (pres->rep_out == WWW_PRESENT) { sprintf(line, " %s,",HTAtom_name(pres->rep)); env_length+=strlen(line); StrAllocCat(command, line); if (env_length>200) { if ((tmp_ptr=strrchr(command,','))!=NULL) { *tmp_ptr='\0'; } sprintf(line, "%c%c",CR,LF); StrAllocCat(command, line); begin_ptr=command+strlen(command); sprintf(line, "Accept:"); env_length=strlen(line); StrAllocCat(command, line); } } } /* This gets rid of the last comma. */ if ((tmp_ptr=strrchr(command,','))!=NULL) { *tmp_ptr='\0'; sprintf(line, "%c%c",CR,LF); StrAllocCat(command, line); } else { /* No accept stuff...get rid of "Accept:" */ begin_ptr='\0'; } #endif /* if reloading, send no-cache pragma to proxy servers. --swp */ /* original patch from Ari L. <*****@*****.**> */ if (reloading) { sprintf(line, "Pragma: no-cache%c%c", CR, LF); StrAllocCat(command, line); } /*This is just used for "not" sending this header on a proxy request*/ if (useKeepAlive) { sprintf(line, "Connection: keep-alive%c%c", CR, LF); StrAllocCat(command, line); } if (sendAgent) { sprintf(line, "User-Agent: %s%c%c",agent[selectedAgent],CR,LF); /* sprintf(line, "User-Agent: %s/%s libwww/%s%c%c", HTAppName ? HTAppName : "unknown", HTAppVersion ? HTAppVersion : "0.0", HTLibraryVersion, CR, LF); */ StrAllocCat(command, line); } if (sendReferer) { /* HTTP Referer field, specifies back-link URL - amb */ if (HTReferer) { sprintf(line, "Referer: %s%c%c", HTReferer, CR, LF); StrAllocCat(command, line); HTReferer = NULL; } } { char *tmp,*startPtr,*endPtr; /* addr is always in URL form */ if (addr && !using_proxy && !using_gateway) { tmp=strdup(addr); startPtr=strchr(tmp,'/'); if (startPtr) { startPtr+=2; /*now at begining of hostname*/ if (*startPtr) { endPtr=strchr(startPtr,':'); if (!endPtr) { endPtr=strchr(startPtr,'/'); if (endPtr && *endPtr) { *endPtr='\0'; } } else { *endPtr='\0'; } sprintf(line, "Host: %s%c%c", startPtr, CR, LF); StrAllocCat(command, line); free(tmp); tmp=startPtr=endPtr=NULL; } } } else if (using_proxy || using_gateway) { sprintf(line, "Host: %s%c%c", proxy_host_fix, CR, LF); StrAllocCat(command, line); } } /* SWP -- 7/10/95 */ /* HTTP Extension headers */ /* Domain Restriction */ sprintf(line,"Extension: Notify-Domain-Restriction%c%c",CR,LF); StrAllocCat(command,line); /* BJS -- 12/05/95 -- allow arbitrary headers sent from browser */ if(extra_headers){ int h; for(h=0;extra_headers[h];h++){ sprintf(line,"%s%c%c",extra_headers[h],CR,LF); StrAllocCat(command,line); } } { char *docname; char *hostname; char *colon; int portnumber; char *auth; docname = HTParse(arg, "", PARSE_PATH); hostname = HTParse(arg, "", PARSE_HOST); if (hostname && NULL != (colon = strchr(hostname, ':'))) { *(colon++) = '\0'; /* Chop off port number */ portnumber = atoi(colon); } else portnumber = 80; if (NULL!=(auth=HTAA_composeAuth(hostname, portnumber, docname))) { sprintf(line, "%s%c%c", auth, CR, LF); StrAllocCat(command, line); } #ifndef DISABLE_TRACE if (www2Trace) { if (auth) fprintf(stderr, "HTTP: Sending authorization: %s\n", auth); else fprintf(stderr, "HTTP: Not sending authorization (yet)\n"); } #endif FREE(hostname); FREE(docname); } } if (do_post && !do_put) { #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Doing post, content-type '%s'\n", post_content_type); #endif sprintf (line, "Content-type: %s%c%c", post_content_type ? post_content_type : "lose", CR, LF); StrAllocCat(command, line); { int content_length; if (!post_data) content_length = 4; /* 4 == "lose" :-) */ else content_length = strlen (post_data); sprintf (line, "Content-length: %d%c%c", content_length, CR, LF); StrAllocCat(command, line); } StrAllocCat(command, crlf); /* Blank line means "end" */ if (post_data) StrAllocCat(command, post_data); else StrAllocCat(command, "lose"); } else if (do_post && do_put) { sprintf (line, "Content-length: %d%c%c", put_file_size, CR, LF); StrAllocCat(command, line); StrAllocCat(command, crlf); /* Blank line means "end" */ } else { StrAllocCat(command, crlf); /* Blank line means "end" */ } #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "Writing:\n%s----------------------------------\n", command); #endif /* HTProgress ("Sending HTTP request."); */ status = NETWRITE(s, command, (int)strlen(command)); if (do_post && do_put) { char buf[BUFSIZ]; int upcnt=0,n; while (status>0) { n=fread(buf,1,BUFSIZ-1,put_fp); upcnt+= status = NETWRITE(s, buf, n); #ifndef DISABLE_TRACE if (www2Trace) { fprintf(stderr,"[%d](%d) %s",status,n,buf); } #endif if (feof(put_fp)) { break; } } if (status<0 || !feof(put_fp) || upcnt!=put_file_size) { char tmpbuf[BUFSIZ]; sprintf(tmpbuf,"Status: %d -- EOF: %d -- UpCnt/FileSize: %d/%d\n\nThe server you connected to either does not support\nthe PUT method, or an error occurred.\n\nYour upload was corrupted! Please try again!",status,(feof(put_fp)?1:0),upcnt,put_file_size); application_error(tmpbuf,"Upload Error!"); } } /* Twirl on each request to make things look nicer -- SWP */ HTCheckActiveIcon(1); #ifndef DISABLE_TRACE if (httpTrace) { fprintf(stderr,"%s",command); } #endif free (command); if (status <= 0) { if (status == 0) { #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Got status 0 in initial write\n"); #endif /* Do nothing. */ } else if ((errno == ENOTCONN || errno == ECONNRESET || errno == EPIPE) && !already_retrying && /* Don't retry if we're posting. */ !do_post) { /* Arrrrgh, HTTP 0/1 compability problem, maybe. */ #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: BONZO ON WRITE Trying again with HTTP0 request.\n"); #endif /* HTProgress ("Retrying as HTTP0 request."); */ NETCLOSE(s); // SAM extensions = NO; already_retrying = 1; goto try_again; } else { if(keepingalive){ #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Timeout on Keep-Alive. Retrying.\n"); #endif HTProgress("Server Timeout: Reconnecting"); goto try_again; } #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Hit unexpected network WRITE error; aborting connection.\n"); #endif NETCLOSE (s); status = -1; HTProgress ("Unexpected network write error; connection aborted."); goto done; } } #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: WRITE delivered OK\n"); #endif HTProgress ("Done sending HTTP request; waiting for response."); /* Read the first line of the response ** ----------------------------------- */ { /* Get numeric status etc */ BOOL end_of_file = NO; int buffer_length = INIT_LINE_SIZE; line_buffer = (char *) malloc(buffer_length * sizeof(char)); do { /* Loop to read in the first line */ /* Extend line buffer if necessary for those crazy WAIS URLs ;-) */ if (buffer_length - length < LINE_EXTEND_THRESH) { buffer_length = buffer_length + buffer_length; line_buffer = (char *) realloc(line_buffer, buffer_length * sizeof(char)); } #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Trying to read %d\n", buffer_length - length - 1); #endif status = NETREAD(s, line_buffer + length, buffer_length - length - 1); #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Read %d\n", status); #endif if (status <= 0) { /* Retry if we get nothing back too; bomb out if we get nothing twice. */ if (status == HT_INTERRUPTED) { #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Interrupted initial read.\n"); #endif HTProgress ("Connection interrupted."); status = HT_INTERRUPTED; NETCLOSE (s); goto clean_up; } else if (status < 0 && (errno == ENOTCONN || errno == ECONNRESET || errno == EPIPE) && !already_retrying && !do_post) { /* Arrrrgh, HTTP 0/1 compability problem, maybe. */ #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: BONZO Trying again with HTTP0 request.\n"); #endif NETCLOSE(s); if (line_buffer) free(line_buffer); if (line_kept_clean) free(line_kept_clean); extensions = NO; already_retrying = 1; HTProgress ("Retrying as HTTP0 request."); goto try_again; } else { if(keepingalive){ #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Timeout on Keep-Alive. Retrying.\n"); #endif HTProgress("Server Timeout: Reconnecting"); goto try_again; } #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Hit unexpected network read error; aborting connection; status %d.\n", status); #endif HTProgress ("Unexpected network read error; connection aborted."); NETCLOSE (s); status = -1; goto clean_up; } } bytes_already_read += status; { char line[256]; sprintf (line, "Read %d bytes of data.", bytes_already_read); HTProgress (line); } if (status == 0) { end_of_file = YES; break; } line_buffer[length+status] = 0; if (line_buffer) { if (line_kept_clean) free (line_kept_clean); line_kept_clean = (char *)malloc (buffer_length * sizeof (char)); /* bcopy (line_buffer, line_kept_clean, buffer_length); */ memcpy (line_kept_clean, line_buffer, buffer_length); } eol = strchr(line_buffer + length, LF); /* Do we *really* want to do this? */ if (eol && eol != line_buffer && *(eol-1) == CR) *(eol-1) = ' '; length = length + status; /* Do we really want to do *this*? */ if (eol) *eol = 0; /* Terminate the line */ /* All we need is the first line of the response. If it's a HTTP/1.0 response, then the first line will be absurdly short and therefore we can safely gate the number of bytes read through this code (as opposed to below) to ~1000. */ /* Well, let's try 100. */ } while (!eol && !end_of_file && bytes_already_read < 100); } /* Scope of loop variables */ /* We now have a terminated unfolded line. Parse it. ** ------------------------------------------------- */ #ifndef DISABLE_TRACE if (www2Trace) fprintf(stderr, "HTTP: Rx: %s\n", line_buffer); #endif { int fields; char server_version[VERSION_LENGTH+1]; int server_status; /*SWP*/ statusError=0; server_version[0] = 0; fields = sscanf(line_buffer, "%20s %d", server_version, &server_status); #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Scanned %d fields from line_buffer\n", fields); #endif #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: line_buffer '%s'\n", line_buffer); #endif /* Rule out HTTP/1.0 reply as best we can. */ if (fields < 2 || !server_version[0] || server_version[0] != 'H' || server_version[1] != 'T' || server_version[2] != 'T' || server_version[3] != 'P' || server_version[4] != '/' || server_version[6] != '.') { /* HTTP0 reply */ HTAtom * encoding; #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "--- Talking HTTP0.\n"); #endif format_in = HTFileFormat(arg, &encoding, WWW_HTML, &compressed); start_of_data = line_kept_clean; } else { /* Decode full HTTP response */ format_in = HTAtom_for("www/mime"); /* We set start_of_data to "" when !eol here because there will be a put_block done below; we do *not* use the value of start_of_data (as a pointer) in the computation of length or anything else in this situation. */ start_of_data = eol ? eol + 1 : ""; length = eol ? length - (start_of_data - line_buffer) : 0; #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "--- Talking HTTP1.\n"); #endif switch (server_status / 100) { case 3: /* Various forms of redirection */ /* We now support this in the parser, at least. */ doing_redirect = 1; break; case 4: /* "I think I goofed" */ switch (server_status) { case 403: statusError=1; /* 403 is "forbidden"; display returned text. */ break; case 401: /* length -= start_of_data - text_buffer; */ if (HTAA_shouldRetryWithAuth(start_of_data, length, s)) { (void)NETCLOSE(s); lsocket = -1; if (line_buffer) free(line_buffer); if (line_kept_clean) free(line_kept_clean); #ifndef DISABLE_TRACE if (www2Trace) fprintf(stderr, "%s %d %s\n", "HTTP: close socket", s, "to retry with Access Authorization"); #endif HTProgress ("Retrying with access authorization information."); goto try_again; break; } else { statusError=1; /* Fall through. */ } default: statusError=1; break; } /* case 4 switch */ break; case 5: /* I think you goofed */ statusError=1; break; case 2: /* Good: Got MIME object */ switch (server_status) { case 204: return_nothing = 1; format_in = HTAtom_for("text/html"); break; case 200: if (do_head) { if (!start_of_data || !*start_of_data) { headData=NULL; } else { char *ptr; headData=strdup(start_of_data); ptr=strchr(headData,'\n'); *ptr='\0'; } } break; default: break; } break; default: /* bad number */ statusError=1; HTAlert("Unknown status reply from server!"); break; } /* Switch on server_status/100 */ } /* Full HTTP reply */ } /* scope of fields */ /* Set up the stream stack to handle the body of the message */ target = HTStreamStack(format_in, format_out, compressed, sink, anAnchor); if (!target) { char buffer[1024]; /* @@@@@@@@ */ sprintf(buffer, "Sorry, no known way of converting %s to %s.", HTAtom_name(format_in), HTAtom_name(format_out)); HTProgress (buffer); status = -1; NETCLOSE (s); lsocket = -1; goto clean_up; } if (!return_nothing) { #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Doing put_block, '%s'\n", start_of_data); #endif /* BJS: parse start_of_data...*/ for(p=start_of_data;*p;p++){ /* if(*p=='C' && !strncmp("Content-length: ",p,16)){ i = 0; p+=16; while(*p && isdigit(*p)){ i = i*10 + *p-'0'; p++; } p--; #ifndef DISABLE_TRACE if(www2Trace) fprintf(stderr, "HTTP: Content Length is %d\n",i); #endif } */ if(*p=='K' && !strncmp("Keep-Alive:",p,11)){ #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Server Agrees to Keep-Alive\n"); #endif lsocket = s; p+=10; } } #ifndef DISABLE_TRACE if (www2Trace && lsocket == -1) fprintf (stderr, "HTTP: Server does not agree to Keep-Alive\n"); #endif /* Recycle the first chunk of data, in all cases. */ (*target->isa->put_block)(target, start_of_data, length); /* Go pull the bulk of the data down. */ /* if we dont use length, header length is wrong due to the discarded first line - bjs*/ rv = HTCopy(s, target, length /*bytes_already_read*/); if (rv == -1) { (*target->isa->handle_interrupt) (target); status = HT_INTERRUPTED; NETCLOSE (s); lsocket = -1; goto clean_up; } if (rv == -2 && !already_retrying && !do_post) { /* Aw hell. */ #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "HTTP: Trying again with HTTP0 request.\n"); #endif /* May as well consider it an interrupt -- right? */ (*target->isa->handle_interrupt) (target); NETCLOSE(s); if (line_buffer) free(line_buffer); if (line_kept_clean) free(line_kept_clean); extensions = NO; already_retrying = 1; HTProgress ("Retrying as HTTP0 request."); goto try_again; } } else { /* return_nothing is high. */ (*target->isa->put_string) (target, "<mosaic-access-override>\n"); HTProgress ("And silence filled the night."); } (*target->isa->end_document)(target); /* Close socket before doing free. */ if(lsocket == -1){ NETCLOSE(s); #ifndef DISABLE_TRACE if(www2Trace) fprintf(stderr,"HTTP: Closing connection\n"); #endif } else { HTProgress("Leaving Server Connection Open"); #ifndef DISABLE_TRACE if(www2Trace) fprintf(stderr,"HTTP: Keeping connection alive\n"); #endif } /* else { NETCLOSE(s); #ifndef DISABLE_TRACE if(www2Trace) fprintf(stderr,"HTTP: Closing connection\n"); #endif } */ (*target->isa->free)(target); if (doing_redirect) { /* OK, now we've got the redirection URL temporarily stored in external variable redirecting_url, exported from HTMIME.c, since there's no straightforward way to do this in the library currently. Do the right thing. */ status = HT_REDIRECTING; } else { status = HT_LOADED; } /* Clean up */ clean_up: if (line_buffer) free(line_buffer); if (line_kept_clean) free(line_kept_clean); done: /* Clear out on exit, just in case. */ do_post = 0; if (statusError) { securityType=HTAA_NONE; #ifndef DISABLE_TRACE if (www2Trace) fprintf(stderr,"Resetting security type to NONE.\n"); #endif } return status; }