📄 htformat.c
字号:
/* 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>PUBLIC float HTMaxSecs = 1e10; /* No effective limit */PUBLIC float HTMaxLength = 1e10; /* No effective limit */PUBLIC long int HTMaxBytes = 0; /* 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>#endifPUBLIC BOOL HTOutputSource = NO; /* Flag: shortcut parser to stdout *//* extern BOOL interactive; LJM */#ifdef ORIGINALstruct _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** --------------------*/PUBLIC HTList * HTPresentations = NULL;PUBLIC HTPresentation * default_presentation = NULL;/* * To free off the presentation list. */#ifdef LY_FIND_LEAKSPRIVATE void HTFreePresentations NOPARAMS;#endif/* Define a presentation system command for a content-type** -------------------------------------------------------*/PUBLIC void HTSetPresentation ARGS6( CONST char *, representation, CONST char *, command, double, quality, double, secs, double, secs_per_byte, long int, maxbytes){ HTPresentation * pres = typecalloc(HTPresentation); if (pres == NULL) outofmem(__FILE__, "HTSetPresentation"); 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->command = NULL; StrAllocCopy(pres->command, command); /* * 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** ---------------------------------------------*/PUBLIC void HTSetConversion ARGS7( CONST char *, representation_in, CONST char *, representation_out, HTConverter*, converter, float, quality, float, secs, float, secs_per_byte, long int, maxbytes){ HTPresentation * pres = typecalloc(HTPresentation); if (pres == NULL) outofmem(__FILE__, "HTSetConversion"); pres->rep = HTAtom_for(representation_in); pres->rep_out = HTAtom_for(representation_out); pres->converter = converter; pres->command = NULL; /* Fixed */ pres->quality = quality; pres->secs = secs; pres->secs_per_byte = secs_per_byte; pres->maxbytes = maxbytes; pres->command = NULL; /* * 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*/PRIVATE void HTFreePresentations NOARGS{ 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); } /* * 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 */PRIVATE char input_buffer[INPUT_BUFFER_SIZE];PRIVATE char * input_pointer;PRIVATE char * input_limit;PRIVATE 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.*/PUBLIC void HTInitInput ARGS1 (int,file_number){ input_file_number = file_number; input_pointer = input_limit = input_buffer;}PUBLIC int interrupted_in_htgetcharacter = 0;PUBLIC int HTGetCharacter NOARGS{ 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_SSLPUBLIC char HTGetSSLCharacter ARGS1(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 */PRIVATE int half_match ARGS2(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;}#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***/PRIVATE HTPresentation * HTFindPresentation ARGS3( HTFormat, rep_in, HTFormat, rep_out, HTPresentation*, fill_in){ HTAtom * wildcard = NULL; /* = HTAtom_for("*"); lookup when needed - kw */ CTRACE((tfp, "HTFormat: Looking up presentation for %s to %s\n", HTAtom_name(rep_in), HTAtom_name(rep_out))); /* don't do anymore do it in the Lynx code at startup LJM */ /* if (!HTPresentations) HTFormatInit(); */ /* set up the list */ { int n = HTList_count(HTPresentations); int i; HTPresentation * pres, *match, *strong_wildcard_match=0, *weak_wildcard_match=0, *last_default_match=0, *strong_subtype_wildcard_match=0; for (i = 0; i < n; i++) { pres = (HTPresentation *)HTList_objectAt(HTPresentations, i); if (pres->rep == rep_in) { if (pres->rep_out == rep_out) { CTRACE((tfp, "FindPresentation: found exact match: %s\n", HTAtom_name(pres->rep))); return pres; } else if (!fill_in) { continue; } else { if (!wildcard) wildcard = WWW_WILDCARD_REP_OUT; if (pres->rep_out == wildcard) { if (!strong_wildcard_match) strong_wildcard_match = pres; /* otherwise use the first one */ CTRACE((tfp, "StreamStack: found strong wildcard match: %s\n", HTAtom_name(pres->rep))); } } } else if (!fill_in) { continue; } else if (half_match(HTAtom_name(pres->rep), HTAtom_name(rep_in))) { if (pres->rep_out == rep_out) { if (!strong_subtype_wildcard_match) strong_subtype_wildcard_match = pres; /* otherwise use the first one */ CTRACE((tfp, "StreamStack: found strong subtype wildcard match: %s\n", HTAtom_name(pres->rep))); } } if (pres->rep == WWW_SOURCE) { if (pres->rep_out == rep_out) { 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) 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.***/PUBLIC HTStream * HTStreamStack ARGS4( 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\n", HTAtom_name(rep_in), HTAtom_name(rep_out))); /* 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))) { if (match == &temp) { CTRACE((tfp, "StreamStack: Using %s\n", HTAtom_name(temp.rep_out))); } else { CTRACE((tfp, "StreamStack: found exact match: %s\n", HTAtom_name(match->rep))); } 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*/PUBLIC void HTReorderPresentation ARGS2( HTFormat, rep_in, HTFormat, rep_out){ HTPresentation *match; if ((match = HTFindPresentation(rep_in, rep_out, 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. */PUBLIC void HTFilterPresentations NOARGS{ int i, j; int n = HTList_count(HTPresentations); HTPresentation *p, *q; BOOL matched; char *s, *t, *x, *y; for (i = 0; i < n; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -