diff options
Diffstat (limited to 'WWW/Library/Implementation/HTFormat.c')
-rw-r--r-- | WWW/Library/Implementation/HTFormat.c | 1899 |
1 files changed, 0 insertions, 1899 deletions
diff --git a/WWW/Library/Implementation/HTFormat.c b/WWW/Library/Implementation/HTFormat.c deleted file mode 100644 index d66f5ae6..00000000 --- a/WWW/Library/Implementation/HTFormat.c +++ /dev/null @@ -1,1899 +0,0 @@ -/* - * $LynxId: HTFormat.c,v 1.68 2009/05/10 23:07:26 tom Exp $ - * - * Manage different file formats HTFormat.c - * ============================= - * - * Bugs: - * Not reentrant. - * - * Assumes the incoming stream is ASCII, rather than a local file - * format, and so ALWAYS converts from ASCII on non-ASCII machines. - * Therefore, non-ASCII machines can't read local files. - * - */ - -#include <HTUtils.h> - -/* Implements: -*/ -#include <HTFormat.h> - -static float HTMaxSecs = 1e10; /* No effective limit */ - -#ifdef UNIX -#ifdef NeXT -#define PRESENT_POSTSCRIPT "open %s; /bin/rm -f %s\n" -#else -#define PRESENT_POSTSCRIPT "(ghostview %s ; /bin/rm -f %s)&\n" - /* Full pathname would be better! */ -#endif /* NeXT */ -#endif /* UNIX */ - -#include <HTML.h> -#include <HTMLDTD.h> -#include <HText.h> -#include <HTAlert.h> -#include <HTList.h> -#include <HTInit.h> -#include <HTTCP.h> -#include <HTTP.h> -/* Streams and structured streams which we use: -*/ -#include <HTFWriter.h> -#include <HTPlain.h> -#include <SGML.h> -#include <HTMLGen.h> - -#include <LYexit.h> -#include <LYUtils.h> -#include <GridText.h> -#include <LYGlobalDefs.h> -#include <LYLeaks.h> - -#ifdef DISP_PARTIAL -#include <LYMainLoop.h> -#endif - -BOOL HTOutputSource = NO; /* Flag: shortcut parser to stdout */ - -#ifdef ORIGINAL -struct _HTStream { - const HTStreamClass *isa; - /* ... */ -}; -#endif /* ORIGINAL */ - -/* this version used by the NetToText stream */ -struct _HTStream { - const HTStreamClass *isa; - BOOL had_cr; - HTStream *sink; -}; - -/* Presentation methods - * -------------------- - */ -HTList *HTPresentations = NULL; -HTPresentation *default_presentation = NULL; - -/* - * To free off the presentation list. - */ -#ifdef LY_FIND_LEAKS -static void HTFreePresentations(void); -#endif - -/* Define a presentation system command for a content-type - * ------------------------------------------------------- - */ -void HTSetPresentation(const char *representation, - const char *command, - const char *testcommand, - double quality, - double secs, - double secs_per_byte, - long int maxbytes, - AcceptMedia media) -{ - HTPresentation *pres = typecalloc(HTPresentation); - - if (pres == NULL) - outofmem(__FILE__, "HTSetPresentation"); - - CTRACE2(TRACE_CFG, - (tfp, - "HTSetPresentation rep=%s, command=%s, test=%s, qual=%f\n", - NonNull(representation), - NonNull(command), - NonNull(testcommand), - quality)); - - pres->rep = HTAtom_for(representation); - pres->rep_out = WWW_PRESENT; /* Fixed for now ... :-) */ - pres->converter = HTSaveAndExecute; /* Fixed for now ... */ - pres->quality = (float) quality; - pres->secs = (float) secs; - pres->secs_per_byte = (float) secs_per_byte; - pres->maxbytes = maxbytes; - pres->get_accept = 0; - pres->accept_opt = media; - - pres->command = NULL; - StrAllocCopy(pres->command, command); - - pres->testcommand = NULL; - StrAllocCopy(pres->testcommand, testcommand); - - /* - * Memory leak fixed. - * 05-28-94 Lynx 2-3-1 Garrett Arch Blythe - */ - if (!HTPresentations) { - HTPresentations = HTList_new(); -#ifdef LY_FIND_LEAKS - atexit(HTFreePresentations); -#endif - } - - if (strcmp(representation, "*") == 0) { - FREE(default_presentation); - default_presentation = pres; - } else { - HTList_addObject(HTPresentations, pres); - } -} - -/* Define a built-in function for a content-type - * --------------------------------------------- - */ -void HTSetConversion(const char *representation_in, - const char *representation_out, - HTConverter *converter, - float quality, - float secs, - float secs_per_byte, - long int maxbytes, - AcceptMedia media) -{ - HTPresentation *pres = typecalloc(HTPresentation); - - if (pres == NULL) - outofmem(__FILE__, "HTSetConversion"); - - CTRACE2(TRACE_CFG, - (tfp, - "HTSetConversion rep_in=%s, rep_out=%s, qual=%f\n", - NonNull(representation_in), - NonNull(representation_out), - quality)); - - pres->rep = HTAtom_for(representation_in); - pres->rep_out = HTAtom_for(representation_out); - pres->converter = converter; - pres->command = NULL; - pres->testcommand = NULL; - pres->quality = quality; - pres->secs = secs; - pres->secs_per_byte = secs_per_byte; - pres->maxbytes = maxbytes; - pres->get_accept = TRUE; - pres->accept_opt = media; - - /* - * Memory Leak fixed. - * 05-28-94 Lynx 2-3-1 Garrett Arch Blythe - */ - if (!HTPresentations) { - HTPresentations = HTList_new(); -#ifdef LY_FIND_LEAKS - atexit(HTFreePresentations); -#endif - } - - HTList_addObject(HTPresentations, pres); -} - -#ifdef LY_FIND_LEAKS -/* - * Purpose: Free the presentation list. - * Arguments: void - * Return Value: void - * Remarks/Portability/Dependencies/Restrictions: - * Made to clean up Lynx's bad leakage. - * Revision History: - * 05-28-94 created Lynx 2-3-1 Garrett Arch Blythe - */ -static void HTFreePresentations(void) -{ - HTPresentation *pres = NULL; - - /* - * Loop through the list. - */ - while (!HTList_isEmpty(HTPresentations)) { - /* - * Free off each item. May also need to free off it's items, but not - * sure as of yet. - */ - pres = (HTPresentation *) HTList_removeLastObject(HTPresentations); - FREE(pres->command); - FREE(pres->testcommand); - FREE(pres); - } - /* - * Free the list itself. - */ - HTList_delete(HTPresentations); - HTPresentations = NULL; -} -#endif /* LY_FIND_LEAKS */ - -/* File buffering - * -------------- - * - * The input file is read using the macro which can read from - * a socket or a file. - * The input buffer size, if large will give greater efficiency and - * release the server faster, and if small will save space on PCs etc. - */ -#define INPUT_BUFFER_SIZE 4096 /* Tradeoff */ -static char input_buffer[INPUT_BUFFER_SIZE]; -static char *input_pointer; -static char *input_limit; -static int input_file_number; - -/* Set up the buffering - * - * These routines are public because they are in fact needed by - * many parsers, and on PCs and Macs we should not duplicate - * the static buffer area. - */ -void HTInitInput(int file_number) -{ - input_file_number = file_number; - input_pointer = input_limit = input_buffer; -} - -int interrupted_in_htgetcharacter = 0; -int HTGetCharacter(void) -{ - char ch; - - interrupted_in_htgetcharacter = 0; - do { - if (input_pointer >= input_limit) { - int status = NETREAD(input_file_number, - input_buffer, INPUT_BUFFER_SIZE); - - if (status <= 0) { - if (status == 0) - return EOF; - if (status == HT_INTERRUPTED) { - CTRACE((tfp, "HTFormat: Interrupted in HTGetCharacter\n")); - interrupted_in_htgetcharacter = 1; - return EOF; - } - CTRACE((tfp, "HTFormat: File read error %d\n", status)); - return EOF; /* -1 is returned by UCX - at end of HTTP link */ - } - input_pointer = input_buffer; - input_limit = input_buffer + status; - } - ch = *input_pointer++; - } while (ch == (char) 13); /* Ignore ASCII carriage return */ - - return FROMASCII(UCH(ch)); -} - -#ifdef USE_SSL -int HTGetSSLCharacter(void *handle) -{ - char ch; - - interrupted_in_htgetcharacter = 0; - if (!handle) - return (char) EOF; - do { - if (input_pointer >= input_limit) { - int status = SSL_read((SSL *) handle, - input_buffer, INPUT_BUFFER_SIZE); - - if (status <= 0) { - if (status == 0) - return (char) EOF; - if (status == HT_INTERRUPTED) { - CTRACE((tfp, - "HTFormat: Interrupted in HTGetSSLCharacter\n")); - interrupted_in_htgetcharacter = 1; - return (char) EOF; - } - CTRACE((tfp, "HTFormat: SSL_read error %d\n", status)); - return (char) EOF; /* -1 is returned by UCX - at end of HTTP link */ - } - input_pointer = input_buffer; - input_limit = input_buffer + status; - } - ch = *input_pointer++; - } while (ch == (char) 13); /* Ignore ASCII carriage return */ - - return FROMASCII(ch); -} -#endif /* USE_SSL */ - -/* Match maintype to any MIME type starting with maintype, for example: - * image/gif should match image - */ -static int half_match(char *trial_type, char *target) -{ - char *cp = strchr(trial_type, '/'); - - /* if no '/' or no '*' */ - if (!cp || *(cp + 1) != '*') - return 0; - - CTRACE((tfp, "HTFormat: comparing %s and %s for half match\n", - trial_type, target)); - - /* main type matches */ - if (!strncmp(trial_type, target, (cp - trial_type) - 1)) - return 1; - - return 0; -} - -/* - * Evaluate a deferred mailcap test command, i.e.,. one that substitutes the - * document's charset or other values in %{name} format. - */ -static BOOL failsMailcap(HTPresentation *pres, HTParentAnchor *anchor) -{ - if (pres->testcommand != 0) { - if (LYTestMailcapCommand(pres->testcommand, - anchor->content_type_params) != 0) - return TRUE; - } - return FALSE; -} - -#define WWW_WILDCARD_REP_OUT HTAtom_for("*") - -/* Look up a presentation - * ---------------------- - * - * If fill_in is NULL, only look for an exact match. - * If a wildcard match is made, *fill_in is used to store - * a possibly modified presentation, and a pointer to it is - * returned. For an exact match, a pointer to the presentation - * in the HTPresentations list is returned. Returns NULL if - * nothing found. - kw - * - */ -static HTPresentation *HTFindPresentation(HTFormat rep_in, - HTFormat rep_out, - HTPresentation *fill_in, - HTParentAnchor *anchor) -{ - HTAtom *wildcard = NULL; /* = HTAtom_for("*"); lookup when needed - kw */ - int n; - int i; - HTPresentation *pres; - HTPresentation *match; - HTPresentation *strong_wildcard_match = 0; - HTPresentation *weak_wildcard_match = 0; - HTPresentation *last_default_match = 0; - HTPresentation *strong_subtype_wildcard_match = 0; - - CTRACE((tfp, "HTFormat: Looking up presentation for %s to %s\n", - HTAtom_name(rep_in), HTAtom_name(rep_out))); - - n = HTList_count(HTPresentations); - for (i = 0; i < n; i++) { - pres = (HTPresentation *) HTList_objectAt(HTPresentations, i); - if (pres->rep == rep_in) { - if (pres->rep_out == rep_out) { - if (failsMailcap(pres, anchor)) - continue; - CTRACE((tfp, "FindPresentation: found exact match: %s -> %s\n", - HTAtom_name(pres->rep), - HTAtom_name(pres->rep_out))); - return pres; - - } else if (!fill_in) { - continue; - } else { - if (!wildcard) - wildcard = WWW_WILDCARD_REP_OUT; - if (pres->rep_out == wildcard) { - if (failsMailcap(pres, anchor)) - continue; - if (!strong_wildcard_match) - strong_wildcard_match = pres; - /* otherwise use the first one */ - CTRACE((tfp, - "StreamStack: found strong wildcard match: %s -> %s\n", - HTAtom_name(pres->rep), - HTAtom_name(pres->rep_out))); - } - } - - } else if (!fill_in) { - continue; - - } else if (half_match(HTAtom_name(pres->rep), - HTAtom_name(rep_in))) { - if (pres->rep_out == rep_out) { - if (failsMailcap(pres, anchor)) - continue; - if (!strong_subtype_wildcard_match) - strong_subtype_wildcard_match = pres; - /* otherwise use the first one */ - CTRACE((tfp, - "StreamStack: found strong subtype wildcard match: %s -> %s\n", - HTAtom_name(pres->rep), - HTAtom_name(pres->rep_out))); - } - } - - if (pres->rep == WWW_SOURCE) { - if (pres->rep_out == rep_out) { - if (failsMailcap(pres, anchor)) - continue; - if (!weak_wildcard_match) - weak_wildcard_match = pres; - /* otherwise use the first one */ - CTRACE((tfp, - "StreamStack: found weak wildcard match: %s\n", - HTAtom_name(pres->rep_out))); - - } else if (!last_default_match) { - if (!wildcard) - wildcard = WWW_WILDCARD_REP_OUT; - if (pres->rep_out == wildcard) { - if (failsMailcap(pres, anchor)) - continue; - last_default_match = pres; - /* otherwise use the first one */ - } - } - } - } - - match = (strong_subtype_wildcard_match - ? strong_subtype_wildcard_match - : (strong_wildcard_match - ? strong_wildcard_match - : (weak_wildcard_match - ? weak_wildcard_match - : last_default_match))); - - if (match) { - *fill_in = *match; /* Specific instance */ - fill_in->rep = rep_in; /* yuk */ - fill_in->rep_out = rep_out; /* yuk */ - return fill_in; - } - - return NULL; -} - -/* Create a filter stack - * --------------------- - * - * If a wildcard match is made, a temporary HTPresentation - * structure is made to hold the destination format while the - * new stack is generated. This is just to pass the out format to - * MIME so far. Storing the format of a stream in the stream might - * be a lot neater. - * - */ -HTStream *HTStreamStack(HTFormat rep_in, - HTFormat rep_out, - HTStream *sink, - HTParentAnchor *anchor) -{ - HTPresentation temp; - HTPresentation *match; - HTStream *result; - - CTRACE((tfp, "HTFormat: Constructing stream stack for %s to %s (%s)\n", - HTAtom_name(rep_in), - HTAtom_name(rep_out), - NONNULL(anchor->content_type_params))); - - /* don't return on WWW_SOURCE some people might like - * to make use of the source!!!! LJM - */ -#if 0 - if (rep_out == WWW_SOURCE || rep_out == rep_in) - return sink; /* LJM */ -#endif - - if (rep_out == rep_in) { - result = sink; - - } else if ((match = HTFindPresentation(rep_in, rep_out, &temp, anchor))) { - if (match == &temp) { - CTRACE((tfp, "StreamStack: Using %s\n", HTAtom_name(temp.rep_out))); - } else { - CTRACE((tfp, "StreamStack: found exact match: %s -> %s\n", - HTAtom_name(match->rep), - HTAtom_name(match->rep_out))); - } - result = (*match->converter) (match, anchor, sink); - } else { - result = NULL; - } - if (TRACE) { - if (result && result->isa && result->isa->name) { - CTRACE((tfp, "StreamStack: Returning \"%s\"\n", result->isa->name)); - } else if (result) { - CTRACE((tfp, "StreamStack: Returning *unknown* stream!\n")); - } else { - CTRACE((tfp, "StreamStack: Returning NULL!\n")); - CTRACE_FLUSH(tfp); /* a crash may be imminent... - kw */ - } - } - return result; -} - -/* Put a presentation near start of list - * ------------------------------------- - * - * Look up a presentation (exact match only) and, if found, reorder - * it to the start of the HTPresentations list. - kw - */ -void HTReorderPresentation(HTFormat rep_in, - HTFormat rep_out) -{ - HTPresentation *match; - - if ((match = HTFindPresentation(rep_in, rep_out, NULL, NULL))) { - HTList_removeObject(HTPresentations, match); - HTList_addObject(HTPresentations, match); - } -} - -/* - * Setup 'get_accept' flag to denote presentations that are not redundant, - * and will be listed in "Accept:" header. - */ -void HTFilterPresentations(void) -{ - int i, j; - int n = HTList_count(HTPresentations); - HTPresentation *p, *q; - BOOL matched; - char *s, *t; - - CTRACE((tfp, "HTFilterPresentations (AcceptMedia %#x)\n", LYAcceptMedia)); - for (i = 0; i < n; i++) { - p = (HTPresentation *) HTList_objectAt(HTPresentations, i); - s = HTAtom_name(p->rep); - - p->get_accept = FALSE; - if ((LYAcceptMedia & p->accept_opt) != 0 - && p->rep_out == WWW_PRESENT - && p->rep != WWW_SOURCE - && strcasecomp(s, "www/mime") - && strcasecomp(s, "www/compressed") - && p->quality <= 1.0 && p->quality >= 0.0) { - matched = TRUE; - for (j = 0; j < i; j++) { - q = (HTPresentation *) HTList_objectAt(HTPresentations, j); - t = HTAtom_name(q->rep); - - if (!strcasecomp(s, t)) { - matched = FALSE; - CTRACE((tfp, " match %s %s\n", s, t)); - break; - } - } - p->get_accept = matched; - } - } -} - -/* Find the cost of a filter stack - * ------------------------------- - * - * Must return the cost of the same stack which StreamStack would set up. - * - * On entry, - * length The size of the data to be converted - */ -float HTStackValue(HTFormat rep_in, - HTFormat rep_out, - float initial_value, - long int length) -{ - HTAtom *wildcard = WWW_WILDCARD_REP_OUT; - - CTRACE((tfp, "HTFormat: Evaluating stream stack for %s worth %.3f to %s\n", - HTAtom_name(rep_in), initial_value, HTAtom_name(rep_out))); - - if (rep_out == WWW_SOURCE || rep_out == rep_in) - return 0.0; - - { - int n = HTList_count(HTPresentations); - int i; - HTPresentation *pres; - - for (i = 0; i < n; i++) { - pres = (HTPresentation *) HTList_objectAt(HTPresentations, i); - if (pres->rep == rep_in && - (pres->rep_out == rep_out || pres->rep_out == wildcard)) { - float value = initial_value * pres->quality; - - if (HTMaxSecs > 0.0) - value = value - (length * pres->secs_per_byte + pres->secs) - / HTMaxSecs; - return value; - } - } - } - - return (float) -1e30; /* Really bad */ - -} - -/* Display the page while transfer in progress - * ------------------------------------------- - * - * Repaint the page only when necessary. - * This is a traverse call for HText_pageDisplay() - it works!. - * - */ -void HTDisplayPartial(void) -{ -#ifdef DISP_PARTIAL - if (display_partial) { - /* - * HText_getNumOfLines() = "current" number of complete lines received - * NumOfLines_partial = number of lines at the moment of last repaint. - * (we update NumOfLines_partial only when we repaint the display.) - * - * display_partial could only be enabled in HText_new() so a new - * HTMainText object available - all HText_ functions use it, lines - * counter HText_getNumOfLines() in particular. - * - * Otherwise HTMainText holds info from the previous document and we - * may repaint it instead of the new one: prev doc scrolled to the - * first line (=Newline_partial) is not good looking :-) 23 Aug 1998 - * Leonid Pauzner - * - * So repaint the page only when necessary: - */ - int Newline_partial = LYGetNewline(); - - if (((Newline_partial + display_lines) - 1 > NumOfLines_partial) - /* current page not complete... */ - && (partial_threshold > 0 ? - ((Newline_partial + partial_threshold) - 1 <= - HText_getNumOfLines()) : - ((Newline_partial + display_lines) - 1 <= HText_getNumOfLines())) - /* - * Originally we rendered by increments of 2 lines, - * but that got annoying on slow network connections. - * Then we switched to full-pages. Now it's configurable. - * If partial_threshold <= 0, then it's a full page - */ - ) { - if (LYMainLoop_pageDisplay(Newline_partial)) - NumOfLines_partial = HText_getNumOfLines(); - } - } -#else /* nothing */ -#endif /* DISP_PARTIAL */ -} - -/* Put this as early as possible, OK just after HTDisplayPartial() */ -void HTFinishDisplayPartial(void) -{ -#ifdef DISP_PARTIAL - /* - * End of incremental rendering stage here. - */ - display_partial = FALSE; -#endif /* DISP_PARTIAL */ -} - -/* Push data from a socket down a stream - * ------------------------------------- - * - * This routine is responsible for creating and PRESENTING any - * graphic (or other) objects described by the file. - * - * The file number given is assumed to be a TELNET stream, i.e., containing - * CRLF at the end of lines which need to be stripped to LF for unix - * when the format is textual. - * - * State of socket and target stream on entry: - * socket (file_number) assumed open, - * target (sink) assumed valid. - * - * Return values: - * HT_INTERRUPTED Interruption or error after some data received. - * -2 Unexpected disconnect before any data received. - * -1 Interruption or error before any data received, or - * (UNIX) other read error before any data received, or - * download cancelled. - * HT_LOADED Normal close of socket (end of file indication - * received), or - * unexpected disconnect after some data received, or - * other read error after some data received, or - * (not UNIX) other read error before any data received. - * - * State of socket and target stream on return depends on return value: - * HT_INTERRUPTED socket still open, target aborted. - * -2 socket still open, target stream still valid. - * -1 socket still open, target aborted. - * otherwise socket closed, target stream still valid. - */ -int HTCopy(HTParentAnchor *anchor, - int file_number, - void *handle GCC_UNUSED, - HTStream *sink) -{ - HTStreamClass targetClass; - BOOL suppress_readprogress = NO; - int bytes; - int rv = 0; - - /* Push the data down the stream - */ - targetClass = *(sink->isa); /* Copy pointers to procedures */ - - /* - * Push binary from socket down sink - * - * This operation could be put into a main event loop - */ - HTReadProgress(bytes = 0, 0); - for (;;) { - int status; - - if (LYCancelDownload) { - LYCancelDownload = FALSE; - (*targetClass._abort) (sink, NULL); - rv = -1; - goto finished; - } - - if (HTCheckForInterrupt()) { - _HTProgress(TRANSFER_INTERRUPTED); - (*targetClass._abort) (sink, NULL); - if (bytes) - rv = HT_INTERRUPTED; - else - rv = -1; - goto finished; - } -#ifdef USE_SSL - if (handle) - status = SSL_read((SSL *) handle, input_buffer, INPUT_BUFFER_SIZE); - else - status = NETREAD(file_number, input_buffer, INPUT_BUFFER_SIZE); -#else - status = NETREAD(file_number, input_buffer, INPUT_BUFFER_SIZE); -#endif /* USE_SSL */ - - if (status <= 0) { - if (status == 0) { - break; - } else if (status == HT_INTERRUPTED) { - _HTProgress(TRANSFER_INTERRUPTED); - (*targetClass._abort) (sink, NULL); - if (bytes) - rv = HT_INTERRUPTED; - else - rv = -1; - goto finished; - } else if (SOCKET_ERRNO == ENOTCONN || -#ifdef _WINDOWS /* 1997/11/10 (Mon) 16:57:18 */ - SOCKET_ERRNO == ETIMEDOUT || -#endif - SOCKET_ERRNO == ECONNRESET || - SOCKET_ERRNO == EPIPE) { - /* - * Arrrrgh, HTTP 0/1 compatibility problem, maybe. - */ - if (bytes <= 0) { - /* - * Don't have any data, so let the calling function decide - * what to do about it. - FM - */ - rv = -2; - goto finished; - } else { -#ifdef UNIX - /* - * Treat what we've received already as the complete - * transmission, but not without giving the user an alert. - * I don't know about all the different TCP stacks for VMS - * etc., so this is currently only for UNIX. - kw - */ - HTInetStatus("NETREAD"); - HTAlert("Unexpected server disconnect."); - CTRACE((tfp, - "HTCopy: Unexpected server disconnect. Treating as completed.\n")); - status = 0; -#else /* !UNIX */ - /* - * Treat what we've gotten already as the complete - * transmission. - FM - */ - CTRACE((tfp, - "HTCopy: Unexpected server disconnect. Treating as completed.\n")); - status = 0; -#endif /* UNIX */ - } -#ifdef UNIX - } else { /* status < 0 and other errno */ - /* - * Treat what we've received already as the complete - * transmission, but not without giving the user an alert. I - * don't know about all the different TCP stacks for VMS etc., - * so this is currently only for UNIX. - kw - */ - HTInetStatus("NETREAD"); - HTAlert("Unexpected read error."); - if (bytes) { - (void) NETCLOSE(file_number); - rv = HT_LOADED; - } else { - (*targetClass._abort) (sink, NULL); - rv = -1; - } - goto finished; -#endif - } - break; - } - - /* - * Suppress ReadProgress messages when collecting a redirection - * message, at least initially (unless/until anchor->content_type gets - * changed, probably by the MIME message parser). That way messages - * put up by the HTTP module or elsewhere can linger in the statusline - * for a while. - kw - */ - suppress_readprogress = (BOOL) (anchor && anchor->content_type && - !strcmp(anchor->content_type, - "message/x-http-redirection")); -#ifdef NOT_ASCII - { - char *p; - - for (p = input_buffer; p < input_buffer + status; p++) { - *p = FROMASCII(*p); - } - } -#endif /* NOT_ASCII */ - - (*targetClass.put_block) (sink, input_buffer, status); - bytes += status; - if (!suppress_readprogress) - HTReadProgress(bytes, anchor ? anchor->content_length : 0); - HTDisplayPartial(); - - } /* next bufferload */ - - _HTProgress(TRANSFER_COMPLETE); - (void) NETCLOSE(file_number); - rv = HT_LOADED; - - finished: - HTFinishDisplayPartial(); - return (rv); -} - -/* Push data from a file pointer down a stream - * ------------------------------------- - * - * This routine is responsible for creating and PRESENTING any - * graphic (or other) objects described by the file. - * - * - * State of file and target stream on entry: - * FILE* (fp) assumed open, - * target (sink) assumed valid. - * - * Return values: - * HT_INTERRUPTED Interruption after some data read. - * HT_PARTIAL_CONTENT Error after some data read. - * -1 Error before any data read. - * HT_LOADED Normal end of file indication on reading. - * - * State of file and target stream on return: - * always fp still open, target stream still valid. - */ -int HTFileCopy(FILE *fp, HTStream *sink) -{ - HTStreamClass targetClass; - int status, bytes; - int rv = HT_OK; - - /* Push the data down the stream - */ - targetClass = *(sink->isa); /* Copy pointers to procedures */ - - /* Push binary from socket down sink - */ - HTReadProgress(bytes = 0, 0); - for (;;) { - status = fread(input_buffer, 1, INPUT_BUFFER_SIZE, fp); - if (status == 0) { /* EOF or error */ - if (ferror(fp) == 0) { - rv = HT_LOADED; - break; - } - CTRACE((tfp, "HTFormat: Read error, read returns %d\n", - ferror(fp))); - if (bytes) { - rv = HT_PARTIAL_CONTENT; - } else { - rv = -1; - } - break; - } - - (*targetClass.put_block) (sink, input_buffer, status); - bytes += status; - HTReadProgress(bytes, 0); - /* Suppress last screen update in partial mode - a regular update under - * control of mainloop() should follow anyway. - kw - */ -#ifdef DISP_PARTIAL - if (display_partial && bytes != HTMainAnchor->content_length) - HTDisplayPartial(); -#endif - - if (HTCheckForInterrupt()) { - _HTProgress(TRANSFER_INTERRUPTED); - if (bytes) { - rv = HT_INTERRUPTED; - } else { - rv = -1; - } - break; - } - } /* next bufferload */ - - HTFinishDisplayPartial(); - return rv; -} - -#ifdef USE_SOURCE_CACHE -/* Push data from an HTChunk down a stream - * --------------------------------------- - * - * This routine is responsible for creating and PRESENTING any - * graphic (or other) objects described by the file. - * - * State of memory and target stream on entry: - * HTChunk* (chunk) and target (sink) assumed valid. - * - * Return values: - * HT_LOADED All data sent. - * HT_INTERRUPTED Interruption after some data read. - * - * State of memory and target stream on return: - * always chunk unchanged, target stream still valid. - */ -int HTMemCopy(HTChunk *chunk, HTStream *sink) -{ - HTStreamClass targetClass; - int bytes = 0; - int rv = HT_OK; - - targetClass = *(sink->isa); - HTReadProgress(0, 0); - for (; chunk != NULL; chunk = chunk->next) { - - /* Push the data down the stream a piece at a time, in case we're - * running a large document on a slow machine. - */ - (*targetClass.put_block) (sink, chunk->data, chunk->size); - bytes += chunk->size; - - HTReadProgress(bytes, 0); - HTDisplayPartial(); - - if (HTCheckForInterrupt()) { - _HTProgress(TRANSFER_INTERRUPTED); - if (bytes) { - rv = HT_INTERRUPTED; - } else { - rv = -1; - } - break; - } - } - - HTFinishDisplayPartial(); - return rv; -} -#endif - -#ifdef USE_ZLIB -/* Push data from a gzip file pointer down a stream - * ------------------------------------- - * - * This routine is responsible for creating and PRESENTING any - * graphic (or other) objects described by the file. - * - * - * State of file and target stream on entry: - * gzFile (gzfp) assumed open (should have gzipped content), - * target (sink) assumed valid. - * - * Return values: - * HT_INTERRUPTED Interruption after some data read. - * HT_PARTIAL_CONTENT Error after some data read. - * -1 Error before any data read. - * HT_LOADED Normal end of file indication on reading. - * - * State of file and target stream on return: - * always gzfp still open, target stream still valid. - */ -static int HTGzFileCopy(gzFile gzfp, HTStream *sink) -{ - HTStreamClass targetClass; - int status, bytes; - int gzerrnum; - int rv = HT_OK; - - /* Push the data down the stream - */ - targetClass = *(sink->isa); /* Copy pointers to procedures */ - - /* read and inflate gzip'd file, and push binary down sink - */ - HTReadProgress(bytes = 0, 0); - for (;;) { - status = gzread(gzfp, input_buffer, INPUT_BUFFER_SIZE); - if (status <= 0) { /* EOF or error */ - if (status == 0) { - rv = HT_LOADED; - break; - } - CTRACE((tfp, "HTGzFileCopy: Read error, gzread returns %d\n", - status)); - CTRACE((tfp, "gzerror : %s\n", - gzerror(gzfp, &gzerrnum))); - if (TRACE) { - if (gzerrnum == Z_ERRNO) - perror("gzerror "); - } - if (bytes) { - rv = HT_PARTIAL_CONTENT; - } else { - rv = -1; - } - break; - } - - (*targetClass.put_block) (sink, input_buffer, status); - bytes += status; - HTReadProgress(bytes, -1); - HTDisplayPartial(); - - if (HTCheckForInterrupt()) { - _HTProgress(TRANSFER_INTERRUPTED); - if (bytes) { - rv = HT_INTERRUPTED; - } else { - rv = -1; - } - break; - } - } /* next bufferload */ - - HTFinishDisplayPartial(); - return rv; -} - -#ifndef HAVE_ZERROR -#define zError(s) LynxZError(s) -static const char *zError(int status) -{ - static char result[80]; - - sprintf(result, "zlib error %d", status); - return result; -} -#endif - -/* Push data from a deflate file pointer down a stream - * ------------------------------------- - * - * This routine is responsible for creating and PRESENTING any - * graphic (or other) objects described by the file. The code is - * loosely based on the inflate.c file from w3m. - * - * - * State of file and target stream on entry: - * FILE (zzfp) assumed open (should have deflated content), - * target (sink) assumed valid. - * - * Return values: - * HT_INTERRUPTED Interruption after some data read. - * HT_PARTIAL_CONTENT Error after some data read. - * -1 Error before any data read. - * HT_LOADED Normal end of file indication on reading. - * - * State of file and target stream on return: - * always zzfp still open, target stream still valid. - */ -static int HTZzFileCopy(FILE *zzfp, HTStream *sink) -{ - static char dummy_head[1 + 1] = - { - 0x8 + 0x7 * 0x10, - (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, - }; - - z_stream s; - HTStreamClass targetClass; - int bytes; - int rv = HT_OK; - char output_buffer[INPUT_BUFFER_SIZE]; - int status; - int flush; - int retry = 0; - int len = 0; - - /* Push the data down the stream - */ - targetClass = *(sink->isa); /* Copy pointers to procedures */ - - s.zalloc = Z_NULL; - s.zfree = Z_NULL; - s.opaque = Z_NULL; - status = inflateInit(&s); - if (status != Z_OK) { - CTRACE((tfp, "HTZzFileCopy inflateInit() %s\n", zError(status))); - exit_immediately(EXIT_FAILURE); - } - s.avail_in = 0; - s.next_out = (Bytef *) output_buffer; - s.avail_out = sizeof(output_buffer); - flush = Z_NO_FLUSH; - - /* read and inflate deflate'd file, and push binary down sink - */ - HTReadProgress(bytes = 0, 0); - for (;;) { - if (s.avail_in == 0) { - s.next_in = (Bytef *) input_buffer; - len = s.avail_in = fread(input_buffer, 1, INPUT_BUFFER_SIZE, zzfp); - } - status = inflate(&s, flush); - if (status == Z_STREAM_END || status == Z_BUF_ERROR) { - len = sizeof(output_buffer) - s.avail_out; - if (len > 0) { - (*targetClass.put_block) (sink, output_buffer, len); - bytes += len; - HTReadProgress(bytes, -1); - HTDisplayPartial(); - } - rv = HT_LOADED; - break; - } else if (status == Z_DATA_ERROR && !retry++) { - status = inflateReset(&s); - if (status != Z_OK) { - CTRACE((tfp, "HTZzFileCopy inflateReset() %s\n", zError(status))); - rv = bytes ? HT_PARTIAL_CONTENT : -1; - break; - } - s.next_in = (Bytef *) dummy_head; - s.avail_in = sizeof(dummy_head); - status = inflate(&s, flush); - s.next_in = (Bytef *) input_buffer; - s.avail_in = len; - continue; - } else if (status != Z_OK) { - CTRACE((tfp, "HTZzFileCopy inflate() %s\n", zError(status))); - rv = bytes ? HT_PARTIAL_CONTENT : -1; - break; - } else if (s.avail_out == 0) { - len = sizeof(output_buffer); - s.next_out = (Bytef *) output_buffer; - s.avail_out = sizeof(output_buffer); - - (*targetClass.put_block) (sink, output_buffer, len); - bytes += len; - HTReadProgress(bytes, -1); - HTDisplayPartial(); - - if (HTCheckForInterrupt()) { - _HTProgress(TRANSFER_INTERRUPTED); - rv = bytes ? HT_INTERRUPTED : -1; - break; - } - } - retry = 1; - } /* next bufferload */ - - inflateEnd(&s); - HTFinishDisplayPartial(); - return rv; -} -#endif /* USE_ZLIB */ - -#ifdef USE_BZLIB -/* Push data from a bzip file pointer down a stream - * ------------------------------------- - * - * This routine is responsible for creating and PRESENTING any - * graphic (or other) objects described by the file. - * - * - * State of file and target stream on entry: - * BZFILE (bzfp) assumed open (should have bzipped content), - * target (sink) assumed valid. - * - * Return values: - * HT_INTERRUPTED Interruption after some data read. - * HT_PARTIAL_CONTENT Error after some data read. - * -1 Error before any data read. - * HT_LOADED Normal end of file indication on reading. - * - * State of file and target stream on return: - * always bzfp still open, target stream still valid. - */ -static int HTBzFileCopy(BZFILE * bzfp, HTStream *sink) -{ - HTStreamClass targetClass; - int status, bytes; - int bzerrnum; - int rv = HT_OK; - - /* Push the data down the stream - */ - targetClass = *(sink->isa); /* Copy pointers to procedures */ - - /* read and inflate bzip'd file, and push binary down sink - */ - HTReadProgress(bytes = 0, 0); - for (;;) { - status = BZ2_bzread(bzfp, input_buffer, INPUT_BUFFER_SIZE); - if (status <= 0) { /* EOF or error */ - if (status == 0) { - rv = HT_LOADED; - break; - } - CTRACE((tfp, "HTBzFileCopy: Read error, bzread returns %d\n", - status)); - CTRACE((tfp, "bzerror : %s\n", - BZ2_bzerror(bzfp, &bzerrnum))); - if (bytes) { - rv = HT_PARTIAL_CONTENT; - } else { - rv = -1; - } - break; - } - - (*targetClass.put_block) (sink, input_buffer, status); - bytes += status; - HTReadProgress(bytes, -1); - HTDisplayPartial(); - - if (HTCheckForInterrupt()) { - _HTProgress(TRANSFER_INTERRUPTED); - if (bytes) { - rv = HT_INTERRUPTED; - } else { - rv = -1; - } - break; - } - } /* next bufferload */ - - HTFinishDisplayPartial(); - return rv; -} -#endif /* USE_BZLIB */ - -/* Push data from a socket down a stream STRIPPING CR - * -------------------------------------------------- - * - * This routine is responsible for creating and PRESENTING any - * graphic (or other) objects described by the socket. - * - * The file number given is assumed to be a TELNET stream ie containing - * CRLF at the end of lines which need to be stripped to LF for unix - * when the format is textual. - * - */ -void HTCopyNoCR(HTParentAnchor *anchor GCC_UNUSED, - int file_number, - HTStream *sink) -{ - HTStreamClass targetClass; - int character; - - /* Push the data, ignoring CRLF, down the stream - */ - targetClass = *(sink->isa); /* Copy pointers to procedures */ - - /* - * Push text from telnet socket down sink - * - * @@@@@ To push strings could be faster? (especially is we cheat and - * don't ignore CR! :-} - */ - HTInitInput(file_number); - for (;;) { - character = HTGetCharacter(); - if (character == EOF) - break; - (*targetClass.put_character) (sink, UCH(character)); - } -} - -/* Parse a socket given format and file number - * - * This routine is responsible for creating and PRESENTING any - * graphic (or other) objects described by the file. - * - * The file number given is assumed to be a TELNET stream ie containing - * CRLF at the end of lines which need to be stripped to LF for unix - * when the format is textual. - * - * State of socket and target stream on entry: - * socket (file_number) assumed open, - * target (sink) usually NULL (will call stream stack). - * - * Return values: - * HT_INTERRUPTED Interruption or error after some data received. - * -501 Stream stack failed (cannot present or convert). - * -2 Unexpected disconnect before any data received. - * -1 Stream stack failed (cannot present or convert), or - * Interruption or error before any data received, or - * (UNIX) other read error before any data received, or - * download cancelled. - * HT_LOADED Normal close of socket (end of file indication - * received), or - * unexpected disconnect after some data received, or - * other read error after some data received, or - * (not UNIX) other read error before any data received. - * - * State of socket and target stream on return depends on return value: - * HT_INTERRUPTED socket still open, target aborted. - * -501 socket still open, target stream NULL. - * -2 socket still open, target freed. - * -1 socket still open, target stream aborted or NULL. - * otherwise socket closed, target stream freed. - */ -int HTParseSocket(HTFormat rep_in, - HTFormat format_out, - HTParentAnchor *anchor, - int file_number, - HTStream *sink) -{ - HTStream *stream; - HTStreamClass targetClass; - int rv; - - stream = HTStreamStack(rep_in, format_out, sink, anchor); - - if (!stream) { - char *buffer = 0; - - if (LYCancelDownload) { - LYCancelDownload = FALSE; - return -1; - } - HTSprintf0(&buffer, CANNOT_CONVERT_I_TO_O, - HTAtom_name(rep_in), HTAtom_name(format_out)); - CTRACE((tfp, "HTFormat: %s\n", buffer)); - rv = HTLoadError(sink, 501, buffer); /* returns -501 */ - FREE(buffer); - } else { - /* - * Push the data, don't worry about CRLF we can strip them later. - */ - targetClass = *(stream->isa); /* Copy pointers to procedures */ - rv = HTCopy(anchor, file_number, NULL, stream); - if (rv != -1 && rv != HT_INTERRUPTED) - (*targetClass._free) (stream); - } - return rv; - /* Originally: full: HT_LOADED; partial: HT_INTERRUPTED; no bytes: -1 */ -} - -/* Parse a file given format and file pointer - * - * This routine is responsible for creating and PRESENTING any - * graphic (or other) objects described by the file. - * - * The file number given is assumed to be a TELNET stream ie containing - * CRLF at the end of lines which need to be stripped to \n for unix - * when the format is textual. - * - * State of file and target stream on entry: - * FILE* (fp) assumed open, - * target (sink) usually NULL (will call stream stack). - * - * Return values: - * -501 Stream stack failed (cannot present or convert). - * -1 Download cancelled. - * HT_NO_DATA Error before any data read. - * HT_PARTIAL_CONTENT Interruption or error after some data read. - * HT_LOADED Normal end of file indication on reading. - * - * State of file and target stream on return: - * always fp still open; target freed, aborted, or NULL. - */ -int HTParseFile(HTFormat rep_in, - HTFormat format_out, - HTParentAnchor *anchor, - FILE *fp, - HTStream *sink) -{ - HTStream *stream; - HTStreamClass targetClass; - int rv; - - if (fp == NULL) - return HT_LOADED; - - stream = HTStreamStack(rep_in, format_out, sink, anchor); - - if (!stream) { - char *buffer = 0; - - if (LYCancelDownload) { - LYCancelDownload = FALSE; - return -1; - } - HTSprintf0(&buffer, CANNOT_CONVERT_I_TO_O, - HTAtom_name(rep_in), HTAtom_name(format_out)); - CTRACE((tfp, "HTFormat(in HTParseFile): %s\n", buffer)); - rv = HTLoadError(sink, 501, buffer); - FREE(buffer); - return rv; - } - - /* - * Push the data down the stream - * - * @@ Bug: This decision ought to be made based on "encoding" rather than - * on content-type. @@@ When we handle encoding. The current method - * smells anyway. - */ - targetClass = *(stream->isa); /* Copy pointers to procedures */ - rv = HTFileCopy(fp, stream); - if (rv == -1 || rv == HT_INTERRUPTED) { - (*targetClass._abort) (stream, NULL); - } else { - (*targetClass._free) (stream); - } - - if (rv == -1) - return HT_NO_DATA; - else if (rv == HT_INTERRUPTED || (rv > 0 && rv != HT_LOADED)) - return HT_PARTIAL_CONTENT; - else - return HT_LOADED; -} - -#ifdef USE_SOURCE_CACHE -/* Parse a document in memory given format and memory block pointer - * - * This routine is responsible for creating and PRESENTING any - * graphic (or other) objects described by the file. - * - * State of memory and target stream on entry: - * HTChunk* (chunk) assumed valid, - * target (sink) usually NULL (will call stream stack). - * - * Return values: - * -501 Stream stack failed (cannot present or convert). - * HT_LOADED All data sent. - * - * State of memory and target stream on return: - * always chunk unchanged; target freed, aborted, or NULL. - */ -int HTParseMem(HTFormat rep_in, - HTFormat format_out, - HTParentAnchor *anchor, - HTChunk *chunk, - HTStream *sink) -{ - HTStream *stream; - HTStreamClass targetClass; - int rv; - - stream = HTStreamStack(rep_in, format_out, sink, anchor); - if (!stream) { - char *buffer = 0; - - HTSprintf0(&buffer, CANNOT_CONVERT_I_TO_O, - HTAtom_name(rep_in), HTAtom_name(format_out)); - CTRACE((tfp, "HTFormat(in HTParseMem): %s\n", buffer)); - rv = HTLoadError(sink, 501, buffer); - FREE(buffer); - return rv; - } - - /* Push the data down the stream - */ - targetClass = *(stream->isa); - rv = HTMemCopy(chunk, stream); - (*targetClass._free) (stream); - return HT_LOADED; -} -#endif - -#ifdef USE_ZLIB -static int HTCloseGzFile(gzFile gzfp) -{ - int gzres; - - if (gzfp == NULL) - return 0; - gzres = gzclose(gzfp); - if (TRACE) { - if (gzres == Z_ERRNO) { - perror("gzclose "); - } else if (gzres != Z_OK) { - CTRACE((tfp, "gzclose : error number %d\n", gzres)); - } - } - return (gzres); -} - -/* HTParseGzFile - * - * State of file and target stream on entry: - * gzFile (gzfp) assumed open, - * target (sink) usually NULL (will call stream stack). - * - * Return values: - * -501 Stream stack failed (cannot present or convert). - * -1 Download cancelled. - * HT_NO_DATA Error before any data read. - * HT_PARTIAL_CONTENT Interruption or error after some data read. - * HT_LOADED Normal end of file indication on reading. - * - * State of file and target stream on return: - * always gzfp closed; target freed, aborted, or NULL. - */ -int HTParseGzFile(HTFormat rep_in, - HTFormat format_out, - HTParentAnchor *anchor, - gzFile gzfp, - HTStream *sink) -{ - HTStream *stream; - HTStreamClass targetClass; - int rv; - - stream = HTStreamStack(rep_in, format_out, sink, anchor); - - if (!stream) { - char *buffer = 0; - - HTCloseGzFile(gzfp); - if (LYCancelDownload) { - LYCancelDownload = FALSE; - return -1; - } - HTSprintf0(&buffer, CANNOT_CONVERT_I_TO_O, - HTAtom_name(rep_in), HTAtom_name(format_out)); - CTRACE((tfp, "HTFormat(in HTParseGzFile): %s\n", buffer)); - rv = HTLoadError(sink, 501, buffer); - FREE(buffer); - return rv; - } - - /* - * Push the data down the stream - * - * @@ Bug: This decision ought to be made based on "encoding" rather than - * on content-type. @@@ When we handle encoding. The current method - * smells anyway. - */ - targetClass = *(stream->isa); /* Copy pointers to procedures */ - rv = HTGzFileCopy(gzfp, stream); - if (rv == -1 || rv == HT_INTERRUPTED) { - (*targetClass._abort) (stream, NULL); - } else { - (*targetClass._free) (stream); - } - - HTCloseGzFile(gzfp); - if (rv == -1) - return HT_NO_DATA; - else if (rv == HT_INTERRUPTED || (rv > 0 && rv != HT_LOADED)) - return HT_PARTIAL_CONTENT; - else - return HT_LOADED; -} - -/* HTParseZzFile - * - * State of file and target stream on entry: - * FILE (zzfp) assumed open, - * target (sink) usually NULL (will call stream stack). - * - * Return values: - * -501 Stream stack failed (cannot present or convert). - * -1 Download cancelled. - * HT_NO_DATA Error before any data read. - * HT_PARTIAL_CONTENT Interruption or error after some data read. - * HT_LOADED Normal end of file indication on reading. - * - * State of file and target stream on return: - * always zzfp closed; target freed, aborted, or NULL. - */ -int HTParseZzFile(HTFormat rep_in, - HTFormat format_out, - HTParentAnchor *anchor, - FILE *zzfp, - HTStream *sink) -{ - HTStream *stream; - HTStreamClass targetClass; - int rv; - - stream = HTStreamStack(rep_in, format_out, sink, anchor); - - if (!stream) { - char *buffer = 0; - - fclose(zzfp); - if (LYCancelDownload) { - LYCancelDownload = FALSE; - return -1; - } - HTSprintf0(&buffer, CANNOT_CONVERT_I_TO_O, - HTAtom_name(rep_in), HTAtom_name(format_out)); - CTRACE((tfp, "HTFormat(in HTParseGzFile): %s\n", buffer)); - rv = HTLoadError(sink, 501, buffer); - FREE(buffer); - return rv; - } - - /* - * Push the data down the stream - * - * @@ Bug: This decision ought to be made based on "encoding" rather than - * on content-type. @@@ When we handle encoding. The current method - * smells anyway. - */ - targetClass = *(stream->isa); /* Copy pointers to procedures */ - rv = HTZzFileCopy(zzfp, stream); - if (rv == -1 || rv == HT_INTERRUPTED) { - (*targetClass._abort) (stream, NULL); - } else { - (*targetClass._free) (stream); - } - - fclose(zzfp); - if (rv == -1) - return HT_NO_DATA; - else if (rv == HT_INTERRUPTED || (rv > 0 && rv != HT_LOADED)) - return HT_PARTIAL_CONTENT; - else - return HT_LOADED; -} -#endif /* USE_ZLIB */ - -#ifdef USE_BZLIB -static void HTCloseBzFile(BZFILE * bzfp) -{ - if (bzfp) - BZ2_bzclose(bzfp); -} - -/* HTParseBzFile - * - * State of file and target stream on entry: - * bzFile (bzfp) assumed open, - * target (sink) usually NULL (will call stream stack). - * - * Return values: - * -501 Stream stack failed (cannot present or convert). - * -1 Download cancelled. - * HT_NO_DATA Error before any data read. - * HT_PARTIAL_CONTENT Interruption or error after some data read. - * HT_LOADED Normal end of file indication on reading. - * - * State of file and target stream on return: - * always bzfp closed; target freed, aborted, or NULL. - */ -int HTParseBzFile(HTFormat rep_in, - HTFormat format_out, - HTParentAnchor *anchor, - BZFILE * bzfp, - HTStream *sink) -{ - HTStream *stream; - HTStreamClass targetClass; - int rv; - - stream = HTStreamStack(rep_in, format_out, sink, anchor); - - if (!stream) { - char *buffer = 0; - - HTCloseBzFile(bzfp); - if (LYCancelDownload) { - LYCancelDownload = FALSE; - return -1; - } - HTSprintf0(&buffer, CANNOT_CONVERT_I_TO_O, - HTAtom_name(rep_in), HTAtom_name(format_out)); - CTRACE((tfp, "HTFormat(in HTParseBzFile): %s\n", buffer)); - rv = HTLoadError(sink, 501, buffer); - FREE(buffer); - return rv; - } - - /* - * Push the data down the stream - * - * @@ Bug: This decision ought to be made based on "encoding" rather than - * on content-type. @@@ When we handle encoding. The current method - * smells anyway. - */ - targetClass = *(stream->isa); /* Copy pointers to procedures */ - rv = HTBzFileCopy(bzfp, stream); - if (rv == -1 || rv == HT_INTERRUPTED) { - (*targetClass._abort) (stream, NULL); - } else { - (*targetClass._free) (stream); - } - - HTCloseBzFile(bzfp); - if (rv == -1) - return HT_NO_DATA; - else if (rv == HT_INTERRUPTED || (rv > 0 && rv != HT_LOADED)) - return HT_PARTIAL_CONTENT; - else - return HT_LOADED; -} -#endif /* USE_BZLIB */ - -/* Converter stream: Network Telnet to internal character text - * ----------------------------------------------------------- - * - * The input is assumed to be in ASCII, with lines delimited - * by (13,10) pairs, These pairs are converted into (CR,LF) - * pairs in the local representation. The (CR,LF) sequence - * when found is changed to a '\n' character, the internal - * C representation of a new line. - */ - -static void NetToText_put_character(HTStream *me, char net_char) -{ - char c = FROMASCII(net_char); - - if (me->had_cr) { - if (c == LF) { - me->sink->isa->put_character(me->sink, '\n'); /* Newline */ - me->had_cr = NO; - return; - } else { - me->sink->isa->put_character(me->sink, CR); /* leftover */ - } - } - me->had_cr = (BOOL) (c == CR); - if (!me->had_cr) - me->sink->isa->put_character(me->sink, c); /* normal */ -} - -static void NetToText_put_string(HTStream *me, const char *s) -{ - const char *p; - - for (p = s; *p; p++) - NetToText_put_character(me, *p); -} - -static void NetToText_put_block(HTStream *me, const char *s, int l) -{ - const char *p; - - for (p = s; p < (s + l); p++) - NetToText_put_character(me, *p); -} - -static void NetToText_free(HTStream *me) -{ - (me->sink->isa->_free) (me->sink); /* Close rest of pipe */ - FREE(me); -} - -static void NetToText_abort(HTStream *me, HTError e) -{ - me->sink->isa->_abort(me->sink, e); /* Abort rest of pipe */ - FREE(me); -} - -/* The class structure -*/ -static HTStreamClass NetToTextClass = -{ - "NetToText", - NetToText_free, - NetToText_abort, - NetToText_put_character, - NetToText_put_string, - NetToText_put_block -}; - -/* The creation method -*/ -HTStream *HTNetToText(HTStream *sink) -{ - HTStream *me = typecalloc(HTStream); - - if (me == NULL) - outofmem(__FILE__, "NetToText"); - me->isa = &NetToTextClass; - - me->had_cr = NO; - me->sink = sink; - return me; -} - -static HTStream HTBaseStreamInstance; /* Made static */ - -/* - * ERROR STREAM - * ------------ - * There is only one error stream shared by anyone who wants a - * generic error returned from all stream methods. - */ -static void HTErrorStream_put_character(HTStream *me GCC_UNUSED, char c GCC_UNUSED) -{ - LYCancelDownload = TRUE; -} - -static void HTErrorStream_put_string(HTStream *me GCC_UNUSED, const char *s) -{ - if (s && *s) - LYCancelDownload = TRUE; -} - -static void HTErrorStream_write(HTStream *me GCC_UNUSED, const char *s, int l) -{ - if (l && s) - LYCancelDownload = TRUE; -} - -static void HTErrorStream_free(HTStream *me GCC_UNUSED) -{ - return; -} - -static void HTErrorStream_abort(HTStream *me GCC_UNUSED, HTError e GCC_UNUSED) -{ - return; -} - -static const HTStreamClass HTErrorStreamClass = -{ - "ErrorStream", - HTErrorStream_free, - HTErrorStream_abort, - HTErrorStream_put_character, - HTErrorStream_put_string, - HTErrorStream_write -}; - -HTStream *HTErrorStream(void) -{ - CTRACE((tfp, "ErrorStream. Created\n")); - HTBaseStreamInstance.isa = &HTErrorStreamClass; /* The rest is random */ - return &HTBaseStreamInstance; -} |