diff options
author | Thomas E. Dickey <dickey@invisible-island.net> | 1997-01-29 21:25:58 -0500 |
---|---|---|
committer | Thomas E. Dickey <dickey@invisible-island.net> | 1997-01-29 21:25:58 -0500 |
commit | c3ec4181d988501e4d7116f32c669d5ca69e7060 (patch) | |
tree | 3a19fc17f13ca34edf02b209e19464f8041984cd /src | |
parent | 6bd78b38830217fa268e678d9637116ec516bf0e (diff) | |
download | lynx-snapshots-c3ec4181d988501e4d7116f32c669d5ca69e7060.tar.gz |
snapshot of project "lynx", label v2_6fm_970129
Diffstat (limited to 'src')
45 files changed, 10626 insertions, 5579 deletions
diff --git a/src/GridText.c b/src/GridText.c index e988c7ba..b4b92503 100644 --- a/src/GridText.c +++ b/src/GridText.c @@ -55,16 +55,14 @@ extern HTCJKlang HTCJK; extern HTStyleSheet * styleSheet; /* Default or overridden */ extern int display_lines; /* number of lines in display */ -extern BOOLEAN ignore_excess; /* flag to ignore chararcters at wrap column */ -extern char HTML_Last_Char; /* Exports */ PUBLIC HText * HTMainText = NULL; /* Equivalent of main window */ PUBLIC HTParentAnchor * HTMainAnchor = NULL; /* Anchor for HTMainText */ -PUBLIC char * HTAppName = "Lynx"; /* Application name */ -PUBLIC char * HTAppVersion = LYNX_VERSION; /* Application version */ +PUBLIC char * HTAppName = "Lynx"; /* Application name */ +PUBLIC char * HTAppVersion = LYNX_VERSION; /* Application version */ PUBLIC int HTFormNumber = 0; PUBLIC int HTFormFields = 0; @@ -91,21 +89,21 @@ typedef struct _line { char data[1]; /* Space for terminator at least! */ } HTLine; -#define LINE_SIZE(l) (sizeof(HTLine)+(l)) /* allow for terminator */ +#define LINE_SIZE(l) (sizeof(HTLine)+(l)) /* Allow for terminator */ typedef struct _TextAnchor { struct _TextAnchor * next; int number; /* For user interface */ int start; /* Characters */ - int line_pos; /* position in text */ + int line_pos; /* Position in text */ int extent; /* Characters */ - int line_num; /* place in document */ - char * hightext; /* the link text */ - char * hightext2; /* a second line*/ - int hightext2offset; /* offset from left */ - int link_type; /* normal or form? */ - FormInfo * input_field; /* info for form links */ - BOOL show_anchor; /* show the anchor? */ + int line_num; /* Place in document */ + char * hightext; /* The link text */ + char * hightext2; /* A second line*/ + int hightext2offset;/* offset from left */ + int link_type; /* Normal or form? */ + FormInfo * input_field; /* Info for form links */ + BOOL show_anchor; /* Show the anchor? */ HTChildAnchor * anchor; } TextAnchor; @@ -123,15 +121,18 @@ typedef struct _HTTabID { struct _HText { HTParentAnchor * node_anchor; HTLine * last_line; - int lines; /* Number of them */ + int Lines; /* Number of them */ int chars; /* Number of them */ TextAnchor * first_anchor; /* Singly linked list */ TextAnchor * last_anchor; int last_anchor_number; /* user number */ - BOOL source; /* is the text source? */ + BOOL source; /* Is the text source? */ BOOL toolbar; /* Toolbar set? */ HTList * tabs; /* TAB IDs */ BOOL no_cache; /* Always refresh? */ + char LastChar; /* For aborbing white space */ + BOOL IgnoreExcess; /* Ignore chars at wrap point */ + /* For Internal use: */ HTStyle * style; /* Current style */ int display_on_the_fly; /* Lines left */ @@ -186,7 +187,8 @@ PRIVATE int HText_TrueLineSize PARAMS((HTLine *line)); /* Creation Method ** --------------- */ -PUBLIC HText * HText_new ARGS1(HTParentAnchor *,anchor) +PUBLIC HText * HText_new ARGS1( + HTParentAnchor *, anchor) { #if defined(VMS) && defined(VAXC) && !defined(__DECC) #include <lib$routines.h> @@ -194,7 +196,8 @@ PUBLIC HText * HText_new ARGS1(HTParentAnchor *,anchor) #endif /* VMS && VAXC && !__DECC */ HTLine * line = NULL; HText * self = (HText *) calloc(1, sizeof(*self)); - if (!self) return self; + if (!self) + return self; #if defined(VMS) && defined (VAXC) && !defined(__DECC) status = lib$stat_vm(&VMType, &VMTotal); @@ -245,7 +248,7 @@ PUBLIC HText * HText_new ARGS1(HTParentAnchor *,anchor) outofmem(__FILE__, "HText_New"); line->next = line->prev = line; line->offset = line->size = 0; - self->lines = self->chars = 0; + self->Lines = self->chars = 0; self->first_anchor = self->last_anchor = NULL; self->style = &default_style; self->top_of_screen = 0; @@ -256,6 +259,9 @@ PUBLIC HText * HText_new ARGS1(HTParentAnchor *,anchor) self->tabs = NULL; self->no_cache = ((anchor->no_cache || anchor->post_data) ? YES : NO); + self->LastChar = '\0'; + self->IgnoreExcess = FALSE; + if (HTOutputFormat == WWW_SOURCE) self->source = YES; else @@ -285,13 +291,13 @@ PUBLIC HText * HText_new ARGS1(HTParentAnchor *,anchor) if (underscore_string[0] != '.') { char *p; /* - * Create and array of dots for the UNDERSCORES macro. - FM + * Create and array of dots for the UNDERSCORES macro. - FM */ memset(underscore_string, '.', (MAX_LINE-1)); underscore_string[(MAX_LINE-1)] = '\0'; underscore_string[MAX_LINE] = '\0'; /* - * Create and array of underscores for the STARS macro. - FM + * Create and array of underscores for the STARS macro. - FM */ memset(star_string, '_', (MAX_LINE-1)); star_string[(MAX_LINE-1)] = '\0'; @@ -310,8 +316,8 @@ PUBLIC HText * HText_new ARGS1(HTParentAnchor *,anchor) ** Stream is assumed open and left open. */ PUBLIC HText * HText_new2 ARGS2( - HTParentAnchor *, anchor, - HTStream*, stream) + HTParentAnchor *, anchor, + HTStream *, stream) { HText * this = HText_new(anchor); @@ -326,7 +332,8 @@ PUBLIC HText * HText_new2 ARGS2( /* Free Entire Text ** ---------------- */ -PUBLIC void HText_free ARGS1(HText *,self) +PUBLIC void HText_free ARGS1( + HText *, self) { if (!self) return; @@ -406,11 +413,11 @@ PUBLIC void HText_free ARGS1(HText *,self) * Free the tabs list. - FM */ if (self->tabs) { - HTTabID * tab = NULL; + HTTabID * Tab = NULL; HTList * cur = self->tabs; - while (NULL != (tab = (HTTabID *)HTList_nextObject(cur))) { - FREE(tab->name); + while (NULL != (Tab = (HTTabID *)HTList_nextObject(cur))) { + FREE(Tab->name); } HTList_delete(self->tabs); } @@ -434,7 +441,8 @@ PUBLIC void HText_free ARGS1(HText *,self) /* Output a line ** ------------- */ -PRIVATE int display_line ARGS1(HTLine *,line) +PRIVATE int display_line ARGS1( + HTLine *, line) { register int i,j; char buffer[3]; @@ -533,7 +541,8 @@ PRIVATE int display_line ARGS1(HTLine *,line) /* Output the title line ** --------------------- */ -PRIVATE void display_title ARGS1(HText *,text) +PRIVATE void display_title ARGS1( + HText *, text) { char *title = NULL; char percent[20], format[20]; @@ -564,7 +573,7 @@ PRIVATE void display_title ARGS1(HText *,text) /* * Generate the page indicator (percent) string. */ - if ((text->lines + 1) > (display_lines)) { + if ((text->Lines + 1) > (display_lines)) { /* * In a small attempt to correct the number of pages counted.... * GAB 07-14-94 @@ -573,10 +582,10 @@ PRIVATE void display_title ARGS1(HText *,text) * FM 02-08-95 */ int total_pages = - (((text->lines + 1) + (display_lines - 1))/(display_lines)); + (((text->Lines + 1) + (display_lines - 1))/(display_lines)); int start_of_last_page = - ((text->lines + 1) < display_lines) ? 0 : - ((text->lines + 1) - display_lines); + ((text->Lines + 1) < display_lines) ? 0 : + ((text->Lines + 1) - display_lines); sprintf(percent, " (p%d of %d)", ((text->top_of_screen >= start_of_last_page) ? @@ -590,9 +599,12 @@ PRIVATE void display_title ARGS1(HText *,text) /* * Generate format string. */ - sprintf(format, "%%%d.%ds%%s\n", - (LYcols-1)-strlen(percent), - (LYcols-1)-strlen(percent)); + sprintf(format, "%s%%%d.%ds%%s\n", + ((text->top_of_screen > 0 && + HText_hasToolbar(text)) ? + "#" : " "), + (LYcols-2)-strlen(percent), + (LYcols-2)-strlen(percent)); /* * Generate and display the complete title string. @@ -633,7 +645,10 @@ PRIVATE void display_title ARGS1(HText *,text) /* Output a page ** ------------- */ -PRIVATE void display_page ARGS3(HText *,text, int,line_number, char *, target) +PRIVATE void display_page ARGS3( + HText *, text, + int, line_number, + char *, target) { HTLine * line = NULL; int i; @@ -643,6 +658,7 @@ PRIVATE void display_page ARGS3(HText *,text, int,line_number, char *, target) FormInfo *FormInfo_ptr; BOOL display_flag = FALSE; HTAnchor *link_dest; + static int last_nlinks = 0; lynx_mode = NORMAL_LYNX_MODE; @@ -664,15 +680,15 @@ PRIVATE void display_page ARGS3(HText *,text, int,line_number, char *, target) } tmp[0] = tmp[1] = tmp[2] = '\0'; - last_screen = text->lines - (display_lines-2); + last_screen = text->Lines - (display_lines-2); line = text->last_line->prev; /* * Constrain the line number to be within the document. */ - if (text->lines < (display_lines)) + if (text->Lines < (display_lines)) line_number = 0; - else if (line_number > text->lines) + else if (line_number > text->Lines) line_number = last_screen; else if (line_number < 0) line_number = 0; @@ -783,7 +799,7 @@ PRIVATE void display_page ARGS3(HText *,text, int,line_number, char *, target) text->stale = NO; /* Display is up-to-date */ /* - * Add the anchors to lynx structures. + * Add the anchors to Lynx structures. */ nlinks = 0; for (Anchor_ptr=text->first_anchor; Anchor_ptr != NULL && @@ -886,11 +902,36 @@ PRIVATE void display_page ARGS3(HText *,text, int,line_number, char *, target) } } - if (Anchor_ptr == text->last_anchor || nlinks == MAXLINKS) + if (Anchor_ptr == text->last_anchor) + /* + * No more links in document. - FM + */ break; + + if (nlinks == MAXLINKS) { + /* + * Links array is full. If interactive, tell user + * to use half-page or two-line scrolling. - FM + */ + if (LYCursesON) { + _statusline(MAXLINKS_REACHED); + sleep(AlertSecs); + } + if (TRACE) + fprintf(stderr, "\ndisplay_page: MAXLINKS reached.\n"); + break; + } } /* + * Free any un-reallocated links[] entries + * from the previous page draw. - FM + */ + for (i = nlinks; i < last_nlinks; i++) + FREE(links[i].lname); + last_nlinks = nlinks; + + /* * If Anchor_ptr is not NULL and is not pointing to the last * anchor, then there are anchors farther down in the document, * and we need to flag this for traversals. @@ -918,7 +959,8 @@ PRIVATE void display_page ARGS3(HText *,text, int,line_number, char *, target) ** ** These are used by a parser to build the text in an object */ -PUBLIC void HText_beginAppend ARGS1(HText *,text) +PUBLIC void HText_beginAppend ARGS1( + HText *, text) { text->permissible_split = 0; text->in_line_1 = YES; @@ -945,12 +987,12 @@ PUBLIC void HText_beginAppend ARGS1(HText *,text) */ #define new_line(text) split_line(text, 0) -PRIVATE void split_line ARGS2(HText *,text, int,split) +PRIVATE void split_line ARGS2( + HText *, text, + int, split) { HTStyle * style = text->style; -#if defined(AIX) || defined(ultrix) - HTLine * temp; /* for realloc() substitute. */ -#endif /* AIX || ultrix */ + HTLine * temp; int spare; int indent = text->in_line_1 ? text->style->indent1st : text->style->leftIndent; @@ -964,14 +1006,14 @@ PRIVATE void split_line ARGS2(HText *,text, int,split) HTLine * line = (HTLine *)calloc(1, LINE_SIZE(MAX_LINE)); ctrl_chars_on_this_line = 0; /*reset since we are going to a new line*/ - HTML_Last_Char = ' '; + text->LastChar = ' '; if (TRACE) fprintf(stderr,"GridText: split_line called\n"); if (line == NULL) outofmem(__FILE__, "split_line"); - text->lines++; + text->Lines++; previous->next->prev = line; line->prev = previous; @@ -1116,31 +1158,24 @@ PRIVATE void split_line ARGS2(HText *,text, int,split) strcat(linedata, p); line->size += plen; } - + /* * Economize on space. */ while ((previous->size > 0) && - (previous->data[previous->size-1] == ' ')) /* Strip trailers */ + (previous->data[previous->size-1] == ' ')) { + /* + * Strip trailers. + */ + previous->data[previous->size-1] = '\0'; previous->size--; - -#if !defined(AIX) && !defined(ultrix) - previous = (HTLine *) realloc (previous, LINE_SIZE(previous->size)); - if (previous == NULL) - outofmem(__FILE__, "split_line"); -#else - /* - * RS6000 has a chaotic bug in realloc argument passing. Same - * problem with Ultrix (4.2) : realloc() is not declared properly. - * So we'll use a substitute for realloc. - */ + } temp = (HTLine *)calloc(1, LINE_SIZE(previous->size)); if (temp == NULL) outofmem(__FILE__, "split_line"); memcpy(temp, previous, LINE_SIZE(previous->size)); FREE(previous); previous = temp; -#endif /* !AIX && !ultrix */ previous->prev->next = previous; /* Link in new line */ previous->next->prev = previous; /* Could be same node of course */ @@ -1194,13 +1229,16 @@ PRIVATE void split_line ARGS2(HText *,text, int,split) /* Allow vertical blank space ** -------------------------- */ -PRIVATE void blank_lines ARGS2(HText *,text, int,newlines) +PRIVATE void blank_lines ARGS2( + HText *, text, + int, newlines) { if (!HText_LastLineSize(text)) { /* No text on current line */ HTLine * line = text->last_line->prev; while ((line != text->last_line) && (HText_TrueLineSize(line) == 0)) { - if (newlines == 0) break; + if (newlines == 0) + break; newlines--; /* Don't bother: already blank */ line = line->prev; } @@ -1219,7 +1257,8 @@ PRIVATE void blank_lines ARGS2(HText *,text, int,newlines) ** ------------------------------ ** See also: setStyle. */ -PUBLIC void HText_appendParagraph ARGS1(HText *,text) +PUBLIC void HText_appendParagraph ARGS1( + HText *, text) { int after = text->style->spaceAfter; int before = text->style->spaceBefore; @@ -1232,7 +1271,9 @@ PUBLIC void HText_appendParagraph ARGS1(HText *,text) ** ** Does not filter unnecessary style changes. */ -PUBLIC void HText_setStyle ARGS2(HText *,text, HTStyle *,style) +PUBLIC void HText_setStyle ARGS2( + HText *, text, + HTStyle *, style) { int after, before; @@ -1251,7 +1292,9 @@ PUBLIC void HText_setStyle ARGS2(HText *,text, HTStyle *,style) /* Append a character to the text object ** ------------------------------------- */ -PUBLIC void HText_appendCharacter ARGS2(HText *,text, char,ch) +PUBLIC void HText_appendCharacter ARGS2( + HText *, text, + char, ch) { HTLine * line; HTStyle * style; @@ -1394,7 +1437,7 @@ PUBLIC void HText_appendCharacter ARGS2(HText *,text, char,ch) } } } else { - goto check_ignore_excess; + goto check_IgnoreExcess; } } else if (ch == '\033') { return; @@ -1463,7 +1506,7 @@ PUBLIC void HText_appendCharacter ARGS2(HText *,text, char,ch) * Tabs. */ if (ch == '\t') { - HTTabStop * tab; + HTTabStop * Tab; int target; /* Where to tab to */ int here; @@ -1478,14 +1521,14 @@ PUBLIC void HText_appendCharacter ARGS2(HText *,text, char,ch) here = (((int)line->size + (int)line->offset) + indent) - ctrl_chars_on_this_line; /* Consider special chars GAB */ if (style->tabs) { /* Use tab table */ - for (tab = style->tabs; - tab->position <= here; - tab++) - if (!tab->position) { + for (Tab = style->tabs; + Tab->position <= here; + Tab++) + if (!Tab->position) { new_line(text); return; } - target = tab->position; + target = Tab->position; } else if (text->in_line_1) { /* Use 2nd indent */ if (here >= (int)style->leftIndent) { new_line(text); /* wrap */ @@ -1537,8 +1580,8 @@ PUBLIC void HText_appendCharacter ARGS2(HText *,text, char,ch) /* * Check if we should ignore characters at the wrap point. */ -check_ignore_excess: - if (ignore_excess && +check_IgnoreExcess: + if (text->IgnoreExcess && ((indent + (int)line->offset + (int)line->size) + (int)style->rightIndent - ctrl_chars_on_this_line) >= (LYcols-1)) return; @@ -1638,12 +1681,53 @@ check_ignore_excess: } } +/* Set LastChar element in the text object. +** ---------------------------------------- +*/ +PUBLIC void HText_setLastChar ARGS2( + HText *, text, + char, ch) +{ + if (!text) + return; + + text->LastChar = ch; +} + +/* Get LastChar element in the text object. +** ---------------------------------------- +*/ +PUBLIC char HText_getLastChar ARGS1( + HText *, text) +{ + if (!text) + return('\0'); + + return((char)text->LastChar); +} + +/* Set IgnoreExcess element in the text object. +** -------------------------------------------- +*/ +PUBLIC void HText_setIgnoreExcess ARGS2( + HText *, text, + BOOL, ignore) +{ + if (!text) + return; + + text->IgnoreExcess = ignore; +} + /* Anchor handling ** --------------- */ + /* Start an anchor field */ -PUBLIC void HText_beginAnchor ARGS2(HText *,text, HTChildAnchor *,anc) +PUBLIC void HText_beginAnchor ARGS2( + HText *, text, + HTChildAnchor *, anc) { char marker[16]; @@ -1682,17 +1766,18 @@ PUBLIC void HText_beginAnchor ARGS2(HText *,text, HTChildAnchor *,anc) } -PUBLIC void HText_endAnchor ARGS1(HText *,text) +PUBLIC void HText_endAnchor ARGS1( + HText *, text) { TextAnchor * a = text->last_anchor; if (a->number) { /* - * If it goes somewhere... + * If it goes somewhere... */ a->extent += text->chars + text->last_line->size - a->start; if (a->extent <= 2) { /* - * Might be a blank anchor from an ALT="". - FM + * Might be a blank anchor from an ALT="". - FM */ int j; a->show_anchor = NO; @@ -1714,7 +1799,9 @@ PUBLIC void HText_endAnchor ARGS1(HText *,text) } -PUBLIC void HText_appendText ARGS2(HText *,text, CONST char *,str) +PUBLIC void HText_appendText ARGS2( + HText *, text, + CONST char *, str) { CONST char *p; @@ -1727,7 +1814,8 @@ PUBLIC void HText_appendText ARGS2(HText *,text, CONST char *,str) } -PRIVATE void remove_special_attr_chars ARGS1(char *,buf) +PRIVATE void remove_special_attr_chars ARGS1( + char *, buf) { register char *cp; @@ -1744,11 +1832,12 @@ PRIVATE void remove_special_attr_chars ARGS1(char *,buf) /* ** This function trims blank lines from the end of the document, and -** then get the hightext from the text by finding the char position, +** then gets the hightext from the text by finding the char position, ** and brings the anchors in line with the text by adding the text ** offset to each of the anchors */ -PUBLIC void HText_endAppend ARGS1(HText *,text) +PUBLIC void HText_endAppend ARGS1( + HText *, text) { int cur_line, cur_char; TextAnchor *anchor_ptr; @@ -1770,7 +1859,7 @@ PUBLIC void HText_endAppend ARGS1(HText *,text) /* * Remove the blank lines at the end of document. */ - while (text->last_line->data[0] == '\0' && text->lines > 2) { + while (text->last_line->data[0] == '\0' && text->Lines > 2) { HTLine *next_to_the_last_line; if (TRACE) @@ -1784,7 +1873,7 @@ PUBLIC void HText_endAppend ARGS1(HText *,text) line_ptr->prev = next_to_the_last_line; FREE(text->last_line); text->last_line = next_to_the_last_line; - text->lines--; + text->Lines--; if (TRACE) fprintf(stderr, "GridText: New bottom line: %s\n", @@ -1846,7 +1935,7 @@ re_parse: * lines, then start the highlighting on the next line. */ if (anchor_ptr->line_pos >= strlen(line_ptr->data) && - cur_line < text->lines) { + cur_line < text->Lines) { anchor_ptr->start++; if (TRACE) @@ -1917,7 +2006,8 @@ re_parse: /* Dump diagnostics to stderr */ -PUBLIC void HText_dump ARGS1(HText *,text) +PUBLIC void HText_dump ARGS1( + HText *, text) { fprintf(stderr, "HText: Dump called\n"); } @@ -1925,7 +2015,8 @@ PUBLIC void HText_dump ARGS1(HText *,text) /* Return the anchor associated with this node */ -PUBLIC HTParentAnchor * HText_nodeAnchor ARGS1(HText *,text) +PUBLIC HTParentAnchor * HText_nodeAnchor ARGS1( + HText *, text) { return text->node_anchor; } @@ -1937,7 +2028,8 @@ PUBLIC HTParentAnchor * HText_nodeAnchor ARGS1(HText *,text) ** ** The index corresponds to the number we print in the anchor. */ -PUBLIC HTChildAnchor * HText_childNumber ARGS1(int,number) +PUBLIC HTChildAnchor * HText_childNumber ARGS1( + int, number) { TextAnchor * a; for (a = HTMainText->first_anchor; a; a = a->next) { @@ -1949,7 +2041,10 @@ PUBLIC HTChildAnchor * HText_childNumber ARGS1(int,number) /* * HTGetLinkInfo returns some link info based on the number. */ -PUBLIC int HTGetLinkInfo ARGS3(int, number, char **, hightext, char **, lname) +PUBLIC int HTGetLinkInfo ARGS3( + int, number, + char **, hightext, + char **, lname) { TextAnchor * a; HTAnchor *link_dest; @@ -1984,7 +2079,7 @@ PUBLIC int HTGetLinkInfo ARGS3(int, number, char **, hightext, char **, lname) */ PUBLIC int HText_getNumOfLines NOARGS { - return(HTMainText->lines); + return(HTMainText->Lines); } /* @@ -2038,7 +2133,9 @@ PUBLIC char * HText_getServer NOARGS * starting from the line 'line_num'-1 * this is the primary call for lynx */ -PUBLIC void HText_pageDisplay ARGS2(int,line_num, char *, target) +PUBLIC void HText_pageDisplay ARGS2( + int, line_num, + char *, target) { display_page(HTMainText, line_num-1, target); @@ -2047,13 +2144,16 @@ PUBLIC void HText_pageDisplay ARGS2(int,line_num, char *, target) /* * HText_LinksInLines returns the number of links in the - * 'lines' number of lines beginning with 'line_num'-1. - FM + * 'Lines' number of lines beginning with 'line_num'-1. - FM */ -PUBLIC int HText_LinksInLines ARGS3(HText *,text, int,line_num, int,lines) +PUBLIC int HText_LinksInLines ARGS3( + HText *, text, + int, line_num, + int, Lines) { int total = 0; int start = (line_num - 1); - int end = (start + lines); + int end = (start + Lines); TextAnchor *Anchor_ptr = NULL; if (!text) @@ -2073,23 +2173,27 @@ PUBLIC int HText_LinksInLines ARGS3(HText *,text, int,line_num, int,lines) return total; } -PUBLIC void HText_setStale ARGS1(HText *,text) +PUBLIC void HText_setStale ARGS1( + HText *, text) { text->stale = YES; } -PUBLIC void HText_refresh ARGS1(HText *,text) +PUBLIC void HText_refresh ARGS1( + HText *, text) { if (text->stale) display_page(text, text->top_of_screen, ""); } -PUBLIC int HText_sourceAnchors ARGS1(HText *,text) +PUBLIC int HText_sourceAnchors ARGS1( + HText *, text) { return (text ? text->last_anchor_number : -1); } -PUBLIC BOOL HText_canScrollUp ARGS1(HText *,text) +PUBLIC BOOL HText_canScrollUp ARGS1( + HText *, text) { return (text->top_of_screen != 0); } @@ -2098,29 +2202,33 @@ PUBLIC BOOL HText_canScrollDown NOARGS { HText * text = HTMainText; - return ((text->top_of_screen + display_lines) < text->lines+1); + return ((text->top_of_screen + display_lines) < text->Lines+1); } /* Scroll actions */ -PUBLIC void HText_scrollTop ARGS1(HText *,text) +PUBLIC void HText_scrollTop ARGS1( + HText *, text) { display_page(text, 0, ""); } -PUBLIC void HText_scrollDown ARGS1(HText *,text) +PUBLIC void HText_scrollDown ARGS1( + HText *, text) { display_page(text, text->top_of_screen + display_lines, ""); } -PUBLIC void HText_scrollUp ARGS1(HText *,text) +PUBLIC void HText_scrollUp ARGS1( + HText *, text) { display_page(text, text->top_of_screen - display_lines, ""); } -PUBLIC void HText_scrollBottom ARGS1(HText *,text) +PUBLIC void HText_scrollBottom ARGS1( + HText *, text) { - display_page(text, text->lines - display_lines, ""); + display_page(text, text->Lines - display_lines, ""); } @@ -2130,7 +2238,9 @@ PUBLIC void HText_scrollBottom ARGS1(HText *,text) /* Bring to front and highlight it */ -PRIVATE int line_for_char ARGS2(HText *,text, int,char_num) +PRIVATE int line_for_char ARGS2( + HText *, text, + int, char_num) { int line_number = 0; int characters = 0; @@ -2144,13 +2254,14 @@ PRIVATE int line_for_char ARGS2(HText *,text, int,char_num) } } -PUBLIC BOOL HText_select ARGS1(HText *,text) +PUBLIC BOOL HText_select ARGS1( + HText *, text) { if (text != HTMainText) { HTMainText = text; HTMainAnchor = text->node_anchor; /* - * Make this text the most current in the loaded texts list. - FM + * Make this text the most current in the loaded texts list. - FM */ if (loaded_texts && HTList_removeObject(loaded_texts, text)) HTList_addObject(loaded_texts, text); @@ -2160,7 +2271,53 @@ PUBLIC BOOL HText_select ARGS1(HText *,text) return YES; } -PUBLIC BOOL HTFindPoundSelector ARGS1(char *,selector) +/* + * This function returns TRUE if doc's post_data, address + * and isHEAD elements are identical to those of a loaded + * (memory cached) text. - FM + */ +PUBLIC BOOL HText_POSTReplyLoaded ARGS1( + document *, doc) +{ + HText *text = NULL; + HTList *cur = loaded_texts; + char *post_data, *address; + BOOL is_head; + + /* + * Make sure we have the structures. - FM + */ + if (!cur || !doc) + return(FALSE); + + /* + * Make sure doc is for a POST reply. - FM + */ + if ((post_data = doc->post_data) == NULL || + (address = doc->address) == NULL) + return(FALSE); + is_head = doc->isHEAD; + + /* + * Loop through the loaded texts looking for a + * POST reply match. - FM + */ + while (NULL != (text = (HText *)HTList_nextObject(cur))) { + if (text->node_anchor && + text->node_anchor->post_data && + !strcmp(post_data, text->node_anchor->post_data) && + text->node_anchor->address && + !strcmp(address, text->node_anchor->address) && + is_head == text->node_anchor->isHEAD) { + return(TRUE); + } + } + + return(FALSE); +} + +PUBLIC BOOL HTFindPoundSelector ARGS1( + char *, selector) { TextAnchor * a; @@ -2185,7 +2342,9 @@ PUBLIC BOOL HTFindPoundSelector ARGS1(char *,selector) } -PUBLIC BOOL HText_selectAnchor ARGS2(HText *,text, HTChildAnchor *,anchor) +PUBLIC BOOL HText_selectAnchor ARGS2( + HText *, text, + HTChildAnchor *, anchor) { TextAnchor * a; @@ -2238,7 +2397,9 @@ PUBLIC BOOL HText_selectAnchor ARGS2(HText *,text, HTChildAnchor *,anchor) */ /* Apply this style to the selection */ -PUBLIC void HText_applyStyle ARGS2(HText *, me, HTStyle *,style) +PUBLIC void HText_applyStyle ARGS2( + HText *, me, + HTStyle *, style) { } @@ -2246,7 +2407,9 @@ PUBLIC void HText_applyStyle ARGS2(HText *, me, HTStyle *,style) /* Update all text with changed style. */ -PUBLIC void HText_updateStyle ARGS2(HText *, me, HTStyle *,style) +PUBLIC void HText_updateStyle ARGS2( + HText *, me, + HTStyle *, style) { } @@ -2255,8 +2418,8 @@ PUBLIC void HText_updateStyle ARGS2(HText *, me, HTStyle *,style) /* Return style of selection */ PUBLIC HTStyle * HText_selectionStyle ARGS2( - HText *,me, - HTStyleSheet *,sheet) + HText *, me, + HTStyleSheet *, sheet) { return 0; } @@ -2265,9 +2428,9 @@ PUBLIC HTStyle * HText_selectionStyle ARGS2( /* Paste in styled text */ PUBLIC void HText_replaceSel ARGS3( - HText *,me, - CONST char *,aString, - HTStyle *,aStyle) + HText *, me, + CONST char *, aString, + HTStyle *, aStyle) { } @@ -2275,7 +2438,9 @@ PUBLIC void HText_replaceSel ARGS3( /* Apply this style to the selection and all similarly formatted text ** (style recovery only) */ -PUBLIC void HTextApplyToSimilar ARGS2(HText *,me, HTStyle *,style) +PUBLIC void HTextApplyToSimilar ARGS2( + HText *, me, + HTStyle *, style) { } @@ -2284,7 +2449,9 @@ PUBLIC void HTextApplyToSimilar ARGS2(HText *,me, HTStyle *,style) /* Select the first unstyled run. ** (style recovery only) */ -PUBLIC void HTextSelectUnstyled ARGS2(HText *,me, HTStyleSheet *,sheet) +PUBLIC void HTextSelectUnstyled ARGS2( + HText *, me, + HTStyleSheet *, sheet) { } @@ -2292,12 +2459,14 @@ PUBLIC void HTextSelectUnstyled ARGS2(HText *,me, HTStyleSheet *,sheet) /* Anchor handling: */ -PUBLIC void HText_unlinkSelection ARGS1(HText *,me) +PUBLIC void HText_unlinkSelection ARGS1( + HText *, me) { } -PUBLIC HTAnchor * HText_referenceSelected ARGS1(HText *,me) +PUBLIC HTAnchor * HText_referenceSelected ARGS1( + HText *, me) { return 0; } @@ -2309,18 +2478,21 @@ PUBLIC int HText_getTopOfScreen NOARGS return text->top_of_screen; } -PUBLIC int HText_getLines ARGS1(HText *,text) +PUBLIC int HText_getLines ARGS1( + HText *, text) { - return text->lines; + return text->Lines; } -PUBLIC HTAnchor * HText_linkSelTo ARGS2(HText *,me, HTAnchor *,anchor) +PUBLIC HTAnchor * HText_linkSelTo ARGS2( + HText *, me, + HTAnchor *, anchor) { return 0; } /* - * Utility for freeing the list of previous isindex and whereis queries. - FM + * Utility for freeing the list of previous isindex and whereis queries. - FM */ PUBLIC void HTSearchQueries_free NOARGS { @@ -2339,10 +2511,11 @@ PUBLIC void HTSearchQueries_free NOARGS } /* - * Utility for listing isindex and whereis queries, making - * any repeated queries the most current in the list. - FM + * Utility for listing isindex and whereis queries, making + * any repeated queries the most current in the list. - FM */ -PUBLIC void HTAddSearchQuery ARGS1(char *, query) +PUBLIC void HTAddSearchQuery ARGS1( + char *, query) { char *new; char *old; @@ -2375,7 +2548,8 @@ PUBLIC void HTAddSearchQuery ARGS1(char *, query) return; } -PUBLIC int do_www_search ARGS1(document *,doc) +PUBLIC int do_www_search ARGS1( + document *, doc) { char searchstring[256], temp[256], *cp, *tmpaddress = NULL; int ch, recall, i; @@ -2384,12 +2558,12 @@ PUBLIC int do_www_search ARGS1(document *,doc) BOOLEAN PreviousSearch = FALSE; /* - * Load the default query buffer + * Load the default query buffer */ if ((cp=strchr(doc->address, '?')) != NULL) { /* - * This is an index from a previous search. - * Use its query as the default. + * This is an index from a previous search. + * Use its query as the default. */ PreviousSearch = TRUE; strcpy(searchstring, ++cp); @@ -2399,19 +2573,19 @@ PUBLIC int do_www_search ARGS1(document *,doc) HTUnEscape(searchstring); strcpy(temp, searchstring); /* - * Make sure it's treated as the most recent query. - FM + * Make sure it's treated as the most recent query. - FM */ HTAddSearchQuery(searchstring); } else { /* - * New search; no default. + * New search; no default. */ searchstring[0] = '\0'; temp[0] = '\0'; } /* - * Prompt for a query string. + * Prompt for a query string. */ if (searchstring[0] == '\0') { if (HTMainAnchor->isIndexPrompt) @@ -2431,19 +2605,19 @@ get_query: if (recall && ch == UPARROW) { if (PreviousSearch) { /* - * Use the second to last query in the list. - FM + * Use the second to last query in the list. - FM */ QueryNum = 1; PreviousSearch = FALSE; } else { /* - * Go back to the previous query in the list. - FM + * Go back to the previous query in the list. - FM */ QueryNum++; } if (QueryNum >= QueryTotal) /* - * Roll around to the last query in the list. - FM + * Roll around to the last query in the list. - FM */ QueryNum = 0; if ((cp=(char *)HTList_objectAt(search_queries, @@ -2462,19 +2636,19 @@ get_query: } else if (recall && ch == DNARROW) { if (PreviousSearch) { /* - * Use the first query in the list. - FM + * Use the first query in the list. - FM */ QueryNum = QueryTotal - 1; PreviousSearch = FALSE; } else { /* - * Advance to the next query in the list. - FM + * Advance to the next query in the list. - FM */ QueryNum--; } if (QueryNum < 0) /* - * Roll around to the first query in the list. - FM + * Roll around to the first query in the list. - FM */ QueryNum = QueryTotal - 1; if ((cp=(char *)HTList_objectAt(search_queries, @@ -2493,7 +2667,7 @@ get_query: } /* - * Search cancelled. + * Search cancelled. */ _statusline(CANCELLED); sleep(InfoSecs); @@ -2501,7 +2675,7 @@ get_query: } /* - * Strip leaders and trailers. - FM + * Strip leaders and trailers. - FM */ cp = searchstring; while (*cp && isspace((unsigned char)*cp)) @@ -2521,7 +2695,7 @@ get_query: *cp-- = '\0'; /* - * Don't resubmit the same query unintentionally. + * Don't resubmit the same query unintentionally. */ if (!LYforce_no_cache && 0 == strcmp(temp, searchstring)) { _statusline(USE_C_R_TO_RESUB_CUR_QUERY); @@ -2530,13 +2704,13 @@ get_query: } /* - * Add searchstring to the query list, - * or make it the most current. - FM + * Add searchstring to the query list, + * or make it the most current. - FM */ HTAddSearchQuery(searchstring); /* - * Show the URL with the new query. + * Show the URL with the new query. */ if ((cp=strchr(doc->address, '?')) != NULL) *cp = '\0'; @@ -2554,7 +2728,7 @@ get_query: *cp = '?'; /* - * OK, now we do the search. + * OK, now we do the search. */ if (HTSearch(searchstring, HTMainAnchor)) { /* @@ -2573,27 +2747,30 @@ get_query: fprintf(stderr,"\ndo_www_search: newfile: %s\n",doc->address); /* - * Yah, the search succeeded. + * Yah, the search succeeded. */ return(NORMAL); } /* - * Either the search failed (Yuk), or we got redirection. - * If it's redirection, use_this_url_instead is set, and - * mainloop() will deal with it such that security features - * and restrictions are checked before acting on the URL, or - * rejecting it. - FM + * Either the search failed (Yuk), or we got redirection. + * If it's redirection, use_this_url_instead is set, and + * mainloop() will deal with it such that security features + * and restrictions are checked before acting on the URL, or + * rejecting it. - FM */ return(NOT_FOUND); } -/* print the contents of the file in HTMainText to - * the file descripter fp. - * if is_reply is true add ">" to the beginning of each - * line to specify the file is a replied to message +/* + * Print the contents of the file in HTMainText to + * the file descripter fp. + * If is_reply is TRUE add ">" to the beginning of each + * line to specify the file is a reply to message. */ -PUBLIC void print_wwwfile_to_fd ARGS2(FILE *,fp, int,is_reply) +PUBLIC void print_wwwfile_to_fd ARGS2( + FILE *, fp, + int, is_reply) { register int i; HTLine * line = HTMainText->last_line->next; @@ -2640,12 +2817,15 @@ PUBLIC void print_wwwfile_to_fd ARGS2(FILE *,fp, int,is_reply) } -/* print the contents of the file in HTMainText to - * the file descripter fp. - * First output line is "thelink", ie, the URL for this file +/* + * Print the contents of the file in HTMainText to + * the file descripter fp. + * First output line is "thelink", ie, the URL for this file. */ -PUBLIC void print_crawl_to_fd ARGS3(FILE *, fp, char *, thelink, - char *, thetitle) +PUBLIC void print_crawl_to_fd ARGS3( + FILE *, fp, + char *, thelink, + char *, thetitle) { register int i; HTLine * line = HTMainText->last_line->next; @@ -2682,7 +2862,9 @@ PUBLIC void print_crawl_to_fd ARGS3(FILE *, fp, char *, thelink, #endif /* VMS */ } -PUBLIC void www_user_search ARGS2(int,start_line, char *,target) +PUBLIC void www_user_search ARGS2( + int, start_line, + char *, target) { register HTLine * line = HTMainText->last_line->next; register int count; @@ -2738,7 +2920,9 @@ PUBLIC void www_user_search ARGS2(int,start_line, char *,target) } -PUBLIC void user_message ARGS2(char *,message, char *,argument) +PUBLIC void user_message ARGS2( + char *, message, + char *, argument) { char *temp = NULL; char temp_arg[256]; @@ -2762,18 +2946,21 @@ PUBLIC void user_message ARGS2(char *,message, char *,argument) return; } -/* HText_getOwner returns the owner of the - * current document +/* + * HText_getOwner returns the owner of the + * current document. */ PUBLIC char * HText_getOwner NOARGS { return((char *)HTAnchor_owner(HTMainText->node_anchor)); } -/* HText_setMainTextOwner sets the owner for the - * current document +/* +* HText_setMainTextOwner sets the owner for the + * current document. */ -PUBLIC void HText_setMainTextOwner ARGS1(CONST char *, owner) +PUBLIC void HText_setMainTextOwner ARGS1( + CONST char *, owner) { if (!HTMainText) return; @@ -2781,15 +2968,34 @@ PUBLIC void HText_setMainTextOwner ARGS1(CONST char *, owner) HTAnchor_setOwner(HTMainText->node_anchor, owner); } -/* HText_getRevTitle returns the RevTitle element of the - * current document, used as the subject for mailto comments - * to the owner. +/* + * HText_getRevTitle returns the RevTitle element of the + * current document, used as the subject for mailto comments + * to the owner. */ PUBLIC char * HText_getRevTitle NOARGS { return((char *)HTAnchor_RevTitle(HTMainText->node_anchor)); } +/* + * HText_getContentBase returns the Content-Base header + * of the current document. + */ +PUBLIC char * HText_getContentBase NOARGS +{ + return((char *)HTAnchor_content_base(HTMainText->node_anchor)); +} + +/* + * HText_getContentLocation returns the Content-Location header + * of the current document. + */ +PUBLIC char * HText_getContentLocation NOARGS +{ + return((char *)HTAnchor_content_location(HTMainText->node_anchor)); +} + PUBLIC void HTuncache_current_document NOARGS { /* should remove current document from memory */ @@ -2847,6 +3053,17 @@ PUBLIC BOOLEAN HTLoadedDocumentIsHEAD NOARGS return (FALSE); } +PUBLIC BOOLEAN HTLoadedDocumentIsSafe NOARGS +{ + if (!HTMainText) + return (FALSE); + + if (HTMainText->node_anchor && HTMainText->node_anchor->safe) + return(HTMainText->node_anchor->safe); + else + return (FALSE); +} + PUBLIC char * HTLoadedDocumentCharset NOARGS { if (!HTMainText) @@ -2879,14 +3096,16 @@ PUBLIC char * HTLoadedDocumentBookmark NOARGS return (NULL); } -PUBLIC int HText_LastLineSize ARGS1(HText *,text) +PUBLIC int HText_LastLineSize ARGS1( + HText *, text) { if (!text || !text->last_line || !text->last_line->size) return 0; return HText_TrueLineSize(text->last_line); } -PUBLIC int HText_PreviousLineSize ARGS1(HText *,text) +PUBLIC int HText_PreviousLineSize ARGS1( + HText *, text) { HTLine * line; @@ -2897,7 +3116,8 @@ PUBLIC int HText_PreviousLineSize ARGS1(HText *,text) return HText_TrueLineSize(line); } -PRIVATE int HText_TrueLineSize ARGS1(HTLine *,line) +PRIVATE int HText_TrueLineSize ARGS1( + HTLine *, line) { int i, true_size = 0; @@ -2912,7 +3132,8 @@ PRIVATE int HText_TrueLineSize ARGS1(HTLine *,line) return true_size; } -PUBLIC void HText_NegateLineOne ARGS1(HText *,text) +PUBLIC void HText_NegateLineOne ARGS1( + HText *, text) { if (text) { text->in_line_1 = NO; @@ -2921,13 +3142,44 @@ PUBLIC void HText_NegateLineOne ARGS1(HText *,text) } /* - * NOTE: This function presently is correct only if the - * alignment is HT_LEFT. The offset is still zero, - * because that's not determined for HT_CENTER or - * HT_RIGHT until subsequent characters are received - * and split_line() is called. - FM + * This function is for removing the first of two + * successive blank lines. It should be called after + * checking the situation with HText_LastLineSize() + * and HText_PreviousLineSize(). Any characters in + * the removed line (i.e., control characters, or it + * wouldn't have tested blank) should have been + * reiterated by split_line() in the retained blank + * line. - FM + */ +PUBLIC void HText_RemovePreviousLine ARGS1( + HText *, text) +{ + HTLine *line, *previous; + char *data; + + if (!(text && text->Lines > 1)) + return; + + line = text->last_line->prev; + data = line->data; + previous = line->prev; + previous->next = text->last_line; + text->last_line->prev = previous; + text->chars -= ((data && *data == '\0') ? + 1 : strlen(line->data) + 1); + text->Lines--; + FREE(line); +} + +/* + * NOTE: This function presently is correct only if the + * alignment is HT_LEFT. The offset is still zero, + * because that's not determined for HT_CENTER or + * HT_RIGHT until subsequent characters are received + * and split_line() is called. - FM */ -PUBLIC int HText_getCurrentColumn ARGS1(HText *,text) +PUBLIC int HText_getCurrentColumn ARGS1( + HText *, text) { int column = 0; @@ -2939,7 +3191,8 @@ PUBLIC int HText_getCurrentColumn ARGS1(HText *,text) return column; } -PUBLIC int HText_getMaximumColumn ARGS1(HText *,text) +PUBLIC int HText_getMaximumColumn ARGS1( + HText *, text) { int column = (LYcols-2); if (text) { @@ -2950,13 +3203,15 @@ PUBLIC int HText_getMaximumColumn ARGS1(HText *,text) } /* - * NOTE: This function uses HText_getCurrentColumn() which - * presently is correct only if the alignment is - * HT_LEFT. - FM + * NOTE: This function uses HText_getCurrentColumn() which + * presently is correct only if the alignment is + * HT_LEFT. - FM */ -PUBLIC void HText_setTabID ARGS2(HText *,text, CONST char *,name) +PUBLIC void HText_setTabID ARGS2( + HText *, text, + CONST char *, name) { - HTTabID * tab = NULL; + HTTabID * Tab = NULL; HTList * cur = text->tabs; HTList * last = NULL; @@ -2966,43 +3221,46 @@ PUBLIC void HText_setTabID ARGS2(HText *,text, CONST char *,name) if (!cur) { cur = text->tabs = HTList_new(); } else { - while (NULL != (tab = (HTTabID *)HTList_nextObject(cur))) { - if (tab->name && !strcmp(tab->name, name)) + while (NULL != (Tab = (HTTabID *)HTList_nextObject(cur))) { + if (Tab->name && !strcmp(Tab->name, name)) return; /* Already set. Keep the first value. */ last = cur; } cur = last; } - if (!tab) { /* New name. Create a new node */ - tab = (HTTabID *)calloc(1, sizeof(HTTabID)); - if (tab == NULL) + if (!Tab) { /* New name. Create a new node */ + Tab = (HTTabID *)calloc(1, sizeof(HTTabID)); + if (Tab == NULL) outofmem(__FILE__, "HText_setTabID"); - HTList_addObject(cur, tab); - StrAllocCopy(tab->name, name); + HTList_addObject(cur, Tab); + StrAllocCopy(Tab->name, name); } - tab->column = HText_getCurrentColumn(text); + Tab->column = HText_getCurrentColumn(text); return; } -PUBLIC int HText_getTabIDColumn ARGS2(HText *,text, CONST char *,name) +PUBLIC int HText_getTabIDColumn ARGS2( + HText *, text, + CONST char *, name) { int column = 0; - HTTabID * tab; + HTTabID * Tab; HTList * cur = text->tabs; if (text && name && *name && cur) { - while (NULL != (tab = (HTTabID *)HTList_nextObject(cur))) { - if (tab->name && !strcmp(tab->name, name)) + while (NULL != (Tab = (HTTabID *)HTList_nextObject(cur))) { + if (Tab->name && !strcmp(Tab->name, name)) break; } - if (tab) - column = tab->column; + if (Tab) + column = Tab->column; } return column; } -/* Form methods +/* + * Form methods * These routines are used to build forms consisting * of input fields */ @@ -3072,23 +3330,24 @@ PUBLIC void HText_beginForm ARGS4( (HTFormEnctype ? HTFormEnctype : "")); } -PUBLIC void HText_endForm ARGS1(HText *,text) +PUBLIC void HText_endForm ARGS1( + HText *, text) { if (HTFormFields == 1 && text && text->first_anchor) { /* - * Support submission of a single text input field in - * the form via <return> instead of a submit botton. - FM + * Support submission of a single text input field in + * the form via <return> instead of a submit botton. - FM */ TextAnchor * a = text->first_anchor; /* - * Go through list of anchors and get our input field. - FM + * Go through list of anchors and get our input field. - FM */ while (1) { if (a->link_type == INPUT_ANCHOR && a->input_field->number == HTFormNumber && a->input_field->type == F_TEXT_TYPE) { /* - * Got it. Make it submitting. - FM + * Got it. Make it submitting. - FM */ a->input_field->submit_action = NULL; StrAllocCopy(a->input_field->submit_action, HTFormAction); @@ -3118,7 +3377,10 @@ PUBLIC void HText_endForm ARGS1(HText *,text) HTFormDisabled = FALSE; } -PUBLIC void HText_beginSelect ARGS3(char *,name, BOOLEAN,multiple, char *, size) +PUBLIC void HText_beginSelect ARGS3( + char *, name, + BOOLEAN, multiple, + char *, size) { /* * Save the group name. @@ -3137,7 +3399,7 @@ PUBLIC void HText_beginSelect ARGS3(char *,name, BOOLEAN,multiple, char *, size) HTCurSelectGroupType = F_RADIO_TYPE; /* - * Length of an option list. + * Length of an option list. */ StrAllocCopy(HTCurSelectGroupSize, size); @@ -3155,9 +3417,12 @@ PUBLIC void HText_beginSelect ARGS3(char *,name, BOOLEAN,multiple, char *, size) ** tag so we have to do it now. Assume that the last anchor ** was the previous options tag. */ -PUBLIC char * HText_setLastOptionValue ARGS5(HText *, text, char *, value, - char*, submit_value, - int, order, BOOLEAN, checked) +PUBLIC char * HText_setLastOptionValue ARGS5( + HText *, text, + char *, value, + char*, submit_value, + int, order, + BOOLEAN, checked) { char *cp; unsigned char *tmp = NULL; @@ -3345,7 +3610,9 @@ PUBLIC char * HText_setLastOptionValue ARGS5(HText *, text, char *, value, * returns the number of charactors to leave blank * so that the input field can fit */ -PUBLIC int HText_beginInput ARGS2(HText *,text, InputFieldData *,I) +PUBLIC int HText_beginInput ARGS2( + HText *, text, + InputFieldData *, I) { TextAnchor * a = (TextAnchor *) calloc(1, sizeof(*a)); @@ -3488,7 +3755,8 @@ PUBLIC int HText_beginInput ARGS2(HText *,text, InputFieldData *,I) */ if (I->size != NULL) { f->size = atoi(I->size); - /* Leave at zero for option lists. + /* + * Leave at zero for option lists. */ if (f->size == 0 && cp_option == NULL) { f->size = 20; /* default */ @@ -3528,15 +3796,7 @@ PUBLIC int HText_beginInput ARGS2(HText *,text, InputFieldData *,I) } else if (!strcasecomp(I->type,"submit")) { f->type = F_SUBMIT_TYPE; } else if (!strcasecomp(I->type,"image")) { - /* - * Ugh, we have a clickable image submit button. - * Set the type to submit, and fake an ALT string. - * If the user activates it, we'll send a 0,0 - * coordinate pair, which typically will return - * the image's default. FM - */ - f->type = F_SUBMIT_TYPE; - StrAllocCopy(f->value, "[IMAGE]-Submit"); + f->type = F_IMAGE_SUBMIT_TYPE; } else if (!strcasecomp(I->type,"reset")) { f->type = F_RESET_TYPE; } else if (!strcasecomp(I->type,"OPTION_LIST")) { @@ -3552,7 +3812,9 @@ PUBLIC int HText_beginInput ARGS2(HText *,text, InputFieldData *,I) } else if (!strcasecomp(I->type,"file")) { f->type = F_FILE_TYPE; } else { - /* Note that TYPE="scribble" defaults to TYPE="text". - FM */ + /* + * Note that TYPE="scribble" defaults to TYPE="text". - FM + */ f->type = F_TEXT_TYPE; /* default */ } } else { @@ -3565,11 +3827,17 @@ PUBLIC int HText_beginInput ARGS2(HText *,text, InputFieldData *,I) if (I->name != NULL) { StrAllocCopy(f->name,I->name); } else { - if (f->type == F_RESET_TYPE || f->type == F_SUBMIT_TYPE) { - /* set name to empty string */ + if (f->type == F_RESET_TYPE || + f->type == F_SUBMIT_TYPE || + f->type == F_IMAGE_SUBMIT_TYPE) { + /* + * Set name to empty string. + */ StrAllocCopy(f->name, ""); } else { - /* error! name must be present */ + /* + * Error! NAME must be present. + */ if (TRACE) fprintf(stderr, "GridText: No name present in input field; not displaying\n"); @@ -3581,46 +3849,49 @@ PUBLIC int HText_beginInput ARGS2(HText *,text, InputFieldData *,I) } /* - * Set VALUE (if it exists). + * Set VALUE, if it exists. Otherwise, if it's not + * an option list make it a zero-length string. - FM */ if (IValue != NULL) { /* * OPTION VALUE is not actually the value to be seen but is to * be sent.... */ - if (f->type != F_OPTION_LIST_TYPE && f->type != F_CHECKBOX_TYPE) { - StrAllocCopy(f->value, IValue); - } else { + if (f->type == F_OPTION_LIST_TYPE || + f->type == F_CHECKBOX_TYPE) { /* * Fill both with the value. The f->value may be * overwritten in HText_setLastOptionValue.... */ - if (!f->value || strcmp(f->value, "[IMAGE]-Submit")) - StrAllocCopy(f->value, IValue); + StrAllocCopy(f->value, IValue); StrAllocCopy(f->cp_submit_value, IValue); + } else { + StrAllocCopy(f->value, IValue); } - } else if (!f->value || strcmp(f->value, "[IMAGE]-Submit")) { - if (f->type != F_OPTION_LIST_TYPE) { - StrAllocCopy(f->value, ""); - } + } else if (f->type != F_OPTION_LIST_TYPE) { + StrAllocCopy(f->value, ""); } /* * Run checks and fill in neccessary values. */ if (f->type == F_RESET_TYPE) { - if (IValue != NULL) { - f->size = strlen(IValue); + if (f->value && *f->value != '\0') { + f->size = strlen(f->value); } else { StrAllocCopy(f->value, "Reset"); f->size = 5; } - } else if (f->type == F_SUBMIT_TYPE) { - if (f->value && !strcmp(f->value, "[IMAGE]-Submit")) { + } else if (f->type == F_IMAGE_SUBMIT_TYPE || + f->type == F_SUBMIT_TYPE) { + if (f->value && *f->value != '\0') { f->size = strlen(f->value); - } else if (IValue != NULL) { - f->size = strlen(IValue); + } else if (f->type == F_IMAGE_SUBMIT_TYPE) { + StrAllocCopy(f->value, "[IMAGE]-Submit"); + f->size = 14; } else { + StrAllocCopy(f->value, "[IMAGE]-Submit"); + f->size = 14; StrAllocCopy(f->value, "Submit"); f->size = 6; } @@ -3678,8 +3949,11 @@ PUBLIC int HText_beginInput ARGS2(HText *,text, InputFieldData *,I) } -PUBLIC void HText_SubmitForm ARGS4(FormInfo *,submit_item, document *,doc, - char *,link_name, char *, link_value) +PUBLIC void HText_SubmitForm ARGS4( + FormInfo *, submit_item, + document *, doc, + char *, link_name, + char *, link_value) { TextAnchor *anchor_ptr = HTMainText->first_anchor; int form_number = submit_item->number; @@ -3754,7 +4028,7 @@ PUBLIC void HText_SubmitForm ARGS4(FormInfo *,submit_item, document *,doc, len += (strlen(form_ptr->name) + (Boundary ? 100 : 10)); /* - * Calculate by the option submit value if present. + * Calculate by the option submit value if present. */ if (form_ptr->cp_submit_value != NULL) { len += (strlen(form_ptr->cp_submit_value) + 10); @@ -3874,12 +4148,15 @@ PUBLIC void HText_SubmitForm ARGS4(FormInfo *,submit_item, document *,doc, case F_SUBMIT_TYPE: case F_TEXT_SUBMIT_TYPE: + case F_IMAGE_SUBMIT_TYPE: /* * If it has a non-zero length name (e.g., because - * it's really a type="image" that's been converted - * to SUBMIT_TYPE, or one of multiple submit buttons, - * or a single type="text" that's been converted to - * a TEXT_SUBMIT_TYPE), include the name=value pair. - FM + * it's IMAGE_SUBMIT_TYPE to be handled homologously + * to an image map, or a SUBMIT_TYPE in a set of + * multiple submit buttons, or a single type="text" + * that's been converted to a TEXT_SUBMIT_TYPE), + * include the name=value pair, or fake name.x=0 and + * name.y=0 pairs for IMAGE_SUBMIT_TYPE. - FM */ if ((form_ptr->name && *form_ptr->name != '\0' && !strcmp(form_ptr->name, link_name)) && @@ -3921,7 +4198,8 @@ PUBLIC void HText_SubmitForm ARGS4(FormInfo *,submit_item, document *,doc, } /* - * Be sure to actually look at the option submit value. + * Be sure to actually look at + * the option submit value. */ if (form_ptr->cp_submit_value != NULL) { for (i = 0; form_ptr->cp_submit_value[i]; i++) { @@ -3972,11 +4250,11 @@ PUBLIC void HText_SubmitForm ARGS4(FormInfo *,submit_item, document *,doc, } } - if (!strcmp(form_ptr->value, "[IMAGE]-Submit")) { + if (form_ptr->type == F_IMAGE_SUBMIT_TYPE) { /* - * It's a clickable image submit button. - * Fake a 0,0 coordinate pair, which - * typically returns the image's default. - FM + * It's a clickable image submit button. + * Fake a 0,0 coordinate pair, which + * typically returns the image's default. - FM */ if (Boundary) { escaped1[(strlen(escaped1) - 4)] = '\0'; @@ -3998,8 +4276,8 @@ PUBLIC void HText_SubmitForm ARGS4(FormInfo *,submit_item, document *,doc, } } else { /* - * It's a standard submit button. - * Use the name=value pair. = FM + * It's a standard submit button. + * Use the name=value pair. = FM */ sprintf(&query[strlen(query)], "%s%s%s%s%s", @@ -4019,7 +4297,9 @@ PUBLIC void HText_SubmitForm ARGS4(FormInfo *,submit_item, document *,doc, case F_RADIO_TYPE: case F_CHECKBOX_TYPE: - /* only add if selected */ + /* + * Only add if selected. + */ if (form_ptr->num_value) { if (first_one) { if (Boundary) { @@ -4056,7 +4336,7 @@ PUBLIC void HText_SubmitForm ARGS4(FormInfo *,submit_item, document *,doc, escaped1 = HTEscape(form_ptr->name, URL_XALPHAS); } /* - * Be sure to use the submit option value. + * Be sure to use the submit option value. */ if (form_ptr->cp_submit_value != NULL) { for (i = 0; form_ptr->cp_submit_value[i]; i++) { @@ -4418,7 +4698,8 @@ PUBLIC void HText_DisableCurrentForm NOARGS return; } -PUBLIC void HText_ResetForm ARGS1(FormInfo *,form) +PUBLIC void HText_ResetForm ARGS1( + FormInfo *, form) { TextAnchor * anchor_ptr = HTMainText->first_anchor; @@ -4465,7 +4746,8 @@ PUBLIC void HText_ResetForm ARGS1(FormInfo *,form) } } -PUBLIC void HText_activateRadioButton ARGS1(FormInfo *,form) +PUBLIC void HText_activateRadioButton ARGS1( + FormInfo *, form) { TextAnchor * anchor_ptr = HTMainText->first_anchor; int form_number = form->number; @@ -4550,7 +4832,8 @@ PRIVATE void free_all_texts NOARGS ** of N internal links. Since the parent link has already been taken, ** it won't go again, hence the (incorrect) links won't cause problems. */ -PUBLIC char * stub_HTAnchor_address ARGS1 (HTAnchor *,me) +PUBLIC char * stub_HTAnchor_address ARGS1( + HTAnchor *, me) { char *addr = NULL; if (me) @@ -4558,26 +4841,30 @@ PUBLIC char * stub_HTAnchor_address ARGS1 (HTAnchor *,me) return addr; } -PUBLIC void HText_setToolbar ARGS1 (HText *, text) +PUBLIC void HText_setToolbar ARGS1( + HText *, text) { if (text) text->toolbar = TRUE; return; } -PUBLIC BOOL HText_hasToolbar ARGS1 (HText *, text) +PUBLIC BOOL HText_hasToolbar ARGS1( + HText *, text) { return ((text && text->toolbar) ? TRUE : FALSE); } -PUBLIC void HText_setNoCache ARGS1 (HText *, text) +PUBLIC void HText_setNoCache ARGS1( + HText *, text) { if (text) text->no_cache = TRUE; return; } -PUBLIC BOOL HText_hasNoCacheSet ARGS1 (HText *, text) +PUBLIC BOOL HText_hasNoCacheSet ARGS1( + HText *, text) { return ((text && text->no_cache) ? TRUE : FALSE); } diff --git a/src/GridText.h b/src/GridText.h index 0ed5cad0..e027c17c 100644 --- a/src/GridText.h +++ b/src/GridText.h @@ -58,7 +58,11 @@ extern void HText_scrollTop PARAMS((HText * text)); extern void HText_scrollBottom PARAMS((HText * text)); extern void HText_pageDisplay PARAMS((int line_num, char *target)); -extern int HText_LinksInLines PARAMS((HText *text, int line_num, int lines)); +extern int HText_LinksInLines PARAMS((HText *text, int line_num, int Lines)); + +extern void HText_setLastChar PARAMS((HText *text, char ch)); +extern char HText_getLastChar PARAMS((HText *text)); +extern void HText_setIgnoreExcess PARAMS((HText *text, BOOL ignore)); extern int HText_sourceAnchors PARAMS((HText * text)); extern void HText_setStale PARAMS((HText * text)); @@ -69,10 +73,14 @@ extern char * HText_getLastModified NOPARAMS; extern char * HText_getDate NOPARAMS; extern char * HText_getServer NOPARAMS; extern char * HText_getOwner NOPARAMS; +extern char * HText_getContentBase NOPARAMS; +extern char * HText_getContentLocation NOPARAMS; extern void HText_setMainTextOwner PARAMS((CONST char * owner)); extern char * HText_getRevTitle NOPARAMS; extern void print_wwwfile_to_fd PARAMS((FILE * fp, int is_reply)); -extern BOOLEAN HTFindPoundSelector PARAMS((char *selector)); +extern BOOL HText_select PARAMS((HText *text)); +extern BOOL HText_POSTReplyLoaded PARAMS((document *doc)); +extern BOOL HTFindPoundSelector PARAMS((char *selector)); extern int HTGetLinkInfo PARAMS((int number, char **hightext, char **lname)); extern int HTisDocumentSource NOPARAMS; extern void HTuncache_current_document NOPARAMS; @@ -83,12 +91,14 @@ extern char * HTLoadedDocumentURL NOPARAMS; extern char * HTLoadedDocumentPost_data NOPARAMS; extern char * HTLoadedDocumentTitle NOPARAMS; extern BOOLEAN HTLoadedDocumentIsHEAD NOPARAMS; +extern BOOLEAN HTLoadedDocumentIsSafe NOPARAMS; extern char * HTLoadedDocumentCharset NOPARAMS; extern void HText_setNodeAnchorBookmark PARAMS((CONST char *bookmark)); extern char * HTLoadedDocumentBookmark NOPARAMS; extern int HText_LastLineSize PARAMS((HText *me)); extern int HText_PreviousLineSize PARAMS((HText *me)); extern void HText_NegateLineOne PARAMS((HText *text)); +extern void HText_RemovePreviousLine PARAMS((HText *text)); extern int HText_getCurrentColumn PARAMS((HText *text)); extern int HText_getMaximumColumn PARAMS((HText *text)); extern void HText_setTabID PARAMS((HText *text, CONST char *name)); diff --git a/src/HTAlert.c b/src/HTAlert.c index 5a3ddc1c..46243c37 100644 --- a/src/HTAlert.c +++ b/src/HTAlert.c @@ -9,7 +9,6 @@ ** */ - #include "HTUtils.h" #include "tcp.h" #include "HTAlert.h" @@ -19,15 +18,20 @@ #include "LYUtils.h" #include "LYSignal.h" #include "GridText.h" +#include "LYCookie.h" #include "LYLeaks.h" #define FREE(x) if (x) {free(x); x = NULL;} -PUBLIC void HTAlert ARGS1(CONST char *, Msg) +/* Issue a message about a problem. HTAlert() +** -------------------------------- +*/ +PUBLIC void HTAlert ARGS1( + CONST char *, Msg) { - if(TRACE) { + if (TRACE) { fprintf(stderr, "\nAlert!: %s", (char *)Msg); fflush(stderr); _user_message("Alert!: %s", (char *)Msg); @@ -39,16 +43,21 @@ PUBLIC void HTAlert ARGS1(CONST char *, Msg) sleep(AlertSecs); } - -PUBLIC void HTProgress ARGS1(CONST char *, Msg) +/* Issue a progress message. HTProgress() +** ------------------------- +*/ +PUBLIC void HTProgress ARGS1( + CONST char *, Msg) { - if(TRACE) + if (TRACE) fprintf(stderr, "%s\n", (char *)Msg); else statusline((char *)Msg); } - +/* Seek confirmation. HTConfirm() +** ------------------ +*/ PUBLIC BOOL HTConfirm ARGS1(CONST char *, Msg) { if (dump_output_immediately) { /* Non-interactive, can't respond */ @@ -59,27 +68,30 @@ PUBLIC BOOL HTConfirm ARGS1(CONST char *, Msg) extern BOOLEAN HadVMSInterrupt; #endif /* VMS */ - _user_message("WWW: %s (y/n) ", (char *) Msg); + _user_message("%s (y/n) ", (char *)Msg); - while(1) { + while (1) { c = LYgetch(); #ifdef VMS - if(HadVMSInterrupt) { + if (HadVMSInterrupt) { HadVMSInterrupt = FALSE; c = 'N'; } #endif /* VMS */ - if(TOUPPER(c)=='Y') + if (TOUPPER(c) == 'Y') return(YES); - if(TOUPPER(c)=='N' || c == 7 || c == 3) /* ^G or ^C cancels */ + if (TOUPPER(c) == 'N' || c == 7 || c == 3) /* ^G or ^C cancels */ return(NO); } } } -/* Prompt for answer and get text back +/* Prompt for answer and get text back. HTPrompt() +** ------------------------------------ */ -PUBLIC char * HTPrompt ARGS2(CONST char *, Msg, CONST char *, deflt) +PUBLIC char * HTPrompt ARGS2( + CONST char *, Msg, + CONST char *, deflt) { char * rep = NULL; char Tmp[200]; @@ -99,14 +111,17 @@ PUBLIC char * HTPrompt ARGS2(CONST char *, Msg, CONST char *, deflt) return rep; } -/* Prompt for password without echoing the reply +/* +** Prompt for password without echoing the reply. HTPromptPassword() +** ---------------------------------------------- */ -PUBLIC char * HTPromptPassword ARGS1(CONST char *, Msg) +PUBLIC char * HTPromptPassword ARGS1( + CONST char *, Msg) { char *result = NULL; char pw[120]; - pw[0]='\0'; + pw[0] = '\0'; if (!dump_output_immediately) { _statusline(Msg ? (char *)Msg : PASSWORD_PROMPT); @@ -119,10 +134,10 @@ PUBLIC char * HTPromptPassword ARGS1(CONST char *, Msg) return result; } - -/* Prompt both username and password HTPromptUsernameAndPassword() -** --------------------------------- -** On entry, +/* Prompt both username and password. HTPromptUsernameAndPassword() +** ---------------------------------- +** +** On entry, ** Msg is the prompting message. ** *username and ** *password are char pointers; they are changed @@ -133,22 +148,23 @@ PUBLIC char * HTPromptPassword ARGS1(CONST char *, Msg) ** Initial value of *password is ** completely discarded. ** -** On exit, +** On exit, ** *username and *password point to newly allocated ** strings -- original strings pointed to by them ** are NOT freed. ** */ -PUBLIC void HTPromptUsernameAndPassword ARGS3(CONST char *, Msg, - char **, username, - char **, password) +PUBLIC void HTPromptUsernameAndPassword ARGS3( + CONST char *, Msg, + char **, username, + char **, password) { if (authentication_info[0] && authentication_info[1]) { /* - * -auth parameter gave us both the username and password - * to use for the first realm, so just use them without - * any prompting. - FM - */ + ** -auth parameter gave us both the username and password + ** to use for the first realm, so just use them without + ** any prompting. - FM + */ StrAllocCopy(*username, authentication_info[0]); FREE(authentication_info[0]); StrAllocCopy(*password, authentication_info[1]); @@ -156,79 +172,204 @@ PUBLIC void HTPromptUsernameAndPassword ARGS3(CONST char *, Msg, } else if (dump_output_immediately) { if (authentication_info[0]) { /* - * Use the command line username. - FM - */ + ** Use the command line username. - FM + */ StrAllocCopy(*username, authentication_info[0]); FREE(authentication_info[0]); } else { /* - * Default to "WWWuser". - FM - */ + ** Default to "WWWuser". - FM + */ StrAllocCopy(*username, "WWWuser"); } if (authentication_info[1]) { /* - * Use the command line password. - FM - */ + ** Use the command line password. - FM + */ StrAllocCopy(*password, authentication_info[1]); FREE(authentication_info[1]); } else { /* - * Default to a zero-length string. - FM - */ + ** Default to a zero-length string. - FM + */ StrAllocCopy(*password, ""); } printf("\n%s\n", USERNAME_PASSWORD_REQUIRED); } else { if (authentication_info[0]) { /* - * Offer command line username in the prompt - * for the first realm. - FM - */ + ** Offer command line username in the prompt + ** for the first realm. - FM + */ StrAllocCopy(*username, authentication_info[0]); FREE(authentication_info[0]); } - if (Msg) { + if (Msg != NULL) { *username = HTPrompt(Msg, *username); } else { *username = HTPrompt(USERNAME_PROMPT, *username); } if (authentication_info[1]) { /* - * Use the command line password for the first realm. - FM - */ + ** Use the command line password for the first realm. - FM + */ StrAllocCopy(*password, authentication_info[1]); FREE(authentication_info[1]); } else if (*username != NULL && *username[0] != '\0') { /* - * If we have a non-zero length username, - * prompt for the password. - FM - */ + ** If we have a non-zero length username, + ** prompt for the password. - FM + */ *password = HTPromptPassword(PASSWORD_PROMPT); } else { /* - * Return a zero-length password. - FM - */ - StrAllocCopy(*password, ""); + ** Return a zero-length password. - FM + */ + StrAllocCopy(*password, ""); } } } +/* Confirm a cookie operation. HTConfirmCookie() +** --------------------------- +** +** On entry, +** server is the server sending the Set-Cookie. +** domain is the domain of the cookie. +** path is the path of the cookie. +** name is the name of the cookie. +** value is the value of the cookie. +** +** On exit, +** Returns FALSE on cancel, +** TRUE if the cookie should be set. +*/ +PUBLIC BOOL HTConfirmCookie ARGS6( + void *, dp, + CONST char *, server, + CONST char *, domain, + CONST char *, path, + CONST char *, name, + CONST char *, value) +{ + char message[256]; + HTList *hl; + domain_entry *de; + int ch, namelen, valuelen, space_free; -#define SERVER_ASKED_FOR_REDIRECTION \ - "Server asked for redirection of POST content to" -#define PROCEED_GET_CANCEL "P)roceed, use G)ET or C)ancel " -#define ADVANCED_POST_REDIRECT \ - "Redirection of POST content. P)roceed, see U)RL, use G)ET or C)ancel" -#define LOCATION_HEADER "Location: " +#ifdef VMS + extern BOOLEAN HadVMSInterrupt; +#endif /* VMS */ + + if ((de = (domain_entry *)dp) == NULL) + return FALSE; + + /* + ** If the user has specified a constant action, don't prompt at all. + */ + if (de->bv == ACCEPT_ALWAYS) + return TRUE; + if (de->bv == REJECT_ALWAYS) + return FALSE; + + if (dump_output_immediately) { + /* + ** Non-interactive, can't respond. Use the LYSetCookies value + * based on its compilation or configuration setting, or on the + ** command line toggle. - FM + */ + return LYSetCookies; + } -/* Confirm redirection of POST HTConfirmPostRedirect() + /* + ** Figure out how much of the cookie we can show. + ** The '37' is the length of ADVANCED_COOKIE_CONFIRMATION, + ** minus the length of the %s directives (10 chars) + */ + if (de != NULL) { + if (de->bv == ACCEPT_ALWAYS) + return TRUE; + if (de->bv == REJECT_ALWAYS) + return FALSE; + } + space_free = (((LYcols - 1) - 37) - strlen(server)); + if (space_free < 0) + space_free = 0; + namelen = strlen(name); + valuelen = strlen(value); + if ((namelen + valuelen) > space_free) { + /* + ** Argh... there isn't enough space on our single line for + ** the whole cookie. Reduce them both by a percentage. + ** This should be smarter. + */ + float percentage; + percentage = (float)space_free/(float)(namelen + valuelen); + namelen = (int)(percentage*(float)namelen); + valuelen = (int)(percentage*(float)valuelen); + } + sprintf(message, ADVANCED_COOKIE_CONFIRMATION, + server, namelen, name, valuelen, value); + _user_message(message, ""); + while (1) { + ch = LYgetch(); +#ifdef VMS + if (HadVMSInterrupt) { + HadVMSInterrupt = FALSE; + ch = 'N'; + } +#endif /* VMS */ + switch(TOUPPER(ch)) { + case 'A': + /* + ** Set to accept all cookies for this domain. + */ + de->bv = ACCEPT_ALWAYS; + _user_message(ALWAYS_ALLOWING_COOKIES, de->domain); + sleep(MessageSecs); + return TRUE; + + case 'N': + case 7: /* Ctrl-G */ + case 3: /* Ctrl-C */ + /* + ** Reject the cookie. + */ + _statusline(REJECTING_COOKIE); + sleep(MessageSecs); + return FALSE; + + case 'V': + /* + ** Set to reject all cookies from this domain. + */ + de->bv = REJECT_ALWAYS; + _user_message(NEVER_ALLOWING_COOKIES, de->domain); + sleep(MessageSecs); + return FALSE; + + case 'Y': + /* + ** Accept the cookie. + */ + _statusline(ALLOWING_COOKIE); + sleep(InfoSecs); + return TRUE; + + default: + continue; + } + } +} + +/* Confirm redirection of POST. HTConfirmPostRedirect() +** ---------------------------- ** -** On entry, +** On entry, ** redirecting_url is the Location. ** -** On exit, +** On exit, ** Returns 0 on cancel, ** 1 for redirect of POST with content, ** 303 for redirect as GET without content @@ -244,8 +385,8 @@ PUBLIC int HTConfirmPostRedirect ARGS1( if (dump_output_immediately) /* - * Treat as 303 (GET without content) if not interactive. - */ + ** Treat as 303 (GET without content) if not interactive. + */ return 303; if (user_mode == NOVICE_MODE) { @@ -277,31 +418,31 @@ PUBLIC int HTConfirmPostRedirect ARGS1( switch (TOUPPER(c)) { case 'P': /* - * Proceed with 301 or 302 redirect of POST - * (we check only for 0 and 303 in HTTP.c). - */ + ** Proceed with 301 or 302 redirect of POST + ** (we check only for 0 and 303 in HTTP.c). + */ FREE(show_POST_url); return 1; case 7: case 'C': /* - * Cancel request. - */ + ** Cancel request. + */ FREE(show_POST_url); return 0; case 'G': /* - * Treat as 303 (GET without content). - */ + ** Treat as 303 (GET without content). + */ FREE(show_POST_url); return 303; case 'U': /* - * Show URL for intermediate or advanced mode. - */ + ** Show URL for intermediate or advanced mode. + */ if (user_mode != NOVICE_MODE) if (on_screen == 1) on_screen = 0; @@ -311,8 +452,8 @@ PUBLIC int HTConfirmPostRedirect ARGS1( default: /* - * Get another character. - */ + ** Get another character. + */ if (on_screen == 1) on_screen = 0; else @@ -320,4 +461,3 @@ PUBLIC int HTConfirmPostRedirect ARGS1( } } } - diff --git a/src/HTAlert.h b/src/HTAlert.h index dc470cfd..73013918 100644 --- a/src/HTAlert.h +++ b/src/HTAlert.h @@ -82,12 +82,35 @@ extern void HTPromptUsernameAndPassword PARAMS(( char ** password)); -/* Confirm redirection of POST HTConfirmPostRedirect() +/* Confirm a cookie operation. HTConfirmCookie() +** --------------------------- ** -** On entry, +** On entry, +** server is the server sending the Set-Cookie. +** domain is the domain of the cookie. +** path is the path of the cookie. +** name is the name of the cookie. +** value is the value of the cookie. +** +** On exit, +** Returns FALSE on cancel, +** TRUE if the cookie should be set. +*/ +extern BOOL HTConfirmCookie PARAMS(( + void * dp, + CONST char * server, + CONST char * domain, + CONST char * path, + CONST char * name, + CONST char * value)); + + +/* Confirm redirection of POST. HTConfirmPostRedirect() +** ---------------------------- +** On entry, ** redirecting_url is the Location. ** -** On exit, +** On exit, ** Returns 0 on cancel, ** 1 for redirect of POST with content, ** 303 for redirect as GET without content diff --git a/src/HTFWriter.c b/src/HTFWriter.c index e9f7d1ee..820d0fa0 100644 --- a/src/HTFWriter.c +++ b/src/HTFWriter.c @@ -710,14 +710,31 @@ PUBLIC HTStream* HTSaveToFile ARGS3( StrAllocCopy(anchor->FileCache, fnam); if (!strncasecomp(pres->rep->name, "text/html", 9)) { /* - * Add the document's URL as a BASE tag at the top of the file, + * Add the document's base as a BASE tag at the top of the file, * so that any partial or relative URLs within it will be resolved * relative to that if no BASE tag is present and replaces it. * Note that the markup will be technically invalid if a DOCTYPE * declaration, or HTML or HEAD tags, are present, and thus the * file may need editing for perfection. - FM */ - fprintf(ret_obj->fp, "<BASE HREF=\"%s\">\n\n", anchor->address); + char *temp = NULL; + + if (anchor->content_base && *anchor->content_base) { + StrAllocCopy(temp, anchor->content_base); + } else if (anchor->content_location && *anchor->content_location) { + StrAllocCopy(temp, anchor->content_location); + } + if (temp) { + collapse_spaces(temp); + if (!is_url(temp)) { + FREE(temp); + } + } + + fprintf(ret_obj->fp, + "<!-- X-URL: %s -->\n<BASE HREF=\"%s\">\n\n", + anchor->address, (temp ? temp : anchor->address)); + FREE(temp); } return ret_obj; } diff --git a/src/HTForms.h b/src/HTForms.h index 269f6b18..612bbb89 100644 --- a/src/HTForms.h +++ b/src/HTForms.h @@ -89,6 +89,8 @@ typedef struct _FormInfo { #define F_RANGE_TYPE 10 #define F_FILE_TYPE 11 #define F_TEXT_SUBMIT_TYPE 12 +#define F_IMAGE_SUBMIT_TYPE 13 +#define F_KEYGEN_TYPE 14 #define WWW_FORM_LINK_TYPE 1 #define WWW_LINK_TYPE 2 diff --git a/src/HTInit.c b/src/HTInit.c index 63933236..0864816c 100644 --- a/src/HTInit.c +++ b/src/HTInit.c @@ -59,6 +59,7 @@ PUBLIC void HTFormatInit NOARGS 1.0, 3.0, 0.0, 0); HTSetPresentation("image/gif", XLOADIMAGE_COMMAND, 1.0, 3.0, 0.0, 0); HTSetPresentation("image/x-xbm", XLOADIMAGE_COMMAND, 1.0, 3.0, 0.0, 0); + HTSetPresentation("image/x-xbitmap", XLOADIMAGE_COMMAND, 1.0, 3.0, 0.0, 0); HTSetPresentation("image/x-png", XLOADIMAGE_COMMAND, 1.0, 3.0, 0.0, 0); HTSetPresentation("image/x-rgb", XLOADIMAGE_COMMAND, 1.0, 3.0, 0.0, 0); HTSetPresentation("image/x-tiff", XLOADIMAGE_COMMAND, 1.0, 3.0, 0.0, 0); @@ -397,7 +398,7 @@ PRIVATE int ProcessMailcapEntry ARGS2(FILE *,fp, struct MailcapEntry *,mc) /* ExceptionalNewline(mc->contenttype, atoi(eq)); */ } else if (eq && !strcmp(arg, "q")) { mc->quality = atof(eq); - if (mc->quality < 0.001) + if (mc->quality > 0.000 && mc->quality < 0.001) mc->quality = 0.001; } else if (eq && !strcmp(arg, "mxb")) { mc->maxbytes = atol(eq); @@ -490,6 +491,7 @@ PRIVATE int PassesTest ARGS1(struct MailcapEntry *,mc) * Save overhead of system() calls by faking these. - FM */ if (0 == strcasecomp(mc->testcommand, "test -n \"$DISPLAY\"")) { + FREE(mc->testcommand); if (TRACE) fprintf(stderr,"Testing for XWINDOWS environment.\n"); if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') { @@ -503,6 +505,7 @@ PRIVATE int PassesTest ARGS1(struct MailcapEntry *,mc) } } if (0 == strcasecomp(mc->testcommand, "test -z \"$DISPLAY\"")) { + FREE(mc->testcommand); if (TRACE) fprintf(stderr,"Testing for NON_XWINDOWS environment.\n"); if (!((cp = getenv(DISPLAY)) != NULL && *cp != '\0')) { @@ -520,6 +523,7 @@ PRIVATE int PassesTest ARGS1(struct MailcapEntry *,mc) * Why do anything but return success for this one! - FM */ if (0 == strcasecomp(mc->testcommand, "test -n \"$LYNX_VERSION\"")){ + FREE(mc->testcommand); if (TRACE) { fprintf(stderr,"Testing for LYNX environment.\n"); fprintf(stderr,"[HTInit] Test passed!\n"); @@ -530,6 +534,7 @@ PRIVATE int PassesTest ARGS1(struct MailcapEntry *,mc) * ... or failure for this one! - FM */ if (0 == strcasecomp(mc->testcommand, "test -z \"$LYNX_VERSION\"")) { + FREE(mc->testcommand); if (TRACE) { fprintf(stderr,"Testing for non-LYNX environment.\n"); fprintf(stderr,"[HTInit] Test failed!\n"); diff --git a/src/HTML.c b/src/HTML.c index e96ab89d..5ca1756c 100644 --- a/src/HTML.c +++ b/src/HTML.c @@ -13,24 +13,29 @@ */ #include "HTUtils.h" #include "tcp.h" -#include "HTML.h" -#include "HTCJK.h" -#include "HTAtom.h" + +#define Lynx_HTML_Handler #include "HTChunk.h" #include "HText.h" #include "HTStyle.h" -#include "HTAlert.h" +#include "HTML.h" + +#include "HTCJK.h" +#include "HTAtom.h" #include "HTMLGen.h" #include "HTParse.h" -#include "HTNestedList.h" + +#include "LYGlobalDefs.h" +#include "LYCharUtils.h" +#include "LYCharSets.h" + +#include "HTAlert.h" +#include "HTFont.h" #include "HTForms.h" +#include "HTNestedList.h" #include "GridText.h" -#include "HTFont.h" -#include "LYGlobalDefs.h" #include "LYSignal.h" #include "LYUtils.h" -#include "LYCharSets.h" -#include "LYCharUtils.h" #include "LYMap.h" #include "LYBookmark.h" @@ -49,10 +54,6 @@ extern HTCJKlang HTCJK; extern BOOLEAN HT_Is_Gopher_URL; -PRIVATE char *LastOptionValue = NULL; - -PUBLIC BOOLEAN ignore_excess = FALSE; - /* from Curses.h */ extern int LYcols; @@ -65,67 +66,9 @@ PRIVATE HTStyle *styles[HTML_ELEMENTS+31]; /* adding 24 nested list styles */ /* and 3 header alignment styles */ /* and 3 div alignment styles */ PRIVATE HTStyle *default_style; -PUBLIC char HTML_Last_Char = '\0'; /* the last character put on the screen */ -PRIVATE char *textarea_name = NULL; -PRIVATE char *textarea_cols = NULL; -PRIVATE int textarea_rows = 4; -PRIVATE int textarea_disabled = NO; -PRIVATE char *textarea_id = NULL; -PRIVATE BOOLEAN LastOptionChecked = FALSE; -PRIVATE BOOLEAN B_hide_mail_header = FALSE; -PRIVATE char *base_href = NULL; -PRIVATE int select_disabled = NO; -PRIVATE int current_default_alignment = HT_LEFT; -PRIVATE BOOLEAN LYUsePlainSpace = FALSE; -PRIVATE BOOLEAN LYHiddenValue = FALSE; - -/* HTML Object -** ----------- -*/ -#define MAX_NESTING 800 /* Should be checked by parser */ - -/* Track if we are in an anchor, paragraph, address, base, etc. - */ -PRIVATE BOOLEAN B_inA = FALSE; -PRIVATE BOOLEAN B_inAPPLET = FALSE; -PRIVATE BOOLEAN B_inAPPLETwithP = FALSE; -PRIVATE BOOLEAN B_inBadHTML = FALSE; -PRIVATE BOOLEAN B_inBASE = FALSE; -PRIVATE BOOLEAN B_inBoldA = FALSE; -PRIVATE BOOLEAN B_inBoldH = FALSE; -PRIVATE BOOLEAN B_inCAPTION = FALSE; -PRIVATE BOOLEAN B_inCREDIT = FALSE; -PRIVATE BOOLEAN B_inFIG = FALSE; -PRIVATE BOOLEAN B_inFIGwithP = FALSE; -PRIVATE BOOLEAN B_inFORM = FALSE; -PRIVATE BOOLEAN B_inLABEL = FALSE; -PRIVATE BOOLEAN B_inP = FALSE; -PRIVATE BOOLEAN B_inPRE = FALSE; -PRIVATE BOOLEAN B_inSELECT = FALSE; -PRIVATE BOOLEAN B_inTABLE = FALSE; -PRIVATE BOOLEAN B_inTEXTAREA = FALSE; -PRIVATE BOOLEAN B_inUnderline = FALSE; - -PRIVATE BOOLEAN B_needBoldH = FALSE; PUBLIC char *LYToolbarName = "LynxPseudoToolbar"; -PUBLIC char *LYMapName = NULL; - -/* used for nested lists */ -PRIVATE int List_Nesting_Level= -1; /* counter for list nesting level */ -PRIVATE int OL_Counter[7]; /* counter for ordered lists */ -PRIVATE char OL_Type[7]; /* types for ordered lists */ -PRIVATE int Last_OL_Count = 0; /* last count in ordered lists */ -PRIVATE char Last_OL_Type = '1'; /* last type in ordered lists */ -PRIVATE int OL_CONTINUE = -29999; /* flag for whether CONTINUE is set */ -PRIVATE int OL_VOID = -29998; /* flag for whether a count is set */ - -PRIVATE int Division_Level = -1; -PRIVATE short DivisionAlignments[MAX_NESTING]; -PRIVATE int Underline_Level = 0; -PRIVATE int Quote_Level = 0; - /* used to turn off a style if the HTML author forgot to PRIVATE int i_prior_style = -1; */ @@ -136,101 +79,18 @@ PRIVATE int i_prior_style = -1; PRIVATE void HTML_end_element PARAMS((HTStructured *me, int element_number, char **include)); -PRIVATE void HTML_put_entity PARAMS((HTStructured *me, int entity_number)); -PRIVATE BOOLEAN HTML_override_default_alignment PARAMS((HTStructured *me)); -PRIVATE void HTML_zero_OL_Counter NOPARAMS; -PRIVATE void HTML_EnsureDoubleSpace PARAMS((HTStructured *me)); -PRIVATE void HTML_EnsureSingleSpace PARAMS((HTStructured *me)); -PRIVATE void HTML_ResetParagraphAlignment PARAMS((HTStructured *me)); -PRIVATE void HTMLFillLocalFileURL PARAMS((char **href, char *base)); - -typedef struct _stack_element { - HTStyle * style; - int tag_number; -} stack_element; - -struct _HTStructured { - CONST HTStructuredClass * isa; - HTParentAnchor * node_anchor; - HText * text; - - HTStream* target; /* Output stream */ - HTStreamClass targetClass; /* Output routines */ - - HTChunk title; /* Grow by 128 */ - HTChunk object; /* Grow by 128 */ - BOOL object_started; - BOOL object_declare; - BOOL object_shapes; - BOOL object_ismap; - char * object_usemap; - char * object_id; - char * object_title; - char * object_data; - char * object_type; - char * object_classid; - char * object_codebase; - char * object_codetype; - char * object_name; - HTChunk option; /* Grow by 128 */ - HTChunk textarea; /* Grow by 128 */ - HTChunk math; /* Grow by 128 */ - HTChunk style_block; /* Grow by 128 */ - HTChunk script; /* Grow by 128 */ - - char * comment_start; /* for literate programming */ - char * comment_end; - - HTTag * current_tag; - BOOL style_change; - HTStyle * new_style; - HTStyle * old_style; - BOOL in_word; /* Have just had a non-white char */ - stack_element stack[MAX_NESTING]; - stack_element *sp; /* Style stack pointer */ -}; - -struct _HTStream { - CONST HTStreamClass * isa; - /* .... */ -}; /* Forward declarations of routines */ PRIVATE void get_styles NOPARAMS; - - PRIVATE void actually_set_style PARAMS((HTStructured * me)); PRIVATE void change_paragraph_style PARAMS((HTStructured * me, HTStyle * style)); -PRIVATE void HTML_CheckForID PARAMS((HTStructured * me, - CONST BOOL * present, - CONST char ** value, - int attribute)); -PRIVATE void HTML_HandleID PARAMS((HTStructured * me, char * id)); - /* Style buffering avoids dummy paragraph begin/ends. */ #define UPDATE_STYLE if (me->style_change) { actually_set_style(me); } -PUBLIC BOOLEAN LYCheckForCSI ARGS2( - HTStructured *, me, - char **, url) -{ - if (me == NULL || !me->node_anchor->address) - return FALSE; - - if (strncasecomp(me->node_anchor->address, "file:", 5)) - return FALSE; - - if (!LYisLocalHost(me->node_anchor->address)) - return FALSE; - - StrAllocCopy(*url, me->node_anchor->address); - return TRUE; -} - /* Flattening the style structure ** ------------------------------ @@ -251,6 +111,7 @@ PRIVATE void actually_set_style ARGS1(HTStructured *, me) HText_beginAppend(me->text); HText_setStyle(me->text, me->new_style); me->in_word = NO; + LYCheckForContentBase(me); } else { HText_setStyle(me->text, me->new_style); } @@ -280,16 +141,8 @@ PRIVATE void change_paragraph_style ARGS2(HTStructured *, me, HTStyle *,style) /* Character handling ** ------------------ */ -PRIVATE void HTML_put_character ARGS2(HTStructured *, me, char, c) +PUBLIC void HTML_put_character ARGS2(HTStructured *, me, char, c) { - /* - * Convert EOL styles: - * macintosh: cr --> lf - * ascii: cr-lf --> lf - * unix: lf --> lf - */ - static int lastraw = -1; - /* * Ignore all non-MAP content when just * scanning a document for MAPs. - FM @@ -299,12 +152,17 @@ PRIVATE void HTML_put_character ARGS2(HTStructured *, me, char, c) /* * Do EOL conversion if needed. - FM + * + * Convert EOL styles: + * macintosh: cr --> lf + * ascii: cr-lf --> lf + * unix: lf --> lf */ - if ((lastraw == '\r') && c == '\n') { - lastraw = -1; + if ((me->lastraw == '\r') && c == '\n') { + me->lastraw = -1; return; } - lastraw = c; + me->lastraw = c; if (c == '\r') c = '\n'; @@ -364,13 +222,13 @@ PRIVATE void HTML_put_character ARGS2(HTStructured *, me, char, c) * But we still want to strip \r's */ if (c != '\r' && - !(c == '\n' && B_inLABEL && !B_inP) && - !(c == '\n' && !B_inPRE)) { - B_inP = TRUE; - B_inLABEL = FALSE; + !(c == '\n' && me->inLABEL && !me->inP) && + !(c == '\n' && !me->inPRE)) { + me->inP = TRUE; + me->inLABEL = FALSE; HText_appendCharacter(me->text, c); } - B_inPRE = TRUE; + me->inPRE = TRUE; break; case HTML_LISTING: /* Litteral text */ @@ -381,8 +239,8 @@ PRIVATE void HTML_put_character ARGS2(HTStructured *, me, char, c) * But we still want to strip \r's */ if (c != '\r') { - B_inP = TRUE; - B_inLABEL = FALSE; + me->inP = TRUE; + me->inLABEL = FALSE; HText_appendCharacter(me->text, c); } break; @@ -393,19 +251,19 @@ PRIVATE void HTML_put_character ARGS2(HTStructured *, me, char, c) */ if (!strcmp(me->sp->style->name,"Preformatted")) { if (c != '\r' && - !(c == '\n' && B_inLABEL && !B_inP) && - !(c == '\n' && !B_inPRE)) { - B_inP = TRUE; - B_inLABEL = FALSE; + !(c == '\n' && me->inLABEL && !me->inP) && + !(c == '\n' && !me->inPRE)) { + me->inP = TRUE; + me->inLABEL = FALSE; HText_appendCharacter(me->text, c); } - B_inPRE = TRUE; + me->inPRE = TRUE; } else if (!strcmp(me->sp->style->name,"Listing") || !strcmp(me->sp->style->name,"Example")) { if (c != '\r') { - B_inP = TRUE; - B_inLABEL = FALSE; + me->inP = TRUE; + me->inLABEL = FALSE; HText_appendCharacter(me->text, c); } @@ -417,18 +275,18 @@ PRIVATE void HTML_put_character ARGS2(HTStructured *, me, char, c) } if (c == '\n') { if (me->in_word) { - if (HTML_Last_Char != ' ') { - B_inP = TRUE; - B_inLABEL = FALSE; + if (HText_getLastChar(me->text) != ' ') { + me->inP = TRUE; + me->inLABEL = FALSE; HText_appendCharacter(me->text, ' '); } me->in_word = NO; } } else if (c == ' ' || c == '\t') { - if (HTML_Last_Char != ' ') { - B_inP = TRUE; - B_inLABEL = FALSE; + if (HText_getLastChar(me->text) != ' ') { + me->inP = TRUE; + me->inLABEL = FALSE; HText_appendCharacter(me->text, ' '); } @@ -436,8 +294,8 @@ PRIVATE void HTML_put_character ARGS2(HTStructured *, me, char, c) /* ignore */ } else { - B_inP = TRUE; - B_inLABEL = FALSE; + me->inP = TRUE; + me->inLABEL = FALSE; HText_appendCharacter(me->text, c); me->in_word = YES; } @@ -445,17 +303,17 @@ PRIVATE void HTML_put_character ARGS2(HTStructured *, me, char, c) } /* end second switch */ if (c == '\n' || c == '\t') { - HTML_Last_Char = ' '; /* set it to a generic seperater */ + HText_setLastChar(me->text, ' '); /* set it to a generic seperater */ /* * \r's are ignored. In order to keep collapsing spaces * correctly we must default back to the previous * seperater if there was one */ - } else if (c == '\r' && HTML_Last_Char == ' ') { - HTML_Last_Char = ' '; /* set it to a generic seperater */ + } else if (c == '\r' && HText_getLastChar(me->text) == ' ') { + HText_setLastChar(me->text, ' '); /* set it to a generic seperater */ } else { - HTML_Last_Char = c; + HText_setLastChar(me->text, c); } } @@ -465,7 +323,7 @@ PRIVATE void HTML_put_character ARGS2(HTStructured *, me, char, c) ** This is written separately from put_character becuase the loop can ** in some cases be promoted to a higher function call level for speed. */ -PRIVATE void HTML_put_string ARGS2(HTStructured *, me, CONST char*, s) +PUBLIC void HTML_put_string ARGS2(HTStructured *, me, CONST char *, s) { if (LYMapsOnly || s == NULL) return; @@ -532,13 +390,13 @@ PRIVATE void HTML_put_string ARGS2(HTStructured *, me, CONST char*, s) } if (*p == '\n') { if (me->in_word) { - if (HTML_Last_Char != ' ') + if (HText_getLastChar(me->text) != ' ') HText_appendCharacter(me->text, ' '); me->in_word = NO; } } else if (*p == ' ' || *p == '\t') { - if (HTML_Last_Char != ' ') + if (HText_getLastChar(me->text) != ' ') HText_appendCharacter(me->text, ' '); } else if (*p == '\r') { @@ -550,16 +408,19 @@ PRIVATE void HTML_put_string ARGS2(HTStructured *, me, CONST char*, s) /* set the Last Character */ if (*p == '\n' || *p == '\t') { - HTML_Last_Char = ' '; /* set it to a generic seperater */ - } else if (*p == '\r' && HTML_Last_Char == ' ') { + /* set it to a generic seperater */ + HText_setLastChar(me->text, ' '); + } else if (*p == '\r' && + HText_getLastChar(me->text) == ' ') { /* * \r's are ignored. In order to keep collapsing * spaces correctly, we must default back to the - * previous seperator, if there was one. + * previous seperator, if there was one. So we + * set LastChar to a generic seperater. */ - HTML_Last_Char = ' '; /* set it to a generic seperater */ + HText_setLastChar(me->text, ' '); } else { - HTML_Last_Char = *p; + HText_setLastChar(me->text, *p); } } /* for */ @@ -570,7 +431,7 @@ PRIVATE void HTML_put_string ARGS2(HTStructured *, me, CONST char*, s) /* Buffer write ** ------------ */ -PRIVATE void HTML_write ARGS3(HTStructured *, me, CONST char*, s, int, l) +PUBLIC void HTML_write ARGS3(HTStructured *, me, CONST char*, s, int, l) { CONST char* p; CONST char* e = s+l; @@ -599,11 +460,11 @@ PRIVATE void HTML_start_element ARGS5( char *title = NULL; char *temp = NULL; static BOOLEAN first_option = TRUE; /* is this the first option tag? */ - static HTChildAnchor *B_CurrentA = NULL; /* current HTML_A anchor */ - HTParentAnchor *dest = NULL; /* the anchor's destination */ + HTParentAnchor *dest = NULL; /* an anchor's destination */ BOOL dest_ismap = FALSE; /* is dest an image map script? */ - HTChildAnchor *B_ID_A = NULL; /* HTML_foo_ID anchor */ - int url_type; + HTChildAnchor *ID_A = NULL; /* HTML_foo_ID anchor */ + int url_type = 0, i = 0; + char *cp = NULL; if (LYMapsOnly) { if (!(element_number == HTML_MAP || element_number == HTML_AREA)) { @@ -615,27 +476,17 @@ PRIVATE void HTML_start_element ARGS5( case HTML_HTML: UPDATE_STYLE; - List_Nesting_Level = -1; - HTML_zero_OL_Counter(); - Division_Level = -1; - Underline_Level = 0; - Quote_Level = 0; - if (B_inUnderline) { - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); - B_inUnderline = FALSE; + if (me->inUnderline) { + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + me->inUnderline = FALSE; } break; case HTML_HEAD: UPDATE_STYLE; - List_Nesting_Level = -1; - HTML_zero_OL_Counter(); - Division_Level = -1; - Underline_Level = 0; - Quote_Level = 0; - if (B_inUnderline) { - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); - B_inUnderline = FALSE; + if (me->inUnderline) { + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + me->inUnderline = FALSE; } break; @@ -645,6 +496,11 @@ PRIVATE void HTML_start_element ARGS5( char *base = NULL; char *related = NULL; + StrAllocCopy(base, (char *)value[HTML_BASE_HREF]); + if (!(url_type = LYLegitimizeHREF(me, (char**)&base, TRUE))) { + HTAlert(BASE_NOT_ABSOLUTE); + } + /* * Get parent's address for defaulted fields. */ @@ -653,16 +509,15 @@ PRIVATE void HTML_start_element ARGS5( /* * Create the access field. */ - StrAllocCopy(base, (char *)value[HTML_BASE_HREF]); - convert_to_spaces(base); - LYUnEscapeToLatinOne(&base, TRUE); if ((temp = HTParse(base, related, PARSE_ACCESS+PARSE_PUNCTUATION)) && - *temp != '\0') - StrAllocCopy(base_href, temp); - else - StrAllocCopy(base_href, (temp = HTParse(related, "", + *temp != '\0') { + StrAllocCopy(me->base_href, temp); + } else { + StrAllocCopy(me->base_href, (temp = HTParse(related, "", PARSE_ACCESS+PARSE_PUNCTUATION))); + } + FREE(temp); /* * Create the host[:port] field. @@ -670,395 +525,58 @@ PRIVATE void HTML_start_element ARGS5( if ((temp = HTParse(base, "", PARSE_HOST+PARSE_PUNCTUATION)) && !strncmp(temp, "//", 2)) { - StrAllocCat(base_href, temp); - if (!strcmp(base_href, "file://")) - StrAllocCat(base_href, "localhost"); + StrAllocCat(me->base_href, temp); + if (!strcmp(me->base_href, "file://")) { + StrAllocCat(me->base_href, "localhost"); + } } else { - if (!strcmp(base_href, "file:")) - StrAllocCat(base_href, "//localhost"); - else - StrAllocCat(base_href, (temp = HTParse(related, "", + if (!strcmp(me->base_href, "file:")) { + StrAllocCat(me->base_href, "//localhost"); + } else if (strcmp(me->base_href, "news:")) { + StrAllocCat(me->base_href, (temp = HTParse(related, "", PARSE_HOST+PARSE_PUNCTUATION))); + } } + FREE(temp); + FREE(related); /* * Create the path field. */ if ((temp = HTParse(base, "", PARSE_PATH+PARSE_PUNCTUATION)) && - *temp != '\0') - StrAllocCat(base_href, temp); - else - StrAllocCat(base_href, "/"); - - B_inBASE = TRUE; - + *temp != '\0') { + StrAllocCat(me->base_href, temp); + FREE(temp); + } else if (!strcmp(me->base_href, "news:")) { + StrAllocCat(me->base_href, "*"); + } else if (!strncmp(me->base_href, "news:", 5) || + !strncmp(me->base_href, "nntp:", 5) || + !strncmp(me->base_href, "snews:", 6)) { + StrAllocCat(me->base_href, "/*"); + } else { + StrAllocCat(me->base_href, "/"); + } FREE(base); - FREE(related); - FREE(temp); + + me->inBASE = TRUE; } break; case HTML_META: if (!me->text) UPDATE_STYLE; - - if (present) { - char *http_equiv = NULL, *name = NULL, *content = NULL; - /* - * Load the attributes for possible use by Lynx. - FM - */ - if (present[HTML_META_HTTP_EQUIV] && - value[HTML_META_HTTP_EQUIV] && *value[HTML_META_HTTP_EQUIV]) { - StrAllocCopy(http_equiv, value[HTML_META_HTTP_EQUIV]); - LYUnEscapeToLatinOne(&http_equiv, FALSE); - LYTrimHead(http_equiv); - LYTrimTail(http_equiv); - if (*http_equiv == '\0') { - FREE(http_equiv); - } - } - if (present[HTML_META_NAME] && - value[HTML_META_NAME] && *value[HTML_META_NAME]) { - StrAllocCopy(name, value[HTML_META_NAME]); - LYUnEscapeToLatinOne(&http_equiv, FALSE); - LYTrimHead(name); - LYTrimTail(name); - if (*name == '\0') { - FREE(name); - } - } - if (present[HTML_META_CONTENT] && - value[HTML_META_CONTENT] && *value[HTML_META_CONTENT]) { - /* - * Technically, we should be creating a comma-separated - * list, but META tags come one at a time, and we'll - * handle (or ignore) them as each is received. Also, - * at this point, we only trim leading and trailing - * blanks from the CONTENT value, without translating - * any named entities or numeric character references, - * because how we should do that depends on what type - * of information it contains, and whether or not any - * of it might be sent to the screen. - FM - */ - StrAllocCopy(content, value[HTML_META_CONTENT]); - LYTrimHead(content); - LYTrimTail(content); - if (*content == '\0') { - FREE(content); - } - } - - if (TRACE) { - fprintf(stderr, - "HTML: META HTTP-EQUIV=\"%s\" NAME=\"%s\" CONTENT=\"%s\"\n", - (http_equiv ? http_equiv : "NULL"), - (name ? name : "NULL"), - (content ? content : "NULL")); - } - - /* - * Add META-handling code or function calls here. - FM - */ - if ((http_equiv || name) && content) { - char *cp, *cp1; - - /* - * Check for a no-cache Pragma - * or Cache-Control directive. - FM - */ - if (!strcasecomp((name ? name : http_equiv), - "Pragma") || - !strcasecomp((name ? name : http_equiv), - "Cache-Control")) { - LYUnEscapeToLatinOne(&content, FALSE); - LYTrimHead(content); - LYTrimTail(content); - if (!strcasecomp(content, "no-cache")) { - me->node_anchor->no_cache = TRUE; - HText_setNoCache(me->text); - } - - /* - * If we didn't get a Cache-Control MIME - * header, and the META has one, store it - * in the anchor element. - FM - */ - if ((!me->node_anchor->cache_control) && - !strcasecomp((name ? name : http_equiv), - "Cache-Control")) { - StrAllocCopy(me->node_anchor->cache_control, - (name ? name : http_equiv)); - } - - /* - * Check for a text/html Content-Type with a - * charset directive, if we didn't already set - * the charset via a server's header. - AAC & FM - */ - } else if (!(me->node_anchor->charset && - *me->node_anchor->charset) && - !strcasecomp((name ? name : http_equiv), - "Content-Type")) { - LYUnEscapeToLatinOne(&content, FALSE); - LYTrimHead(content); - LYTrimTail(content); - /* - * Force the Content-type value to all lower case. - FM - */ - for (cp = content; *cp; cp++) - *cp = TOLOWER(*cp); - - if ((cp=strstr(content, "text/html;")) != NULL && - (cp1=strstr(content, "charset")) != NULL && - cp1 > cp) { - cp1 += 7; - while (*cp1 == ' ' || *cp1 == '=') - cp1++; - if (!strncmp(cp1, "us-ascii", 8) || - !strncmp(cp1, "iso-8859-1", 10)) { - StrAllocCopy(me->node_anchor->charset, - "iso-8859-1"); - HTCJK = NOCJK; - } else if (!strncmp(cp1, "iso-8859-2", 10) && - !strncmp(LYchar_set_names[current_char_set], - "ISO Latin 2", 11)) { - StrAllocCopy(me->node_anchor->charset, - "iso-8859-2"); - HTPassEightBitRaw = TRUE; - } else if (!strncmp(cp1, "iso-8859-", 9) && - !strncmp(LYchar_set_names[current_char_set], - "Other ISO Latin", 15)) { - /* - ** Hope it's a match, for now. - FM - */ - StrAllocCopy(me->node_anchor->charset, - "iso-8859- "); - me->node_anchor->charset[9] = cp1[9]; - HTPassEightBitRaw = TRUE; - HTAlert(me->node_anchor->charset); - } else if (!strncmp(cp1, "koi8-r", 6) && - !strncmp(LYchar_set_names[current_char_set], - "KOI8-R character set", 20)) { - StrAllocCopy(me->node_anchor->charset, - "koi8-r"); - HTPassEightBitRaw = TRUE; - } else if (!strncmp(cp1, "euc-jp", 6) && - HTCJK == JAPANESE) { - StrAllocCopy(me->node_anchor->charset, - "euc-jp"); - } else if (!strncmp(cp1, "shift_jis", 9) && - HTCJK == JAPANESE) { - StrAllocCopy(me->node_anchor->charset, - "shift_jis"); - } else if (!strncmp(cp1, "iso-2022-jp", 11) && - HTCJK == JAPANESE) { - StrAllocCopy(me->node_anchor->charset, - "iso-2022-jp"); - } else if (!strncmp(cp1, "iso-2022-jp-2", 13) && - HTCJK == JAPANESE) { - StrAllocCopy(me->node_anchor->charset, - "iso-2022-jp-2"); - } else if (!strncmp(cp1, "euc-kr", 6) && - HTCJK == KOREAN) { - StrAllocCopy(me->node_anchor->charset, - "euc-kr"); - } else if (!strncmp(cp1, "iso-2022-kr", 11) && - HTCJK == KOREAN) { - StrAllocCopy(me->node_anchor->charset, - "iso-2022-kr"); - } else if ((!strncmp(cp1, "big5", 4) || - !strncmp(cp1, "cn-big5", 7)) && - HTCJK == TAIPEI) { - StrAllocCopy(me->node_anchor->charset, - "big5"); - } else if (!strncmp(cp1, "euc-cn", 6) && - HTCJK == CHINESE) { - StrAllocCopy(me->node_anchor->charset, - "euc-cn"); - } else if ((!strncmp(cp1, "gb2312", 6) || - !strncmp(cp1, "cn-gb", 5)) && - HTCJK == CHINESE) { - StrAllocCopy(me->node_anchor->charset, - "gb2312"); - } else if (!strncmp(cp1, "iso-2022-cn", 11) && - HTCJK == CHINESE) { - StrAllocCopy(me->node_anchor->charset, - "iso-2022-cn"); - } - if (TRACE && me->node_anchor->charset) { - fprintf(stderr, "HTML: New charset: %s\n", - me->node_anchor->charset); - } - } - /* - * Set the kcode element based on the charset. - FM - */ - HText_setKcode(me->text, me->node_anchor->charset); - - /* - * Check for a Refresh directive. - FM - */ - } else if (!strcasecomp((name ? name : http_equiv), - "Refresh")) { - char *Seconds = NULL; - - /* - * Look for the Seconds field. - FM - */ - cp = content; - while (*cp && isspace((unsigned char)*cp)) - cp++; - if (*cp && isdigit(*cp)) { - cp1 = cp; - while (*cp1 && isdigit(*cp1)) - cp1++; - *cp1 = '\0'; - StrAllocCopy(Seconds, cp); - cp1++; - } - if (Seconds) { - /* - * We have the seconds field. - * Now look for a URL field - FM - */ - while (*cp1) { - if (!strncasecomp(cp1, "URL", 3)) { - cp = (cp1 + 3); - while (*cp && (*cp == '=' || - isspace((unsigned char)*cp))) - cp++; - cp1 = cp; - while (*cp1 && !isspace((unsigned char)*cp1)) - cp1++; - *cp1 = '\0'; - if (*cp) { - StrAllocCopy(href, cp); - convert_to_spaces(href); - /* - * Translate any named or numeric - * character references with the - * isURL flag set. - FM - */ - LYUnEscapeToLatinOne(&href, TRUE); - } - break; - } - cp1++; - } - if (href) { - /* - * We found a URL field, so check it out. - FM - */ - if (!is_url(href)) { - /* - * The specs require a complete URL, - * but this is a Netscapism, so don't - * expect the author to know that. - FM - */ - if (*href != '\0' && *href != '/') - HTSimplify(href); - /* - * Use the document's address - * as the base. - FM - */ - if (*href != '\0') { - temp = HTParse(href, - me->node_anchor->address, - PARSE_ALL); - StrAllocCopy(href, temp); - FREE(temp); - } else { - StrAllocCopy(href, - me->node_anchor->address); - HText_setNoCache(me->text); - } - } - /* - * Check whether to fill in localhost. - FM - */ - HTMLFillLocalFileURL((char **)&href, - (B_inBASE ? base_href : - me->node_anchor->address)); - /* - * Set the no_cache flag if the Refresh URL - * is the same as the document's address. - FM - */ - if (!strcmp(href, me->node_anchor->address)) { - HText_setNoCache(me->text); - } - } else { - /* - * We didn't find a URL field, so use - * the document's own address and set - * the no_cache flag. - FM - */ - StrAllocCopy(href, me->node_anchor->address); - HText_setNoCache(me->text); - } - /* - * Check for an anchor in http or https URLs. - FM - */ - if ((strncmp(href, "http", 4) == 0) && - (cp = strrchr(href, '#')) != NULL) { - StrAllocCopy(id_string, cp); - *cp = '\0'; - } - B_CurrentA = HTAnchor_findChildAndLink( - me->node_anchor, /* Parent */ - id_string, /* Tag */ - href, /* Addresss */ - (void *)0); /* Type */ - if (id_string) - *cp = '#'; - FREE(id_string); - HTML_EnsureSingleSpace(me); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text, - LY_UNDERLINE_START_CHAR); - HTML_put_string(me, "REFRESH("); - HTML_put_string(me, Seconds); - HTML_put_string(me, " sec):"); - FREE(Seconds); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text, - LY_UNDERLINE_END_CHAR); - HTML_put_character(me, ' '); - me->in_word = NO; - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text, LY_BOLD_START_CHAR); - HTML_put_string(me, href); - FREE(href); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text, LY_BOLD_END_CHAR); - HText_endAnchor(me->text); - HTML_EnsureSingleSpace(me); - } - } - } - - /* - * Free the copies. - FM - */ - FREE(http_equiv); - FREE(name); - FREE(content); - } + if (present) + LYHandleMETA(me, present, (CONST char **)value, (char **)&include); break; case HTML_TITLE: HTChunkClear(&me->title); - List_Nesting_Level = -1; - HTML_zero_OL_Counter(); - Division_Level = -1; - Underline_Level = 0; - Quote_Level = 0; - if (B_inUnderline) { + if (me->inUnderline) { if (!me->text) UPDATE_STYLE; - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); - B_inUnderline = FALSE; + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + me->inUnderline = FALSE; } break; @@ -1067,30 +585,22 @@ PRIVATE void HTML_start_element ARGS5( /* * Prepare to do housekeeping on the reference. - FM */ - if (!(value[HTML_LINK_HREF] && *value[HTML_LINK_HREF])) { - if (B_inBASE && base_href && *base_href) { - StrAllocCopy(href, base_href); + if (!value[HTML_LINK_HREF]) { + if (me->inBASE && me->base_href && *me->base_href) { + StrAllocCopy(href, me->base_href); } else { StrAllocCopy(href, me->node_anchor->address); } } else { StrAllocCopy(href, value[HTML_LINK_HREF]); - convert_to_spaces(href); - LYUnEscapeToLatinOne(&href, TRUE); + url_type = LYLegitimizeHREF(me, (char**)&href, TRUE); } - url_type = is_url(href); - - /* - * Don't simplify absolute HREFs. - FM - */ - if (!url_type && *href != '/' && *href != '\0') - HTSimplify(href); /* * Check whether a base tag is in effect. - FM */ - if ((B_inBASE) && - (temp = HTParse(href, base_href, PARSE_ALL)) && + if ((me->inBASE && *href != '\0' && *href != '#') && + (temp = HTParse(href, me->base_href, PARSE_ALL)) && *temp != '\0') /* * Use reference related to the base. @@ -1101,41 +611,65 @@ PRIVATE void HTML_start_element ARGS5( /* * Check whether to fill in localhost. - FM */ - HTMLFillLocalFileURL((char **)&href, - (B_inBASE ? base_href : - me->node_anchor->address)); + LYFillLocalFileURL((char **)&href, + ((*href != '\0' && *href != '#' && + me->inBASE) ? + me->base_href : me->node_anchor->address)); /* - * Handle REV="made" or REV="owner". - LM & FM + * Handle links with a REV attribute. - FM */ if (present && present[HTML_LINK_REV] && value[HTML_LINK_REV]) { - if (!strcasecomp("made", value[HTML_LINK_REV]) || - !strcasecomp("owner", value[HTML_LINK_REV])) - HTAnchor_setOwner(me->node_anchor, href); /* - * Load the RevTitle element if a TITLE attribute - * and value are present. - FM - */ - if (present && present[HTML_LINK_TITLE] && - value[HTML_LINK_TITLE] && - *value[HTML_LINK_TITLE] != '\0') { - StrAllocCopy(title, value[HTML_LINK_TITLE]); - if (current_char_set) - LYExpandString(&title); + * Handle REV="made" or REV="owner". - LM & FM + */ + if (!strcasecomp("made", value[HTML_LINK_REV]) || + !strcasecomp("owner", value[HTML_LINK_REV])) { /* - * Convert any HTML entities or decimal escaping. - FM + * Load the owner element. - FM */ - LYUnEscapeEntities(title, TRUE, FALSE); - LYTrimHead(title); - LYTrimTail(title); - if (*title != '\0') - HTAnchor_setRevTitle(me->node_anchor, title); - FREE(title); - } + if (!is_url(href)) { + temp = HTParse(href, + (me->inBASE ? + me->base_href : me->node_anchor->address), + PARSE_ALL); + StrAllocCopy(href, temp); + FREE(temp); + LYFillLocalFileURL((char **)&href, + (me->inBASE ? + me->base_href : + me->node_anchor->address)); + } + HTAnchor_setOwner(me->node_anchor, href); + if (TRACE) + fprintf(stderr, + "HTML: DOC OWNER '%s' found\n", href); + FREE(href); - if (TRACE) - fprintf(stderr,"HTML.c: DOC OWNER found\n"); + /* + * Load the RevTitle element if a TITLE attribute + * and value are present. - FM + */ + if (present && present[HTML_LINK_TITLE] && + value[HTML_LINK_TITLE] && + *value[HTML_LINK_TITLE] != '\0') { + StrAllocCopy(title, value[HTML_LINK_TITLE]); + if (current_char_set) + LYExpandString(&title); + /* + * Convert any HTML entities + * or decimal escaping. - FM + */ + LYUnEscapeEntities(title, TRUE, FALSE); + LYTrimHead(title); + LYTrimTail(title); + if (*title != '\0') + HTAnchor_setRevTitle(me->node_anchor, title); + FREE(title); + } + break; + } } /* @@ -1143,14 +677,13 @@ PRIVATE void HTML_start_element ARGS5( */ if (present && present[HTML_LINK_REL] && value[HTML_LINK_REL]) { - /* * Ignore style sheets, for now. - FM */ if (!strcasecomp(value[HTML_LINK_REL], "StyleSheet")) { if (TRACE) { fprintf(stderr, - "HTML.c: StyleSheet link found.\n"); + "HTML: StyleSheet link found.\n"); fprintf(stderr, " StyleSheets not yet implemented.\n"); } @@ -1159,40 +692,94 @@ PRIVATE void HTML_start_element ARGS5( } /* - * Ignore anything not registered as of 28-Mar-95 - * IETF specs. We'll make this more efficient when - * the situation stabilizes, and for now, we'll treat - * "Banner" as another toolbar element. - FM + * Ignore anything not registered in the the 28-Mar-95 + * IETF HTML 3.0 draft and W3C HTML 3.2 draft, or not + * appropriate for Lynx banner links in the expired + * Maloney and Quin relrev draft. We'll make this more + * efficient when the situation stabilizes, and for now, + * we'll treat "Banner" as another toolbar element. - FM */ - if (strcasecomp(value[HTML_LINK_REL], "Home") && - strcasecomp(value[HTML_LINK_REL], "ToC") && - strcasecomp(value[HTML_LINK_REL], "Index") && - strcasecomp(value[HTML_LINK_REL], "Glossary") && - strcasecomp(value[HTML_LINK_REL], "Copyright") && - strcasecomp(value[HTML_LINK_REL], "Up") && - strcasecomp(value[HTML_LINK_REL], "Next") && - strcasecomp(value[HTML_LINK_REL], "Previous") && - strcasecomp(value[HTML_LINK_REL], "Help") && - strcasecomp(value[HTML_LINK_REL], "Bookmark") && - strcasecomp(value[HTML_LINK_REL], "Banner")) { + if (!strcasecomp(value[HTML_LINK_REL], "Home") || + !strcasecomp(value[HTML_LINK_REL], "ToC") || + !strcasecomp(value[HTML_LINK_REL], "Contents") || + !strcasecomp(value[HTML_LINK_REL], "Index") || + !strcasecomp(value[HTML_LINK_REL], "Glossary") || + !strcasecomp(value[HTML_LINK_REL], "Copyright") || + !strcasecomp(value[HTML_LINK_REL], "Up") || + !strcasecomp(value[HTML_LINK_REL], "Next") || + !strcasecomp(value[HTML_LINK_REL], "Previous") || + !strcasecomp(value[HTML_LINK_REL], "Prev") || + !strcasecomp(value[HTML_LINK_REL], "Help") || + !strcasecomp(value[HTML_LINK_REL], "Search") || + !strcasecomp(value[HTML_LINK_REL], "Bookmark") || + !strcasecomp(value[HTML_LINK_REL], "Banner") || + !strcasecomp(value[HTML_LINK_REL], "Top") || + !strcasecomp(value[HTML_LINK_REL], "Origin") || + !strcasecomp(value[HTML_LINK_REL], "Navigator") || + !strcasecomp(value[HTML_LINK_REL], "Child") || + !strcasecomp(value[HTML_LINK_REL], "Disclaimer") || + !strcasecomp(value[HTML_LINK_REL], "Sibling") || + !strcasecomp(value[HTML_LINK_REL], "Parent") || + !strcasecomp(value[HTML_LINK_REL], "Author") || + !strcasecomp(value[HTML_LINK_REL], "Editor") || + !strcasecomp(value[HTML_LINK_REL], "Publisher") || + !strcasecomp(value[HTML_LINK_REL], "Trademark") || + !strcasecomp(value[HTML_LINK_REL], "Meta") || + !strcasecomp(value[HTML_LINK_REL], "URC") || + !strcasecomp(value[HTML_LINK_REL], "Hotlist") || + !strcasecomp(value[HTML_LINK_REL], "Begin") || + !strcasecomp(value[HTML_LINK_REL], "First") || + !strcasecomp(value[HTML_LINK_REL], "End") || + !strcasecomp(value[HTML_LINK_REL], "Last") || + !strcasecomp(value[HTML_LINK_REL], "Pointer") || + !strcasecomp(value[HTML_LINK_REL], "Translation") || + !strcasecomp(value[HTML_LINK_REL], "Definition") || + !strcasecomp(value[HTML_LINK_REL], "Chapter") || + !strcasecomp(value[HTML_LINK_REL], "Documentation") || + !strcasecomp(value[HTML_LINK_REL], "Biblioentry") || + !strcasecomp(value[HTML_LINK_REL], "Bibliography")) { + StrAllocCopy(title, value[HTML_LINK_REL]); + } else { if (TRACE) { fprintf(stderr, - "HTML.c: LINK with REL=\"%s\" ignored.\n", + "HTML: LINK with REL=\"%s\" ignored.\n", value[HTML_LINK_REL]); } FREE(href); break; } - - /* - * Create a title (link name) from the TITLE value, - * if present, or default to the REL value. - FM - */ - if (present && present[HTML_LINK_TITLE] && - value[HTML_LINK_TITLE] && *value[HTML_LINK_TITLE] != '\0') - StrAllocCopy(title, value[HTML_LINK_TITLE]); - else - StrAllocCopy(title, value[HTML_LINK_REL]); + } + } else if (present && + present[HTML_LINK_REL] && value[HTML_LINK_REL]) { + /* + * If no HREF was specified, handle special REL links + * with self-designated HREFs. - FM + */ + if (!strcasecomp(value[HTML_LINK_REL], "Home")) { + StrAllocCopy(href, LynxHome); + } else if (!strcasecomp(value[HTML_LINK_REL], "Help")) { + StrAllocCopy(href, helpfile); + } else if (!strcasecomp(value[HTML_LINK_REL], "Index")) { + StrAllocCopy(href, indexfile); + } else { + if (TRACE) { + fprintf(stderr, + "HTML: LINK with REL=\"%s\" and no HREF ignored.\n", + value[HTML_LINK_REL]); + } + break; + } + StrAllocCopy(title, value[HTML_LINK_REL]); + } + if (href) { + /* + * Create a title (link name) from the TITLE value, + * if present, or default to the REL value that was + * loaded into title. - FM + */ + if (present && present[HTML_LINK_TITLE] && + value[HTML_LINK_TITLE] && *value[HTML_LINK_TITLE] != '\0') { + StrAllocCopy(title, value[HTML_LINK_TITLE]); if (current_char_set) LYExpandString(&title); /* @@ -1201,55 +788,57 @@ PRIVATE void HTML_start_element ARGS5( LYUnEscapeEntities(title, TRUE, FALSE); LYTrimHead(title); LYTrimTail(title); + } + if (!(title && *title)) { + FREE(href); + FREE(title); + break; + } - /* - * Create anchors for the links that simulate - * a toolbar. - FM - */ - B_CurrentA = HTAnchor_findChildAndLink( + /* + * Create anchors for the links that simulate + * a toolbar. - FM + */ + me->CurrentA = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ NULL, /* Tag */ href, /* Addresss */ (void *)0); /* Type */ - { - if (dest = HTAnchor_parent( - HTAnchor_followMainLink((HTAnchor*)B_CurrentA) - )) { - if (!HTAnchor_title(dest)) - HTAnchor_setTitle(dest, title); - } - UPDATE_STYLE; - if (!HText_hasToolbar(me->text) && - (B_ID_A = HTAnchor_findChildAndLink( + if (dest = HTAnchor_parent( + HTAnchor_followMainLink((HTAnchor*)me->CurrentA) + )) { + if (!HTAnchor_title(dest)) + HTAnchor_setTitle(dest, title); + dest = NULL; + } + UPDATE_STYLE; + if (!HText_hasToolbar(me->text) && + (ID_A = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ LYToolbarName, /* Tag */ NULL, /* Addresss */ (void *)0))) { /* Type */ - HText_beginAnchor(me->text, B_ID_A); - HText_endAnchor(me->text); - HText_setToolbar(me->text); - } - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); - HTML_put_string(me, title); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); - HText_endAnchor(me->text); - dest = NULL; - } - FREE(title); + HText_appendCharacter(me->text, '#'); + HText_beginAnchor(me->text, ID_A); + HText_endAnchor(me->text); + HText_setToolbar(me->text); } - FREE(href); + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); + HTML_put_string(me, title); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); + HText_endAnchor(me->text); } + FREE(href); + FREE(title); break; case HTML_ISINDEX: - if (present && - ((present[HTML_ISINDEX_HREF] && - value[HTML_ISINDEX_HREF] && *value[HTML_ISINDEX_HREF]) || - (present[HTML_ISINDEX_ACTION] && - value[HTML_ISINDEX_ACTION] && *value[HTML_ISINDEX_ACTION]))) { + if (((present)) && + ((present[HTML_ISINDEX_HREF] && value[HTML_ISINDEX_HREF]) || + (present[HTML_ISINDEX_ACTION] && value[HTML_ISINDEX_ACTION]))) { char * action = NULL; char * isindex_href = NULL; @@ -1259,44 +848,35 @@ PRIVATE void HTML_start_element ARGS5( * use that too, but allow use of ACTION as an alternate * until people have fully switched over. - FM */ - if (present[HTML_ISINDEX_HREF]) + if (present[HTML_ISINDEX_HREF] && value[HTML_ISINDEX_HREF]) StrAllocCopy(isindex_href, value[HTML_ISINDEX_HREF]); else StrAllocCopy(isindex_href, value[HTML_ISINDEX_ACTION]); - convert_to_spaces(isindex_href); - LYUnEscapeToLatinOne(&isindex_href, TRUE); - url_type = is_url(isindex_href); - if (!url_type && *isindex_href != '/' && *isindex_href != '\0') - HTSimplify(isindex_href); + url_type = LYLegitimizeHREF(me, (char**)&isindex_href, TRUE); /* * Check whether a base tag is in effect. */ - if (B_inBASE) - action = HTParse(isindex_href, base_href, PARSE_ALL); - if (!(action && *action)) { - char *related = NULL; + if (me->inBASE && *isindex_href != '\0' && *isindex_href != '#') + action = HTParse(isindex_href, me->base_href, PARSE_ALL); + if (!(action && *action)) + action = HTParse(isindex_href, + me->node_anchor->address, PARSE_ALL); + FREE(isindex_href); - StrAllocCopy(related, me->node_anchor->address); - action = HTParse(isindex_href, related, PARSE_ALL); - FREE(related); - } if (action && *action) { HTAnchor_setIndex(me->node_anchor, action); - } else if (B_inBASE) { - HTAnchor_setIndex(me->node_anchor, base_href); } else { HTAnchor_setIndex(me->node_anchor, me->node_anchor->address); } - FREE(isindex_href); FREE(action); } else { - if (B_inBASE) + if (me->inBASE) /* * Use base. */ - HTAnchor_setIndex(me->node_anchor, base_href); + HTAnchor_setIndex(me->node_anchor, me->base_href); else /* * Use index's address. @@ -1360,16 +940,13 @@ PRIVATE void HTML_start_element ARGS5( case HTML_BODY: UPDATE_STYLE; - List_Nesting_Level = -1; - HTML_zero_OL_Counter(); - Division_Level = -1; - Underline_Level = 0; - Quote_Level = 0; - if (B_inUnderline) { - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); - B_inUnderline = FALSE; + if (me->inUnderline) { + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + me->inUnderline = FALSE; } - HTML_CheckForID(me, present, value, (int)HTML_BODY_ID); + LYCheckForID(me, present, value, (int)HTML_BODY_ID); + if (HText_hasToolbar(me->text)) + HText_appendParagraph(me->text); break; case HTML_FRAMESET: @@ -1395,17 +972,13 @@ PRIVATE void HTML_start_element ARGS5( if (present && present[HTML_FRAME_SRC] && value[HTML_FRAME_SRC] && *value[HTML_FRAME_SRC] != '\0') { StrAllocCopy(href, value[HTML_FRAME_SRC]); - convert_to_spaces(href); - LYUnEscapeToLatinOne(&href, TRUE); - url_type = is_url(href); - if (!url_type && *href != '/' && *href != '\0') - HTSimplify(href); + url_type = LYLegitimizeHREF(me, (char**)&href, TRUE); /* * Check whether a base tag is in effect. - FM */ - if ((B_inBASE) && - (temp = HTParse(href, base_href, PARSE_ALL)) && + if ((me->inBASE && *href != '\0' && *href != '#') && + (temp = HTParse(href, me->base_href, PARSE_ALL)) && *temp != '\0') /* * Use reference related to the base. @@ -1416,99 +989,102 @@ PRIVATE void HTML_start_element ARGS5( /* * Check whether to fill in localhost. - FM */ - HTMLFillLocalFileURL((char **)&href, - (B_inBASE ? base_href : - me->node_anchor->address)); + LYFillLocalFileURL((char **)&href, + ((*href != '\0' && *href != '#' && + me->inBASE) ? + me->base_href : me->node_anchor->address)); - B_CurrentA = HTAnchor_findChildAndLink( + me->CurrentA = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ NULL, /* Tag */ href, /* Addresss */ (void *)0); /* Type */ - HTML_EnsureSingleSpace(me); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); + LYEnsureSingleSpace(me); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); HTML_put_string(me, "FRAME:"); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); HTML_put_character(me, ' '); me->in_word = NO; - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); HTML_put_string(me, (id_string ? id_string : href)); FREE(href); FREE(id_string); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); HText_endAnchor(me->text); - HTML_EnsureSingleSpace(me); + LYEnsureSingleSpace(me); } break; case HTML_NOFRAMES: if (!me->text) UPDATE_STYLE; - HTML_EnsureDoubleSpace(me); - HTML_ResetParagraphAlignment(me); + LYEnsureDoubleSpace(me); + LYResetParagraphAlignment(me); break; case HTML_BANNER: case HTML_MARQUEE: change_paragraph_style(me, styles[HTML_BANNER]); UPDATE_STYLE; + if (me->sp->tag_number == element_number) + LYEnsureDoubleSpace(me); if (!HText_hasToolbar(me->text) && - (B_ID_A = HTAnchor_findChildAndLink( + (ID_A = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ LYToolbarName, /* Tag */ NULL, /* Addresss */ (void *)0))) { /* Type */ - HText_beginAnchor(me->text, B_ID_A); + HText_beginAnchor(me->text, ID_A); HText_endAnchor(me->text); HText_setToolbar(me->text); } - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); break; case HTML_CENTER: case HTML_DIV: - if (Division_Level < MAX_NESTING) { - Division_Level++; + if (me->Division_Level < MAX_NESTING) { + me->Division_Level++; } else if (TRACE) { fprintf(stderr, "HTML: ****** Maximum nesting of %d divisions exceeded!\n", MAX_NESTING); } if (element_number == HTML_CENTER) { - DivisionAlignments[Division_Level] = HT_CENTER; + me->DivisionAlignments[me->Division_Level] = HT_CENTER; change_paragraph_style(me, styles[HTML_DCENTER]); UPDATE_STYLE; - current_default_alignment = styles[HTML_DCENTER]->alignment; + me->current_default_alignment = styles[HTML_DCENTER]->alignment; } else if (present && present[HTML_DIV_ALIGN] && value[HTML_DIV_ALIGN] && *value[HTML_DIV_ALIGN]) { if (!strcasecomp(value[HTML_DIV_ALIGN], "center")) { - DivisionAlignments[Division_Level] = HT_CENTER; + me->DivisionAlignments[me->Division_Level] = HT_CENTER; change_paragraph_style(me, styles[HTML_DCENTER]); UPDATE_STYLE; - current_default_alignment = styles[HTML_DCENTER]->alignment; + me->current_default_alignment = styles[HTML_DCENTER]->alignment; } else if (!strcasecomp(value[HTML_DIV_ALIGN], "right")) { - DivisionAlignments[Division_Level] = HT_RIGHT; + me->DivisionAlignments[me->Division_Level] = HT_RIGHT; change_paragraph_style(me, styles[HTML_DRIGHT]); UPDATE_STYLE; - current_default_alignment = styles[HTML_DRIGHT]->alignment; + me->current_default_alignment = styles[HTML_DRIGHT]->alignment; } else { - DivisionAlignments[Division_Level] = HT_LEFT; + me->DivisionAlignments[me->Division_Level] = HT_LEFT; change_paragraph_style(me, styles[HTML_DLEFT]); UPDATE_STYLE; - current_default_alignment = styles[HTML_DLEFT]->alignment; + me->current_default_alignment = styles[HTML_DLEFT]->alignment; } } else { - DivisionAlignments[Division_Level] = HT_LEFT; + me->DivisionAlignments[me->Division_Level] = HT_LEFT; change_paragraph_style(me, styles[HTML_DLEFT]); UPDATE_STYLE; - current_default_alignment = styles[HTML_DLEFT]->alignment; + me->current_default_alignment = styles[HTML_DLEFT]->alignment; } - HTML_CheckForID(me, present, value, (int)HTML_DIV_ID); + LYCheckForID(me, present, value, (int)HTML_DIV_ID); break; case HTML_H1: @@ -1541,27 +1117,27 @@ PRIVATE void HTML_start_element ARGS5( change_paragraph_style(me, styles[HTML_HLEFT]); else change_paragraph_style(me, styles[element_number]); - } else if (Division_Level >= 0) { - if (DivisionAlignments[Division_Level] == HT_CENTER) { + } else if (me->Division_Level >= 0) { + if (me->DivisionAlignments[me->Division_Level] == HT_CENTER) { change_paragraph_style(me, styles[HTML_HCENTER]); - } else if (DivisionAlignments[Division_Level] == HT_LEFT) { + } else if (me->DivisionAlignments[me->Division_Level] == HT_LEFT) { change_paragraph_style(me, styles[HTML_HLEFT]); - } else if (DivisionAlignments[Division_Level] == HT_RIGHT) { + } else if (me->DivisionAlignments[me->Division_Level] == HT_RIGHT) { change_paragraph_style(me, styles[HTML_HRIGHT]); } } else { change_paragraph_style(me, styles[element_number]); } UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_H_ID); + LYCheckForID(me, present, value, (int)HTML_H_ID); if ((bold_headers == TRUE || (element_number == HTML_H1 && bold_H1 == TRUE)) && (styles[element_number]->font&HT_BOLD)) { - if (B_inBoldA == FALSE && B_inBoldH == FALSE) { - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); + if (me->inBoldA == FALSE && me->inBoldH == FALSE) { + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); } - B_inBoldH = TRUE; + me->inBoldH = TRUE; } break; @@ -1573,28 +1149,28 @@ PRIVATE void HTML_start_element ARGS5( * If we encounter a P in either's content, we set flags to treat * the content as a block. - FM */ - if (B_inFIG) - B_inFIGwithP = TRUE; + if (me->inFIG) + me->inFIGwithP = TRUE; - if (B_inAPPLET) - B_inAPPLETwithP = TRUE; + if (me->inAPPLET) + me->inAPPLETwithP = TRUE; UPDATE_STYLE; - if (List_Nesting_Level >= 0) { + if (me->List_Nesting_Level >= 0) { /* * We're in a list. Treat P as an instruction to * create one blank line, if not already present, * then fall through to handle attributes, with * the "second line" margins. - FM */ - if (B_inP) { - if (B_inFIG || B_inAPPLET || - B_inCAPTION || B_inCREDIT || + if (me->inP) { + if (me->inFIG || me->inAPPLET || + me->inCAPTION || me->inCREDIT || me->sp->style->spaceAfter > 0 || me->sp->style->spaceBefore > 0) { - HTML_EnsureDoubleSpace(me); + LYEnsureDoubleSpace(me); } else { - HTML_EnsureSingleSpace(me); + LYEnsureSingleSpace(me); } } } else if (me->sp[0].tag_number == HTML_ADDRESS) { @@ -1606,75 +1182,79 @@ PRIVATE void HTML_start_element ARGS5( if (HText_LastLineSize(me->text)) { HText_appendCharacter(me->text, '\r'); } - } else if (!(B_inLABEL && !B_inP)) { + } else if (!(me->inLABEL && !me->inP)) { HText_appendParagraph(me->text); - B_inLABEL = FALSE; + me->inLABEL = FALSE; } me->in_word = NO; - if (HTML_override_default_alignment(me)) { + if (LYoverride_default_alignment(me)) { me->sp->style->alignment = styles[me->sp[0].tag_number]->alignment; - } else if (List_Nesting_Level >= 0 || - ((Division_Level < 0) && + } else if (me->List_Nesting_Level >= 0 || + ((me->Division_Level < 0) && (!strcmp(me->sp->style->name, "Normal") || !strcmp(me->sp->style->name, "Preformatted")))) { me->sp->style->alignment = HT_LEFT; } else { - me->sp->style->alignment = current_default_alignment; + me->sp->style->alignment = me->current_default_alignment; } if (present && present[HTML_P_ALIGN] && value[HTML_P_ALIGN]) { if (!strcasecomp(value[HTML_P_ALIGN], "center") && - !(List_Nesting_Level >= 0 && !B_inP)) + !(me->List_Nesting_Level >= 0 && !me->inP)) me->sp->style->alignment = HT_CENTER; else if (!strcasecomp(value[HTML_P_ALIGN], "right") && - !(List_Nesting_Level >= 0 && !B_inP)) + !(me->List_Nesting_Level >= 0 && !me->inP)) me->sp->style->alignment = HT_RIGHT; else if (!strcasecomp(value[HTML_H_ALIGN], "left") || !strcasecomp(value[HTML_H_ALIGN], "justify")) me->sp->style->alignment = HT_LEFT; } - HTML_CheckForID(me, present, value, (int)HTML_P_ID); + LYCheckForID(me, present, value, (int)HTML_P_ID); /* * Mark that we are starting a new paragraph * and don't have any of it's text yet. - FM * */ - B_inP = FALSE; + me->inP = FALSE; break; case HTML_BR: UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); - HTML_Last_Char = ' '; /* absorb white space */ - HText_appendCharacter(me->text, '\r'); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); + if (LYCollapseBRs == FALSE || HText_LastLineSize(me->text)) { + HText_setLastChar(me->text, ' '); /* absorb white space */ + HText_appendCharacter(me->text, '\r'); + } me->in_word = NO; - B_inP = FALSE; + me->inP = FALSE; break; case HTML_HR: { - register int i, width, old_alignment; + int width; /* * Start a new line only if we had printable * characters following the previous newline, - * and save the current style's alignment. - FM + * or remove the previous line if both it and + * the last line are blank. - FM */ UPDATE_STYLE; if (HText_LastLineSize(me->text)) { HText_appendCharacter(me->text, '\r'); - me->in_word = NO; - B_inP = FALSE; + } else if (!HText_PreviousLineSize(me->text)) { + HText_RemovePreviousLine(me->text); } - old_alignment = me->sp->style->alignment; + me->in_word = NO; + me->inP = FALSE; /* - * Add and ID link if needed. - FM + * Add an ID link if needed. - FM */ - HTML_CheckForID(me, present, value, (int)HTML_HR_ID); + LYCheckForID(me, present, value, (int)HTML_HR_ID); /* * Center lines within the current margins, if @@ -1719,12 +1299,38 @@ PRIVATE void HTML_start_element ARGS5( } for (i = 0; i < width; i++) HTML_put_character(me, '_'); - - HText_appendCharacter(me->text, '\r'); HText_appendCharacter(me->text, '\r'); me->in_word = NO; - B_inP = FALSE; - me->sp->style->alignment = old_alignment; + me->inP = FALSE; + + /* + * Reset the alignment appropriately + * for the division and/or block. - FM + */ + if (me->List_Nesting_Level < 0 && + me->Division_Level >= 0) { + me->sp->style->alignment = + me->DivisionAlignments[me->Division_Level]; + } else if (!strcmp(me->sp->style->name, "HeadingCenter") || + !strcmp(me->sp->style->name, "Heading1")) { + me->sp->style->alignment = HT_CENTER; + } else if (!strcmp(me->sp->style->name, "HeadingRight")) { + me->sp->style->alignment = HT_RIGHT; + } else { + me->sp->style->alignment = HT_LEFT; + } + + /* + * Add a blank line and set the second line + * indentation for lists and addresses, or a + * paragraph separator for other blocks. - FM + */ + if (me->List_Nesting_Level >= 0 || + me->sp[0].tag_number == HTML_ADDRESS) { + HText_appendCharacter(me->text, '\r'); + } else { + HText_appendParagraph(me->text); + } } break; @@ -1749,8 +1355,8 @@ PRIVATE void HTML_start_element ARGS5( fprintf(stderr, "HTML: ALIGN not 'left'. Using space instead of TAB.\n"); - } else if (!HTML_override_default_alignment(me) && - current_default_alignment != HT_LEFT) { + } else if (!LYoverride_default_alignment(me) && + me->current_default_alignment != HT_LEFT) { /* * Just ensure a collapsible space, until we * can replace HText_getCurrentColumn() in @@ -1767,7 +1373,7 @@ PRIVATE void HTML_start_element ARGS5( (present[HTML_TAB_INDENT] && value[HTML_TAB_INDENT] && isdigit(*value[HTML_TAB_INDENT]))) { - int i, column, target = -1; + int column, target = -1; int enval = 2; column = HText_getCurrentColumn(me->text); @@ -1841,25 +1447,25 @@ PRIVATE void HTML_start_element ARGS5( case HTML_EM: case HTML_STRONG: UPDATE_STYLE; - Underline_Level++; - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); + me->Underline_Level++; + LYCheckForID(me, present, value, (int)HTML_GEN_ID); /* * Ignore this if inside of a bold anchor or header. * Can't display both underline and bold at same time. */ - if (B_inBoldA == TRUE || B_inBoldH == TRUE) { + if (me->inBoldA == TRUE || me->inBoldH == TRUE) { if (TRACE) - fprintf(stderr,"Underline Level is %d\n", Underline_Level); + fprintf(stderr,"Underline Level is %d\n", me->Underline_Level); break; } - if (B_inUnderline == FALSE) { - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); - B_inUnderline = TRUE; + if (me->inUnderline == FALSE) { + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); + me->inUnderline = TRUE; if (TRACE) fprintf(stderr,"Beginning underline\n"); } else { if (TRACE) - fprintf(stderr,"Underline Level is %d\n", Underline_Level); + fprintf(stderr,"Underline Level is %d\n", me->Underline_Level); } break; @@ -1879,7 +1485,7 @@ PRIVATE void HTML_start_element ARGS5( case HTML_VAR: if (!me->text) UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); break; /* ignore */ case HTML_DEL: @@ -1887,12 +1493,12 @@ PRIVATE void HTML_start_element ARGS5( case HTML_STRIKE: if (!me->text) UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); HTML_put_string(me, "[DEL:"); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); HTML_put_character(me, ' '); me->in_word = NO; break; @@ -1900,12 +1506,12 @@ PRIVATE void HTML_start_element ARGS5( case HTML_INS: if (!me->text) UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); HTML_put_string(me, "[INS:"); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); HTML_put_character(me, ' '); me->in_word = NO; break; @@ -1913,7 +1519,7 @@ PRIVATE void HTML_start_element ARGS5( case HTML_Q: if (!me->text) UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); /* * Should check LANG and/or DIR attributes, and the * me->node_anchor->charset and/or yet to be added @@ -1921,24 +1527,24 @@ PRIVATE void HTML_start_element ARGS5( * use chevrons, but for now we'll always use double- * or single-quotes. - FM */ - if (!(Quote_Level & 1)) + if (!(me->Quote_Level & 1)) HText_appendCharacter(me->text, '"'); else HText_appendCharacter(me->text, '`'); - Quote_Level++; + me->Quote_Level++; break; case HTML_PRE: /* Formatted text */ if (!HText_PreviousLineSize(me->text)) - B_inPRE = FALSE; + me->inPRE = FALSE; else - B_inPRE = TRUE; + me->inPRE = TRUE; case HTML_LISTING: /* Litteral text */ case HTML_XMP: case HTML_PLAINTEXT: change_paragraph_style(me, styles[element_number]); UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); if (me->comment_end) HText_appendText(me->text, me->comment_end); break; @@ -1947,16 +1553,19 @@ PRIVATE void HTML_start_element ARGS5( case HTML_BQ: change_paragraph_style(me, styles[element_number]); UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_BQ_ID); + if (me->sp->tag_number == element_number) + LYEnsureDoubleSpace(me); + LYCheckForID(me, present, value, (int)HTML_BQ_ID); break; case HTML_NOTE: change_paragraph_style(me, styles[element_number]); UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_NOTE_ID); + if (me->sp->tag_number == element_number) + LYEnsureDoubleSpace(me); + LYCheckForID(me, present, value, (int)HTML_NOTE_ID); { char *note = NULL; - int i; /* * Indicate the type of NOTE. @@ -1980,77 +1589,79 @@ PRIVATE void HTML_start_element ARGS5( } else { StrAllocCopy(note, "NOTE:"); } - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); HTML_put_string(me, note); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); HTML_put_character(me, ' '); FREE(note); } - B_inLABEL = TRUE; + me->inLABEL = TRUE; me->in_word = NO; - B_inP = FALSE; + me->inP = FALSE; break; case HTML_ADDRESS: change_paragraph_style(me, styles[element_number]); UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_ADDRESS_ID); + if (me->sp->tag_number == element_number) + LYEnsureDoubleSpace(me); + LYCheckForID(me, present, value, (int)HTML_ADDRESS_ID); break; case HTML_DL: - List_Nesting_Level++; /* increment the List nesting level */ - if (List_Nesting_Level <= 0) { + me->List_Nesting_Level++; /* increment the List nesting level */ + if (me->List_Nesting_Level <= 0) { change_paragraph_style(me, present && present[HTML_DL_COMPACT] ? styles[HTML_DLC] : styles[HTML_DL]); - } else if (List_Nesting_Level >= 6) { + } else if (me->List_Nesting_Level >= 6) { change_paragraph_style(me, present && present[HTML_DL_COMPACT] ? styles[HTML_DLC6] : styles[HTML_DL6]); } else { change_paragraph_style(me, present && present[HTML_DL_COMPACT] - ? styles[(HTML_DLC1 - 1) + List_Nesting_Level] - : styles[(HTML_DL1 - 1) + List_Nesting_Level]); + ? styles[(HTML_DLC1 - 1) + me->List_Nesting_Level] + : styles[(HTML_DL1 - 1) + me->List_Nesting_Level]); } UPDATE_STYLE; /* update to the new style */ - HTML_CheckForID(me, present, value, (int)HTML_DL_ID); + LYCheckForID(me, present, value, (int)HTML_DL_ID); break; case HTML_DLC: - List_Nesting_Level++; /* increment the List nesting level */ - if (List_Nesting_Level <= 0) { + me->List_Nesting_Level++; /* increment the List nesting level */ + if (me->List_Nesting_Level <= 0) { change_paragraph_style(me, styles[HTML_DLC]); - } else if (List_Nesting_Level >= 6) { + } else if (me->List_Nesting_Level >= 6) { change_paragraph_style(me, styles[HTML_DLC6]); } else { change_paragraph_style(me, - styles[(HTML_DLC1 - 1) + List_Nesting_Level]); + styles[(HTML_DLC1 - 1) + me->List_Nesting_Level]); } UPDATE_STYLE; /* update to the new style */ - HTML_CheckForID(me, present, value, (int)HTML_DL_ID); + LYCheckForID(me, present, value, (int)HTML_DL_ID); break; case HTML_DT: if (!me->text) UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); if (!me->style_change) { HText_appendParagraph(me->text); me->in_word = NO; me->sp->style->alignment = HT_LEFT; } - B_inP = FALSE; + me->inP = FALSE; break; case HTML_DD: if (!me->text) UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); - HTML_Last_Char = ' '; /* absorb white space */ + LYCheckForID(me, present, value, (int)HTML_GEN_ID); + HText_setLastChar(me->text, ' '); /* absorb white space */ if (!me->style_change) HText_appendCharacter(me->text, '\r'); else @@ -2060,15 +1671,15 @@ PRIVATE void HTML_start_element ARGS5( } me->sp->style->alignment = HT_LEFT; me->in_word = NO; - B_inP = FALSE; + me->inP = FALSE; break; case HTML_OL: /* * Set the default TYPE. */ - OL_Type[(List_Nesting_Level < 5 ? - List_Nesting_Level+1 : 6)] = '1'; + me->OL_Type[(me->List_Nesting_Level < 5 ? + me->List_Nesting_Level+1 : 6)] = '1'; /* * Check whether we have a starting sequence number, @@ -2101,23 +1712,23 @@ PRIVATE void HTML_start_element ARGS5( */ if (present[HTML_OL_TYPE] && value[HTML_OL_TYPE]) { if (*value[HTML_OL_TYPE] == 'A') { - OL_Type[(List_Nesting_Level < 5 ? - List_Nesting_Level+1 : 6)] = 'A'; + me->OL_Type[(me->List_Nesting_Level < 5 ? + me->List_Nesting_Level+1 : 6)] = 'A'; if (seqnum < 1) seqnum = 1; } else if (*value[HTML_OL_TYPE] == 'a') { - OL_Type[(List_Nesting_Level < 5 ? - List_Nesting_Level+1 : 6)] = 'a'; + me->OL_Type[(me->List_Nesting_Level < 5 ? + me->List_Nesting_Level+1 : 6)] = 'a'; if (seqnum < 1) seqnum = 1; } else if (*value[HTML_OL_TYPE] == 'I') { - OL_Type[(List_Nesting_Level < 5 ? - List_Nesting_Level+1 : 6)] = 'I'; + me->OL_Type[(me->List_Nesting_Level < 5 ? + me->List_Nesting_Level+1 : 6)] = 'I'; if (seqnum < 1) seqnum = 1; } else if (*value[HTML_OL_TYPE] == 'i') { - OL_Type[(List_Nesting_Level < 5 ? - List_Nesting_Level+1 : 6)] = 'i'; + me->OL_Type[(me->List_Nesting_Level < 5 ? + me->List_Nesting_Level+1 : 6)] = 'i'; if (seqnum < 1) seqnum = 1; } else { @@ -2128,52 +1739,52 @@ PRIVATE void HTML_start_element ARGS5( seqnum = OL_VOID + 1; } - OL_Counter[(List_Nesting_Level < 5 ? - List_Nesting_Level+1 : 6)] = seqnum; + me->OL_Counter[(me->List_Nesting_Level < 5 ? + me->List_Nesting_Level+1 : 6)] = seqnum; } else if (present && present[HTML_OL_CONTINUE]) { - OL_Counter[List_Nesting_Level < 5 ? - List_Nesting_Level+1 : 6] = OL_CONTINUE; + me->OL_Counter[me->List_Nesting_Level < 5 ? + me->List_Nesting_Level+1 : 6] = OL_CONTINUE; } else { - OL_Counter[(List_Nesting_Level < 5 ? - List_Nesting_Level+1 : 6)] = 1; + me->OL_Counter[(me->List_Nesting_Level < 5 ? + me->List_Nesting_Level+1 : 6)] = 1; if (present && present[HTML_OL_TYPE] && value[HTML_OL_TYPE]) { if (*value[HTML_OL_TYPE] == 'A') { - OL_Type[(List_Nesting_Level < 5 ? - List_Nesting_Level+1 : 6)] = 'A'; + me->OL_Type[(me->List_Nesting_Level < 5 ? + me->List_Nesting_Level+1 : 6)] = 'A'; } else if (*value[HTML_OL_TYPE] == 'a') { - OL_Type[(List_Nesting_Level < 5 ? - List_Nesting_Level+1 : 6)] = 'a'; + me->OL_Type[(me->List_Nesting_Level < 5 ? + me->List_Nesting_Level+1 : 6)] = 'a'; } else if (*value[HTML_OL_TYPE] == 'I') { - OL_Type[(List_Nesting_Level < 5 ? - List_Nesting_Level+1 : 6)] = 'I'; + me->OL_Type[(me->List_Nesting_Level < 5 ? + me->List_Nesting_Level+1 : 6)] = 'I'; } else if (*value[HTML_OL_TYPE] == 'i') { - OL_Type[(List_Nesting_Level < 5 ? - List_Nesting_Level+1 : 6)] = 'i'; + me->OL_Type[(me->List_Nesting_Level < 5 ? + me->List_Nesting_Level+1 : 6)] = 'i'; } } } - List_Nesting_Level++; + me->List_Nesting_Level++; - if (List_Nesting_Level <= 0) { + if (me->List_Nesting_Level <= 0) { change_paragraph_style(me, styles[element_number]); - } else if (List_Nesting_Level >= 6) { + } else if (me->List_Nesting_Level >= 6) { change_paragraph_style(me, styles[HTML_OL6]); } else { change_paragraph_style(me, - styles[HTML_OL1 + List_Nesting_Level - 1]); + styles[HTML_OL1 + me->List_Nesting_Level - 1]); } UPDATE_STYLE; /* update to the new style */ - HTML_CheckForID(me, present, value, (int)HTML_OL_ID); + LYCheckForID(me, present, value, (int)HTML_OL_ID); break; case HTML_UL: - List_Nesting_Level++; + me->List_Nesting_Level++; - if (List_Nesting_Level <= 0) { + if (me->List_Nesting_Level <= 0) { if (!(present && present[HTML_UL_PLAIN]) && !(present && present[HTML_UL_TYPE] && value[HTML_UL_TYPE] && @@ -2184,7 +1795,7 @@ PRIVATE void HTML_start_element ARGS5( element_number = HTML_DIR; } - } else if (List_Nesting_Level >= 6) { + } else if (me->List_Nesting_Level >= 6) { if (!(present && present[HTML_UL_PLAIN]) && !(present && present[HTML_UL_TYPE] && value[HTML_UL_TYPE] && @@ -2201,39 +1812,39 @@ PRIVATE void HTML_start_element ARGS5( value[HTML_UL_TYPE] && 0==strcasecomp(value[HTML_UL_TYPE], "PLAIN"))) { change_paragraph_style(me, - styles[HTML_OL1 + List_Nesting_Level - 1]); + styles[HTML_OL1 + me->List_Nesting_Level - 1]); } else { change_paragraph_style(me, - styles[HTML_MENU1 + List_Nesting_Level - 1]); + styles[HTML_MENU1 + me->List_Nesting_Level - 1]); element_number = HTML_DIR; } } UPDATE_STYLE; /* update to the new style */ - HTML_CheckForID(me, present, value, (int)HTML_UL_ID); + LYCheckForID(me, present, value, (int)HTML_UL_ID); break; case HTML_MENU: case HTML_DIR: - List_Nesting_Level++; + me->List_Nesting_Level++; - if (List_Nesting_Level <= 0) { + if (me->List_Nesting_Level <= 0) { change_paragraph_style(me, styles[element_number]); - } else if (List_Nesting_Level >= 6) { + } else if (me->List_Nesting_Level >= 6) { change_paragraph_style(me, styles[HTML_MENU6]); } else { change_paragraph_style(me, - styles[HTML_MENU1 + List_Nesting_Level - 1]); + styles[HTML_MENU1 + me->List_Nesting_Level - 1]); } UPDATE_STYLE; /* update to the new style */ - HTML_CheckForID(me, present, value, (int)HTML_UL_ID); + LYCheckForID(me, present, value, (int)HTML_UL_ID); break; case HTML_LH: UPDATE_STYLE; /* update to the new style */ HText_appendParagraph(me->text); - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); HText_appendCharacter(me->text, ' '); me->in_word = NO; break; @@ -2242,24 +1853,24 @@ PRIVATE void HTML_start_element ARGS5( UPDATE_STYLE; /* update to the new style */ HText_appendParagraph(me->text); me->sp->style->alignment = HT_LEFT; - HTML_CheckForID(me, present, value, (int)HTML_LI_ID); + LYCheckForID(me, present, value, (int)HTML_LI_ID); if (me->sp[0].tag_number == HTML_OL) { char number_string[20]; - register int i, counter, seqnum; + int counter, seqnum; char seqtype; - counter = List_Nesting_Level < 6 ? List_Nesting_Level : 6; + counter = me->List_Nesting_Level < 6 ? me->List_Nesting_Level : 6; if (present && present[HTML_LI_TYPE] && value[HTML_LI_TYPE]) { if (*value[HTML_LI_TYPE] == '1') { - OL_Type[counter] = '1'; + me->OL_Type[counter] = '1'; } else if (*value[HTML_LI_TYPE] == 'A') { - OL_Type[counter] = 'A'; + me->OL_Type[counter] = 'A'; } else if (*value[HTML_LI_TYPE] == 'a') { - OL_Type[counter] = 'a'; + me->OL_Type[counter] = 'a'; } else if (*value[HTML_LI_TYPE] == 'I') { - OL_Type[counter] = 'I'; + me->OL_Type[counter] = 'I'; } else if (*value[HTML_LI_TYPE] == 'i') { - OL_Type[counter] = 'i'; + me->OL_Type[counter] = 'i'; } } if (present && present[HTML_LI_VALUE] && @@ -2271,24 +1882,24 @@ PRIVATE void HTML_start_element ARGS5( seqnum = atoi(value[HTML_LI_VALUE]); if (seqnum <= OL_VOID) seqnum = OL_VOID + 1; - seqtype = OL_Type[counter]; + seqtype = me->OL_Type[counter]; if (seqtype != '1' && seqnum < 1) seqnum = 1; - OL_Counter[counter] = seqnum + 1; - } else if (OL_Counter[counter] >= OL_VOID) { - seqnum = OL_Counter[counter]++; - seqtype = OL_Type[counter]; + me->OL_Counter[counter] = seqnum + 1; + } else if (me->OL_Counter[counter] >= OL_VOID) { + seqnum = me->OL_Counter[counter]++; + seqtype = me->OL_Type[counter]; if (seqtype != '1' && seqnum < 1) { seqnum = 1; - OL_Counter[counter] = seqnum + 1; + me->OL_Counter[counter] = seqnum + 1; } } else { - seqnum = Last_OL_Count + 1; - seqtype = Last_OL_Type; + seqnum = me->Last_OL_Count + 1; + seqtype = me->Last_OL_Type; for (i = (counter - 1); i >= 0; i--) { - if (OL_Counter[i] > OL_VOID) { - seqnum = OL_Counter[i]++; - seqtype = OL_Type[i]; + if (me->OL_Counter[i] > OL_VOID) { + seqnum = me->OL_Counter[i]++; + seqtype = me->OL_Type[i]; i = 0; } } @@ -2304,8 +1915,8 @@ PRIVATE void HTML_start_element ARGS5( } else { sprintf(number_string, "%2d.", seqnum); } - Last_OL_Count = seqnum; - Last_OL_Type = seqtype; + me->Last_OL_Count = seqnum; + me->Last_OL_Type = seqtype; /* hack, because there is no append string! */ for (i = 0; number_string[i] != '\0'; i++) if (number_string[i] == ' ') @@ -2314,7 +1925,7 @@ PRIVATE void HTML_start_element ARGS5( HTML_put_character(me, number_string[i]); /* use HTML_put_character so that any other spaces - * comming through will be collapsed + * coming through will be collapsed */ HTML_put_character(me, ' '); /* the spacing charactor */ @@ -2328,7 +1939,7 @@ PRIVATE void HTML_start_element ARGS5( * Use HTML_put_character so that any other spaces * comming through will be collapsed */ - switch(List_Nesting_Level % 7) { + switch(me->List_Nesting_Level % 7) { case 0: HTML_put_character(me, '*'); break; @@ -2361,13 +1972,13 @@ PRIVATE void HTML_start_element ARGS5( HText_appendCharacter(me->text, ' '); } me->in_word = NO; - B_inP = FALSE; + me->inP = FALSE; break; case HTML_SPAN: if (!me->text) UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); /* * Should check LANG and/or DIR attributes, and the * me->node_anchor->charset and/or yet to be added @@ -2378,7 +1989,7 @@ PRIVATE void HTML_start_element ARGS5( case HTML_BDO: if (!me->text) UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); /* * Should check DIR (and LANG) attributes, and the * me->node_anchor->charset and/or yet to be added @@ -2389,117 +2000,109 @@ PRIVATE void HTML_start_element ARGS5( case HTML_SPOT: if (!me->text) UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); break; case HTML_FN: change_paragraph_style(me, styles[element_number]); UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_FN_ID); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); + if (me->sp->tag_number == element_number) + LYEnsureDoubleSpace(me); + LYCheckForID(me, present, value, (int)HTML_FN_ID); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); HTML_put_string(me, "FOOTNOTE:"); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); HTML_put_character(me, ' '); - B_inLABEL = TRUE; + me->inLABEL = TRUE; me->in_word = NO; - B_inP = FALSE; + me->inP = FALSE; break; case HTML_A: - { - /* - * Set to know we are in an anchor. - */ - B_inA = TRUE; + /* + * Set to know we are in an anchor. + */ + me->inA = TRUE; + /* + * Load id_string if we have an ID or NAME. - FM + */ + if (present && present[HTML_A_ID] && + value[HTML_A_ID] && *value[HTML_A_ID]) { + StrAllocCopy(id_string, value[HTML_A_ID]); + } else if (present && present[HTML_A_NAME] && + value[HTML_A_NAME] && *value[HTML_A_NAME]) { + StrAllocCopy(id_string, value[HTML_A_NAME]); + } + if (id_string) { + LYUnEscapeToLatinOne(&id_string, TRUE); + if (*id_string == '\0') { + FREE(id_string); + } + } + + /* + * Handle the reference. - FM + */ + if (present && present[HTML_A_HREF]) { /* - * Load id_string if we have an ID or NAME. - FM + * Prepare to do housekeeping on the reference. - FM */ - if (present && present[HTML_A_ID] && - value[HTML_A_ID] && *value[HTML_A_ID]) { - StrAllocCopy(id_string, value[HTML_A_ID]); - } else if (present && present[HTML_A_NAME] && - value[HTML_A_NAME] && *value[HTML_A_NAME]) { - StrAllocCopy(id_string, value[HTML_A_NAME]); - } - if (id_string) { - LYUnEscapeToLatinOne(&id_string, TRUE); - if (*id_string == '\0') { - FREE(id_string); + if (!value[HTML_A_HREF] || *value[HTML_A_HREF] == '\0') { + StrAllocCopy(href, me->node_anchor->address); + } else if (*value[HTML_A_HREF] == '#') { + StrAllocCopy(href, me->node_anchor->address); + if (strlen(value[HTML_A_HREF]) > 1) { + StrAllocCat(href, value[HTML_A_HREF]); } + } else { + StrAllocCopy(href, value[HTML_A_HREF]); } + url_type = LYLegitimizeHREF(me, (char**)&href, TRUE); /* - * Handle the reference. - FM + * Deal with our ftp gateway kludge. - FM */ - if (present && present[HTML_A_HREF]) { - /* - * Prepare to do housekeeping on the reference. - FM - */ - if (!(value[HTML_A_HREF] && *value[HTML_A_HREF])) { - if (B_inBASE && base_href && *base_href) { - StrAllocCopy(href, base_href); - } else { - StrAllocCopy(href, me->node_anchor->address); - } - } else { - StrAllocCopy(href, value[HTML_A_HREF]); - convert_to_spaces(href); - LYUnEscapeToLatinOne(&href, TRUE); - } - url_type = is_url(href); - - /* - * Deal with our ftp gateway kludge. - FM - */ - if (!url_type && !strncmp(href, "/foo/..", 7) && - (!strncmp(me->node_anchor->address, "ftp:", 4) || - !strncmp(me->node_anchor->address, "file:", 5))) { - int i; - for (i = 0; href[i]; i++) - href[i] = href[i+7]; - } + if (!url_type && !strncmp(href, "/foo/..", 7) && + (!strncmp(me->node_anchor->address, "ftp:", 4) || + !strncmp(me->node_anchor->address, "file:", 5))) { + for (i = 0; href[i]; i++) + href[i] = href[i+7]; + } - /* - * Don't simplify gopher gateway URLs or absolute HREFs. - FM - */ - if (HT_Is_Gopher_URL) { - HT_Is_Gopher_URL = FALSE; - } else if (!url_type && *href != '/' && *href != '\0') - HTSimplify(href); + /* + * Set to know we are making the content bold. + */ + me->inBoldA = TRUE; + /* + * Check whether a base tag is in effect. - FM + */ + if ((me->inBASE && *href != '\0' && *href != '#') && + (temp = HTParse(href, me->base_href, PARSE_ALL)) && + *temp != '\0') /* - * Set to know we are making the content bold. - */ - B_inBoldA = TRUE; - - /* - * Check whether a base tag is in effect. - FM + * Use reference related to the base. */ - if ((B_inBASE) && - (temp = HTParse(href, base_href, PARSE_ALL)) && - *temp != '\0') - /* - * Use reference related to the base. - */ - StrAllocCopy(href, temp); - FREE(temp); + StrAllocCopy(href, temp); + FREE(temp); - /* - * Check whether to fill in localhost. - FM - */ - HTMLFillLocalFileURL((char **)&href, - (B_inBASE ? base_href : - me->node_anchor->address)); - } else { - if (bold_name_anchors == TRUE) { - B_inBoldA = TRUE; - } + /* + * Check whether to fill in localhost. - FM + */ + LYFillLocalFileURL((char **)&href, + ((*href != '\0' && *href != '#' && + me->inBASE) ? + me->base_href : me->node_anchor->address)); + } else { + if (bold_name_anchors == TRUE) { + me->inBoldA = TRUE; } + } - B_CurrentA = HTAnchor_findChildAndLink( + me->CurrentA = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ id_string, /* Tag */ href, /* Address */ @@ -2508,49 +2111,48 @@ PRIVATE void HTML_start_element ARGS5( value[HTML_A_TYPE]) ? (HTLinkType*)HTAtom_for(value[HTML_A_TYPE]) : (void *)0); /* Type */ - /* - * Get rid of href since no longer needed. - * Memory leak fixed - * 06-16-94 Lynx 2-3-1 Garrett Arch Blythe - */ - FREE(href); - FREE(id_string); + /* + * Get rid of href since no longer needed. + * Memory leak fixed + * 06-16-94 Lynx 2-3-1 Garrett Arch Blythe + */ + FREE(href); + FREE(id_string); - if (B_CurrentA && present) { - if (present[HTML_A_TITLE] && - value[HTML_A_TITLE] && *value[HTML_A_TITLE] != '\0') { - StrAllocCopy(title, value[HTML_A_TITLE]); - if (current_char_set) - LYExpandString(&title); - /* - * Convert any HTML entities or decimal escaping. - FM - */ - LYUnEscapeEntities(title, TRUE, FALSE); - LYTrimHead(title); - LYTrimTail(title); - if (*title == '\0') { - FREE(title); - } + if (me->CurrentA && present) { + if (present[HTML_A_TITLE] && + value[HTML_A_TITLE] && *value[HTML_A_TITLE] != '\0') { + StrAllocCopy(title, value[HTML_A_TITLE]); + if (current_char_set) + LYExpandString(&title); + /* + * Convert any HTML entities or decimal escaping. - FM + */ + LYUnEscapeEntities(title, TRUE, FALSE); + LYTrimHead(title); + LYTrimTail(title); + if (*title == '\0') { + FREE(title); } - if (present[HTML_A_ISMAP]) - dest_ismap = TRUE; - if (title != NULL || dest_ismap == TRUE) - dest = HTAnchor_parent( - HTAnchor_followMainLink((HTAnchor*)B_CurrentA) - ); - if (dest && title != NULL && HTAnchor_title(dest) == NULL) - HTAnchor_setTitle(dest, title); - if (dest && dest_ismap) - dest->isISMAPScript = TRUE; - dest = NULL; - dest_ismap = FALSE; - FREE(title); } - UPDATE_STYLE; - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldA == TRUE && B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); + if (present[HTML_A_ISMAP]) + dest_ismap = TRUE; + if (title != NULL || dest_ismap == TRUE) + dest = HTAnchor_parent( + HTAnchor_followMainLink((HTAnchor*)me->CurrentA) + ); + if (dest && title != NULL && HTAnchor_title(dest) == NULL) + HTAnchor_setTitle(dest, title); + if (dest && dest_ismap) + dest->isISMAPScript = TRUE; + dest = NULL; + dest_ismap = FALSE; + FREE(title); } + UPDATE_STYLE; + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldA == TRUE && me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); break; case HTML_IMG: /* Images */ @@ -2561,9 +2163,9 @@ PRIVATE void HTML_start_element ARGS5( * set our flags for faking a 0,0 coordinate pair, * which typically returns the image's default. - FM */ - if (B_inA && B_CurrentA) { + if (me->inA && me->CurrentA) { if (dest = HTAnchor_parent( - HTAnchor_followMainLink((HTAnchor*)B_CurrentA) + HTAnchor_followMainLink((HTAnchor*)me->CurrentA) )) { if (dest->isISMAPScript == TRUE) { dest_ismap = TRUE; @@ -2588,22 +2190,18 @@ PRIVATE void HTML_start_element ARGS5( if (present && present[HTML_IMG_USEMAP] && value[HTML_IMG_USEMAP] && *value[HTML_IMG_USEMAP]) { StrAllocCopy(map_href, value[HTML_IMG_USEMAP]); - convert_to_spaces(map_href); - LYUnEscapeToLatinOne(&map_href, TRUE); + url_type = LYLegitimizeHREF(me, (char**)&map_href, TRUE); if (*map_href == '\0') { FREE(map_href); } } if (map_href && strchr(map_href, '#')) { - url_type = is_url(map_href); - if (!url_type && *map_href != '#') - HTSimplify(map_href); /* * Check whether a base tag is in effect. - FM */ - if ((B_inBASE) && - (temp = HTParse(map_href, base_href, PARSE_ALL)) && + if ((me->inBASE && *map_href != '#') && + (temp = HTParse(map_href, me->base_href, PARSE_ALL)) && *temp != '\0') /* * Use reference related to the base. @@ -2614,9 +2212,10 @@ PRIVATE void HTML_start_element ARGS5( /* * Check whether to fill in localhost. - FM */ - HTMLFillLocalFileURL((char **)&map_href, - (B_inBASE ? base_href : - me->node_anchor->address)); + LYFillLocalFileURL((char **)&map_href, + ((*map_href != '\0' && *map_href != '#' && + me->inBASE) ? + me->base_href : me->node_anchor->address)); /* * If it's not yet a URL, resolve versus @@ -2673,7 +2272,7 @@ PRIVATE void HTML_start_element ARGS5( * Convert any HTML entities or decimal escaping. - FM */ LYUnEscapeEntities(alt_string, - LYUsePlainSpace, LYHiddenValue); + me->UsePlainSpace, me->HiddenValue); /* * If it's all spaces and we are making SRC or * USEMAP links, treat it as zero-length. - FM @@ -2688,7 +2287,7 @@ PRIVATE void HTML_start_element ARGS5( else if (dest_ismap || present[HTML_IMG_ISMAP]) { StrAllocCopy(alt_string, (title ? title : "[ISMAP]")); - } else if (B_inA == TRUE) { + } else if (me->inA == TRUE) { StrAllocCopy(alt_string, (title ? title : "[LINK]")); } else { @@ -2708,7 +2307,7 @@ PRIVATE void HTML_start_element ARGS5( StrAllocCopy(alt_string, (title ? title : "[ISMAP]")); - } else if (B_inA == TRUE) { + } else if (me->inA == TRUE) { StrAllocCopy(alt_string, (title ? title : "[LINK]")); @@ -2732,7 +2331,7 @@ PRIVATE void HTML_start_element ARGS5( map_href ? 1 : 0, (dest_ismap || (present && present[HTML_IMG_ISMAP])) ? 1 : 0, - B_inA, B_inP); + me->inA, me->inP); } /* @@ -2754,17 +2353,13 @@ PRIVATE void HTML_start_element ARGS5( present && present[HTML_IMG_SRC] && value[HTML_IMG_SRC] && *value[HTML_IMG_SRC] != '\0') { StrAllocCopy(href, value[HTML_IMG_SRC]); - convert_to_spaces(href); - LYUnEscapeToLatinOne(&href, TRUE); - url_type = is_url(href); - if (!url_type && *href != '\0') - HTSimplify(href); + url_type = LYLegitimizeHREF(me, (char**)&href, TRUE); /* * Check whether a base tag is in effect. - FM */ - if ((B_inBASE) && - (temp = HTParse(href, base_href, PARSE_ALL)) && + if ((me->inBASE && *href != '\0' && *href != '#') && + (temp = HTParse(href, me->base_href, PARSE_ALL)) && *temp != '\0') /* * Use reference related to the base. @@ -2775,15 +2370,16 @@ PRIVATE void HTML_start_element ARGS5( /* * Check whether to fill in localhost. - FM */ - HTMLFillLocalFileURL((char **)&href, - (B_inBASE ? base_href : - me->node_anchor->address)); + LYFillLocalFileURL((char **)&href, + ((*href != '\0' && *href != '#' && + me->inBASE) ? + me->base_href : me->node_anchor->address)); /* * If it's an ISMAP and/or USEMAP, or graphic for an * anchor, end that anchor and start one for the SRC. - FM */ - if (B_inA) { + if (me->inA) { /* * If we have a USEMAP, end this anchor and * start a new one for the client-side MAP. - FM @@ -2794,46 +2390,46 @@ PRIVATE void HTML_start_element ARGS5( } else { HTML_put_string(me, "[LINK]"); } - if (B_inBoldA == TRUE && B_inBoldH == FALSE) { - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (me->inBoldA == TRUE && me->inBoldH == FALSE) { + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); } - B_inBoldA = FALSE; + me->inBoldA = FALSE; HText_endAnchor(me->text); HText_appendCharacter(me->text, '-'); if (id_string) { - if (B_ID_A = HTAnchor_findChildAndLink( + if (ID_A = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ id_string, /* Tag */ NULL, /* Addresss */ (void *)0)) { /* Type */ - HText_beginAnchor(me->text, B_ID_A); + HText_beginAnchor(me->text, ID_A); HText_endAnchor(me->text); } } - B_CurrentA = HTAnchor_findChildAndLink( + me->CurrentA = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ NULL, /* Tag */ map_href, /* Addresss */ (void *)0); /* Type */ - if (B_CurrentA && title) { + if (me->CurrentA && title) { if (dest = HTAnchor_parent( - HTAnchor_followMainLink((HTAnchor*)B_CurrentA) + HTAnchor_followMainLink((HTAnchor*)me->CurrentA) )) { if (!HTAnchor_title(dest)) HTAnchor_setTitle(dest, title); } } - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldA == FALSE && B_inBoldH == FALSE) { - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldA == FALSE && me->inBoldH == FALSE) { + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); } - B_inBoldA = TRUE; + me->inBoldA = TRUE; } HTML_put_string(me, alt_string); - if (B_inBoldA == TRUE && B_inBoldH == FALSE) { - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (me->inBoldA == TRUE && me->inBoldH == FALSE) { + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); } - B_inBoldA = FALSE; + me->inBoldA = FALSE; HText_endAnchor(me->text); HText_appendCharacter(me->text, '-'); StrAllocCopy(alt_string, @@ -2842,12 +2438,12 @@ PRIVATE void HTML_start_element ARGS5( ((map_href || dest_ismap) ? "(IMAGE)" : "(OBJECT)") : "[IMAGE]")); if (id_string && !map_href) { - if (B_ID_A = HTAnchor_findChildAndLink( + if (ID_A = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ id_string, /* Tag */ NULL, /* Addresss */ (void *)0)) { /* Type */ - HText_beginAnchor(me->text, B_ID_A); + HText_beginAnchor(me->text, ID_A); HText_endAnchor(me->text); } } @@ -2855,37 +2451,37 @@ PRIVATE void HTML_start_element ARGS5( HTML_put_character(me, ' '); /* space char may be ignored */ me->in_word = NO; if (id_string) { - if (B_ID_A = HTAnchor_findChildAndLink( + if (ID_A = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ id_string, /* Tag */ NULL, /* Addresss */ (void *)0)) { /* Type */ - HText_beginAnchor(me->text, B_ID_A); + HText_beginAnchor(me->text, ID_A); HText_endAnchor(me->text); } } - B_CurrentA = HTAnchor_findChildAndLink( + me->CurrentA = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ NULL, /* Tag */ map_href, /* Addresss */ (void *)0); /* Type */ - if (B_CurrentA && title) { + if (me->CurrentA && title) { if (dest = HTAnchor_parent( - HTAnchor_followMainLink((HTAnchor*)B_CurrentA) + HTAnchor_followMainLink((HTAnchor*)me->CurrentA) )) { if (!HTAnchor_title(dest)) HTAnchor_setTitle(dest, title); } } - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldA == FALSE && B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); - B_inBoldA = TRUE; + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldA == FALSE && me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); + me->inBoldA = TRUE; HTML_put_string(me, alt_string); - if (B_inBoldA == TRUE && B_inBoldH == FALSE) { - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (me->inBoldA == TRUE && me->inBoldH == FALSE) { + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); } - B_inBoldA = FALSE; + me->inBoldA = FALSE; HText_endAnchor(me->text); HText_appendCharacter(me->text, '-'); StrAllocCopy(alt_string, @@ -2896,12 +2492,12 @@ PRIVATE void HTML_start_element ARGS5( HTML_put_character(me, ' '); /* space char may be ignored */ me->in_word = NO; if (id_string) { - if (B_ID_A = HTAnchor_findChildAndLink( + if (ID_A = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ id_string, /* Tag */ NULL, /* Addresss */ (void *)0)) { /* Type */ - HText_beginAnchor(me->text, B_ID_A); + HText_beginAnchor(me->text, ID_A); HText_endAnchor(me->text); } } @@ -2910,27 +2506,27 @@ PRIVATE void HTML_start_element ARGS5( /* * Create the link to the SRC. - FM */ - B_CurrentA = HTAnchor_findChildAndLink( + me->CurrentA = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ NULL, /* Tag */ href, /* Addresss */ (void *)0); /* Type */ FREE(href); - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); HTML_put_string(me, alt_string); - if (!B_inA) { - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (!me->inA) { + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); HText_endAnchor(me->text); HTML_put_character(me, ' '); /* space char may be ignored */ me->in_word = NO; } else { - B_inBoldA = TRUE; + me->inBoldA = TRUE; } } else if (map_href) { - if (B_inA) { + if (me->inA) { /* * We're in an anchor and have a USEMAP, so end the anchor * and start a new one for the client-side MAP. - FM @@ -2940,40 +2536,40 @@ PRIVATE void HTML_start_element ARGS5( } else { HTML_put_string(me, "[LINK]"); } - if (B_inBoldA == TRUE && B_inBoldH == FALSE) { - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (me->inBoldA == TRUE && me->inBoldH == FALSE) { + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); } - B_inBoldA = FALSE; + me->inBoldA = FALSE; HText_endAnchor(me->text); HText_appendCharacter(me->text, '-'); } else { HTML_put_character(me, ' '); me->in_word = NO; } - B_CurrentA = HTAnchor_findChildAndLink( + me->CurrentA = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ NULL, /* Tag */ map_href, /* Addresss */ (void *)0); /* Type */ - if (B_CurrentA && title) { + if (me->CurrentA && title) { if (dest = HTAnchor_parent( - HTAnchor_followMainLink((HTAnchor*)B_CurrentA) + HTAnchor_followMainLink((HTAnchor*)me->CurrentA) )) { if (!HTAnchor_title(dest)) HTAnchor_setTitle(dest, title); } } - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldA == FALSE && B_inBoldH == FALSE) { - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldA == FALSE && me->inBoldH == FALSE) { + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); } - B_inBoldA = TRUE; + me->inBoldA = TRUE; HTML_put_string(me, alt_string); - if (!B_inA) { - if (B_inBoldA == TRUE && B_inBoldH == FALSE) { - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (!me->inA) { + if (me->inBoldA == TRUE && me->inBoldH == FALSE) { + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); } - B_inBoldA = FALSE; + me->inBoldA = FALSE; HText_endAnchor(me->text); } } else { @@ -2982,22 +2578,22 @@ PRIVATE void HTML_start_element ARGS5( * for the current anchor or inline, with an * ID link if indicated. - FM */ - if (!B_inA) { + if (!me->inA) { HTML_put_character(me, ' '); /* space char may be ignored */ me->in_word = NO; } if (id_string) { - if (B_ID_A = HTAnchor_findChildAndLink( + if (ID_A = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ id_string, /* Tag */ NULL, /* Addresss */ (void *)0)) { /* Type */ - HText_beginAnchor(me->text, B_ID_A); + HText_beginAnchor(me->text, ID_A); HText_endAnchor(me->text); } } HTML_put_string(me, alt_string); - if (!B_inA) { + if (!me->inA) { HTML_put_character(me, ' '); /* space char may be ignored */ me->in_word = NO; } @@ -3029,19 +2625,18 @@ PRIVATE void HTML_start_element ARGS5( } /* - * Load LYMapName. - FM + * Load map_address. - FM */ if (id_string) { - char * cp; - if (B_inBASE && base_href && *base_href) { - StrAllocCopy(LYMapName, base_href); + if (me->inBASE && me->base_href && *me->base_href) { + StrAllocCopy(me->map_address, me->base_href); } else { - StrAllocCopy(LYMapName, me->node_anchor->address); + StrAllocCopy(me->map_address, me->node_anchor->address); } - if ((cp=strrchr(LYMapName, '#')) != NULL) + if ((cp = strrchr(me->map_address, '#')) != NULL) *cp = '\0'; - StrAllocCat(LYMapName, "#"); - StrAllocCat(LYMapName, id_string); + StrAllocCat(me->map_address, "#"); + StrAllocCat(me->map_address, id_string); FREE(id_string); if (present && present[HTML_MAP_TITLE] && value[HTML_MAP_TITLE] && *value[HTML_MAP_TITLE] != '\0') { @@ -3058,30 +2653,26 @@ PRIVATE void HTML_start_element ARGS5( FREE(title); } } - LYAddImageMap(LYMapName, title); + LYAddImageMap(me->map_address, title); FREE(title); } break; case HTML_AREA: - if (LYMapName && + if (me->map_address && present && present[HTML_AREA_HREF] && value[HTML_AREA_HREF] && *value[HTML_AREA_HREF]) { /* * Resolve the HREF. - FM */ StrAllocCopy(href, value[HTML_AREA_HREF]); - convert_to_spaces(href); - LYUnEscapeToLatinOne(&href, TRUE); - url_type = is_url(href); - if (!url_type && *href != '/' && *href != '\0') - HTSimplify(href); + url_type = LYLegitimizeHREF(me, (char**)&href, TRUE); /* * Check whether a base tag is in effect. - FM */ - if ((B_inBASE) && - (temp = HTParse(href, base_href, PARSE_ALL)) && + if ((me->inBASE && *href != '\0' && *href != '#') && + (temp = HTParse(href, me->base_href, PARSE_ALL)) && *temp != '\0') /* * Use reference related to the base. @@ -3092,9 +2683,10 @@ PRIVATE void HTML_start_element ARGS5( /* * Check whether to fill in localhost. - FM */ - HTMLFillLocalFileURL((char **)&href, - (B_inBASE ? base_href : - me->node_anchor->address)); + LYFillLocalFileURL((char **)&href, + ((*href != '\0' && *href != '#' && + me->inBASE) ? + me->base_href : me->node_anchor->address)); if (!(url_type = is_url(href))) { temp = HTParse(href, me->node_anchor->address, PARSE_ALL); @@ -3127,7 +2719,7 @@ PRIVATE void HTML_start_element ARGS5( * Convert any HTML entities or decimal escaping. - FM */ LYUnEscapeEntities(alt_string, - LYUsePlainSpace, LYHiddenValue); + me->UsePlainSpace, me->HiddenValue); /* * Make sure it's not just space(s). - FM */ @@ -3143,7 +2735,7 @@ PRIVATE void HTML_start_element ARGS5( StrAllocCopy(alt_string, href); } - LYAddMapElement(LYMapName, href, alt_string); + LYAddMapElement(me->map_address, href, alt_string); FREE(href); FREE(alt_string); } @@ -3158,7 +2750,7 @@ PRIVATE void HTML_start_element ARGS5( break; case HTML_BODYTEXT: - HTML_CheckForID(me, present, value, (int)HTML_BODYTEXT_ID); + LYCheckForID(me, present, value, (int)HTML_BODYTEXT_ID); /* * We may need to look at this someday to deal with * OBJECTs optimally, but just ignore it for now. - FM @@ -3166,7 +2758,7 @@ PRIVATE void HTML_start_element ARGS5( break; case HTML_TEXTFLOW: - HTML_CheckForID(me, present, value, (int)HTML_BODYTEXT_ID); + LYCheckForID(me, present, value, (int)HTML_BODYTEXT_ID); /* * We may need to look at this someday to deal with * APPLETs optimally, but just ignore it for now. - FM @@ -3174,37 +2766,32 @@ PRIVATE void HTML_start_element ARGS5( break; case HTML_FIG: - B_inFIG = TRUE; + me->inFIG = TRUE; if (!me->text) UPDATE_STYLE; if (!present || (present && !present[HTML_FIG_ISOBJECT])) { - HTML_EnsureDoubleSpace(me); - HTML_ResetParagraphAlignment(me); - B_inFIGwithP = TRUE; + LYEnsureDoubleSpace(me); + LYResetParagraphAlignment(me); + me->inFIGwithP = TRUE; } else { - B_inFIGwithP = FALSE; + me->inFIGwithP = FALSE; HTML_put_character(me, ' '); /* space char may be ignored */ } - HTML_CheckForID(me, present, value, (int)HTML_FIG_ID); + LYCheckForID(me, present, value, (int)HTML_FIG_ID); me->in_word = NO; - B_inP = FALSE; + me->inP = FALSE; if (clickable_images && present && present[HTML_FIG_SRC] && value[HTML_FIG_SRC] && *value[HTML_FIG_SRC] != '\0') { StrAllocCopy(href, value[HTML_FIG_SRC]); - convert_to_spaces(href); - LYUnEscapeToLatinOne(&href, TRUE); + url_type = LYLegitimizeHREF(me, (char**)&href, TRUE); if (*href) { - url_type = is_url(href); - if (!url_type && *href != '/') - HTSimplify(href); - /* * Check whether a base tag is in effect. - FM */ - if ((B_inBASE) && - (temp = HTParse(href, base_href, PARSE_ALL)) && + if ((me->inBASE && *href != '#') && + (temp = HTParse(href, me->base_href, PARSE_ALL)) && *temp != '\0') /* * Use reference related to the base. @@ -3215,27 +2802,28 @@ PRIVATE void HTML_start_element ARGS5( /* * Check whether to fill in localhost. - FM */ - HTMLFillLocalFileURL((char **)&href, - (B_inBASE ? - base_href : me->node_anchor->address)); + LYFillLocalFileURL((char **)&href, + ((*href != '#' && + me->inBASE) ? + me->base_href : me->node_anchor->address)); - if ((B_CurrentA = HTAnchor_findChildAndLink( + if ((me->CurrentA = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ NULL, /* Tag */ href, /* Addresss */ (void *)0))) { /* Type */ - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); HTML_put_string(me, (present[HTML_FIG_ISOBJECT] ? (present[HTML_FIG_IMAGEMAP] ? "(IMAGE)" : "(OBJECT)") : "[FIGURE]")); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); HText_endAnchor(me->text); HText_appendCharacter(me->text, '-'); - HTML_put_character(me, ' '); /* space char may be ignored */ + HTML_put_character(me, ' '); /* space char may be ignored */ me->in_word = NO; } } @@ -3366,22 +2954,17 @@ PRIVATE void HTML_start_element ARGS5( break; case HTML_OVERLAY: - if (clickable_images && B_inFIG && + if (clickable_images && me->inFIG && present && present[HTML_OVERLAY_SRC] && value[HTML_OVERLAY_SRC] && *value[HTML_OVERLAY_SRC] != '\0') { StrAllocCopy(href, value[HTML_OVERLAY_SRC]); - convert_to_spaces(href); - LYUnEscapeToLatinOne(&href, TRUE); + url_type = LYLegitimizeHREF(me, (char**)&href, TRUE); if (*href) { - url_type = is_url(href); - if (!url_type && *href != '/') - HTSimplify(href); - /* * Check whether a base tag is in effect. - FM */ - if ((B_inBASE) && - (temp = HTParse(href, base_href, PARSE_ALL)) && + if ((me->inBASE && *href != '#') && + (temp = HTParse(href, me->base_href, PARSE_ALL)) && *temp != '\0') /* * Use reference related to the base. @@ -3392,11 +2975,12 @@ PRIVATE void HTML_start_element ARGS5( /* * Check whether to fill in localhost. - FM */ - HTMLFillLocalFileURL((char **)&href, - (B_inBASE ? - base_href : me->node_anchor->address)); + LYFillLocalFileURL((char **)&href, + ((*href != '#' && + me->inBASE) ? + me->base_href : me->node_anchor->address)); - if ((B_CurrentA = HTAnchor_findChildAndLink( + if ((me->CurrentA = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ NULL, /* Tag */ href, /* Addresss */ @@ -3407,12 +2991,12 @@ PRIVATE void HTML_start_element ARGS5( HTML_put_character(me, ' '); HText_appendCharacter(me->text, '+'); } - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); HTML_put_string(me, "[OVERLAY]"); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); HText_endAnchor(me->text); HTML_put_character(me, ' '); me->in_word = NO; @@ -3423,8 +3007,8 @@ PRIVATE void HTML_start_element ARGS5( break; case HTML_APPLET: - B_inAPPLET = TRUE; - B_inAPPLETwithP = FALSE; + me->inAPPLET = TRUE; + me->inAPPLETwithP = FALSE; if (!me->text) UPDATE_STYLE; HTML_put_character(me, ' '); /* space char may be ignored */ @@ -3440,7 +3024,7 @@ PRIVATE void HTML_start_element ARGS5( } if (id_string) { LYUnEscapeToLatinOne(&id_string, TRUE); - HTML_HandleID(me, id_string); + LYHandleID(me, id_string); FREE(id_string); } me->in_word = NO; @@ -3459,7 +3043,7 @@ PRIVATE void HTML_start_element ARGS5( * Convert any HTML entities or decimal escaping. - FM */ LYUnEscapeEntities(alt_string, - LYUsePlainSpace, LYHiddenValue); + me->UsePlainSpace, me->HiddenValue); /* * If it's all spaces and we are making sources links, * treat it as zero-length. - FM @@ -3493,7 +3077,7 @@ PRIVATE void HTML_start_element ARGS5( if (present[HTML_APPLET_CODEBASE] && value[HTML_APPLET_CODEBASE] && *value[HTML_APPLET_CODEBASE]) { StrAllocCopy(base, value[HTML_APPLET_CODEBASE]); - convert_to_spaces(base); + collapse_spaces(base); LYUnEscapeToLatinOne(&base, TRUE); /* * Force it to be a directory. - FM @@ -3502,27 +3086,21 @@ PRIVATE void HTML_start_element ARGS5( StrAllocCopy(base, "/"); if (base[strlen(base)-1] != '/') StrAllocCat(base, "/"); - url_type = is_url(base); - - /* - * Don't simplify absolute CODEBASEs. - FM - */ - if (!url_type && *base != '/') - HTSimplify(base); + url_type = LYLegitimizeHREF(me, (char**)&base, TRUE); /* * Check whether to fill in localhost. - FM */ - HTMLFillLocalFileURL((char **)&base, - (B_inBASE ? base_href : - me->node_anchor->address)); + LYFillLocalFileURL((char **)&base, + (me->inBASE ? + me->base_href : me->node_anchor->address)); if (!(url_type = is_url(base))) { /* * Check whether a base tag is in effect. */ - if (B_inBASE) { - temp = HTParse(base, base_href, PARSE_ALL); + if (me->inBASE) { + temp = HTParse(base, me->base_href, PARSE_ALL); } else { temp = HTParse(base, me->node_anchor->address, PARSE_ALL); @@ -3531,33 +3109,31 @@ PRIVATE void HTML_start_element ARGS5( FREE(temp); } } else { - if (B_inBASE) { - StrAllocCopy(base, base_href); + if (me->inBASE) { + StrAllocCopy(base, me->base_href); } else { StrAllocCopy(base, me->node_anchor->address); } } StrAllocCopy(code, value[HTML_APPLET_CODE]); - convert_to_spaces(code); - LYUnEscapeToLatinOne(&code, TRUE); - HTSimplify(code); + url_type = LYLegitimizeHREF(me, (char**)&code, TRUE); href = HTParse(code, base, PARSE_ALL); FREE(base); FREE(code); if ((href && *href) && - (B_CurrentA = HTAnchor_findChildAndLink( + (me->CurrentA = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ NULL, /* Tag */ href, /* Addresss */ (void *)0))) { /* Type */ - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); HTML_put_string(me, alt_string); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); HText_endAnchor(me->text); HTML_put_character(me, ' '); /* space char may be ignored */ me->in_word = NO; @@ -3582,21 +3158,17 @@ PRIVATE void HTML_start_element ARGS5( if (clickable_images && present && present[HTML_BGSOUND_SRC] && value[HTML_BGSOUND_SRC] && *value[HTML_BGSOUND_SRC] != '\0') { StrAllocCopy(href, value[HTML_BGSOUND_SRC]); - convert_to_spaces(href); - LYUnEscapeToLatinOne(&href, TRUE); + url_type = LYLegitimizeHREF(me, (char**)&href, TRUE); if (*href == '\0') { FREE(href); break; } - url_type = is_url(href); - if (!url_type && *href != '/') - HTSimplify(href); /* * Check whether a base tag is in effect. - FM */ - if ((B_inBASE) && - (temp = HTParse(href, base_href, PARSE_ALL)) && + if ((me->inBASE && *href != '#') && + (temp = HTParse(href, me->base_href, PARSE_ALL)) && *temp != '\0') /* * Use reference related to the base. @@ -3607,25 +3179,26 @@ PRIVATE void HTML_start_element ARGS5( /* * Check whether to fill in localhost. - FM */ - HTMLFillLocalFileURL((char **)&href, - (B_inBASE ? base_href : - me->node_anchor->address)); + LYFillLocalFileURL((char **)&href, + ((*href != '#' && + me->inBASE) ? + me->base_href : me->node_anchor->address)); if (!me->text) UPDATE_STYLE; - if ((B_CurrentA = HTAnchor_findChildAndLink( + if ((me->CurrentA = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ NULL, /* Tag */ href, /* Addresss */ (void *)0))) { /* Type */ HTML_put_character(me, ' '); /* space char may be ignored */ me->in_word = NO; - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); HTML_put_string(me, "[BGSOUND]"); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); HText_endAnchor(me->text); HTML_put_character(me, ' '); /* space char may be ignored */ me->in_word = NO; @@ -3651,7 +3224,7 @@ PRIVATE void HTML_start_element ARGS5( } if (id_string) { LYUnEscapeToLatinOne(&id_string, TRUE); - HTML_HandleID(me, id_string); + LYHandleID(me, id_string); FREE(id_string); } if (pseudo_inline_alts || clickable_images) @@ -3671,7 +3244,7 @@ PRIVATE void HTML_start_element ARGS5( * Convert any HTML entities or decimal escaping. - FM */ LYUnEscapeEntities(alt_string, - LYUsePlainSpace, LYHiddenValue); + me->UsePlainSpace, me->HiddenValue); /* * If it's all spaces and we are making sources links, * treat it as zero-length. - FM @@ -3696,18 +3269,13 @@ PRIVATE void HTML_start_element ARGS5( if (clickable_images && present && present[HTML_EMBED_SRC] && value[HTML_EMBED_SRC] && *value[HTML_EMBED_SRC] != '\0') { StrAllocCopy(href, value[HTML_EMBED_SRC]); - convert_to_spaces(href); - LYUnEscapeToLatinOne(&href, TRUE); + url_type = LYLegitimizeHREF(me, (char**)&href, TRUE); if (*href != '\0') { - url_type = is_url(href); - if (!url_type && *href != '/') - HTSimplify(href); - /* * Check whether a base tag is in effect. - FM */ - if ((B_inBASE) && - (temp = HTParse(href, base_href, PARSE_ALL)) && + if ((me->inBASE && *href != '#') && + (temp = HTParse(href, me->base_href, PARSE_ALL)) && *temp != '\0') /* * Use reference related to the base. @@ -3718,21 +3286,22 @@ PRIVATE void HTML_start_element ARGS5( /* * Check whether to fill in localhost. - FM */ - HTMLFillLocalFileURL((char **)&href, - (B_inBASE ? - base_href : me->node_anchor->address)); + LYFillLocalFileURL((char **)&href, + ((*href != '#' && + me->inBASE) ? + me->base_href : me->node_anchor->address)); - if ((B_CurrentA = HTAnchor_findChildAndLink( + if ((me->CurrentA = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ NULL, /* Tag */ href, /* Addresss */ (void *)0))) { /* Type */ - HText_beginAnchor(me->text, B_CurrentA); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); HTML_put_string(me, alt_string); - if (B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); HText_endAnchor(me->text); HTML_put_character(me, ' '); me->in_word = NO; @@ -3754,67 +3323,67 @@ PRIVATE void HTML_start_element ARGS5( case HTML_CREDIT: if (!me->text) UPDATE_STYLE; - HTML_EnsureDoubleSpace(me); - HTML_ResetParagraphAlignment(me); - B_inCREDIT = TRUE; - HTML_CheckForID(me, present, value, (int)HTML_CREDIT_ID); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); + LYEnsureDoubleSpace(me); + LYResetParagraphAlignment(me); + me->inCREDIT = TRUE; + LYCheckForID(me, present, value, (int)HTML_CREDIT_ID); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); HTML_put_string(me, "CREDIT:"); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); HTML_put_character(me, ' '); - if (B_inFIG) + if (me->inFIG) /* * Assume all text in the FIG container is intended * to be paragraphed. - FM */ - B_inFIGwithP = TRUE; + me->inFIGwithP = TRUE; - if (B_inAPPLET) + if (me->inAPPLET) /* * Assume all text in the APPLET container is intended * to be paragraphed. - FM */ - B_inAPPLETwithP = TRUE; + me->inAPPLETwithP = TRUE; - B_inLABEL = TRUE; + me->inLABEL = TRUE; me->in_word = NO; - B_inP = FALSE; + me->inP = FALSE; break; case HTML_CAPTION: if (!me->text) UPDATE_STYLE; - HTML_EnsureDoubleSpace(me); - HTML_ResetParagraphAlignment(me); - B_inCAPTION = TRUE; - HTML_CheckForID(me, present, value, (int)HTML_CAPTION_ID); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); + LYEnsureDoubleSpace(me); + LYResetParagraphAlignment(me); + me->inCAPTION = TRUE; + LYCheckForID(me, present, value, (int)HTML_CAPTION_ID); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); HTML_put_string(me, "CAPTION:"); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); HTML_put_character(me, ' '); - if (B_inFIG) + if (me->inFIG) /* * Assume all text in the FIG container is intended * to be paragraphed. - FM */ - B_inFIGwithP = TRUE; + me->inFIGwithP = TRUE; - if (B_inAPPLET) + if (me->inAPPLET) /* * Assume all text in the APPLET container is intended * to be paragraphed. - FM */ - B_inAPPLETwithP = TRUE; + me->inAPPLETwithP = TRUE; - B_inLABEL = TRUE; + me->inLABEL = TRUE; me->in_word = NO; - B_inP = FALSE; + me->inP = FALSE; break; case HTML_FORM: @@ -3822,14 +3391,13 @@ PRIVATE void HTML_start_element ARGS5( char * action = NULL; char * method = NULL; char * enctype = NULL; - char * cp; HTChildAnchor * source; HTAnchor *link_dest; /* * Set to know we are in a form. */ - B_inFORM = TRUE; + me->inFORM = TRUE; UPDATE_STYLE; if (present && present[HTML_FORM_ACTION] && @@ -3838,30 +3406,34 @@ PRIVATE void HTML_start_element ARGS5( * Prepare to do housekeeping on the reference. - FM */ StrAllocCopy(action, value[HTML_FORM_ACTION]); - convert_to_spaces(action); - LYUnEscapeToLatinOne(&action, TRUE); - url_type = is_url(action); + url_type = LYLegitimizeHREF(me, (char**)&action, TRUE); /* - * Don't simplify absolute ACTIONs. - FM - */ - if (!url_type && *action != '/' && *action != '\0') - HTSimplify(action); - /* * Check whether a base tag is in effect. */ - if ((B_inBASE) && - (temp = HTParse(action, base_href, PARSE_ALL)) && - *temp != '\0') + if ((me->inBASE && *action != '\0' && *action != '#') && + (temp = HTParse(action, me->base_href, PARSE_ALL)) && + *temp != '\0') { /* * Use action related to the base. */ StrAllocCopy(action, temp); + } else if ((temp = HTParse(action, + me->node_anchor->address, + PARSE_ALL)) && + *temp != '\0') { + /* + * Use action related to the current document. + */ + StrAllocCopy(action, temp); + } else { + FREE(action); + } FREE(temp); } if (!(action && *action)) { - if (B_inBASE && base_href && *base_href) { - StrAllocCopy(action, base_href); + if (me->inBASE && me->base_href && *me->base_href) { + StrAllocCopy(action, me->base_href); } else { StrAllocCopy(action, me->node_anchor->address); } @@ -3938,31 +3510,37 @@ PRIVATE void HTML_start_element ARGS5( } if (!me->text) UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_FORM_ID); + LYCheckForID(me, present, value, (int)HTML_FORM_ID); break; case HTML_FIELDSET: - HTML_CheckForID(me, present, value, (int)HTML_FIELDSET_ID); + LYCheckForID(me, present, value, (int)HTML_FIELDSET_ID); break; case HTML_LABEL: - HTML_CheckForID(me, present, value, (int)HTML_LABEL_ID); + LYCheckForID(me, present, value, (int)HTML_LABEL_ID); + break; + + case HTML_KEYGEN: + LYCheckForID(me, present, value, (int)HTML_KEYGEN_ID); break; case HTML_INPUT: { InputFieldData I; int chars; + BOOL UseALTasVALUE = FALSE; + BOOL HaveSRClink = FALSE; /* * Make sure we're in a form. */ - if (!B_inFORM) { + if (!me->inFORM) { if (TRACE) { fprintf(stderr, "HTML: INPUT tag not within FORM tag\n"); - } else if (!B_inBadHTML) { + } else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); - B_inBadHTML = TRUE; + me->inBadHTML = TRUE; sleep(MessageSecs); } /* @@ -3974,12 +3552,12 @@ PRIVATE void HTML_start_element ARGS5( } /* Check for unclosed TEXTAREA */ - if (B_inTEXTAREA) { + if (me->inTEXTAREA) { if (TRACE) { fprintf(stderr, "HTML: Missing TEXTAREA end tag\n"); - } else if (!B_inBadHTML) { + } else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); - B_inBadHTML = TRUE; + me->inBadHTML = TRUE; sleep(MessageSecs); } } @@ -4027,12 +3605,12 @@ PRIVATE void HTML_start_element ARGS5( /* * Not yet implemented. */ - if (B_inUnderline == FALSE) { + if (me->inUnderline == FALSE) { HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); } HTML_put_string(me,"[FILE Input] (Not yet implemented.)"); - if (B_inUnderline == FALSE) { + if (me->inUnderline == FALSE) { HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); } @@ -4042,8 +3620,75 @@ PRIVATE void HTML_start_element ARGS5( break; } } - if (present && present[HTML_INPUT_VALUE] && - value[HTML_INPUT_VALUE] && *value[HTML_INPUT_VALUE]) { + if ((present && present[HTML_INPUT_ALT] && + value[HTML_INPUT_ALT] && *value[HTML_INPUT_ALT] && + I.type && !strcasecomp(I.type, "image")) && + !(present && present[HTML_INPUT_VALUE] && + value[HTML_INPUT_VALUE] && *value[HTML_INPUT_VALUE])) { + /* + * This is a TYPE="image" using an ALT rather than + * VALUE attribute to indicate the link string for + * text clients or GUIs with image loading off, so + * set the flag to use that at if it were a VALUE + * attribute. - FM + */ + UseALTasVALUE = TRUE; + } + if (clickable_images == TRUE && + present && present[HTML_INPUT_SRC] && + value[HTML_INPUT_SRC] && *value[HTML_INPUT_SRC] && + I.type && !strcasecomp(I.type, "image")) { + StrAllocCopy(href, (char *)value[HTML_INPUT_SRC]); + /* + * We have a TYPE="image" with a non-zero-length SRC + * attribute and want clickable images. Make the + * SRC's value a link if it's still not zero-length + * legitiimizing it. - FM + */ + url_type = LYLegitimizeHREF(me, (char**)&href, TRUE); + if (*href) { + /* + * Check whether a base tag is in effect. - FM + */ + if ((me->inBASE && *href != '#') && + (temp = HTParse(href, me->base_href, PARSE_ALL)) && + *temp != '\0') + /* + * Use reference related to the base. + */ + StrAllocCopy(href, temp); + FREE(temp); + + /* + * Check whether to fill in localhost. - FM + */ + LYFillLocalFileURL((char **)&href, + ((*href != '#' && + me->inBASE) ? + me->base_href : + me->node_anchor->address)); + + if ((me->CurrentA = HTAnchor_findChildAndLink( + me->node_anchor, /* Parent */ + NULL, /* Tag */ + href, /* Addresss */ + (void *)0))) { /* Type */ + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); + HTML_put_string(me, "[IMAGE]"); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); + HText_endAnchor(me->text); + HText_appendCharacter(me->text, '-'); + } + HaveSRClink = TRUE; + } + FREE(href); + } + if ((UseALTasVALUE == TRUE) || + (present && present[HTML_INPUT_VALUE] && + value[HTML_INPUT_VALUE] && *value[HTML_INPUT_VALUE])) { /* * Convert any HTML entities or decimal escaping. - FM */ @@ -4054,24 +3699,31 @@ PRIVATE void HTML_start_element ARGS5( int len; if (I.type && !strcasecomp(I.type, "hidden")) { - LYHiddenValue = TRUE; + me->HiddenValue = TRUE; current_char_set = 0; /* Default ISO-Latin1 */ LYUseDefaultRawMode = TRUE; HTMLSetCharacterHandling(current_char_set); } if (!I.type) - LYUsePlainSpace = TRUE; + me->UsePlainSpace = TRUE; else if (!strcasecomp(I.type, "text") || !strcasecomp(I.type, "submit") || + !strcasecomp(I.type, "image") || !strcasecomp(I.type, "reset")) - LYUsePlainSpace = TRUE; - if (current_char_set && LYUsePlainSpace) - LYExpandString((char**)&value[HTML_INPUT_VALUE]); - LYUnEscapeEntities((char *)value[HTML_INPUT_VALUE], - LYUsePlainSpace, LYHiddenValue); - I.value = (char *)value[HTML_INPUT_VALUE]; - if (LYUsePlainSpace == TRUE) { + me->UsePlainSpace = TRUE; + if (current_char_set && me->UsePlainSpace) + LYExpandString(((UseALTasVALUE == TRUE) ? + (char **)&value[HTML_INPUT_ALT] : + (char **)&value[HTML_INPUT_VALUE])); + LYUnEscapeEntities(((UseALTasVALUE == TRUE) ? + (char *)value[HTML_INPUT_ALT] : + (char *)value[HTML_INPUT_VALUE]), + me->UsePlainSpace, me->HiddenValue); + I.value = ((UseALTasVALUE == TRUE) ? + (char *)value[HTML_INPUT_ALT] : + (char *)value[HTML_INPUT_VALUE]); + if (me->UsePlainSpace == TRUE) { /* * Convert any newlines or tabs to spaces, * and trim any lead or trailing spaces. - FM @@ -4083,17 +3735,25 @@ PRIVATE void HTML_start_element ARGS5( while (len > 0 && I.value[len] == ' ') I.value[len--] = '\0'; } - LYUsePlainSpace = FALSE; + me->UsePlainSpace = FALSE; if (I.type && !strcasecomp(I.type, "hidden")) { - LYHiddenValue = FALSE; + me->HiddenValue = FALSE; current_char_set = CurrentCharSet; LYUseDefaultRawMode = CurrentUseDefaultRawMode; HTMLSetCharacterHandling(current_char_set); HTPassEightBitRaw = CurrentEightBitRaw; HTCJK = CurrentHTCJK; } + } else if (HaveSRClink == TRUE) { + /* + * We put up an [IMAGE] link and '-' for a TYPE="image" + * and didn't get a VALUE or ALT string, so fake a + * "Submit" value. If we didn't put up a link, then + * HText_beginInput() will use "[IMAGE]-Submit". - FM + */ + I.value = "Submit"; } if (present && present[HTML_INPUT_CHECKED]) I.checked = YES; @@ -4124,7 +3784,7 @@ PRIVATE void HTML_start_element ARGS5( if (present && present[HTML_INPUT_ID] && value[HTML_INPUT_ID] && *value[HTML_INPUT_ID]) { I.id = (char *)value[HTML_INPUT_ID]; - HTML_CheckForID(me, present, value, (int)HTML_INPUT_ID); + LYCheckForID(me, present, value, (int)HTML_INPUT_ID); } if (present && present[HTML_INPUT_LANG] && /* Not yet used. */ value[HTML_INPUT_LANG] && *value[HTML_INPUT_LANG]) @@ -4132,9 +3792,6 @@ PRIVATE void HTML_start_element ARGS5( if (present && present[HTML_INPUT_MD] && /* Not yet used. */ value[HTML_INPUT_MD] && *value[HTML_INPUT_MD]) I.md = (char *)value[HTML_INPUT_MD]; - if (present && present[HTML_INPUT_SRC] && /* Not yet used. */ - value[HTML_INPUT_MD] && *value[HTML_INPUT_MD]) - I.src = (char *)value[HTML_INPUT_SRC]; /* Should be resolved. */ chars = HText_beginInput(me->text, &I); if (me->sp[0].tag_number == HTML_PRE && chars > 20) { @@ -4143,16 +3800,15 @@ PRIVATE void HTML_start_element ARGS5( * We'll put up a minimum of 20 underscores, and if any * more would exceed the wrap column, we'll ignore them. */ - int i; for (i = 0; i < 20; i++) { HTML_put_character(me, '_'); chars--; } - ignore_excess = TRUE; + HText_setIgnoreExcess(me->text, TRUE); } for (; chars > 0; chars--) HTML_put_character(me, '_'); - ignore_excess = FALSE; + HText_setIgnoreExcess(me->text, FALSE); } break; @@ -4160,13 +3816,13 @@ PRIVATE void HTML_start_element ARGS5( /* * Make sure we're in a form. */ - if (!B_inFORM) { + if (!me->inFORM) { if (TRACE) { fprintf(stderr, "HTML: TEXTAREA start tag not within FORM tag\n"); - } else if (!B_inBadHTML) { + } else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); - B_inBadHTML = TRUE; + me->inBadHTML = TRUE; sleep(MessageSecs); } /* @@ -4178,7 +3834,7 @@ PRIVATE void HTML_start_element ARGS5( /* * Set to know we are in a textarea. */ - B_inTEXTAREA = TRUE; + me->inTEXTAREA = TRUE; /* * Get ready for the value. @@ -4186,50 +3842,50 @@ PRIVATE void HTML_start_element ARGS5( HTChunkClear(&me->textarea); if (present && present[HTML_TEXTAREA_NAME] && value[HTML_TEXTAREA_NAME]) - StrAllocCopy(textarea_name, value[HTML_TEXTAREA_NAME]); + StrAllocCopy(me->textarea_name, value[HTML_TEXTAREA_NAME]); else - StrAllocCopy(textarea_name, ""); + StrAllocCopy(me->textarea_name, ""); if (present && present[HTML_TEXTAREA_COLS] && value[HTML_TEXTAREA_COLS] && isdigit((unsigned char)*value[HTML_TEXTAREA_COLS])) - StrAllocCopy(textarea_cols, value[HTML_TEXTAREA_COLS]); + StrAllocCopy(me->textarea_cols, value[HTML_TEXTAREA_COLS]); else - StrAllocCopy(textarea_cols, "60"); + StrAllocCopy(me->textarea_cols, "60"); if (present && present[HTML_TEXTAREA_ROWS] && value[HTML_TEXTAREA_ROWS] && isdigit((unsigned char)*value[HTML_TEXTAREA_ROWS])) - textarea_rows = atoi(value[HTML_TEXTAREA_ROWS]); + me->textarea_rows = atoi(value[HTML_TEXTAREA_ROWS]); else - textarea_rows = 4; + me->textarea_rows = 4; if (present && present[HTML_TEXTAREA_DISABLED]) - textarea_disabled = YES; + me->textarea_disabled = YES; else - textarea_disabled = NO; + me->textarea_disabled = NO; if (present && present[HTML_TEXTAREA_ID] && value[HTML_TEXTAREA_ID] && *value[HTML_TEXTAREA_ID]) { StrAllocCopy(id_string, value[HTML_TEXTAREA_ID]); LYUnEscapeToLatinOne(&id_string, TRUE); if ((id_string != '\0') && - (B_ID_A = HTAnchor_findChildAndLink( + (ID_A = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ id_string, /* Tag */ NULL, /* Addresss */ (void *)0))) { /* Type */ if (!me->text) UPDATE_STYLE; - HText_beginAnchor(me->text, B_ID_A); + HText_beginAnchor(me->text, ID_A); HText_endAnchor(me->text); - StrAllocCopy(textarea_id, id_string); + StrAllocCopy(me->textarea_id, id_string); } else { - FREE(textarea_id); + FREE(me->textarea_id); } FREE(id_string); } else { - FREE(textarea_id); + FREE(me->textarea_id); } break; @@ -4242,18 +3898,18 @@ PRIVATE void HTML_start_element ARGS5( /* * Initialize the disable attribute. */ - select_disabled = NO; + me->select_disabled = FALSE; /* * Make sure we're in a form. */ - if (!B_inFORM) { + if (!me->inFORM) { if (TRACE) { fprintf(stderr, "HTML: SELECT start tag not within FORM tag\n"); - } else if (!B_inBadHTML) { + } else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); - B_inBadHTML = TRUE; + me->inBadHTML = TRUE; sleep(MessageSecs); } @@ -4266,12 +3922,12 @@ PRIVATE void HTML_start_element ARGS5( /* * Check for unclosed TEXTAREA. */ - if (B_inTEXTAREA) { + if (me->inTEXTAREA) { if (TRACE) { fprintf(stderr, "HTML: Missing TEXTAREA end tag\n"); - } else if (!B_inBadHTML) { + } else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); - B_inBadHTML = TRUE; + me->inBadHTML = TRUE; sleep(MessageSecs); } } @@ -4279,7 +3935,7 @@ PRIVATE void HTML_start_element ARGS5( /* * Set to know we are in a select tag. */ - B_inSELECT = TRUE; + me->inSELECT = TRUE; if (!me->text) UPDATE_STYLE; @@ -4291,7 +3947,7 @@ PRIVATE void HTML_start_element ARGS5( if (present && present[HTML_SELECT_MULTIPLE]) multiple=YES; if (present && present[HTML_SELECT_DISABLED]) - select_disabled=YES; + me->select_disabled = TRUE; if (present && present[HTML_SELECT_SIZE] && value[HTML_SELECT_SIZE] && *value[HTML_SELECT_SIZE]) { #ifdef NOTDEFINED @@ -4307,19 +3963,19 @@ PRIVATE void HTML_start_element ARGS5( #endif /* NOTDEFINED */ } - if (B_inBoldH == TRUE && + if (me->inBoldH == TRUE && (multiple == NO || LYSelectPopups == FALSE)) { - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); - B_inBoldH = FALSE; - B_needBoldH = TRUE; + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); + me->inBoldH = FALSE; + me->needBoldH = TRUE; } - if (B_inUnderline == TRUE && + if (me->inUnderline == TRUE && (multiple == NO || LYSelectPopups == FALSE)) { - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); - B_inUnderline = FALSE; + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + me->inUnderline = FALSE; } - HTML_CheckForID(me, present, value, (int)HTML_SELECT_ID); + LYCheckForID(me, present, value, (int)HTML_SELECT_ID); HText_beginSelect(name, multiple, size); FREE(name); @@ -4335,18 +3991,17 @@ PRIVATE void HTML_start_element ARGS5( * An option is a special case of an input field. */ InputFieldData I; - int i; /* * Make sure we're in a select tag. */ - if (!B_inSELECT) { + if (!me->inSELECT) { if (TRACE) { fprintf(stderr, "HTML: OPTION tag not within SELECT tag\n"); - } else if (!B_inBadHTML) { + } else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); - B_inBadHTML = TRUE; + me->inBadHTML = TRUE; sleep(MessageSecs); } @@ -4368,8 +4023,10 @@ PRIVATE void HTML_start_element ARGS5( * Finish the previous option @@@@@ */ HText_setLastOptionValue(me->text, - me->option.data, LastOptionValue, - MIDDLE_ORDER, LastOptionChecked); + me->option.data, + me->LastOptionValue, + MIDDLE_ORDER, + me->LastOptionChecked); } /* @@ -4385,7 +4042,7 @@ PRIVATE void HTML_start_element ARGS5( /* * Start a newline before each option. */ - HTML_EnsureSingleSpace(me); + LYEnsureSingleSpace(me); } else { /* * Add option list designation character. @@ -4426,7 +4083,7 @@ PRIVATE void HTML_start_element ARGS5( HTMLSetCharacterHandling(current_char_set); } LYUnEscapeEntities((char *)value[HTML_OPTION_VALUE], - LYUsePlainSpace, LYHiddenValue); + me->UsePlainSpace, me->HiddenValue); if (CurrentCharSet) { current_char_set = CurrentCharSet; LYUseDefaultRawMode = CurrentUseDefaultRawMode; @@ -4438,18 +4095,18 @@ PRIVATE void HTML_start_element ARGS5( I.value = (char *)value[HTML_OPTION_VALUE]; } - if (select_disabled || + if (me->select_disabled || (present && present[HTML_OPTION_DISABLED])) I.disabled=YES; if (present && present[HTML_OPTION_ID] && value[HTML_OPTION_ID] && *value[HTML_OPTION_ID]) { - if (B_ID_A = HTAnchor_findChildAndLink( + if (ID_A = HTAnchor_findChildAndLink( me->node_anchor, /* Parent */ value[HTML_OPTION_ID], /* Tag */ NULL, /* Addresss */ (void *)0)) { /* Type */ - HText_beginAnchor(me->text, B_ID_A); + HText_beginAnchor(me->text, ID_A); HText_endAnchor(me->text); I.id = (char *)value[HTML_OPTION_ID]; } @@ -4476,24 +4133,24 @@ PRIVATE void HTML_start_element ARGS5( if ((present && present[HTML_OPTION_SELECTED]) || (first_option && LYSelectPopups == FALSE && HTCurSelectGroupType == F_RADIO_TYPE)) - LastOptionChecked = TRUE; + me->LastOptionChecked = TRUE; else - LastOptionChecked = FALSE; + me->LastOptionChecked = FALSE; first_option = FALSE; if (present && present[HTML_OPTION_VALUE] && value[HTML_OPTION_VALUE]) - StrAllocCopy(LastOptionValue, value[HTML_OPTION_VALUE]); + StrAllocCopy(me->LastOptionValue, value[HTML_OPTION_VALUE]); else - StrAllocCopy(LastOptionValue, me->option.data); + StrAllocCopy(me->LastOptionValue, me->option.data); } break; case HTML_TABLE: UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_TABLE_ID); - B_inTABLE = TRUE; + LYCheckForID(me, present, value, (int)HTML_TABLE_ID); + me->inTABLE = TRUE; break; case HTML_TR: @@ -4505,7 +4162,7 @@ PRIVATE void HTML_start_element ARGS5( if (HText_LastLineSize(me->text)) { HText_appendCharacter(me->text, '\r'); } - HTML_CheckForID(me, present, value, (int)HTML_TR_ID); + LYCheckForID(me, present, value, (int)HTML_TR_ID); me->in_word = NO; break; @@ -4516,7 +4173,7 @@ PRIVATE void HTML_start_element ARGS5( * Not yet implemented. Just check for an ID link. - FM */ UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_TR_ID); + LYCheckForID(me, present, value, (int)HTML_TR_ID); break; case HTML_COL: @@ -4525,12 +4182,12 @@ PRIVATE void HTML_start_element ARGS5( * Not yet implemented. Just check for an ID link. - FM */ UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_COL_ID); + LYCheckForID(me, present, value, (int)HTML_COL_ID); break; case HTML_TH: UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_TD_ID); + LYCheckForID(me, present, value, (int)HTML_TD_ID); /* * Not yet implemented. Just add a collapsible space and break. - FM */ @@ -4540,7 +4197,7 @@ PRIVATE void HTML_start_element ARGS5( case HTML_TD: UPDATE_STYLE; - HTML_CheckForID(me, present, value, (int)HTML_TD_ID); + LYCheckForID(me, present, value, (int)HTML_TD_ID); /* * Not yet implemented. Just add a collapsible space and break. - FM */ @@ -4556,7 +4213,7 @@ PRIVATE void HTML_start_element ARGS5( if (!me->text) UPDATE_STYLE; HTChunkClear(&me->math); - HTML_CheckForID(me, present, value, (int)HTML_GEN_ID); + LYCheckForID(me, present, value, (int)HTML_GEN_ID); break; default: @@ -4601,8 +4258,8 @@ PRIVATE void HTML_end_element ARGS3( int, element_number, char **, include) { - int i; - char *temp = NULL; + int i = 0; + char *temp = NULL, *cp = NULL; #ifdef CAREFUL /* parser assumed to produce good nesting */ if (element_number != me->sp[0].tag_number) { @@ -4642,12 +4299,12 @@ PRIVATE void HTML_end_element ARGS3( /* * Check for unclosed TEXTAREA. - FM */ - if (B_inTEXTAREA && element_number != HTML_TEXTAREA) + if (me->inTEXTAREA && element_number != HTML_TEXTAREA) if (TRACE) { fprintf(stderr, "HTML: Missing TEXTAREA end tag\n"); - } else if (!B_inBadHTML) { + } else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); - B_inBadHTML = TRUE; + me->inBadHTML = TRUE; sleep(MessageSecs); } @@ -4657,44 +4314,35 @@ PRIVATE void HTML_end_element ARGS3( switch(element_number) { case HTML_HTML: - List_Nesting_Level = -1; - HTML_zero_OL_Counter(); - Division_Level = -1; - Underline_Level = 0; - Quote_Level = 0; - if (B_inUnderline) { + if (me->inUnderline) { if (!me->text) UPDATE_STYLE; - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); - B_inUnderline = FALSE; + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + me->inUnderline = FALSE; } - if (B_inA || B_inFORM || B_inSELECT || B_inTEXTAREA) + if (me->inA || me->inFORM || me->inSELECT || me->inTEXTAREA) if (TRACE) fprintf(stderr, "HTML: Something not closed before HTML close-tag\n"); - else if (!B_inBadHTML) { + else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); } break; case HTML_HEAD: - List_Nesting_Level = -1; - HTML_zero_OL_Counter(); - Division_Level = -1; - Underline_Level = 0; - Quote_Level = 0; - if (B_inUnderline) { - if (!me->text) - UPDATE_STYLE; - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); - B_inUnderline = FALSE; + UPDATE_STYLE; + if (me->inUnderline) { + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + me->inUnderline = FALSE; } + if (HText_hasToolbar(me->text)) + HText_appendParagraph(me->text); break; #ifdef NOT_DEFINED /* BASE will be a container in HTML+ */ case HTML_BASE: - FREE(base_href); - B_inBASE = FALSE; + FREE(me->base_href); + me->inBASE = FALSE; break; #endif /* NOT_DEFINED */ @@ -4703,32 +4351,43 @@ PRIVATE void HTML_end_element ARGS3( HTAnchor_setTitle(me->node_anchor, me->title.data); HTChunkClear(&me->title); /* - * Check if it's a bookmark file, and if so, insert the - * current description string and filepath for it. - FM + * Check if it's a bookmark file, and if so, and multiple + * bookmark support is on, or it's off but this isn't the + * default bookmark file (e.g., because it was on before, + * and this is another bookmark file that has been retrieved + * as a previous document), insert the current description + * string and filepath for it. We pass the strings back to + * the SGML parser so that any 8 bit or multibyte/CJK + * characters will be handled by the parser's state and + * charset routines. - FM */ if (me->node_anchor->bookmark && *me->node_anchor->bookmark) { - for (i = 0; i <= MBM_V_MAXFILES; i++) { - if (MBM_A_subbookmark[i] && - !strcmp(MBM_A_subbookmark[i], - me->node_anchor->bookmark)) { - StrAllocCat(*include, "<H2><EM>Description:</EM> "); - StrAllocCopy(temp, - ((MBM_A_subdescript[i] && - *MBM_A_subdescript[i]) ? - MBM_A_subdescript[i] : "(none)")); - LYEntify((char **)&temp, TRUE); - StrAllocCat(*include, temp); - StrAllocCat(*include, - "<BR><EM> Filepath:</EM> "); - StrAllocCopy(temp, - ((MBM_A_subbookmark[i] && - *MBM_A_subbookmark[i]) ? - MBM_A_subbookmark[i] : "(unknown)")); - LYEntify((char **)&temp, TRUE); - StrAllocCat(*include, temp); - FREE(temp); - StrAllocCat(*include, "</H2>"); - break; + if ((LYMultiBookmarks == TRUE) || + ((bookmark_page && *bookmark_page) && + strcmp(me->node_anchor->bookmark, bookmark_page))) { + for (i = 0; i <= MBM_V_MAXFILES; i++) { + if (MBM_A_subbookmark[i] && + !strcmp(MBM_A_subbookmark[i], + me->node_anchor->bookmark)) { + StrAllocCat(*include, "<H2><EM>Description:</EM> "); + StrAllocCopy(temp, + ((MBM_A_subdescript[i] && + *MBM_A_subdescript[i]) ? + MBM_A_subdescript[i] : "(none)")); + LYEntify((char **)&temp, TRUE); + StrAllocCat(*include, temp); + StrAllocCat(*include, + "<BR><EM> Filepath:</EM> "); + StrAllocCopy(temp, + ((MBM_A_subbookmark[i] && + *MBM_A_subbookmark[i]) ? + MBM_A_subbookmark[i] : "(unknown)")); + LYEntify((char **)&temp, TRUE); + StrAllocCat(*include, temp); + FREE(temp); + StrAllocCat(*include, "</H2>"); + break; + } } } } @@ -4765,22 +4424,17 @@ PRIVATE void HTML_end_element ARGS3( break; case HTML_BODY: - List_Nesting_Level = -1; - HTML_zero_OL_Counter(); - Division_Level = -1; - Underline_Level = 0; - Quote_Level = 0; - if (B_inUnderline) { + if (me->inUnderline) { if (!me->text) UPDATE_STYLE; - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); - B_inUnderline = FALSE; + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + me->inUnderline = FALSE; } - if (B_inA || B_inFORM || B_inSELECT || B_inTEXTAREA) + if (me->inA || me->inFORM || me->inSELECT || me->inTEXTAREA) if (TRACE) fprintf(stderr, "HTML: Something not closed before BODY close-tag\n"); - else if (!B_inBadHTML) { + else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); } break; @@ -4794,8 +4448,8 @@ PRIVATE void HTML_end_element ARGS3( case HTML_NOFRAMES: if (!me->text) UPDATE_STYLE; - HTML_EnsureDoubleSpace(me); - HTML_ResetParagraphAlignment(me); + LYEnsureDoubleSpace(me); + LYResetParagraphAlignment(me); change_paragraph_style(me, me->sp->style); /* Often won't really change */ break; @@ -4811,20 +4465,23 @@ PRIVATE void HTML_end_element ARGS3( */ change_paragraph_style(me, me->sp->style); UPDATE_STYLE; - if (List_Nesting_Level >= 0) + if (me->sp->tag_number == element_number) + LYEnsureDoubleSpace(me); + if (me->List_Nesting_Level >= 0) HText_NegateLineOne(me->text); break; case HTML_CENTER: case HTML_DIV: - if (Division_Level >= 0) - Division_Level--; - if (Division_Level >= 0) - me->sp->style->alignment = DivisionAlignments[Division_Level]; + if (me->Division_Level >= 0) + me->Division_Level--; + if (me->Division_Level >= 0) + me->sp->style->alignment = + me->DivisionAlignments[me->Division_Level]; change_paragraph_style(me, me->sp->style); UPDATE_STYLE; - current_default_alignment = me->sp->style->alignment; - if (List_Nesting_Level >= 0) + me->current_default_alignment = me->sp->style->alignment; + if (me->List_Nesting_Level >= 0) HText_NegateLineOne(me->text); break; @@ -4834,22 +4491,30 @@ PRIVATE void HTML_end_element ARGS3( case HTML_H4: case HTML_H5: case HTML_H6: - if (Division_Level >= 0) { - me->sp->style->alignment = DivisionAlignments[Division_Level]; + if (me->Division_Level >= 0) { + me->sp->style->alignment = + me->DivisionAlignments[me->Division_Level]; + } else if (!strcmp(me->sp->style->name, "HeadingCenter") || + !strcmp(me->sp->style->name, "Heading1")) { + me->sp->style->alignment = HT_CENTER; + } else if (!strcmp(me->sp->style->name, "HeadingRight")) { + me->sp->style->alignment = HT_RIGHT; + } else { + me->sp->style->alignment = HT_LEFT; } change_paragraph_style(me, me->sp->style); UPDATE_STYLE; if (styles[element_number]->font & HT_BOLD) { - if (B_inBoldA == FALSE && B_inBoldH == TRUE) { - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (me->inBoldA == FALSE && me->inBoldH == TRUE) { + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); } - B_inBoldH = FALSE; + me->inBoldH = FALSE; } - if (List_Nesting_Level >= 0) + if (me->List_Nesting_Level >= 0) HText_NegateLineOne(me->text); - if (Underline_Level > 0 && B_inUnderline == FALSE) { - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); - B_inUnderline = TRUE; + if (me->Underline_Level > 0 && me->inUnderline == FALSE) { + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); + me->inUnderline = TRUE; } break; @@ -4868,16 +4533,16 @@ PRIVATE void HTML_end_element ARGS3( case HTML_STRONG: if (!me->text) UPDATE_STYLE; - if (Underline_Level > 0) - Underline_Level--; - if (B_inUnderline == TRUE && Underline_Level < 1) { - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); - B_inUnderline = FALSE; + if (me->Underline_Level > 0) + me->Underline_Level--; + if (me->inUnderline == TRUE && me->Underline_Level < 1) { + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + me->inUnderline = FALSE; if (TRACE) fprintf(stderr,"Ending underline\n"); } else { if (TRACE) - fprintf(stderr,"Underline Level is %d\n", Underline_Level); + fprintf(stderr,"Underline Level is %d\n", me->Underline_Level); } break; @@ -4903,11 +4568,11 @@ PRIVATE void HTML_end_element ARGS3( if (!me->text) UPDATE_STYLE; HTML_put_character(me, ' '); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); HTML_put_string(me, ":DEL]"); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); HTML_put_character(me, ' '); me->in_word = NO; break; @@ -4916,18 +4581,18 @@ PRIVATE void HTML_end_element ARGS3( if (!me->text) UPDATE_STYLE; HTML_put_character(me, ' '); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); HTML_put_string(me, ":INS]"); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); HTML_put_character(me, ' '); me->in_word = NO; break; case HTML_Q: - if (Quote_Level > 0) - Quote_Level--; + if (me->Quote_Level > 0) + me->Quote_Level--; /* * Should check LANG and/or DIR attributes, and the * me->node_anchor->charset and/or yet to be added @@ -4935,7 +4600,7 @@ PRIVATE void HTML_end_element ARGS3( * use chevrons, but for now we'll always use double- * or single-quotes. - FM */ - if (!(Quote_Level & 1)) + if (!(me->Quote_Level & 1)) HText_appendCharacter(me->text, '"'); else HText_appendCharacter(me->text, '\''); @@ -4956,25 +4621,27 @@ PRIVATE void HTML_end_element ARGS3( case HTML_FN: change_paragraph_style(me, me->sp->style); /* Often won't really change */ UPDATE_STYLE; - if (List_Nesting_Level >= 0) + if (me->sp->tag_number == element_number) + LYEnsureDoubleSpace(me); + if (me->List_Nesting_Level >= 0) HText_NegateLineOne(me->text); - B_inLABEL = FALSE; + me->inLABEL = FALSE; break; case HTML_OL: - OL_Counter[List_Nesting_Level < 6 ? - List_Nesting_Level : 6] = OL_VOID; + me->OL_Counter[me->List_Nesting_Level < 6 ? + me->List_Nesting_Level : 6] = OL_VOID; case HTML_DL: case HTML_UL: case HTML_MENU: case HTML_DIR: - List_Nesting_Level--; + me->List_Nesting_Level--; if (TRACE) - fprintf(stderr,"Reducing List Nesting Level to %d\n", - List_Nesting_Level); + fprintf(stderr, "Reducing List Nesting Level to %d\n", + me->List_Nesting_Level); change_paragraph_style(me, me->sp->style); /* Often won't really change */ UPDATE_STYLE; - if (List_Nesting_Level >= 0) + if (me->List_Nesting_Level >= 0) HText_NegateLineOne(me->text); break; @@ -4995,23 +4662,24 @@ PRIVATE void HTML_end_element ARGS3( break; case HTML_A: - /* Set to know that we are no longer in an anchor. + /* + * Set to know that we are no longer in an anchor. */ - B_inA = FALSE; + me->inA = FALSE; UPDATE_STYLE; - if (B_inBoldA == TRUE && B_inBoldH == FALSE) - HText_appendCharacter(me->text,LY_BOLD_END_CHAR); + if (me->inBoldA == TRUE && me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); HText_endAnchor(me->text); - B_inBoldA = FALSE; - if (Underline_Level > 0 && B_inUnderline == FALSE) { - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); - B_inUnderline = TRUE; + me->inBoldA = FALSE; + if (me->Underline_Level > 0 && me->inUnderline == FALSE) { + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); + me->inUnderline = TRUE; } break; case HTML_MAP: - FREE(LYMapName); + FREE(me->map_address); break; case HTML_BODYTEXT: @@ -5031,14 +4699,14 @@ PRIVATE void HTML_end_element ARGS3( break; case HTML_FIG: - if (B_inFIGwithP) { - HTML_EnsureDoubleSpace(me); + if (me->inFIGwithP) { + LYEnsureDoubleSpace(me); } else { HTML_put_character(me, ' '); /* space char may be ignored */ } - HTML_ResetParagraphAlignment(me); - B_inFIGwithP = FALSE; - B_inFIG = FALSE; + LYResetParagraphAlignment(me); + me->inFIGwithP = FALSE; + me->inFIG = FALSE; change_paragraph_style(me, me->sp->style); /* Often won't really change */ break; @@ -5049,10 +4717,10 @@ PRIVATE void HTML_end_element ARGS3( * Finish the data off. */ { - int s = 0, e = 0, i = 0, n = 0; + int s = 0, e = 0, n = 0; char *start = NULL, *first_end = NULL; BOOL have_param = FALSE; - char *cp = NULL, *data = NULL; + char *data = NULL; HTPresentation *Pres; HTChunkTerminate(&me->object); @@ -5110,9 +4778,9 @@ PRIVATE void HTML_end_element ARGS3( fprintf(stderr, "HTML: Unmatched OBJECT start and end tags. Discarding content:\n%s\n", me->object.data); - } else if (!B_inBadHTML) { + } else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); - B_inBadHTML = TRUE; + me->inBadHTML = TRUE; sleep(MessageSecs); } goto End_Object; @@ -5136,7 +4804,7 @@ PRIVATE void HTML_end_element ARGS3( */ if (me->object_declare == TRUE) { if (me->object_id && *me->object_id) - HTML_HandleID(me, me->object_id); + LYHandleID(me, me->object_id); if (TRACE) fprintf(stderr, "HTML: DECLAREd OBJECT. Ignoring!\n"); goto End_Object; @@ -5150,7 +4818,7 @@ PRIVATE void HTML_end_element ARGS3( */ if (me->object_name != NULL) { if (me->object_id && *me->object_id) - HTML_HandleID(me, me->object_id); + LYHandleID(me, me->object_id); if (TRACE) fprintf(stderr, "HTML: NAMEd OBJECT. Ignoring!\n"); goto End_Object; @@ -5188,9 +4856,9 @@ PRIVATE void HTML_end_element ARGS3( fprintf(stderr, "HTML: Unmatched OBJECT start and end tags. Discarding content.\n"); goto End_Object; - } else if (!B_inBadHTML) { + } else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); - B_inBadHTML = TRUE; + me->inBadHTML = TRUE; sleep(MessageSecs); goto End_Object; } @@ -5285,7 +4953,7 @@ Object_as_IMG: * Add an ID link if needed. - FM */ if (me->object_id && *me->object_id) - HTML_HandleID(me, me->object_id); + LYHandleID(me, me->object_id); /* * Add the OBJECTs content if not empty. - FM @@ -5315,7 +4983,7 @@ Object_as_IMG: * an image or not, and set the link name * accordingly. - FM */ - if (B_inA) + if (me->inA) StrAllocCat(*include, "</A>"); StrAllocCat(*include, " -<A HREF=\""); StrAllocCat(*include, me->object_data); @@ -5354,41 +5022,41 @@ End_Object: break; case HTML_APPLET: - if (B_inAPPLETwithP) { - HTML_EnsureDoubleSpace(me); + if (me->inAPPLETwithP) { + LYEnsureDoubleSpace(me); } else { HTML_put_character(me, ' '); /* space char may be ignored */ } - HTML_ResetParagraphAlignment(me); - B_inAPPLETwithP = FALSE; - B_inAPPLET = FALSE; + LYResetParagraphAlignment(me); + me->inAPPLETwithP = FALSE; + me->inAPPLET = FALSE; change_paragraph_style(me, me->sp->style); /* Often won't really change */ break; case HTML_CAPTION: - HTML_EnsureDoubleSpace(me); - HTML_ResetParagraphAlignment(me); - B_inCAPTION = FALSE; + LYEnsureDoubleSpace(me); + LYResetParagraphAlignment(me); + me->inCAPTION = FALSE; change_paragraph_style(me, me->sp->style); /* Often won't really change */ - B_inLABEL = FALSE; + me->inLABEL = FALSE; break; case HTML_CREDIT: - HTML_EnsureDoubleSpace(me); - HTML_ResetParagraphAlignment(me); - B_inCREDIT = FALSE; + LYEnsureDoubleSpace(me); + LYResetParagraphAlignment(me); + me->inCREDIT = FALSE; change_paragraph_style(me, me->sp->style); /* Often won't really change */ - B_inLABEL = FALSE; + me->inLABEL = FALSE; break; case HTML_FORM: /* Make sure we had a form start tag. */ - if (!B_inFORM) { + if (!me->inFORM) { if (TRACE) { fprintf(stderr, "HTML: Unmatched FORM end tag\n"); - } else if (!B_inBadHTML) { + } else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); - B_inBadHTML = TRUE; + me->inBadHTML = TRUE; sleep(MessageSecs); } /* @@ -5402,7 +5070,7 @@ End_Object: /* * Set to know that we are no longer in an form. */ - B_inFORM = FALSE; + me->inFORM = FALSE; UPDATE_STYLE; HText_endForm(me->text); @@ -5419,18 +5087,16 @@ End_Object: { InputFieldData I; int chars; - char *cp = NULL; - int i; /* * Make sure we had a textarea start tag. */ - if (!B_inTEXTAREA) { + if (!me->inTEXTAREA) { if (TRACE) { fprintf(stderr, "HTML: Unmatched TEXTAREA end tag\n"); - } else if (!B_inBadHTML) { + } else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); - B_inBadHTML = TRUE; + me->inBadHTML = TRUE; sleep(MessageSecs); } break; @@ -5439,7 +5105,7 @@ End_Object: /* * Set to know that we are no longer in a textarea tag. */ - B_inTEXTAREA = FALSE; + me->inTEXTAREA = FALSE; /* * Initialize. @@ -5467,19 +5133,18 @@ End_Object: HTChunkTerminate(&me->textarea); I.type = "textarea"; - I.value = cp; /* may be NULL */ - I.size = textarea_cols; - I.name = textarea_name; - I.disabled = textarea_disabled; - I.id = textarea_id; + I.size = me->textarea_cols; + I.name = me->textarea_name; + I.disabled = me->textarea_disabled; + I.id = me->textarea_id; - LYUsePlainSpace = TRUE; + me->UsePlainSpace = TRUE; if (current_char_set) LYExpandString(&me->textarea.data); cp = strtok(me->textarea.data, "\n"); - LYUnEscapeEntities(cp, LYUsePlainSpace, LYHiddenValue); - for (i = 0; i < textarea_rows; i++) { + LYUnEscapeEntities(cp, me->UsePlainSpace, me->HiddenValue); + for (i = 0; i < me->textarea_rows; i++) { I.value = cp; chars = HText_beginInput(me->text, &I); @@ -5488,7 +5153,7 @@ End_Object: HText_appendCharacter(me->text, '\r'); cp = strtok(NULL, "\n"); - LYUnEscapeEntities(cp, LYUsePlainSpace, LYHiddenValue); + LYUnEscapeEntities(cp, me->UsePlainSpace, me->HiddenValue); } /* @@ -5498,20 +5163,20 @@ End_Object: I.value = cp; chars = HText_beginInput(me->text, &I); - for (chars = atoi(textarea_cols); chars>0; chars--) + for (chars = atoi(me->textarea_cols); chars>0; chars--) HTML_put_character(me, '_'); HText_appendCharacter(me->text, '\r'); cp = strtok(NULL, "\n"); - LYUnEscapeEntities(cp, LYUsePlainSpace, LYHiddenValue); + LYUnEscapeEntities(cp, me->UsePlainSpace, me->HiddenValue); } - LYUsePlainSpace = FALSE; + me->UsePlainSpace = FALSE; HTChunkClear(&me->textarea); - FREE(textarea_name); - FREE(textarea_cols); - FREE(textarea_id); + FREE(me->textarea_name); + FREE(me->textarea_cols); + FREE(me->textarea_id); break; } @@ -5524,12 +5189,12 @@ End_Object: /* * Make sure we had a select start tag. */ - if (!B_inSELECT) { + if (!me->inSELECT) { if (TRACE) { fprintf(stderr, "HTML: Unmatched SELECT end tag\n"); - } else if (!B_inBadHTML) { + } else if (!me->inBadHTML) { _statusline(BAD_HTML_USE_TRACE); - B_inBadHTML = TRUE; + me->inBadHTML = TRUE; sleep(MessageSecs); } break; @@ -5538,12 +5203,12 @@ End_Object: /* * Set to know that we are no longer in a select tag. */ - B_inSELECT = FALSE; + me->inSELECT = FALSE; /* * Clear the disable attribute. */ - select_disabled=NO; + me->select_disabled = FALSE; /* * Finish the data off. @@ -5551,18 +5216,20 @@ End_Object: HTChunkTerminate(&me->option); /* finish the previous option @@@@@ */ ptr = HText_setLastOptionValue(me->text, - me->option.data, LastOptionValue, - LAST_ORDER, LastOptionChecked); - FREE(LastOptionValue); + me->option.data, + me->LastOptionValue, + LAST_ORDER, + me->LastOptionChecked); + FREE(me->LastOptionValue); - LastOptionChecked = FALSE; + me->LastOptionChecked = FALSE; if (HTCurSelectGroupType == F_CHECKBOX_TYPE || LYSelectPopups == FALSE) { /* * Start a newline after the last checkbox/button option. */ - HTML_EnsureSingleSpace(me); + LYEnsureSingleSpace(me); } else { /* * Output popup box with the default option to screen, @@ -5575,7 +5242,6 @@ End_Object: * We'll put up a minimum of 20 characters, and if any * more would exceed the wrap column, we'll ignore them. */ - int i; for (i = 0; i < 20; i++) { if (*ptr == ' ') HText_appendCharacter(me->text,HT_NON_BREAK_SPACE); @@ -5583,7 +5249,7 @@ End_Object: HText_appendCharacter(me->text,*ptr); ptr++; } - ignore_excess = TRUE; + HText_setIgnoreExcess(me->text, TRUE); } for (; ptr && *ptr != '\0'; ptr++) { if (*ptr == ' ') @@ -5595,26 +5261,26 @@ End_Object: * Add end option character. */ HText_appendCharacter(me->text, ']'); - HTML_Last_Char = ']'; + HText_setLastChar(me->text, ']'); me->in_word = YES; - ignore_excess = FALSE; + HText_setIgnoreExcess(me->text, FALSE); } HTChunkClear(&me->option); - if (Underline_Level > 0 && B_inUnderline == FALSE) { - HText_appendCharacter(me->text,LY_UNDERLINE_START_CHAR); - B_inUnderline = TRUE; + if (me->Underline_Level > 0 && me->inUnderline == FALSE) { + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); + me->inUnderline = TRUE; } - if (B_needBoldH == TRUE && B_inBoldH == FALSE) { - HText_appendCharacter(me->text,LY_BOLD_START_CHAR); - B_inBoldH = TRUE; - B_needBoldH = FALSE; + if (me->needBoldH == TRUE && me->inBoldH == FALSE) { + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); + me->inBoldH = TRUE; + me->needBoldH = FALSE; } } break; case HTML_TABLE: - B_inTABLE = FALSE; + me->inTABLE = FALSE; break; #ifdef NOTDEFINED /* These are SGML_EMPTY for now. - FM */ @@ -5637,33 +5303,30 @@ End_Object: #endif /* NOTDEFINED */ case HTML_MATH: - { - int i; - if (!me->text) - UPDATE_STYLE; - /* - * We're getting it as Litteral text, which, until we can process - * it, we'll display as is, within brackets to alert the user. - FM - */ - HTChunkPutc(&me->math, ' '); - HTChunkTerminate(&me->math); - if (me->math.size > 2) { - HTML_EnsureSingleSpace(me); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); - HTML_put_string(me, "[MATH:"); - HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); - HTML_put_character(me, ' '); - HTML_put_string(me, me->math.data); + if (!me->text) + UPDATE_STYLE; + /* + * We're getting it as Litteral text, which, until we can process + * it, we'll display as is, within brackets to alert the user. - FM + */ + HTChunkPutc(&me->math, ' '); + HTChunkTerminate(&me->math); + if (me->math.size > 2) { + LYEnsureSingleSpace(me); + if (me->inUnderline == FALSE) HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); - HTML_put_string(me, ":MATH]"); - if (B_inUnderline == FALSE) - HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); - HTML_EnsureSingleSpace(me); - } - HTChunkClear(&me->math); - break; + HTML_put_string(me, "[MATH:"); + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + HTML_put_character(me, ' '); + HTML_put_string(me, me->math.data); + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); + HTML_put_string(me, ":MATH]"); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + LYEnsureSingleSpace(me); } + HTChunkClear(&me->math); + break; default: change_paragraph_style(me, me->sp->style); /* Often won't really change */ @@ -5677,7 +5340,7 @@ End_Object: */ /* (In fact, they all shrink!) */ -PRIVATE void HTML_put_entity ARGS2(HTStructured *, me, int, entity_number) +PUBLIC void HTML_put_entity ARGS2(HTStructured *, me, int, entity_number) { HTML_put_string(me, p_entity_values[entity_number]); } @@ -5697,11 +5360,11 @@ PUBLIC void HTML_free ARGS1(HTStructured *, me) { UPDATE_STYLE; /* Creates empty document here! */ if (me->comment_end) - HTML_put_string(me,me->comment_end); + HTML_put_string(me, me->comment_end); if (me->text) { - if (B_inUnderline) { - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); - B_inUnderline = FALSE; + if (me->inUnderline) { + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + me->inUnderline = FALSE; } HText_endAppend(me->text); } @@ -5709,14 +5372,10 @@ PUBLIC void HTML_free ARGS1(HTStructured *, me) if (me->target) { (*me->targetClass._free)(me->target); } - List_Nesting_Level = -1; - HTML_zero_OL_Counter(); - Division_Level = -1; - Underline_Level = 0; - Quote_Level = 0; if (me->sp && me->sp->style && me->sp->style->name) { if (!strcmp(me->sp->style->name, "DivCenter") || - !strcmp(me->sp->style->name, "HeadingCenter")) { + !strcmp(me->sp->style->name, "HeadingCenter") || + !strcmp(me->sp->style->name, "Heading1")) { me->sp->style->alignment = HT_CENTER; } else if (!strcmp(me->sp->style->name, "DivRight") || !strcmp(me->sp->style->name, "HeadingRight")) { @@ -5726,25 +5385,17 @@ PUBLIC void HTML_free ARGS1(HTStructured *, me) } styles[HTML_PRE]->alignment = HT_LEFT; } - FREE(base_href); - B_inBASE = FALSE; - FREE(LYMapName); + FREE(me->base_href); + FREE(me->map_address); + FREE(me->LastOptionValue); FREE(me); } PRIVATE void HTML_abort ARGS2(HTStructured *, me, HTError, e) { - List_Nesting_Level = -1; - HTML_zero_OL_Counter(); - Division_Level = -1; - Underline_Level = 0; - Quote_Level = 0; - if (me->text) { - if (B_inUnderline) { - HText_appendCharacter(me->text,LY_UNDERLINE_END_CHAR); - B_inUnderline = FALSE; - } + if (me->inUnderline) + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); HText_endAppend(me->text); } @@ -5753,7 +5404,8 @@ PRIVATE void HTML_abort ARGS2(HTStructured *, me, HTError, e) } if (me->sp && me->sp->style && me->sp->style->name) { if (!strcmp(me->sp->style->name, "DivCenter") || - !strcmp(me->sp->style->name, "HeadingCenter")) { + !strcmp(me->sp->style->name, "HeadingCenter") || + !strcmp(me->sp->style->name, "Heading1")) { me->sp->style->alignment = HT_CENTER; } else if (!strcmp(me->sp->style->name, "DivRight") || !strcmp(me->sp->style->name, "HeadingRight")) { @@ -5763,9 +5415,12 @@ PRIVATE void HTML_abort ARGS2(HTStructured *, me, HTError, e) } styles[HTML_PRE]->alignment = HT_LEFT; } - FREE(base_href); - B_inBASE = FALSE; - FREE(LYMapName); + FREE(me->base_href); + FREE(me->map_address); + FREE(me->textarea_name); + FREE(me->textarea_cols); + FREE(me->textarea_id); + FREE(me->LastOptionValue); FREE(me); } @@ -5841,6 +5496,7 @@ PRIVATE void get_styles NOARGS styles[HTML_PRE] = HTStyleNamed(styleSheet, "Preformatted"); styles[HTML_LISTING] = HTStyleNamed(styleSheet, "Listing"); } + /* P U B L I C */ @@ -5871,39 +5527,6 @@ PUBLIC HTStructured* HTML_new ARGS3( HTStructured * me; - /* Reset to know that we aren't in a list, anchor, bold header - * or paragraph. Hmm... May as well reset all of the flags. - */ - List_Nesting_Level = -1; - HTML_zero_OL_Counter(); - Division_Level = -1; - Underline_Level = 0; - Quote_Level = 0; - FREE(base_href); - FREE(LYMapName); - - B_inA = FALSE; - B_inAPPLET = FALSE; - B_inAPPLETwithP = FALSE; - B_inBadHTML = FALSE; - B_inBASE = FALSE; - B_inBoldA = FALSE; - B_inBoldH = FALSE; - B_inCAPTION = FALSE; - B_inCREDIT = FALSE; - B_inFIG = FALSE; - B_inFIGwithP = FALSE; - B_inFORM = FALSE; - B_inLABEL = FALSE; - B_inP = FALSE; - B_inPRE = FALSE; - B_inSELECT = FALSE; - B_inTABLE = FALSE; - B_inUnderline = FALSE; - - B_needBoldH = FALSE; - current_default_alignment=HT_LEFT; - if (format_out != WWW_PLAINTEXT && format_out != WWW_PRESENT) { HTStream * intermediate = HTStreamStack(WWW_HTML, format_out, stream, anchor); @@ -5933,15 +5556,21 @@ PUBLIC HTStructured* HTML_new ARGS3( default_style = HTStyleNamed(styleSheet, "Normal"); me->isa = &HTMLPresentation; - me->node_anchor = anchor; + me->node_anchor = anchor; + + me->CurrentA = NULL; + me->base_href = NULL;; + me->map_address = NULL; + me->title.size = 0; me->title.growby = 128; me->title.allocated = 0; - me->title.data = 0; + me->title.data = NULL; + me->object.size = 0; me->object.growby = 128; me->object.allocated = 0; - me->object.data = 0; + me->object.data = NULL; me->object_started = FALSE; me->object_declare = FALSE; me->object_shapes = FALSE; @@ -5955,37 +5584,90 @@ PUBLIC HTStructured* HTML_new ARGS3( me->object_codetype = NULL; me->object_usemap = NULL; me->object_name = NULL; + me->option.size = 0; me->option.growby = 128; me->option.allocated = 0; - me->option.data = 0; + me->option.data = NULL; + me->LastOptionValue = NULL; + me->LastOptionChecked = FALSE; + me->select_disabled = FALSE; + me->textarea.size = 0; me->textarea.growby = 128; me->textarea.allocated = 0; - me->textarea.data = 0; + me->textarea.data = NULL; + me->textarea_name = NULL; + me->textarea_cols = NULL; + me->textarea_rows = 4; + me->textarea_disabled = NO; + me->textarea_id = NULL; + me->math.size = 0; me->math.growby = 128; me->math.allocated = 0; - me->math.data = 0; + me->math.data = NULL; + me->style_block.size = 0; me->style_block.growby = 128; me->style_block.allocated = 0; - me->style_block.data = 0; + me->style_block.data = NULL; + me->script.size = 0; me->script.growby = 128; me->script.allocated = 0; - me->script.data = 0; + me->script.data = NULL; + me->text = 0; me->style_change = YES; /* Force check leading to text creation */ me->new_style = default_style; me->old_style = 0; + me->current_default_alignment = HT_LEFT; me->sp = me->stack + MAX_NESTING - 1; me->sp->tag_number = -1; /* INVALID */ me->sp->style = default_style; /* INVALID */ me->sp->style->alignment = HT_LEFT; + me->Division_Level = -1; + me->Underline_Level = 0; + me->Quote_Level = 0; + + me->UsePlainSpace = FALSE; + me->HiddenValue = FALSE; + me->lastraw = -1; + + /* + * Used for nested lists. - FM + */ + me->List_Nesting_Level = -1; /* counter for list nesting level */ + LYZero_OL_Counter(me); /* Initializes OL_Counter[7] and OL_Type[7] */ + me->Last_OL_Count = 0; /* last count in ordered lists */ + me->Last_OL_Type = '1'; /* last type in ordered lists */ + + me->inA = FALSE; + me->inAPPLET = FALSE; + me->inAPPLETwithP = FALSE; + me->inBadHTML = FALSE; + me->inBASE = FALSE; + me->inBoldA = FALSE; + me->inBoldH = FALSE; + me->inCAPTION = FALSE; + me->inCREDIT = FALSE; + me->inFIG = FALSE; + me->inFIGwithP = FALSE; + me->inFORM = FALSE; + me->inLABEL = FALSE; + me->inP = FALSE; + me->inPRE = FALSE; + me->inSELECT = FALSE; + me->inTABLE = FALSE; + me->inUnderline = FALSE; + + me->needBoldH = FALSE; + me->comment_start = NULL; me->comment_end = NULL; + me->target = stream; if (stream) me->targetClass = *stream->isa; /* Copy pointers */ @@ -6071,254 +5753,3 @@ PUBLIC int HTLoadError ARGS3( HTAlert(message); /* @@@@@@@@@@@@@@@@@@@ */ return -number; } - -/* -** This function checks whether we want to overrride -** the current default alignment for parargraphs and -** instead use that specified in the element's style -** sheet. - FM -*/ -PRIVATE BOOLEAN HTML_override_default_alignment ARGS1( - HTStructured *, me) -{ - switch(me->sp[0].tag_number) { - case HTML_BLOCKQUOTE: - case HTML_BQ: - case HTML_NOTE: - case HTML_FN: - case HTML_ADDRESS: - me->sp->style->alignment = HT_LEFT; - return YES; - break; - - default: - break; - } - return NO; -} - -/* -** This function initializes the Ordered List counter. - FM -*/ -PRIVATE void HTML_zero_OL_Counter NOARGS -{ - int i; - - for (i = 0; i < 7; i++) { - OL_Counter[i] = OL_VOID; - OL_Type[i] = '1'; - } - - Last_OL_Count = 0; - Last_OL_Type = '1'; - - return; -} - -/* -** This function inserts newlines if needed to create double spacing, -** and sets the left margin for subsequent text to the second line -** indentation of the current style. - FM -*/ -PRIVATE void HTML_EnsureDoubleSpace ARGS1( - HTStructured *, me) -{ - if (!me || !me->text) - return; - - if (HText_LastLineSize(me->text)) { - HText_appendCharacter(me->text, '\r'); - HText_appendCharacter(me->text, '\r'); - } else if (HText_PreviousLineSize(me->text)) { - HText_appendCharacter(me->text, '\r'); - } else if (List_Nesting_Level >= 0) { - HText_NegateLineOne(me->text); - } - me->in_word = NO; - return; -} - -/* -** This function inserts a newline if needed to create single spacing, -** and sets the left margin for subsequent text to the second line -** indentation of the current style. - FM -*/ -PRIVATE void HTML_EnsureSingleSpace ARGS1( - HTStructured *, me) -{ - if (!me || !me->text) - return; - - if (HText_LastLineSize(me->text)) { - HText_appendCharacter(me->text, '\r'); - } else if (List_Nesting_Level >= 0) { - HText_NegateLineOne(me->text); - } - me->in_word = NO; - return; -} - -/* -** This function resets paragraph alignments for block -** elements which do not have a defined style sheet. - FM -*/ -PRIVATE void HTML_ResetParagraphAlignment ARGS1( - HTStructured *, me) -{ - if (!me) - return; - - if (List_Nesting_Level >= 0 || - ((Division_Level < 0) && - (!strcmp(me->sp->style->name, "Normal") || - !strcmp(me->sp->style->name, "Preformatted")))) { - me->sp->style->alignment = HT_LEFT; - } else { - me->sp->style->alignment = current_default_alignment; - } - return; -} - -/* -** If an HREF, itself or if resolved against a base, -** represents a file URL, and the host is defaulted, -** force in "//localhost". We need this until -** all the other Lynx code which performs security -** checks based on the "localhost" string is changed -** to assume "//localhost" when a host field is not -** present in file URLs - FM -*/ -PRIVATE void HTMLFillLocalFileURL ARGS2( - char **, href, - char *, base) -{ - char * temp = NULL; - - if (*href == NULL || *(*href) == '\0') - return; - - if (!strcmp(*href, "//") || !strncmp(*href, "///", 3)) { - if (base != NULL && !strncmp(base, "file:", 5)) { - StrAllocCopy(temp, "file:"); - StrAllocCat(temp, *href); - StrAllocCopy(*href, temp); - } - } - if (!strncmp(*href, "file:", 5)) { - if (*(*href+5) == '\0') { - StrAllocCat(*href, "//localhost"); - } else if (!strcmp(*href, "file://")) { - StrAllocCat(*href, "localhost"); - } else if (!strncmp(*href, "file:///", 8)) { - StrAllocCopy(temp, (*href+7)); - StrAllocCopy(*href, "file://localhost"); - StrAllocCat(*href, temp); - } else if (!strncmp(*href, "file:/", 6) && *(*href+6) != '/') { - StrAllocCopy(temp, (*href+5)); - StrAllocCopy(*href, "file://localhost"); - StrAllocCat(*href, temp); - } - } - - /* - * No path in a file://localhost URL means a - * directory listing for the current default. - FM - */ - if (!strcmp(*href, "file://localhost")) { -#ifdef VMS - StrAllocCat(*href, HTVMS_wwwName(getenv("PATH"))); -#else - char curdir[DIRNAMESIZE]; -#ifdef NO_GETCWD - getwd (curdir); -#else - getcwd (curdir, DIRNAMESIZE); -#endif /* NO_GETCWD */ - StrAllocCat(*href, curdir); -#endif /* VMS */ - } - -#ifdef VMS - /* - * On VMS, a file://localhost/ URL means - * a listing for the login directory. - FM - */ - if (!strcmp(*href, "file://localhost/")) - StrAllocCat(*href, (HTVMS_wwwName((char *)Home_Dir())+1)); -#endif /* VMS */ - - FREE(temp); - return; -} - -/* -** This function creates NAMEd Anchors of a non-zero-length NAME -** or ID attribute was present in the tag. -*/ -PRIVATE void HTML_CheckForID ARGS4( - HTStructured *, me, - CONST BOOL *, present, - CONST char **, value, - int, attribute) -{ - HTChildAnchor *B_ID_A = NULL; - char *temp = NULL; - - if (!(me && me->text)) - return; - - if (present && present[attribute] - && value[attribute] && *value[attribute]) { - /* - * Translate any named or numeric character references. - FM - */ - StrAllocCopy(temp, value[attribute]); - LYUnEscapeToLatinOne(&temp, TRUE); - - /* - * Create the link if we still have a non-zero-length string. - FM - */ - if ((temp[0] != '\0') && - (B_ID_A = HTAnchor_findChildAndLink( - me->node_anchor, /* Parent */ - temp, /* Tag */ - NULL, /* Addresss */ - (void *)0))) { /* Type */ - HText_beginAnchor(me->text, B_ID_A); - HText_endAnchor(me->text); - } - FREE(temp); - } - - return; -} - -/* -** This function creates a NAMEd Anchor for the ID string -** passed to it directly as an argument. It assumes the -** does not need checking for character references. - FM -*/ -PRIVATE void HTML_HandleID ARGS2( - HTStructured *, me, - char *, id) -{ - HTChildAnchor *B_ID_A = NULL; - - if (!(me && me->text) || - !(id && *id)) - return; - - /* - * Create the link if we still have a non-zero-length string. - FM - */ - if (B_ID_A = HTAnchor_findChildAndLink( - me->node_anchor, /* Parent */ - id, /* Tag */ - NULL, /* Addresss */ - (void *)0)) { /* Type */ - HText_beginAnchor(me->text, B_ID_A); - HText_endAnchor(me->text); - } - - return; -} diff --git a/src/HTML.h b/src/HTML.h index aada006f..23d89e17 100644 --- a/src/HTML.h +++ b/src/HTML.h @@ -1,9 +1,9 @@ -/* HTML to rich text converter for libwww - THE HTML TO RTF OBJECT CONVERTER - - This interprets the HTML semantics. - - */ +/* HTML to rich text converter for libwww +** +** THE HTML TO RTF OBJECT CONVERTER +** +** This interprets the HTML semantics. +*/ #ifndef HTML_H #define HTML_H @@ -20,22 +20,150 @@ extern CONST HTStructuredClass HTMLPresentation; +#ifdef Lynx_HTML_Handler /* +** This section is semi-private to HTML.c and it's helper modules. - FM +** -------------------------------------------------------------------- +*/ -HTConverter to present HTML +typedef struct _stack_element { + HTStyle * style; + int tag_number; +} stack_element; + +/* HTML Object +** ----------- +*/ +#define MAX_NESTING 800 /* Should be checked by parser */ + +struct _HTStructured { + CONST HTStructuredClass * isa; + HTParentAnchor * node_anchor; + HText * text; + + HTStream* target; /* Output stream */ + HTStreamClass targetClass; /* Output routines */ + + HTChildAnchor * CurrentA; /* current HTML_A anchor */ + char * base_href; /* current HTML_BASE href */ + char * map_address; /* current HTML_MAP address */ + + HTChunk title; /* Grow by 128 */ + HTChunk object; /* Grow by 128 */ + BOOL object_started; + BOOL object_declare; + BOOL object_shapes; + BOOL object_ismap; + char * object_usemap; + char * object_id; + char * object_title; + char * object_data; + char * object_type; + char * object_classid; + char * object_codebase; + char * object_codetype; + char * object_name; + HTChunk option; /* Grow by 128 */ + char * LastOptionValue; + BOOL LastOptionChecked; + BOOL select_disabled; + HTChunk textarea; /* Grow by 128 */ + char * textarea_name; + char * textarea_cols; + int textarea_rows; + int textarea_disabled; + char * textarea_id; + HTChunk math; /* Grow by 128 */ + HTChunk style_block; /* Grow by 128 */ + HTChunk script; /* Grow by 128 */ + + /* + * Used for nested lists. - FM + */ + int List_Nesting_Level; /* counter for list nesting level */ + int OL_Counter[7]; /* counter for ordered lists */ + char OL_Type[7]; /* types for ordered lists */ + int Last_OL_Count; /* last count in ordered lists */ + char Last_OL_Type; /* last type in ordered lists */ + + int Division_Level; + short DivisionAlignments[MAX_NESTING]; + int Underline_Level; + int Quote_Level; + + BOOL UsePlainSpace; + BOOL HiddenValue; + int lastraw; + + char * comment_start; /* for literate programming */ + char * comment_end; + + HTTag * current_tag; + BOOL style_change; + HTStyle * new_style; + HTStyle * old_style; + int current_default_alignment; + BOOL in_word; /* Have just had a non-white char */ + stack_element stack[MAX_NESTING]; + stack_element *sp; /* Style stack pointer */ + + /* + ** Track if we are in an anchor, paragraph, address, base, etc. + */ + BOOL inA; + BOOL inAPPLET; + BOOL inAPPLETwithP; + BOOL inBadHTML; + BOOL inBASE; + BOOL inBoldA; + BOOL inBoldH; + BOOL inCAPTION; + BOOL inCREDIT; + BOOL inFIG; + BOOL inFIGwithP; + BOOL inFORM; + BOOL inLABEL; + BOOL inP; + BOOL inPRE; + BOOL inSELECT; + BOOL inTABLE; + BOOL inTEXTAREA; + BOOL inUnderline; + + BOOL needBoldH; +}; + +struct _HTStream { + CONST HTStreamClass * isa; + /* .... */ +}; +/* + * Semi-Private functions. - FM */ -PUBLIC HTStream* HTMLToPlain PARAMS(( +extern void HTML_put_character PARAMS((HTStructured *me, char c)); +extern void HTML_put_string PARAMS((HTStructured *me, CONST char *s)); +extern void HTML_write PARAMS((HTStructured *me, CONST char *s, int l)); +extern void HTML_put_entity PARAMS((HTStructured *me, int entity_number)); +#endif /* Lynx_HTML_Handler */ + +/* P U B L I C +*/ + +/* +** HTConverter to present HTML +*/ +extern HTStream* HTMLToPlain PARAMS(( HTPresentation * pres, HTParentAnchor * anchor, HTStream * sink)); -PUBLIC HTStream* HTMLToC PARAMS(( +extern HTStream* HTMLToC PARAMS(( HTPresentation * pres, HTParentAnchor * anchor, HTStream * sink)); -PUBLIC HTStream* HTMLPresent PARAMS(( +extern HTStream* HTMLPresent PARAMS(( HTPresentation * pres, HTParentAnchor * anchor, HTStream * sink)); @@ -45,7 +173,8 @@ extern HTStructured* HTML_new PARAMS(( HTFormat format_out, HTStream * target)); -/* Names for selected internal representations: +/* +** Names for selected internal representations. */ typedef enum _HTMLCharacterSet { HTML_ISO_LATIN1, @@ -53,27 +182,24 @@ typedef enum _HTMLCharacterSet { HTML_PC_CP950 } HTMLCharacterSet; - /* - -Record error message as a hypertext object - - The error message should be marked as an error so that it can be reloaded later. This - implementation just throws up an error message and leaves the document unloaded. - - */ -/* On entry, +** Record error message as a hypertext object. +** +** The error message should be marked as an error so that it can be +** reloaded later. This implementation just throws up an error message +** and leaves the document unloaded. +** +** On entry, ** sink is a stream to the output device if any ** number is the HTTP error number ** message is the human readable message. -** On exit, +** On exit, ** a retrun code like HT_LOADED if object exists else 60; 0 */ - -PUBLIC int HTLoadError PARAMS(( - HTStream * sink, - int number, - CONST char * message)); +extern int HTLoadError PARAMS(( + HTStream * sink, + int number, + CONST char * message)); #endif /* HTML_H */ diff --git a/src/LYBookmark.c b/src/LYBookmark.c index 4ba29d0b..8f574bc1 100644 --- a/src/LYBookmark.c +++ b/src/LYBookmark.c @@ -10,6 +10,7 @@ #include "LYKeymap.h" #include "LYCharUtils.h" #include "LYCurses.h" +#include "GridText.h" #ifdef VMS #include "HTVMSUtils.h" @@ -25,22 +26,29 @@ PRIVATE BOOLEAN is_mosaic_hotlist=FALSE; PRIVATE char * convert_mosaic_bookmark_file PARAMS((char *filename_buffer)); /* - * Tries to open the bookmark file for reading. - * if successful the file is closed and the filename - * is returned and the URL is given in name. - * - * Returns a zero-length pointer to flag a cancel, - * a space to flag an undefined selection, and - * NULL for a failure (processing error). - FM + * Tries to open a bookmark file for reading, which may be + * the default, or based on offering the user a choice from + * the MBM_A_subbookmark[] array. If successful the file is + * closed, and the filename in system path specs is returned, + * the URL is allocated into *URL, and the MBM_A_subbookmark[] + * filepath is allocated into the BookmarkPage global. Returns + * a zero-length pointer to flag a cancel, or a space to flag + * an undefined selection, without allocating into *URL or + * BookmarkPage. Returns NULL with allocating into BookmarkPage + * but not *URL is the selection is valid but the file doesn't + * yet exist. - FM */ PUBLIC char * get_bookmark_filename ARGS1( - char **, URL) + char **, URL) { char URL_buffer[256]; static char filename_buffer[256]; char string_buffer[256]; FILE *fp; int MBM_tmp; +#ifndef VMS + int len; +#endif /* !VMS */ /* * Multi_Bookmarks support. - FMG & FM @@ -49,7 +57,7 @@ PUBLIC char * get_bookmark_filename ARGS1( MBM_tmp = select_multi_bookmarks(); if (MBM_tmp == -2) /* - * Zero-length pointer flags a cancel. + * Zero-length pointer flags a cancel. - FM */ return(""); if (MBM_tmp == -1) { @@ -59,23 +67,28 @@ PUBLIC char * get_bookmark_filename ARGS1( _statusline(string_buffer); sleep(AlertSecs); /* - * Space flags an undefined selection. - */ + * Space flags an undefined selection. - FMG + */ return(" "); } else { + /* + * Save the filepath as a global. The system path will be + * loaded into to the (static) filename_buffer as the return + * value, the URL will be allocated into *URL, and we also + * need the filepath available to calling functions. This + * is all pitifully non-reentrant, a la the original Lynx, + * and should be redesigned someday. - FM + */ StrAllocCopy(BookmarkPage, MBM_A_subbookmark[MBM_tmp]); } /* - * Seek it in the home path. + * Seek it in the home path. - FM */ -#ifdef VMS - LYVMS_HomePathAndFilename(filename_buffer, - sizeof(filename_buffer), - BookmarkPage); -#else - sprintf(filename_buffer,"%s/%s", Home_Dir(), BookmarkPage); -#endif /* VMS */ + filename_buffer[255] = '\0'; + LYAddPathToHome(filename_buffer, + sizeof(filename_buffer), + BookmarkPage); if (TRACE) fprintf(stderr, "\nget_bookmark_filename: SEEKING %s\n AS %s\n\n", BookmarkPage, filename_buffer); @@ -124,8 +137,12 @@ success: } /* big end */ +/* + * Converts a Mosaic hotlist file into an HTML + * file for handling as a Lynx bookmark file. - FM + */ PRIVATE char * convert_mosaic_bookmark_file ARGS1( - char *, filename_buffer) + char *, filename_buffer) { static char newfile[256]; static BOOLEAN first = TRUE; @@ -144,7 +161,7 @@ PRIVATE char * convert_mosaic_bookmark_file ARGS1( } if ((nfp = fopen(newfile, "w")) == NULL) { - _statusline(NO_TEMP_FOR_HOTLIST); + LYMBM_statusline(NO_TEMP_FOR_HOTLIST); sleep(AlertSecs); return (""); } @@ -181,87 +198,130 @@ PRIVATE char * convert_mosaic_bookmark_file ARGS1( return(newfile); } +/* + * Adds a link to a bookmark file, creating the file + * if it doesn't already exist, and making sure that + * no_cache is set for a pre-existing, cached file, + * so that the change will be evident on return to + * to that file. - FM + */ PUBLIC void save_bookmark_link ARGS2( - char *, address, - char *, title) + char *, address, + char *, title) { FILE *fp; BOOLEAN first_time = FALSE; char *filename; char *bookmark_URL = NULL; char filename_buffer[256]; + char string_buffer[256]; char *Address = NULL; char *Title = NULL; + int i, c; + DocAddress WWWDoc; + HTParentAnchor *tmpanchor; + HText *text; + /* + * Make sure we were passed something to save. - FM + */ if (!(address && *address)) { HTAlert(MALFORMED_ADDRESS); return; } + /* + * Offer a choice of bookmark files, + * or get the default. - FMG + */ filename = get_bookmark_filename(&bookmark_URL); /* - * If filename is a space, invalid bookmark - * file was selected. If zero-length, user - * cancelled. Ignore request in both cases! + * If filename is NULL, must create a new file. If + * filename is a space, an invalid bookmark file was + * selected, or if zero-length, the user cancelled. + * Ignore request in both cases. Otherwise, make + * a copy before anything might change the static + * get_bookmark_filename() buffer. - FM */ - if (filename) - if (*filename == '\0' || !strcmp(filename," ")) - return; + if (filename == NULL) { + first_time = TRUE; + filename_buffer[0] = '\0'; + } else { + if (*filename == '\0' || !strcmp(filename," ")) { + FREE(bookmark_URL); + return; + } + strcpy(filename_buffer, filename); + } + /* - * If BookmarkPage didn't get loaded, something - * went wrong, so ignore the request. + * If BookmarkPage is NULL, something went + * wrong, so ignore the request. - FM */ - if (!BookmarkPage) + if (BookmarkPage == NULL) { + FREE(bookmark_URL); return; + } - /* - * We don't need the full URL. - */ - FREE(bookmark_URL); + /* + * If the link will be added to the same + * bookmark file, get confirmation. - FM + */ + if (LYMultiBookmarks == TRUE && + strstr(HTLoadedDocumentURL(), + (*BookmarkPage == '.' ? + (BookmarkPage+1) : BookmarkPage)) != NULL) { + LYMBM_statusline(MULTIBOOKMARKS_SELF); + c = LYgetch(); + if (TOUPPER(c) != 'L') { + FREE(bookmark_URL); + return; + } + } /* * Allow user to change the title. - FM */ - filename_buffer[255] = '\0'; - LYstrncpy(filename_buffer, title, 255); - convert_to_spaces(filename_buffer); - _statusline(TITLE_PROMPT); - LYgetstr(filename_buffer, VISIBLE, sizeof(filename_buffer), NORECALL); - if (*filename_buffer == '\0') { - _statusline(CANCELLED); + string_buffer[255] = '\0'; + LYstrncpy(string_buffer, title, 255); + convert_to_spaces(string_buffer); + LYMBM_statusline(TITLE_PROMPT); + LYgetstr(string_buffer, VISIBLE, sizeof(string_buffer), NORECALL); + if (*string_buffer == '\0') { + LYMBM_statusline(CANCELLED); sleep(MessageSecs); + FREE(bookmark_URL); return; } /* - * Create the Title with any left-angle-brackets converted to < - * entities and any ampersands converted to & entities. - FM + * Create the Title with any left-angle-brackets + * converted to < entities and any ampersands + * converted to & entities. - FM */ - StrAllocCopy(Title, filename_buffer); + StrAllocCopy(Title, string_buffer); LYEntify(&Title, TRUE); /* - * Open the bookmark file. - FM + * Create the bookmark file, if it doesn't exist already, + * Otherwise, open the pre-existing bookmark file. - FM */ - if (filename == NULL) - first_time = TRUE; - /* - * Try in the home directory. - */ -#ifdef VMS - LYVMS_HomePathAndFilename(filename_buffer, - sizeof(filename_buffer), - BookmarkPage); -#else - sprintf(filename_buffer, "%s/%s", Home_Dir(), BookmarkPage); -#endif /* VMS */ + if (first_time) { + /* + * Seek it in the home path. - FM + */ + LYAddPathToHome(filename_buffer, + sizeof(filename_buffer), + BookmarkPage); + } if (TRACE) fprintf(stderr, "\nsave_bookmark_link: SEEKING %s\n AS %s\n\n", BookmarkPage, filename_buffer); if ((fp = fopen(filename_buffer, (first_time ? "w" : "a+"))) == NULL) { - _statusline(BOOKMARK_OPEN_FAILED); + LYMBM_statusline(BOOKMARK_OPEN_FAILED); sleep(AlertSecs); + FREE(bookmark_URL); return; } @@ -300,15 +360,51 @@ PUBLIC void save_bookmark_link ARGS2( } else { fprintf(fp,"<LI><a href=\"%s\">%s</a>\n", Address, Title); } - fclose(fp); + + /* + * If this is a cached bookmark file, set nocache for + * it so we'll see the new bookmark link when that + * cache is retrieved. - FM + */ + if (!first_time && nhist > 0 && bookmark_URL) { + for (i = 0; i < nhist; i++) { + if (history[i].bookmark && + !strcmp(history[i].address, bookmark_URL)) { + WWWDoc.address = history[i].address; + WWWDoc.post_data = NULL; + WWWDoc.post_content_type = NULL; + WWWDoc.bookmark = history[i].bookmark; + WWWDoc.isHEAD = FALSE; + WWWDoc.safe = FALSE; + if (((tmpanchor = HTAnchor_parent( + HTAnchor_findAddress(&WWWDoc) + )) != NULL) && + (text = (HText *)HTAnchor_document(tmpanchor)) != NULL) { + HText_setNoCache(text); + } + break; + } + } + } + + /* + * Clean up and report success. + */ FREE(Title); FREE(Address); - - _statusline(OPERATION_DONE); + FREE(bookmark_URL); + LYMBM_statusline(OPERATION_DONE); sleep(MessageSecs); } +/* + * Remove a link from a bookmark file. The calling + * function is expected to have used get_filename_link(), + * pass us the link number as cur, the MBM_A_subbookmark[] + * string as cur_bookmark_page, and to have set up no_cache + * itself. - FM + */ PUBLIC void remove_bookmark_link ARGS2( int, cur, char *, cur_bookmark_page) @@ -332,13 +428,9 @@ PUBLIC void remove_bookmark_link ARGS2( if (!cur_bookmark_page) return; -#ifdef VMS - LYVMS_HomePathAndFilename(filename_buffer, - sizeof(filename_buffer), - cur_bookmark_page); -#else - sprintf(filename_buffer,"%s/%s", Home_Dir(), cur_bookmark_page); -#endif /* VMS */ + LYAddPathToHome(filename_buffer, + sizeof(filename_buffer), + cur_bookmark_page); if (TRACE) fprintf(stderr, "\nremove_bookmark_link: SEEKING %s\n AS %s\n\n", cur_bookmark_page, filename_buffer); @@ -407,7 +499,7 @@ PUBLIC void remove_bookmark_link ARGS2( seen++; if (++n == cur) { if (seen != 1 || !LYstrstr(buf, "</a>") || - LYstrstr(cp+1, "<a href=")) { + LYstrstr((cp + 1), "<a href=")) { _statusline(BOOKMARK_LINK_NOT_ONE_LINE); sleep(AlertSecs); goto failure; @@ -507,13 +599,7 @@ PUBLIC int select_multi_bookmarks NOARGS * still show the screen and let them do it the "long" way. */ if (LYMBMAdvanced && user_mode == ADVANCED_MODE) { - move(LYlines-1, 0); - clrtoeol(); - start_reverse(); - addstr("Select subbookmark, '=' for menu, or ^G to cancel: "); - stop_reverse(); - refresh(); - + LYMBM_statusline(MULTIBOOKMARKS_SELECT); get_advanced_choice: c = LYgetch(); #ifdef VMS @@ -581,6 +667,7 @@ PUBLIC int select_menu_multi_bookmarks NOARGS int c, MBM_counter, MBM_tmp_count, MBM_allow; int MBM_screens, MBM_from, MBM_to, MBM_current; char string_buffer[256]; + char shead_buffer[256]; char *cp, *cp1; /* @@ -626,7 +713,7 @@ PUBLIC int select_menu_multi_bookmarks NOARGS return (-2); } /* - * Load the bad choice message. + * Load the bad choice message buffer. */ sprintf(string_buffer, BOOKMARK_FILE_NOT_DEFINED, @@ -648,29 +735,36 @@ draw_bookmark_choices: MBM_to = MBM_V_MAXFILES; /* - * Display menu of bookmarks. + * Display menu of bookmarks. NOTE that we avoid printw()'s + * to increase the chances that any non-ASCII or multibyte/CJK + * characters will be handled properly. - FM */ clear(); move(1, 5); if (bold_H1 || bold_headers) start_bold(); - if (MBM_screens > 1) - printw(" Select Bookmark (screen %d of %d)", MBM_current, MBM_screens); - else - printw(" Select Bookmark"); + if (MBM_screens > 1) { + sprintf(shead_buffer, + MULTIBOOKMARKS_SHEAD_MASK, MBM_current, MBM_screens); + addstr(shead_buffer); + } else { + addstr(MULTIBOOKMARKS_SHEAD); + } if (bold_H1 || bold_headers) stop_bold(); MBM_tmp_count = 0; for (c = MBM_from; c <= MBM_to; c++) { move(3+MBM_tmp_count, 5); - printw("%c : %s",(c+'A'), - (!MBM_A_subdescript[c] ? "" : MBM_A_subdescript[c])); - + addch((unsigned char)(c + 'A')); + addstr(" : "); + if (MBM_A_subdescript[c]) + addstr(MBM_A_subdescript[c]); move(3+MBM_tmp_count,36); - printw("(%s)", - (!MBM_A_subbookmark[c] ? "" : MBM_A_subbookmark[c])); - + addch('('); + if (MBM_A_subbookmark[c]) + addstr(MBM_A_subbookmark[c]); + addch(')'); MBM_tmp_count++; } @@ -679,16 +773,21 @@ draw_bookmark_choices: */ if (MBM_screens > 1) { move(LYlines-2, 0); - addstr(MULTIBOOKMARKS_MOVE); + addstr("'"); + standout(); + addstr("["); + standend(); + addstr("' "); + addstr(PREVIOUS); + addstr(", '"); + standout(); + addstr("]"); + standend(); + addstr("' "); + addstr(NEXT_SCREEN); } - move(LYlines-1, 0); - clrtoeol(); - start_reverse(); - addstr(MULTIBOOKMARKS_SAVE); - stop_reverse(); - refresh(); - + LYMBM_statusline(MULTIBOOKMARKS_SAVE); get_bookmark_choice: c = LYgetch(); #ifdef VMS @@ -749,19 +848,9 @@ get_bookmark_choice: if (c < 0 || c > MBM_V_MAXFILES) { goto get_bookmark_choice; } else if (!MBM_A_subbookmark[c]) { - move(LYlines-1, 0); - clrtoeol(); - start_reverse(); - addstr(string_buffer); - stop_reverse(); - refresh(); + LYMBM_statusline(string_buffer); sleep(AlertSecs); - move(LYlines-1, 0); - clrtoeol(); - start_reverse(); - addstr(MULTIBOOKMARKS_SAVE); - stop_reverse(); - refresh(); + LYMBM_statusline(MULTIBOOKMARKS_SAVE); goto get_bookmark_choice; } else { return(c); @@ -784,3 +873,23 @@ PUBLIC BOOLEAN LYHaveSubBookmarks NOARGS return(FALSE); } + +/* + * This function passes a string to _statusline(), making + * sure it is at the bottom of the screen if LYMultiBookmarks + * is TRUE, otherwise, letting it go to the normal statusline + * position based on the current user mode. We want to use + * _statusline() so that any multibyte/CJK characters in the + * string will be handled properly. - FM + */ + PUBLIC void LYMBM_statusline ARGS1( + char *, text) +{ + if (LYMultiBookmarks == TRUE && user_mode == NOVICE_MODE) { + LYStatusLine = (LYlines - 1); + _statusline(text); + LYStatusLine = -1; + } else { + _statusline(text); + } +} diff --git a/src/LYBookmark.h b/src/LYBookmark.h index 41f54c6b..a776a81a 100644 --- a/src/LYBookmark.h +++ b/src/LYBookmark.h @@ -12,8 +12,7 @@ extern void remove_bookmark_link PARAMS((int cur, char *cur_bookmark_page)); extern int select_multi_bookmarks NOPARAMS; extern int select_menu_multi_bookmarks NOPARAMS; extern BOOLEAN LYHaveSubBookmarks NOPARAMS; - -extern void edit_bookmarks NOPARAMS; /* in LYOptions.c */ +extern void LYMBM_statusline PARAMS((char *text)); #define BOOKMARK_TITLE "Bookmark file" #define MOSAIC_BOOKMARK_TITLE "Converted Mosaic Hotlist" diff --git a/src/LYCgi.c b/src/LYCgi.c index 9a81fadb..de6293ec 100644 --- a/src/LYCgi.c +++ b/src/LYCgi.c @@ -296,14 +296,19 @@ PUBLIC int LYLoadCGI ARGS4( char post_len[32]; int argv_cnt = 3; /* name, one arg and terminator */ char **cur_argv = NULL; + char buf[BUFSIZ]; /* Set up output pipe */ close(fd2[0]); dup2(fd2[1], fileno(stdout)); /* Should check success code */ dup2(fd2[1], fileno(stderr)); close(fd2[1]); - - + + sprintf(buf, "HTTP_ACCEPT_LANGUAGE=%.*s", + (sizeof(buf) - 22), language); + buf[(sizeof(buf) - 1)] = '\0'; + add_environment_value(buf); + if (anAnchor->post_data) { /* post script, read stdin */ close(fd1[1]); dup2(fd1[0], fileno(stdin)); diff --git a/src/LYCharUtils.c b/src/LYCharUtils.c index 18aa65d0..5b6b94dd 100644 --- a/src/LYCharUtils.c +++ b/src/LYCharUtils.c @@ -1,22 +1,39 @@ /* -** Functions associated with LYCharSets.c and the Lynx version of HTML.c - FM -** ========================================================================== -** -** These functions should be prototyped in the Lynx version of HTML.c. +** Functions associated with LYCharSets.c and the Lynx version of HTML.c - FM +** ========================================================================== */ #include "HTUtils.h" #include "tcp.h" +#define Lynx_HTML_Handler +#include "HTChunk.h" +#include "HText.h" +#include "HTStyle.h" #include "HTML.h" -#include "HTFont.h" + #include "HTCJK.h" +#include "HTAtom.h" +#include "HTMLGen.h" #include "HTParse.h" #include "LYGlobalDefs.h" -#include "LYCharSets.h" #include "LYCharUtils.h" -#include "LYUtils.h" +#include "LYCharSets.h" + +#include "HTAlert.h" +#include "HTFont.h" +#include "HTForms.h" +#include "HTNestedList.h" #include "GridText.h" +#include "LYSignal.h" +#include "LYUtils.h" +#include "LYMap.h" +#include "LYBookmark.h" + +#ifdef VMS +#include "LYCurses.h" +#include "HTVMSUtils.h" +#endif /* VMS */ #include "LYexit.h" #include "LYLeaks.h" @@ -30,6 +47,16 @@ extern BOOL HTPassHighCtrlNum; extern HTkcode kanji_code; extern HTCJKlang HTCJK; +extern void LYSetCookie PARAMS(( + CONST char * header, + CONST char * address)); + +/* + * Used for nested lists. - FM + */ +PUBLIC int OL_CONTINUE = -29999; /* flag for whether CONTINUE is set */ +PUBLIC int OL_VOID = -29998; /* flag for whether a count is set */ + /* ** This function converts HTML named entities within a string @@ -787,7 +814,6 @@ PUBLIC void LYUnEscapeToLatinOne ARGS2( StrAllocCopy(*str, url); FREE(url); } - return; } /* @@ -868,7 +894,6 @@ PUBLIC void LYExpandString ARGS1( } StrAllocCat(*str, q); free_and_clear(&p); - return; } /* @@ -952,8 +977,6 @@ PUBLIC void LYEntify ARGS2( } } StrAllocCopy(*str, cp); - - return; } /* @@ -977,8 +1000,6 @@ PUBLIC void LYTrimHead ARGS1( } str[j] = '\0'; } - - return; } /* @@ -1002,8 +1023,6 @@ PUBLIC void LYTrimTail ARGS1( break; i--; } - - return; } /* @@ -1117,6 +1136,78 @@ PUBLIC char *LYFindEndOfComment ARGS1( } /* +** If an HREF, itself or if resolved against a base, +** represents a file URL, and the host is defaulted, +** force in "//localhost". We need this until +** all the other Lynx code which performs security +** checks based on the "localhost" string is changed +** to assume "//localhost" when a host field is not +** present in file URLs - FM +*/ +PUBLIC void LYFillLocalFileURL ARGS2( + char **, href, + char *, base) +{ + char * temp = NULL; + + if (*href == NULL || *(*href) == '\0') + return; + + if (!strcmp(*href, "//") || !strncmp(*href, "///", 3)) { + if (base != NULL && !strncmp(base, "file:", 5)) { + StrAllocCopy(temp, "file:"); + StrAllocCat(temp, *href); + StrAllocCopy(*href, temp); + } + } + if (!strncmp(*href, "file:", 5)) { + if (*(*href+5) == '\0') { + StrAllocCat(*href, "//localhost"); + } else if (!strcmp(*href, "file://")) { + StrAllocCat(*href, "localhost"); + } else if (!strncmp(*href, "file:///", 8)) { + StrAllocCopy(temp, (*href+7)); + StrAllocCopy(*href, "file://localhost"); + StrAllocCat(*href, temp); + } else if (!strncmp(*href, "file:/", 6) && *(*href+6) != '/') { + StrAllocCopy(temp, (*href+5)); + StrAllocCopy(*href, "file://localhost"); + StrAllocCat(*href, temp); + } + } + + /* + * No path in a file://localhost URL means a + * directory listing for the current default. - FM + */ + if (!strcmp(*href, "file://localhost")) { +#ifdef VMS + StrAllocCat(*href, HTVMS_wwwName(getenv("PATH"))); +#else + char curdir[DIRNAMESIZE]; +#ifdef NO_GETCWD + getwd (curdir); +#else + getcwd (curdir, DIRNAMESIZE); +#endif /* NO_GETCWD */ + StrAllocCat(*href, curdir); +#endif /* VMS */ + } + +#ifdef VMS + /* + * On VMS, a file://localhost/ URL means + * a listing for the login directory. - FM + */ + if (!strcmp(*href, "file://localhost/")) + StrAllocCat(*href, (HTVMS_wwwName((char *)Home_Dir())+1)); +#endif /* VMS */ + + FREE(temp); + return; +} + +/* ** This function returns OL TYPE="A" strings in ** the range of " A." (1) to "ZZZ." (18278). - FM */ @@ -1448,3 +1539,748 @@ PUBLIC char *LYLowercaseI_OL_String ARGS1( return OLstring; } +/* +** This function initializes the Ordered List counter. - FM +*/ +PUBLIC void LYZero_OL_Counter ARGS1( + HTStructured *, me) +{ + int i; + + if (!me) + return; + + for (i = 0; i < 7; i++) { + me->OL_Counter[i] = OL_VOID; + me->OL_Type[i] = '1'; + } + + me->Last_OL_Count = 0; + me->Last_OL_Type = '1'; + + return; +} + +/* +** This function processes META tags in HTML streams. - FM +*/ +PUBLIC void LYHandleMETA ARGS4( + HTStructured *, me, + CONST BOOL*, present, + CONST char **, value, + char **, include) +{ + char *http_equiv = NULL, *name = NULL, *content = NULL; + char *href = NULL, *id_string = NULL, *temp = NULL; + char *cp, *cp0, *cp1; + int url_type = 0, i; + + if (!me || !present) + return; + + /* + * Load the attributes for possible use by Lynx. - FM + */ + if (present[HTML_META_HTTP_EQUIV] && + value[HTML_META_HTTP_EQUIV] && *value[HTML_META_HTTP_EQUIV]) { + StrAllocCopy(http_equiv, value[HTML_META_HTTP_EQUIV]); + convert_to_spaces(http_equiv); + LYUnEscapeToLatinOne(&http_equiv, FALSE); + LYTrimHead(http_equiv); + LYTrimTail(http_equiv); + if (*http_equiv == '\0') { + FREE(http_equiv); + } + } + if (present[HTML_META_NAME] && + value[HTML_META_NAME] && *value[HTML_META_NAME]) { + StrAllocCopy(name, value[HTML_META_NAME]); + convert_to_spaces(name); + LYUnEscapeToLatinOne(&name, FALSE); + LYTrimHead(name); + LYTrimTail(name); + if (*name == '\0') { + FREE(name); + } + } + if (present[HTML_META_CONTENT] && + value[HTML_META_CONTENT] && *value[HTML_META_CONTENT]) { + /* + * Technically, we should be creating a comma-separated + * list, but META tags come one at a time, and we'll + * handle (or ignore) them as each is received. Also, + * at this point, we only trim leading and trailing + * blanks from the CONTENT value, without translating + * any named entities or numeric character references, + * because how we should do that depends on what type + * of information it contains, and whether or not any + * of it might be sent to the screen. - FM + */ + StrAllocCopy(content, value[HTML_META_CONTENT]); + convert_to_spaces(content); + LYTrimHead(content); + LYTrimTail(content); + if (*content == '\0') { + FREE(content); + } + } + if (TRACE) { + fprintf(stderr, + "LYHandleMETA: HTTP-EQUIV=\"%s\" NAME=\"%s\" CONTENT=\"%s\"\n", + (http_equiv ? http_equiv : "NULL"), + (name ? name : "NULL"), + (content ? content : "NULL")); + } + + /* + * Make sure we have META name/value pairs to handle. - FM + */ + if (!(http_equiv || name) || !content) + goto free_META_copies; + + /* + * Check for a no-cache Pragma + * or Cache-Control directive. - FM + */ + if (!strcasecomp((name ? name : http_equiv), "Pragma") || + !strcasecomp((name ? name : http_equiv), "Cache-Control")) { + LYUnEscapeToLatinOne(&content, FALSE); + LYTrimHead(content); + LYTrimTail(content); + if (!strcasecomp(content, "no-cache")) { + me->node_anchor->no_cache = TRUE; + HText_setNoCache(me->text); + } + + /* + * If we didn't get a Cache-Control MIME header, + * and the META has one, convert to lowercase, + * store it in the anchor element, and if we + * haven't yet set no_cache, check whether we + * should. - FM + */ + if ((!me->node_anchor->cache_control) && + !strcasecomp((name ? name : http_equiv), "Cache-Control")) { + for (i = 0; content[i]; i++) + content[i] = TOLOWER(content[i]); + StrAllocCopy(me->node_anchor->cache_control, content); + if (me->node_anchor->no_cache == FALSE) { + cp0 = content; + while ((cp = strstr(cp0, "no-cache")) != NULL) { + cp += 8; + while (*cp != '\0' && WHITE(*cp)) + cp++; + if (*cp == '\0' || *cp == ';') { + me->node_anchor->no_cache = TRUE; + HText_setNoCache(me->text); + break; + } + cp0 = cp; + } + if (me->node_anchor->no_cache == TRUE) + goto free_META_copies; + cp0 = content; + while ((cp = strstr(cp0, "max-age")) != NULL) { + cp += 7; + while (*cp != '\0' && WHITE(*cp)) + cp++; + if (*cp == '=') { + cp++; + while (*cp != '\0' && WHITE(*cp)) + cp++; + if (isdigit((unsigned char)*cp)) { + cp0 = cp; + while (isdigit((unsigned char)*cp)) + cp++; + if (*cp0 == '0' && cp == (cp0 + 1)) { + me->node_anchor->no_cache = TRUE; + HText_setNoCache(me->text); + break; + } + } + } + cp0 = cp; + } + } + } + + /* + * Check for an Expires directive. - FM + */ + } else if (!strcasecomp((name ? name : http_equiv), "Expires")) { + /* + * If we didn't get a Expires MIME header, + * store it in the anchor element, and if we + * haven't yet set no_cache, check whether we + * should. - FM + */ + LYUnEscapeToLatinOne(&content, FALSE); + LYTrimHead(content); + LYTrimTail(content); + StrAllocCopy(me->node_anchor->expires, content); + if (me->node_anchor->no_cache == FALSE) { + if ((content[0] == '0' && content[1] == '\0') || + LYmktime(content) <= 0) { + me->node_anchor->no_cache = TRUE; + HText_setNoCache(me->text); + } + } + + /* + * Check for a text/html Content-Type with a + * charset directive, if we didn't already set + * the charset via a server's header. - AAC & FM + */ + } else if (!(me->node_anchor->charset && *me->node_anchor->charset) && + !strcasecomp((name ? name : http_equiv), "Content-Type")) { + LYUnEscapeToLatinOne(&content, FALSE); + LYTrimHead(content); + LYTrimTail(content); + /* + * Force the Content-type value to all lower case. - FM + */ + for (cp = content; *cp; cp++) + *cp = TOLOWER(*cp); + + if ((cp = strstr(content, "text/html;")) != NULL && + (cp1 = strstr(content, "charset")) != NULL && + cp1 > cp) { + cp1 += 7; + while (*cp1 == ' ' || *cp1 == '=') + cp1++; + + if (!strncmp(cp1, "us-ascii", 8) || + !strncmp(cp1, "iso-8859-1", 10)) { + StrAllocCopy(me->node_anchor->charset, "iso-8859-1"); + HTCJK = NOCJK; + + } else if (!strncmp(cp1, "iso-8859-2", 10) && + !strncmp(LYchar_set_names[current_char_set], + "ISO Latin 2", 11)) { + StrAllocCopy(me->node_anchor->charset, "iso-8859-2"); + HTPassEightBitRaw = TRUE; + + } else if (!strncmp(cp1, "iso-8859-", 9) && + !strncmp(LYchar_set_names[current_char_set], + "Other ISO Latin", 15)) { + /* + * Hope it's a match, for now. - FM + */ + StrAllocCopy(me->node_anchor->charset, "iso-8859- "); + me->node_anchor->charset[9] = cp1[9]; + HTPassEightBitRaw = TRUE; + HTAlert(me->node_anchor->charset); + + } else if (!strncmp(cp1, "koi8-r", 6) && + !strncmp(LYchar_set_names[current_char_set], + "KOI8-R character set", 20)) { + StrAllocCopy(me->node_anchor->charset, "koi8-r"); + HTPassEightBitRaw = TRUE; + + } else if (!strncmp(cp1, "euc-jp", 6) && HTCJK == JAPANESE) { + StrAllocCopy(me->node_anchor->charset, "euc-jp"); + + } else if (!strncmp(cp1, "shift_jis", 9) && HTCJK == JAPANESE) { + StrAllocCopy(me->node_anchor->charset, "shift_jis"); + + } else if (!strncmp(cp1, "iso-2022-jp", 11) && + HTCJK == JAPANESE) { + StrAllocCopy(me->node_anchor->charset, "iso-2022-jp"); + + } else if (!strncmp(cp1, "iso-2022-jp-2", 13) && + HTCJK == JAPANESE) { + StrAllocCopy(me->node_anchor->charset, "iso-2022-jp-2"); + + } else if (!strncmp(cp1, "euc-kr", 6) && HTCJK == KOREAN) { + StrAllocCopy(me->node_anchor->charset, "euc-kr"); + + } else if (!strncmp(cp1, "iso-2022-kr", 11) && HTCJK == KOREAN) { + StrAllocCopy(me->node_anchor->charset, "iso-2022-kr"); + + } else if ((!strncmp(cp1, "big5", 4) || + !strncmp(cp1, "cn-big5", 7)) && + HTCJK == TAIPEI) { + StrAllocCopy(me->node_anchor->charset, "big5"); + + } else if (!strncmp(cp1, "euc-cn", 6) && HTCJK == CHINESE) { + StrAllocCopy(me->node_anchor->charset, "euc-cn"); + + } else if ((!strncmp(cp1, "gb2312", 6) || + !strncmp(cp1, "cn-gb", 5)) && + HTCJK == CHINESE) { + StrAllocCopy(me->node_anchor->charset, "gb2312"); + + } else if (!strncmp(cp1, "iso-2022-cn", 11) && HTCJK == CHINESE) { + StrAllocCopy(me->node_anchor->charset, "iso-2022-cn"); + } + + if (TRACE && me->node_anchor->charset) { + fprintf(stderr, + "HTML: New charset: %s\n", + me->node_anchor->charset); + } + } + /* + * Set the kcode element based on the charset. - FM + */ + HText_setKcode(me->text, me->node_anchor->charset); + + /* + * Check for a Refresh directive. - FM + */ + } else if (!strcasecomp((name ? name : http_equiv), "Refresh")) { + char *Seconds = NULL; + + /* + * Look for the Seconds field. - FM + */ + cp = content; + while (*cp && isspace((unsigned char)*cp)) + cp++; + if (*cp && isdigit(*cp)) { + cp1 = cp; + while (*cp1 && isdigit(*cp1)) + cp1++; + *cp1 = '\0'; + StrAllocCopy(Seconds, cp); + cp1++; + } + if (Seconds) { + /* + * We have the seconds field. + * Now look for a URL field - FM + */ + while (*cp1) { + if (!strncasecomp(cp1, "URL", 3)) { + cp = (cp1 + 3); + while (*cp && (*cp == '=' || isspace((unsigned char)*cp))) + cp++; + cp1 = cp; + while (*cp1 && !isspace((unsigned char)*cp1)) + cp1++; + *cp1 = '\0'; + if (*cp) + StrAllocCopy(href, cp); + break; + } + cp1++; + } + if (href) { + /* + * We found a URL field, so check it out. - FM + */ + if (!(url_type = LYLegitimizeHREF(me, (char**)&href, TRUE))) { + /* + * The specs require a complete URL, + * but this is a Netscapism, so don't + * expect the author to know that. - FM + */ + HTAlert(REFRESH_URL_NOT_ABSOLUTE); + /* + * Use the document's address + * as the base. - FM + */ + if (*href != '\0') { + temp = HTParse(href, + me->node_anchor->address, PARSE_ALL); + StrAllocCopy(href, temp); + FREE(temp); + } else { + StrAllocCopy(href, me->node_anchor->address); + HText_setNoCache(me->text); + } + } + /* + * Check whether to fill in localhost. - FM + */ + LYFillLocalFileURL((char **)&href, + (me->inBASE ? + me->base_href : me->node_anchor->address)); + /* + * Set the no_cache flag if the Refresh URL + * is the same as the document's address. - FM + */ + if (!strcmp(href, me->node_anchor->address)) { + HText_setNoCache(me->text); + } + } else { + /* + * We didn't find a URL field, so use + * the document's own address and set + * the no_cache flag. - FM + */ + StrAllocCopy(href, me->node_anchor->address); + HText_setNoCache(me->text); + } + /* + * Check for an anchor in http or https URLs. - FM + */ + if ((strncmp(href, "http", 4) == 0) && + (cp = strrchr(href, '#')) != NULL) { + StrAllocCopy(id_string, cp); + *cp = '\0'; + } + me->CurrentA = HTAnchor_findChildAndLink( + me->node_anchor, /* Parent */ + id_string, /* Tag */ + href, /* Addresss */ + (void *)0); /* Type */ + if (id_string) + *cp = '#'; + FREE(id_string); + LYEnsureSingleSpace(me); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR); + HTML_put_string(me, "REFRESH("); + HTML_put_string(me, Seconds); + HTML_put_string(me, " sec):"); + FREE(Seconds); + if (me->inUnderline == FALSE) + HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); + HTML_put_character(me, ' '); + me->in_word = NO; + HText_beginAnchor(me->text, me->CurrentA); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_START_CHAR); + HTML_put_string(me, href); + FREE(href); + if (me->inBoldH == FALSE) + HText_appendCharacter(me->text, LY_BOLD_END_CHAR); + HText_endAnchor(me->text); + LYEnsureSingleSpace(me); + } + + /* + * Check for a suggested filename via a Content-Disposition with + * file; filename=name.suffix in it, if we don't already have it + * via a server header. - FM + */ + } else if (!(me->node_anchor->SugFname && *me->node_anchor->SugFname) && + !strcasecomp((name ? + name : http_equiv), "Content-Disposition")) { + cp = content; + while (*cp != '\0' && strncasecomp(cp, "file;", 5)) + cp++; + if (*cp != '\0') { + cp += 5; + while (*cp != '\0' && WHITE(*cp)) + cp++; + if (*cp != '\0') { + while (*cp != '\0' && strncasecomp(cp, "filename=", 9)) + cp++; + if (*cp != '\0') { + StrAllocCopy(me->node_anchor->SugFname, (cp + 9)); + cp = me->node_anchor->SugFname; + while (*cp != '\0' && !WHITE(*cp)) + cp++; + *cp = '\0'; + if (*me->node_anchor->SugFname == '\0') + FREE(me->node_anchor->SugFname); + } + } + } + /* + * Check for a Set-Cookie directive. - AK + */ + } else if (!strcasecomp((name ? name : http_equiv), "Set-Cookie")) { + /* + * We're using the Request-URI as the second argument, + * regardless of whether a Content-Base header or BASE + * tag are present. + */ + LYSetCookie(content, me->node_anchor->address); + } + + /* + * Free the copies. - FM + */ +free_META_copies: + FREE(http_equiv); + FREE(name); + FREE(content); +} + +/* +** This function strips white characters and +** generally fixes up attribute values that +** were received from the SGML parser and +** are to be treated as partial or absolute +** URLs. - FM +*/ +PUBLIC int LYLegitimizeHREF ARGS3( + HTStructured *, me, + char **, href, + BOOL, force_slash) +{ + int url_type = 0; + + if (!me || !href || *href == NULL || *(*href) == '\0') + return(url_type); + + collapse_spaces(*href); + LYUnEscapeToLatinOne(&(*href), TRUE); + url_type = is_url(*href); + if (!url_type && force_slash && + (!strcmp(*href, ".") || !strcmp(*href, "..")) && + strncmp((me->inBASE ? + me->base_href : me->node_anchor->address), + "file:", 5)) { + /* + * The Fielding RFC/ID for resolving partial HREFs says + * that a slash should be on the end or the preceding + * symbolic element for "." and "..", but all tested + * browsers only do that for an explicit "./" or "../", + * so we'll respect the RFC/ID only if force_slash was + * TRUE and it's not a file URL. - FM + */ + StrAllocCat(*href, "/"); + } + return(url_type); +} + +/* +** This function checks for a Content-Base header, +** and if not present, a Content-Location header +** which is an absolute URL, and sets the BASE +** accordingly. If set, it will be replaced by +** any BASE tag in the HTML stream, itself. - FM +*/ +PUBLIC void LYCheckForContentBase ARGS1( + HTStructured *, me) +{ + char *cp = NULL; + BOOL present[HTML_BASE_ATTRIBUTES]; + CONST char *value[HTML_BASE_ATTRIBUTES]; + int i; + + if (!(me && me->node_anchor)) + return; + + if (me->node_anchor->content_base != NULL) { + /* + * We have a Content-Base value. Use it + * if it's non-zero length. - FM + */ + if (*me->node_anchor->content_base == '\0') + return; + StrAllocCopy(cp, me->node_anchor->content_base); + collapse_spaces(cp); + } else if (me->node_anchor->content_location != NULL) { + /* + * We didn't have a Content-Base value, but do + * have a Content-Location value. Use it if + * it's an absolute URL. - FM + */ + if (*me->node_anchor->content_location == '\0') + return; + StrAllocCopy(cp, me->node_anchor->content_location); + collapse_spaces(cp); + if (!is_url(cp)) { + FREE(cp); + return; + } + } else { + /* + * We had neither a Content-Base nor + * Content-Location value. - FM + */ + return; + } + + /* + * If we collapsed to a zero-length value, + * ignore it. - FM + */ + if (*cp == '\0') { + FREE(cp); + return; + } + + /* + * Pass the value to HTML_start_element as + * the HREF of a BASE tag. - FM + */ + for (i = 0; i < HTML_BASE_ATTRIBUTES; i++) + present[i] = NO; + present[HTML_BASE_HREF] = YES; + value[HTML_BASE_HREF] = (CONST char *)cp; + (*me->isa->start_element)(me, HTML_BASE, present, value, 0); + FREE(cp); +} + +/* +** This function creates NAMEd Anchors if a non-zero-length NAME +** or ID attribute was present in the tag. - FM +*/ +PUBLIC void LYCheckForID ARGS4( + HTStructured *, me, + CONST BOOL *, present, + CONST char **, value, + int, attribute) +{ + HTChildAnchor *ID_A = NULL; + char *temp = NULL; + + if (!(me && me->text)) + return; + + if (present && present[attribute] + && value[attribute] && *value[attribute]) { + /* + * Translate any named or numeric character references. - FM + */ + StrAllocCopy(temp, value[attribute]); + LYUnEscapeToLatinOne(&temp, TRUE); + + /* + * Create the link if we still have a non-zero-length string. - FM + */ + if ((temp[0] != '\0') && + (ID_A = HTAnchor_findChildAndLink( + me->node_anchor, /* Parent */ + temp, /* Tag */ + NULL, /* Addresss */ + (void *)0))) { /* Type */ + HText_beginAnchor(me->text, ID_A); + HText_endAnchor(me->text); + } + FREE(temp); + } +} + +/* +** This function creates a NAMEd Anchor for the ID string +** passed to it directly as an argument. It assumes the +** does not need checking for character references. - FM +*/ +PUBLIC void LYHandleID ARGS2( + HTStructured *, me, + char *, id) +{ + HTChildAnchor *ID_A = NULL; + + if (!(me && me->text) || + !(id && *id)) + return; + + /* + * Create the link if we still have a non-zero-length string. - FM + */ + if (ID_A = HTAnchor_findChildAndLink( + me->node_anchor, /* Parent */ + id, /* Tag */ + NULL, /* Addresss */ + (void *)0)) { /* Type */ + HText_beginAnchor(me->text, ID_A); + HText_endAnchor(me->text); + } +} + +/* +** This function checks whether we want to overrride +** the current default alignment for parargraphs and +** instead use that specified in the element's style +** sheet. - FM +*/ +PUBLIC BOOLEAN LYoverride_default_alignment ARGS1( + HTStructured *, me) +{ + if (!me) + return NO; + + switch(me->sp[0].tag_number) { + case HTML_BLOCKQUOTE: + case HTML_BQ: + case HTML_NOTE: + case HTML_FN: + case HTML_ADDRESS: + me->sp->style->alignment = HT_LEFT; + return YES; + break; + + default: + break; + } + return NO; +} + +/* +** This function inserts newlines if needed to create double spacing, +** and sets the left margin for subsequent text to the second line +** indentation of the current style. - FM +*/ +PUBLIC void LYEnsureDoubleSpace ARGS1( + HTStructured *, me) +{ + if (!me || !me->text) + return; + + if (HText_LastLineSize(me->text)) { + HText_appendCharacter(me->text, '\r'); + HText_appendCharacter(me->text, '\r'); + } else if (HText_PreviousLineSize(me->text)) { + HText_appendCharacter(me->text, '\r'); + } else if (me->List_Nesting_Level >= 0) { + HText_NegateLineOne(me->text); + } + me->in_word = NO; + return; +} + +/* +** This function inserts a newline if needed to create single spacing, +** and sets the left margin for subsequent text to the second line +** indentation of the current style. - FM +*/ +PUBLIC void LYEnsureSingleSpace ARGS1( + HTStructured *, me) +{ + if (!me || !me->text) + return; + + if (HText_LastLineSize(me->text)) { + HText_appendCharacter(me->text, '\r'); + } else if (me->List_Nesting_Level >= 0) { + HText_NegateLineOne(me->text); + } + me->in_word = NO; + return; +} + +/* +** This function resets paragraph alignments for block +** elements which do not have a defined style sheet. - FM +*/ +PUBLIC void LYResetParagraphAlignment ARGS1( + HTStructured *, me) +{ + if (!me) + return; + + if (me->List_Nesting_Level >= 0 || + ((me->Division_Level < 0) && + (!strcmp(me->sp->style->name, "Normal") || + !strcmp(me->sp->style->name, "Preformatted")))) { + me->sp->style->alignment = HT_LEFT; + } else { + me->sp->style->alignment = me->current_default_alignment; + } + return; +} + +PUBLIC BOOLEAN LYCheckForCSI ARGS2( + HTStructured *, me, + char **, url) +{ + if (!(me && me->node_anchor && me->node_anchor->address)) + return FALSE; + + if (strncasecomp(me->node_anchor->address, "file:", 5)) + return FALSE; + + if (!LYisLocalHost(me->node_anchor->address)) + return FALSE; + + StrAllocCopy(*url, me->node_anchor->address); + return TRUE; +} diff --git a/src/LYCharUtils.h b/src/LYCharUtils.h index 880bd19a..94c5e1fd 100644 --- a/src/LYCharUtils.h +++ b/src/LYCharUtils.h @@ -6,20 +6,71 @@ #include "HTUtils.h" #endif /* HTUTILS_H */ -extern char * LYUnEscapeEntities PARAMS((char *str, - BOOLEAN plain_space, - BOOLEAN hidden)); -extern void LYUnEscapeToLatinOne PARAMS((char **str, - BOOLEAN isURL)); -extern void LYExpandString PARAMS((char **str)); -extern void LYEntify PARAMS((char **str, - BOOLEAN isTITLE)); -extern void LYTrimHead PARAMS((char *str)); -extern void LYTrimTail PARAMS((char *str)); -extern char *LYFindEndOfComment PARAMS((char *str)); -extern char *LYUppercaseA_OL_String PARAMS((int seqnum)); -extern char *LYLowercaseA_OL_String PARAMS((int seqnum)); -extern char *LYUppercaseI_OL_String PARAMS((int seqnum)); -extern char *LYLowercaseI_OL_String PARAMS((int seqnum)); +extern char * LYUnEscapeEntities PARAMS(( + char * str, + BOOLEAN plain_space, + BOOLEAN hidden)); +extern void LYUnEscapeToLatinOne PARAMS(( + char ** str, + BOOLEAN isURL)); +extern void LYExpandString PARAMS(( + char ** str)); +extern void LYEntify PARAMS(( + char ** str, + BOOLEAN isTITLE)); +extern void LYTrimHead PARAMS(( + char * str)); +extern void LYTrimTail PARAMS(( + char * str)); +extern char *LYFindEndOfComment PARAMS(( + char * str)); +extern void LYFillLocalFileURL PARAMS(( + char ** href, + char * base)); + +#ifdef Lynx_HTML_Handler +extern int OL_CONTINUE; /* flag for whether CONTINUE is set */ +extern int OL_VOID; /* flag for whether a count is set */ +extern void LYZero_OL_Counter PARAMS(( + HTStructured * me)); +extern char *LYUppercaseA_OL_String PARAMS(( + int seqnum)); +extern char *LYLowercaseA_OL_String PARAMS(( + int seqnum)); +extern char *LYUppercaseI_OL_String PARAMS(( + int seqnum)); +extern char *LYLowercaseI_OL_String PARAMS(( + int seqnum)); +extern void LYHandleMETA PARAMS(( + HTStructured * me, + CONST BOOL* present, + CONST char ** value, + char ** include)); +extern int LYLegitimizeHREF PARAMS(( + HTStructured * me, + char ** href, + BOOL force_slash)); +extern void LYCheckForContentBase PARAMS(( + HTStructured * me)); +extern void LYCheckForID PARAMS(( + HTStructured * me, + CONST BOOL * present, + CONST char ** value, + int attribute)); +extern void LYHandleID PARAMS(( + HTStructured * me, + char * id)); +extern BOOLEAN LYoverride_default_alignment PARAMS(( + HTStructured * me)); +extern void LYEnsureDoubleSpace PARAMS(( + HTStructured * me)); +extern void LYEnsureSingleSpace PARAMS(( + HTStructured * me)); +extern void LYResetParagraphAlignment PARAMS(( + HTStructured * me)); +extern BOOLEAN LYCheckForCSI PARAMS(( + HTStructured * me, + char ** url)); +#endif /* Lynx_HTML_Handler */ #endif /* LYCHARUTILS_H */ diff --git a/src/LYClean.c b/src/LYClean.c index ed2238a8..2d97a386 100644 --- a/src/LYClean.c +++ b/src/LYClean.c @@ -11,40 +11,51 @@ #include "LYexit.h" #include "LYLeaks.h" +#define FREE(x) if (x) {free(x); x = NULL;} + #ifdef VMS BOOLEAN HadVMSInterrupt = FALSE; #endif /* VMS */ /* - * Interrupt handler. Stop curses and exit gracefully. + * Interrupt handler. Stop curses and exit gracefully. */ -PUBLIC void cleanup_sig ARGS1(int,sig) +PUBLIC void cleanup_sig ARGS1( + int, sig) { #ifdef IGNORE_CTRL_C - if(sig == SIGINT) { - /* Need to rearm the signal */ - signal(SIGINT, cleanup_sig); - sigint = TRUE; - return; - } + if (sig == SIGINT) { + /* + * Need to rearm the signal. + */ + signal(SIGINT, cleanup_sig); + sigint = TRUE; + return; + } #endif /* IGNORE_CTRL_C */ #ifdef VMS if (!dump_output_immediately) { int c; - /* Reassert the AST */ + /* + * Reassert the AST. + */ (void) signal(SIGINT, cleanup_sig); HadVMSInterrupt = TRUE; if (!LYCursesON) return; - /* Refresh screen to get rid of "cancel" message, then query */ + /* + * Refresh screen to get rid of "cancel" message, then query. + */ clearok(curscr, TRUE); refresh(); - /* Ask if exit is intended */ + /* + * Ask if exit is intended. + */ _statusline(REALLY_EXIT); c = LYgetch(); #ifdef QUIT_DEFAULT_YES @@ -56,10 +67,15 @@ PUBLIC void cleanup_sig ARGS1(int,sig) } #endif /* VMS */ - /* ignore further interrupts */ /* mhc: 11/2/91 */ + /* + * Ignore further interrupts. - mhc: 11/2/91 + */ (void) signal(SIGHUP, SIG_IGN); -#ifdef VMS /* use ttclose() from cleanup() for VMS if not dumping */ +#ifdef VMS + /* + * Use ttclose() from cleanup() for VMS if not dumping. + */ if (dump_output_immediately) #else /* Unix: */ (void) signal(SIGINT, SIG_IGN); @@ -67,18 +83,24 @@ PUBLIC void cleanup_sig ARGS1(int,sig) (void) signal(SIGTERM, SIG_IGN); + if (traversal) + dump_traversal_history(); + if (sig != SIGHUP) { - if (!dump_output_immediately) - cleanup(); /* <==also calls cleanup_files() */ - printf("\nExiting via interrupt: %d\n", sig); - fflush(stdout); + if (!dump_output_immediately) { + /* + * cleanup() also calls cleanup_files(). + */ + cleanup(); + } + if (sig != 0) { + printf("\r\nExiting via interrupt: %d\r\n", sig); + fflush(stdout); + } } else { cleanup_files(); } - if (traversal) - dump_traversal_history(); - (void) signal(SIGHUP, SIG_DFL); (void) signal(SIGTERM, SIG_DFL); #ifndef VMS @@ -86,33 +108,38 @@ PUBLIC void cleanup_sig ARGS1(int,sig) #endif /* !VMS */ #ifdef SIGTSTP if (no_suspend) - (void) signal(SIGTSTP,SIG_DFL); + (void) signal(SIGTSTP, SIG_DFL); #endif /* SIGTSTP */ - exit(0); + if (sig != 0) { + exit(0); + } } /* - * called by Interrupt handler or at quit time. - * Erases the temporary files that lynx created - * temporary files are removed by tempname - * which created them + * Called by Interrupt handler or at quit time. + * Erases the temporary files that lynx created + * temporary files are removed by tempname + * which created them. */ PUBLIC void cleanup_files NOARGS { - char filename[120]; + char filename[256]; - tempname(filename, REMOVE_FILES); - + tempname(filename, REMOVE_FILES); + FREE(lynx_temp_space); } PUBLIC void cleanup NOARGS { + int i; #ifdef VMS extern BOOLEAN DidCleanup; #endif /* VMS */ - /* cleanup signals - just in case */ - /* ignore further interrupts */ /* mhc: 11/2/91 */ + /* + * Cleanup signals - just in case. + * Ignore further interrupts. - mhc: 11/2/91 + */ (void) signal (SIGHUP, SIG_IGN); (void) signal (SIGTERM, SIG_IGN); @@ -132,11 +159,18 @@ PUBLIC void cleanup NOARGS stop_curses(); } cleanup_files(); + for (i = 0; i < nhist; i++) { + FREE(history[i].title); + FREE(history[i].address); + FREE(history[i].post_data); + FREE(history[i].post_content_type); + FREE(history[i].bookmark); + } + nhist = 0; #ifdef VMS ttclose(); DidCleanup = TRUE; #endif /* VMS */ - fflush(stdout); + fflush(stdout); } - diff --git a/src/LYCookie.c b/src/LYCookie.c new file mode 100644 index 00000000..957314bf --- /dev/null +++ b/src/LYCookie.c @@ -0,0 +1,1262 @@ +/* Lynx Cookie Support LYCookies.c +** =================== +** +** Author: AMK A.M. Kuchling (amk@magnet.com) 12/25/96 +** +** Incorporated with mods by FM 01/16/97 +** +** Based on: +** http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-state-mgmt-05.txt +** +** TO DO: (roughly in order of decreasing priority) + * host_matches() is only lightly tested in the Internet at large. + * Hex escaping isn't considered at all. Any semi-colons, commas, + or spaces actually in cookie names or values (i.e., not serving + as punctuation for the overall Set-Cookie value) should be hex + escaped if not quoted, but presumeably the server is expecting + them to be hex escaped in our Cookie request header as well, so + in theory we need not unescape them. We'll see how this works + out in practice. + * The prompt should show more information about the cookie being + set in Novice mode. + * The truncation heuristic in HTConfirmCookie should probably be + smarter, smart enough to leave a really short name/value string + alone. + * We protect against denial-of-service attacks (see section 6.3.1 + of the draft) by limiting a domain to 50 cookies, limiting the + total number of cookies to 500, and limiting a processed cookie + to a maximum of 4096 bytes, but we count on the normal garbage + collections to bring us back down under the limits, rather than + actively removing cookies and/or domains based on age or frequency + of use. + * The comments in this file chould contain extracts from the -05 + HTTP State Management draft (URL above). + * If the a cookie has the secure flag set, we presently treat only + SSL connections as secure. This may need to be expanded for other + secure communication protocols that become standarized. + * Cookies could be optionally stored in a file from session to session. +*/ + +#include "HTUtils.h" +#include "tcp.h" +#include "HTAccess.h" +#include "HTParse.h" +#include "HTAlert.h" +#include "LYCurses.h" +#include "LYSignal.h" +#include "LYUtils.h" +#include "LYCharUtils.h" +#include "LYClean.h" +#include "LYGlobalDefs.h" +#include "LYEdit.h" +#include "LYStrings.h" +#include "LYSystem.h" +#include "GridText.h" +#include "LYCookie.h" + +#define FREE(x) if (x) {free(x); x = NULL;} + +/* +** The first level of the cookie list is a list indexed by the domain +** string; cookies with the same domain will be placed in the same +** list. Thus, finding the cookies that apply to a given URL is a +** two-level scan; first we check each domain to see if it applies, +** and if so, then we check the paths of all the cookies on that +** list. We keep a running total of cookies as we add or delete +** them +*/ +PRIVATE HTList *domain_list = NULL; +PRIVATE HTList *cookie_list = NULL; +PRIVATE int total_cookies = 0; + +struct _cookie { + char *lynx_id; /* Lynx cookie identifier */ + char *name; /* Name of this cookie */ + char *value; /* Value of this cookie */ + int version; /* Cookie protocol version (=1) */ + char *comment; /* Comment to show to user */ + char *domain; /* Domain for which this cookie is valid */ + int port; /* Server port from which this cookie was given (usu. 80) */ + char *path; /* Path prefix for which this cookie is valid */ + int pathlen; /* Length of the path */ + int flags; /* Various flags */ + time_t expires; /* The time when this cookie expires */ +}; +typedef struct _cookie cookie; + +#define COOKIE_FLAG_SECURE 1 /* If set, cookie requires secure links */ +#define COOKIE_FLAG_EXPIRES_SET 2 /* If set, an expiry date was set */ + +struct _HTStream +{ + HTStreamClass * isa; +}; + +PRIVATE void MemAllocCopy ARGS3( + char **, dest, + CONST char *, start, + CONST char *, end) +{ + char *temp = (char *)calloc(1, ((end - start) + 1)); + + if (temp == NULL) + outofmem(__FILE__, "MemAllocCopy"); + + LYstrncpy(temp, (char *)start, (end - start)); + HTSACopy(dest, temp); + FREE(temp); +} + +PRIVATE cookie * newCookie NOARGS +{ + cookie *p = (cookie *)calloc(1, sizeof(cookie)); + char lynx_id[64]; + + if (p == NULL) + outofmem(__FILE__, "newCookie"); + sprintf(lynx_id, "%p", p); + StrAllocCopy(p->lynx_id, lynx_id); + p->port = 80; + return p; +} + +PRIVATE void freeCookie ARGS1( + cookie *, co) +{ + if (co) { + FREE(co->lynx_id); + FREE(co->name); + FREE(co->value); + FREE(co->comment); + FREE(co->domain); + FREE(co->path); + FREE(co); + } +} + +PRIVATE void LYCookieJar_free NOARGS +{ + HTList *dl = domain_list; + domain_entry *de = NULL; + HTList *cl = NULL, *next = NULL; + cookie *co = NULL; + + while (dl) { + if ((de = dl->object) != NULL) { + cl = de->cookie_list; + while (cl) { + next = cl->next; + if (co) { + co = cl->object; + HTList_removeObject(de->cookie_list, co); + freeCookie(co); + co = NULL; + } + cl = next; + } + FREE(de->domain); + HTList_delete(de->cookie_list); + de->cookie_list = NULL; + } + dl = dl->next; + } + cookie_list = NULL; + HTList_delete(domain_list); + domain_list = NULL; +} + +/* +** Compare two hostnames as specified in Section 2 of: +** http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-state-mgmt-05.txt +*/ +PRIVATE BOOLEAN host_matches ARGS2( + CONST char *, A, + CONST char *, B) +{ + /* + * The following line will handle both numeric IP addresses and + * FQDNs. Do numeric addresses require special handling? + */ + if (*B != '.' && !strcmp(A, B)) + return YES; + + /* + * The following will pass a "dotted tail" match to "a.b.c.e" + * as described in Section 2 of the -05 draft. + */ + if (*B == '.') { + int diff = (strlen(A) - strlen(B)); + if (diff > 0) { + if (!strcmp((A + diff), B)) + return YES; + } + } + return NO; +} + +/* +** Store a cookie somewhere in the domain list. +*/ +PRIVATE void store_cookie ARGS3( + cookie *, co, + CONST char *, hostname, + CONST char *, path) +{ + HTList *hl, *next; + cookie *c2; + time_t now = time(NULL); + int pathlen, pos; + CONST char *ptr; + domain_entry *de = NULL; + + if (co == NULL) + return; + + /* + * Apply sanity checks. + * + * Section 4.3.2, condition 1: The value for the Path attribute is + * not a prefix of the request-URI. + */ + if (strncmp(co->path, path, co->pathlen) != 0) + return; + /* + * The next 4 conditions do NOT apply if the domain is still + * the default of request-host. + */ + if (strcmp(co->domain, hostname) != 0) { + /* + * The hostname does not contain a dot. + */ + if (strchr(hostname, '.') == NULL) + return; + + /* + * Section 4.3.2, condition 2: The value for the Domain attribute + * contains no embedded dots or does not start with a dot. + * (A dot is embedded if it's neither the first nor last character.) + */ + if (co->domain[0] != '.' || co->domain[1] == '\0') + return; + ptr = strchr((co->domain + 1), '.'); + if (ptr == NULL || ptr[1] == '\0') + return; + + /* + * Section 4.3.2, condition 3: The value for the request-host does + * not domain-match the Domain attribute. + */ + if (!host_matches(hostname, co->domain)) + return; + + /* + * Section 4.3.2, condition 4: The request-host is a FQDN (not IP + * address) and has the form HD, where D is the value of the Domain + * attribute, and H is a string that contains one or more dots. + */ + ptr = ((hostname + strlen(hostname)) - strlen(co->domain)); + if (strchr(hostname, '.') < ptr) + return; + } + + /* + * Ensure that the domain list exists. + */ + if (domain_list == NULL) { + atexit(LYCookieJar_free); + domain_list = HTList_new(); + total_cookies = 0; + } + + /* + * Look through domain_list to see if the cookie's domain + * is already listed. + */ + if (dump_output_immediately) { /* Non-interactive, can't respond */ + if (cookie_list == NULL) + cookie_list = HTList_new(); + } else { + cookie_list = NULL; + for (hl = domain_list; hl != NULL; hl = hl->next) { + de = (domain_entry *)hl->object; + if ((de != NULL && de->domain != NULL) && + !strcmp(co->domain, de->domain)) { + cookie_list = de->cookie_list; + break; + } + } + if (hl == NULL) { + /* + * Domain not found; add a new entry for this domain. + */ + de = (domain_entry *)calloc(1, sizeof(domain_entry)); + if (de == NULL) + outofmem(__FILE__, "store_cookie"); + de->bv = QUERY_USER; + cookie_list = de->cookie_list = HTList_new(); + StrAllocCopy(de->domain, co->domain); + HTList_addObject(domain_list, de); + } + } + + /* + * Loop over the cookie list, deleting expired and matching cookies. + */ + hl = cookie_list; + pos = 0; + while (hl) { + c2 = (cookie *)hl->object; + next = hl->next; + /* + * Check if this cookie has expired. + */ + if ((c2 != NULL) && + (c2->flags & COOKIE_FLAG_EXPIRES_SET) && + c2->expires < now) { + HTList_removeObject(cookie_list, c2); + freeCookie(c2); + c2 = NULL; + total_cookies--; + + /* + * Check if this cookie matches the one we're inserting. + */ + } else if ((c2) && (co->port == c2->port) && + !strcmp(co->domain, c2->domain) && + !strcmp(co->path, c2->path) && + !strcmp(co->name, c2->name)) { + HTList_removeObject(cookie_list, c2); + freeCookie(c2); + c2 = NULL; + total_cookies--; + + } else if ((c2) && (c2->pathlen) > (co->pathlen)) { + pos++; + } + hl = next; + } + + /* + * Don't bother to add the cookie if it's already expired. + */ + if ((co->flags & COOKIE_FLAG_EXPIRES_SET) && co->expires < now) { + freeCookie(co); + co = NULL; + + /* + * Don't add the cookie if we're over the domain's limit. - FM + */ + } else if (HTList_count(cookie_list) > 50) { + if (TRACE) + fprintf(stderr, + "store_cookie: Domain's cookie limit exceeded! Rejecting cookie.\n"); + freeCookie(co); + co = NULL; + + /* + * Don't add the cookie if we're over the total cookie limit. - FM + */ + } else if (total_cookies > 500) { + if (TRACE) + fprintf(stderr, + "store_cookie: Total cookie limit exceeded! Rejecting cookie.\n"); + freeCookie(co); + co = NULL; + + /* + * Get confirmation if we need it, and add cookie + * if confirmed or 'allow' is set to always. - FM + */ + } else if (HTConfirmCookie(de, hostname, + co->domain, co->path, co->name, co->value)) { + HTList_insertObjectAt(cookie_list, co, pos); + total_cookies++; + } else { + freeCookie(co); + co = NULL; + } +} + +PRIVATE char * scan_cookie_sublist ARGS6( + CONST char *, hostname, + CONST char *, path, + int, port, + HTList *, sublist, + char *, header, + BOOL, secure) +{ + HTList *hl = sublist, *next = NULL; + cookie *co; + time_t now = time(NULL); + + while (hl) { + co = (cookie *)hl->object; + next = hl->next; + + if (TRACE && co) { + fprintf(stderr, "Checking cookie %x %s=%s\n", + hl, + (co->name ? co->name : "(no name)"), + (co->value ? co->value : "(no value)")); + fprintf(stderr, "%s %s %i %s %s %i%s\n", + hostname, + (co->domain ? co->domain : "(no domain)"), + host_matches(hostname, co->domain), + path, co->path, ((co->pathlen > 0) ? + strncmp(path, co->path, co->pathlen) : 0), + ((co->flags & COOKIE_FLAG_SECURE) ? + " secure" : "")); + } + /* + * Check if this cookie has expired, and if so, delete it. + */ + if (((co) && (co->flags & COOKIE_FLAG_EXPIRES_SET)) && + co->expires < now) { + HTList_removeObject(sublist, co); + freeCookie(co); + co = NULL; + total_cookies--; + } + + /* + * Check if we have a unexpired match, and handle if we do. + */ + if (((co != NULL) && + co->port == port && host_matches(hostname, co->domain)) && + (co->pathlen == 0 || !strncmp(path, co->path, co->pathlen))) { + /* + * Skip if the secure flag is set and we don't have + * a secure connection. HTTP.c presently treats only + * SSL connections as secure. - FM + */ + if ((co->flags & COOKIE_FLAG_SECURE) && secure == FALSE) { + hl = next; + continue; + } + + /* + * Start or append to the request header. + */ + if (header == NULL) { + if (co->version > 0) { + /* + * For Version 1 (or greater) cookies, + * the version number goes before the + * first cookie. + */ + char version[16]; + sprintf(version, "$Version=%i; ", co->version); + StrAllocCopy(header, version); + } + } else { + /* + * There's already cookie data there, + * so add a separator. + */ + StrAllocCat(header, "; "); + } + /* + * Include the cookie name=value pair. + */ + StrAllocCat(header, co->name); + StrAllocCat(header, "="); + StrAllocCat(header, co->value); + /* + * For Version 1 (or greater) cookies, add + * attributes for the cookie. - FM + */ + if (co->version > 0) { + if (co->path) { + /* + * Append the path attribute. - FM + */ + StrAllocCat(header, "; $Path="); + StrAllocCat(header, co->path); + } + if (co->domain) { + /* + * Append the domain attribute. - FM + */ + StrAllocCat(header, "; $Domain="); + StrAllocCat(header, co->domain); + } + } + } + hl = next; + } + + return(header); +} + +PUBLIC void LYSetCookie ARGS2( + CONST char *, header, + CONST char *, address) +{ + CONST char *p, *attr_start, *attr_end, *value_start, *value_end; + char *hostname = NULL, *path = NULL, *ptr; + cookie *cur_cookie = NULL; + int port = 80; + int length = 0; + + /* + * Get the hostname, port and path of the address, and report + * the Set-Cookie request if trace mode is on, but set the cookie + * only if LYSetCookies is TRUE. - FM + */ + if (((hostname = HTParse(address, "", PARSE_HOST)) != NULL) && + (ptr = strchr(hostname, ':')) != NULL) { + /* + * Replace default port number. + */ + *ptr = '\0'; + ptr++; + port = atoi(ptr); + } else if (!strncasecomp(address, "https:", 6)) { + port = 443; + } + if (((path = HTParse(address, "", + PARSE_PATH|PARSE_PUNCTUATION)) != NULL) && + (ptr = strrchr(path, '/')) != NULL) { + if (ptr == path) + *(ptr+1) = '\0'; /* Leave a single '/' alone */ + else + *ptr = '\0'; + } + if (TRACE) { + fprintf(stderr, + "LYSetCookie called with host '%s', path '%s',\n and header '%s'%s\n", + (hostname ? hostname : ""), + (path ? path : ""), + (header ? header : ""), + (LYSetCookies ? "" : "\n Ignoring this Set-Cookie request.")); + } + if (LYSetCookies == FALSE) { + FREE(hostname); + FREE(path); + return; + } + + /* + * Process the Set-Cookie header value. + */ + p = (char *)header; + while (length <= 4096 && *p) { + attr_start = attr_end = value_start = value_end = NULL; +#define SKIP_SPACES while (*p != '\0' && isspace((unsigned char)*p)) p++; + SKIP_SPACES; + /* + * Get the attribute name. + */ + attr_start = p; + while (*p != '\0' && !isspace((unsigned char)*p) && + *p != '=' && *p != ';' && *p != ',') + p++; + attr_end = p; + + if (*p == '=') { + /* + * Get the value string. + */ + p++; + SKIP_SPACES; + /* + * Hack alert! We must handle Netscape-style cookies with + * "Expires=Mon, 01-Jan-96 13:45:35 GMT" or + * "Expires=Mon, 1 Jan 1996 13:45:35 GMT". + * No quotes, but there are spaces. Argh... + * Anyway, we know it will have at least 3 space separators + * within it, and two dashes or two more spaces, so this code + * looks for a space after the 5th space separator or dash to + * mark the end of the value. - FM + */ + if ((attr_end - attr_start) == 7 && + !strncasecomp(attr_start, "Expires", 7)) { + int spaces = 6; + value_start = p; + while (*p != '\0' && *p != ';' && spaces) { + p++; + if (isspace((unsigned char)*p)) { + while (isspace((unsigned char)*(p + 1))) + p++; + spaces--; + } else if (*p == '-') { + spaces--; + } + } + value_end = p; + } else if (*p == '"') { + /* + * It's a quoted string. + */ + p++; + value_start = p; + while (*p != '\0' && *p != '"') + p++; + value_end = p; + if (*p == '"') + p++; + } else { + /* + * Otherwise, it's an unquoted string. + */ + SKIP_SPACES; + value_start = p; + while (*p != '\0' && !isspace((unsigned char)*p) && *p != ';') + p++; + value_end = p; + } + } + + /* + * Check for a separator character, and skip it. + */ + if (*p == ';') + p++; + + /* + * Now, we can handle this attribute/value pair. + */ + if (attr_end != attr_start) { + int len = (attr_end - attr_start); + BOOLEAN known_attr = NO; + char *value = NULL; + + if (value_end > value_start) { + int value_len = (value_end - value_start); + + length += value_len; + if (length > 4096) + break; + value = (char *)calloc(1, value_len + 1); + if (value == NULL) + outofmem(__FILE__, "LYSetCookie"); + LYstrncpy(value, (char *)value_start, value_len); + } + if (len == 6 && !strncasecomp(attr_start, "secure", 6)) { + known_attr = YES; + if (cur_cookie != NULL) + cur_cookie->flags |= COOKIE_FLAG_SECURE; + } else if (len == 7 && !strncasecomp(attr_start, "comment", 7)) { + known_attr = YES; + if (cur_cookie != NULL && value) + StrAllocCopy(cur_cookie->comment, value); + } else if (len == 6 && !strncasecomp(attr_start, "domain", 6)) { + known_attr = YES; + if (cur_cookie != NULL && value) + StrAllocCopy(cur_cookie->domain, value); + } else if (len == 4 && !strncasecomp(attr_start, "path", 4)) { + known_attr = YES; + if (cur_cookie != NULL && value) { + StrAllocCopy(cur_cookie->path, value); + cur_cookie->pathlen = strlen(cur_cookie->path); + } + } else if (len == 7 && !strncasecomp(attr_start, "version", 7)) { + known_attr = YES; + if (cur_cookie != NULL && value) { + int temp = strtol(value, NULL, 10); + if (errno != -ERANGE) + cur_cookie->version = temp; + } + } else if (len == 7 && !strncasecomp(attr_start, "max-age", 7)) { + known_attr = YES; + if (cur_cookie != NULL && value) { + int temp = strtol(value, NULL, 10); + cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET; + if (errno == -ERANGE) { + cur_cookie->expires = (time_t)0; + } else { + cur_cookie->expires = (time(NULL) + temp); + if (TRACE) + fprintf(stderr, + "LYSetCooke: expires %i, %s", + cur_cookie->expires, + ctime(&cur_cookie->expires)); + } + } + } else if (len == 7 && !strncasecomp(attr_start, "expires", 7)) { + /* + * Convert an 'expires' attribute value for Version 0 + * cookies to the equivalent of a Version 1 (or greater) + * 'max-age' value added to 'time(NULL)'. - FM + */ + if (cur_cookie && cur_cookie->version < 1) { + known_attr = YES; + if (value) { + cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET; + cur_cookie->expires = LYmktime(value); + if (cur_cookie->expires > 0) { + if (TRACE) + fprintf(stderr, + "LYSetCooke: expires %i, %s", + cur_cookie->expires, + ctime(&cur_cookie->expires)); + } + } + } + /* + * If it's a version 1 (or greater) cookie, then you + * really can set a cookie named 'expires', so we don't + * set known_attr. + */ + } + + /* + * If none of the above comparisions succeeded, then we have + * an unknown pair of the form 'foo=bar', which means it's + * time to create a new cookie. + */ + if (!known_attr) { + store_cookie(cur_cookie, hostname, path); + cur_cookie = newCookie(); + length += len; + if (length > 4096) { + FREE(value); + break; + } + StrAllocCopy(cur_cookie->domain, hostname); + StrAllocCopy(cur_cookie->path, path); + cur_cookie->pathlen = strlen(cur_cookie->path); + cur_cookie->port = port; + MemAllocCopy(&(cur_cookie->name), attr_start, attr_end); + MemAllocCopy(&(cur_cookie->value), value_start, value_end); + } + FREE(value); + } + if (TRACE) { + fprintf(stderr, "LYSetCookie: attr=value pair: "); + if (attr_start == attr_end) { + fprintf(stderr, "[No attr]"); + } else { + CONST char *i; + + for (i = attr_start; i < attr_end; i++) + putc(*i, stderr); + } + fprintf(stderr, "="); + if (value_start >= value_end) { + fprintf(stderr, "[No value]"); + } else { + CONST char *i; + + for (i = value_start; i < value_end; i++) + putc(*i, stderr); + } + fprintf(stderr, "\n"); + } + } + + /* + * Store the final cookie if within length limit. - FM + */ + if (length <= 4096) { + /* + * Force the secure flag on if it's not + * set but this is an https URL. - FM + */ + if (!strncasecomp(address, "https:", 6) && + !(cur_cookie->flags & COOKIE_FLAG_SECURE)) { + cur_cookie->flags |= COOKIE_FLAG_SECURE; + if (TRACE) + fprintf(stderr, "LYSetCookie: Forced the 'secure' flag on.\n"); + } + store_cookie(cur_cookie, hostname, path); + } else { + if (TRACE) + fprintf(stderr, "LYSetCookie: Rejecting cookie due to length!\n"); + freeCookie(cur_cookie); + } + FREE(hostname); + FREE(path); +} + +PUBLIC char * LYCookie ARGS4( + CONST char *, hostname, + CONST char *, path, + int, port, + BOOL, secure) +{ + char *header = NULL; + HTList *hl = domain_list, *next = NULL; + domain_entry *de; + + if (TRACE) { + fprintf(stderr, + "LYCookie: Searching for '%s:%i', '%s'.\n", + (hostname ? hostname : "(null)"), + port, + (path ? path : "(null)")); + } + + /* + * Search the cookie_list elements in the domain_list + * for any cookies associated with the //hostname:port/path + */ + while (hl) { + de = (domain_entry *)hl->object; + next = hl->next; + + if (de != NULL) { + if (!HTList_isEmpty(de->cookie_list)) { + /* + * Scan the domain's cookie_list for + * any cookies we should include in + * our request header. + */ + header = scan_cookie_sublist(hostname, path, port, + de->cookie_list, header, secure); + } else if (de->bv == QUERY_USER) { + /* + * No cookies in this domain, and no default + * accept/reject choice was set by the user, + * so delete the domain. - FM + */ + FREE(de->domain); + HTList_delete(de->cookie_list); + de->cookie_list = NULL; + HTList_removeObject(domain_list, de); + de = NULL; + } + } + hl = next; + } + if (header) + return(header); + + /* + * If we set a header, perhaps all the cookies have + * expired and we deleted the last of them above, so + * check if we should delete and NULL the domain_list. - FM + */ + if (domain_list) { + if (HTList_isEmpty(domain_list)) { + HTList_delete(domain_list); + domain_list = NULL; + } + } + return(NULL); +} + +/* LYHandleCookies - F.Macrides (macrides@sci.wfeb.edu) +** --------------- +** +** Lists all cookies by domain, and allows deletions of +** individual cookies or entire domains, and changes of +** 'allow' settings. The list is invoked via the COOKIE_JAR +** command (Ctrl-K), and deletions or changes of 'allow' +** settings are done by activating links in that list. +** The procedure uses a LYNXCOOKIE: internal URL scheme. +** +** Semantics: +** LYNXCOOKIE:/ Create and load the Cookie Jar Page. +** LYNXCOOKIE://domain Manipulate the domain. +** LYNXCOOKIE://domain/lynx_id Delete cookie with lynx_id in domain. +** +** New functions can be added as extensions to the path, and/or by +** assigning meanings to ;parameters, a ?searchpart, and/or #fragments. +*/ +PRIVATE int LYHandleCookies ARGS4 ( + CONST char *, arg, + HTParentAnchor *, anAnchor, + HTFormat, format_out, + HTStream*, sink) +{ + HTFormat format_in = WWW_HTML; + HTStream *target = NULL; + char buf[1024]; + char *domain = NULL; + char *lynx_id = NULL; + HTList *dl, *cl, *next; + domain_entry *de; + cookie *co; + char *name = NULL, *value = NULL, *path = NULL, *comment = NULL; + int ch; +#ifdef VMS + extern BOOLEAN HadVMSInterrupt; +#endif /* VMS */ + + /* + * Check whether we have something to do. - FM + */ + if (domain_list == NULL) { + HTProgress(COOKIE_JAR_IS_EMPTY); + sleep(MessageSecs); + return(HT_NO_DATA); + } + + /* + * If there's a domain string in the "host" field of the + * LYNXCOOKIE: URL, this is a request to delete something + * or change and 'allow' setting. - FM + */ + if ((domain = HTParse(arg, "", PARSE_HOST)) != NULL) { + if (*domain == '\0') { + FREE(domain); + } else { + /* + * If there is a path string (not just a slash) in the + * LYNXCOOKIE: URL, that's a cookie's lynx_id and this + * is a request to delete it from the Cookie Jar. - FM + */ + if ((lynx_id = HTParse(arg, "", PARSE_PATH)) != NULL) { + if (*lynx_id == '\0') { + FREE(lynx_id); + } + } + } + } + if (domain) { + /* + * Seek the domain in the domain_list structure. - FM + */ + for (dl = domain_list; dl != NULL; dl = dl->next) { + de = dl->object; + if (!(de && de->domain)) + /* + * First object in the list always is empty. - FM + */ + continue; + if (!strcmp(domain, de->domain)) { + /* + * We found the domain. Check + * whether a lynx_id is present. - FM + */ + if (lynx_id) { + /* + * Seek and delete the cookie with this lynx_id + * in the domain's cookie list. - FM + */ + for (cl = de->cookie_list; cl != NULL; cl = cl->next) { + if ((co = (cookie *)cl->object) == NULL) + /* + * First object is always empty. - FM + */ + continue; + if (!strcmp(lynx_id, co->lynx_id)) { + /* + * We found the cookie. + * Delete it if confirmed. - FM + */ + if (HTConfirm(DELETE_COOKIE_CONFIRMATION) == FALSE) + return(HT_NO_DATA); + HTList_removeObject(de->cookie_list, co); + freeCookie(co); + co = NULL; + total_cookies--; + if ((de->bv == QUERY_USER && + HTList_isEmpty(de->cookie_list)) && + HTConfirm(DELETE_EMPTY_DOMAIN_CONFIRMATION)) { + /* + * No more cookies in this domain, no + * default accept/reject choice was set + * by the user, and got confirmation on + * deleting the domain, so do it. - FM + */ + FREE(de->domain); + HTList_delete(de->cookie_list); + de->cookie_list = NULL; + HTList_removeObject(domain_list, de); + de = NULL; + HTProgress(DOMAIN_EATEN); + } else { + HTProgress(COOKIE_EATEN); + } + sleep(MessageSecs); + break; + } + } + } else { + /* + * Prompt whether to delete all of the cookies in + * this domain, or the domain if no cookies in it, + * or to change its 'allow' setting, or to cancel, + * and then act on the user's response. - FM + */ + if (HTList_isEmpty(de->cookie_list)) { + _statusline(DELETE_DOMAIN_SET_ALLOW_OR_CANCEL); + } else { + _statusline(DELETE_COOKIES_SET_ALLOW_OR_CANCEL); + } + while (1) { + ch = LYgetch(); +#ifdef VMS + if (HadVMSInterrupt) { + HadVMSInterrupt = FALSE; + ch = 'C'; + } +#endif /* VMS */ + switch(TOUPPER(ch)) { + case 'A': + /* + * Set to accept all cookies + * from this domain. - FM + */ + de->bv = QUERY_USER; + _user_message(ALWAYS_ALLOWING_COOKIES, + de->domain); + sleep(MessageSecs); + return(HT_NO_DATA); + + case 'C': + case 7: /* Ctrl-G */ + case 3: /* Ctrl-C */ + /* + * Cancelled. - FM + */ + _statusline(CANCELLED); + sleep(MessageSecs); + return(HT_NO_DATA); + + case 'D': + if (HTList_isEmpty(de->cookie_list)) { + /* + * We had an empty domain, so we + * were asked to delete it. - FM + */ + FREE(de->domain); + HTList_delete(de->cookie_list); + de->cookie_list = NULL; + HTList_removeObject(domain_list, de); + de = NULL; + HTProgress(DOMAIN_EATEN); + sleep(MessageSecs); + break; + } +Delete_all_cookies_in_domain: + /* + * Delete all cookies in this domain. - FM + */ + cl = de->cookie_list; + while (cl) { + next = cl->next; + co = cl->object; + if (co) { + HTList_removeObject(de->cookie_list, + co); + freeCookie(co); + co = NULL; + total_cookies--; + } + cl = next; + } + HTProgress(DOMAIN_COOKIES_EATEN); + sleep(MessageSecs); + /* + * If a default accept/reject + * choice is set, we're done. - FM + */ + if (de->bv != QUERY_USER) + return(HT_NO_DATA); + /* + * Check whether to delete + * the empty domain. - FM + */ + if(HTConfirm( + DELETE_EMPTY_DOMAIN_CONFIRMATION)) { + FREE(de->domain); + HTList_delete(de->cookie_list); + de->cookie_list = NULL; + HTList_removeObject(domain_list, de); + de = NULL; + HTProgress(DOMAIN_EATEN); + sleep(MessageSecs); + } + break; + + case 'P': + /* + * Set to prompt for cookie acceptence + * from this domain. - FM + */ + de->bv = QUERY_USER; + _user_message(PROMTING_TO_ALLOW_COOKIES, + de->domain); + sleep(MessageSecs); + return(HT_NO_DATA); + + case 'V': + /* + * Set to reject all cookies + * from this domain. - FM + */ + de->bv = REJECT_ALWAYS; + _user_message(NEVER_ALLOWING_COOKIES, + de->domain); + sleep(MessageSecs); + if ((!HTList_isEmpty(de->cookie_list)) && + HTConfirm(DELETE_ALL_COOKIES_IN_DOMAIN)) + goto Delete_all_cookies_in_domain; + return(HT_NO_DATA); + + default: + continue; + } + break; + } + } + break; + } + } + if (HTList_isEmpty(domain_list)) { + /* + * There are no more domains left, + * so delete the domain_list. - FM + */ + HTList_delete(domain_list); + domain_list = NULL; + HTProgress(ALL_COOKIES_EATEN); + sleep(MessageSecs); + } + return(HT_NO_DATA); + } + + /* + * If we get to here, it was a LYNXCOOKIE:/ URL + * for creating and displaying the Cookie Jar Page, + * or we didn't find the domain or cookie in a + * deletion request. Set up an HTML stream and + * return an updated Cookie Jar Page. - FM + */ + target = HTStreamStack(format_in, + format_out, + sink, anAnchor); + if (!target || target == NULL) { + sprintf(buf, CANNOT_CONVERT_I_TO_O, + HTAtom_name(format_in), HTAtom_name(format_out)); + HTAlert(buf); + return(HT_NOT_LOADED); + } + + /* + * Load HTML strings into buf and pass buf + * to the target for parsing and rendering. - FM + */ + sprintf(buf, "<HEAD>\n<TITLE>%s</title>\n</HEAD>\n<BODY>\n", + COOKIE_JAR_TITLE); + (*target->isa->put_block)(target, buf, strlen(buf)); + + sprintf(buf, "<H1>%s</H1>\n", REACHED_COOKIE_JAR_PAGE); + (*target->isa->put_block)(target, buf, strlen(buf)); + sprintf(buf, "<H2>%s Version %s</H2>\n", LYNX_NAME, LYNX_VERSION); + (*target->isa->put_block)(target, buf, strlen(buf)); + + sprintf(buf, "<NOTE>%s\n", ACTIVATE_TO_GOBBLE); + (*target->isa->put_block)(target, buf, strlen(buf)); + sprintf(buf, "%s</NOTE>\n", OR_CHANGE_ALLOW); + (*target->isa->put_block)(target, buf, strlen(buf)); + + sprintf(buf, "<DL COMPACT>\n"); + (*target->isa->put_block)(target, buf, strlen(buf)); + for (dl = domain_list; dl != NULL; dl = dl->next) { + de = dl->object; + if (de == NULL) + /* + * First object always is NULL. - FM + */ + continue; + + /* + * Show the domain link and 'allow' setting. - FM + */ + sprintf(buf, "<DT><A HREF=\"LYNXCOOKIE://%s/\">Domain=%s</A>\n", + de->domain, de->domain); + (*target->isa->put_block)(target, buf, strlen(buf)); + switch (de->bv) { + case (ACCEPT_ALWAYS): + sprintf(buf, COOKIES_ALWAYS_ALLOWED); + break; + case (REJECT_ALWAYS): + sprintf(buf, COOKIES_NEVER_ALLOWED); + break; + case (QUERY_USER): + sprintf(buf, COOKIES_ALLOWED_VIA_PROMPT); + break; + } + (*target->isa->put_block)(target, buf, strlen(buf)); + + /* + * Show the domain's cookies. - FM + */ + for (cl = de->cookie_list; cl != NULL; cl = cl->next) { + if ((co = (cookie *)cl->object) == NULL) + /* + * First object is always NULL. - FM + */ + continue; + + /* + * Show the name=value pair. - FM + */ + if (co->name) { + StrAllocCopy(name, co->name); + LYEntify(&name, TRUE); + } else { + StrAllocCopy(name, NO_NAME); + } + if (co->value) { + StrAllocCopy(value, co->value); + LYEntify(&value, TRUE); + } else { + StrAllocCopy(value, NO_VALUE); + } + sprintf(buf, "<DD><A HREF=\"LYNXCOOKIE://%s/%s\">%s=%s</A>\n", + de->domain, co->lynx_id, name, value); + FREE(name); + FREE(value); + (*target->isa->put_block)(target, buf, strlen(buf)); + + /* + * Show the path, port, and secure setting. - FM + */ + if (co->path) { + StrAllocCopy(path, co->path); + LYEntify(&path, TRUE); + } else { + StrAllocCopy(path, "/"); + } + sprintf(buf, "<DD>Path=%s\n<DD>Port: %i Secure: %s\n", + path, co->port, + ((co->flags & COOKIE_FLAG_SECURE) ? "YES" : "NO")); + FREE(path); + (*target->isa->put_block)(target, buf, strlen(buf)); + + /* + * Show the Maximum Gobble Date. - FM + */ + sprintf(buf, "<DD><EM>Maximum Gobble Date:</EM> %s%s", + ((co->expires > 0) ? + ctime(&co->expires) : END_OF_SESSION), + ((co->expires > 0) ? + "" : "\n")); + (*target->isa->put_block)(target, buf, strlen(buf)); + + /* + * Show the comment, if we have one. - FM + */ + if (co->comment) { + StrAllocCopy(comment, co->comment); + LYEntify(&comment, TRUE); + sprintf(buf, "<DD><EM>Comment:</EM> %s\n", comment); + FREE(comment); + (*target->isa->put_block)(target, buf, strlen(buf)); + } + } + sprintf(buf, "</DT>\n"); + (*target->isa->put_block)(target, buf, strlen(buf)); + } + sprintf(buf, "</DL>\n</BODY>\n"); + (*target->isa->put_block)(target, buf, strlen(buf)); + + /* + * Free the target to complete loading of the + * Cookie Jar Page, and report a successful load. - FM + */ + (*target->isa->_free)(target); + return(HT_LOADED); +} + +#ifdef GLOBALDEF_IS_MACRO +#define _LYCOOKIE_C_GLOBALDEF_1_INIT { "LYNXCOOKIE",LYHandleCookies,0} +GLOBALDEF (HTProtocol,LYLynxCookies,_LYCOOKIE_C_GLOBALDEF_1_INIT); +#else +GLOBALDEF PUBLIC HTProtocol LYLynxCookies = {"LYNXCOOKIE",LYHandleCookies,0}; +#endif /* GLOBALDEF_IS_MACRO */ diff --git a/src/LYCookie.h b/src/LYCookie.h new file mode 100644 index 00000000..abc8a018 --- /dev/null +++ b/src/LYCookie.h @@ -0,0 +1,23 @@ + +#ifndef LYCOOKIES_H +#define LYCOOKIES_H + +extern void LYSetCookie PARAMS(( + CONST char * header, + CONST char * address)); +extern char *LYCookie PARAMS(( + CONST char * hostname, + CONST char * partialpath, + int port, + BOOL secure)); + +typedef enum {ACCEPT_ALWAYS, REJECT_ALWAYS, QUERY_USER} behaviour; + +struct _domain_entry { + char * domain; /* Domain for which these cookies are valid */ + behaviour bv; + HTList * cookie_list; +}; +typedef struct _domain_entry domain_entry; + +#endif /* LYCOOKIES_H */ diff --git a/src/LYCurses.c b/src/LYCurses.c index 52402448..8ec8b4d2 100644 --- a/src/LYCurses.c +++ b/src/LYCurses.c @@ -5,6 +5,7 @@ #include "LYGlobalDefs.h" #include "LYSignal.h" #include "LYClean.h" +#include "LYStrings.h" #ifdef USE_SLANG #include "LYCharSets.h" #endif /* USE_SLANG */ @@ -12,6 +13,8 @@ #include "LYexit.h" #include "LYLeaks.h" +#define FREE(x) if (x) {free(x); x = NULL;} + #ifdef VMS #define DISPLAY "DECW$DISPLAY" #else @@ -29,9 +32,8 @@ extern int _NOSHARE(COLS); #endif /* VMS && __GNUC__ */ /* - * These are routines to start and stop curses and to cleanup - * the screen at the end - * + * These are routines to start and stop curses and to cleanup + * the screen at the end. */ PRIVATE int dumbterm PARAMS((char *terminal)); @@ -63,13 +65,15 @@ PUBLIC void VTHome NOARGS } #endif /* VMS */ -PUBLIC void sl_add_attr ARGS1(int, a) +PUBLIC void sl_add_attr ARGS1( + int, a) { Current_Attr |= a; SLsmg_set_color(Current_Attr); } -PUBLIC void sl_sub_attr ARGS1(int, a) +PUBLIC void sl_sub_attr ARGS1( + int, a) { Current_Attr &= ~a; SLsmg_set_color(Current_Attr); @@ -81,13 +85,17 @@ PUBLIC void lynx_setup_colors NOARGS SLtt_set_color(1, NULL, "blue", "white"); /* bold */ SLtt_set_color(2, NULL, "yellow", "blue"); /* reverse */ SLtt_set_color(4, NULL, "magenta", "white"); /* underline */ - /* The other objects are '|'ed together to get rest */ + /* + * The other objects are '|'ed together to get rest. + */ SLtt_set_color(3, NULL, "green", "white"); /* bold-reverse */ SLtt_set_color(5, NULL, "blue", "white"); /* bold-underline */ SLtt_set_color(6, NULL, "red", "white"); /* reverse-underline */ SLtt_set_color(7, NULL, "magenta", "cyan"); /* reverse-underline-bold */ - /* Now set monchrome attributes */ + /* + * Now set monchrome attributes. + */ SLtt_set_mono(1, NULL, SLTT_BOLD_MASK); SLtt_set_mono(2, NULL, SLTT_REV_MASK); SLtt_set_mono(3, NULL, SLTT_REV_MASK | SLTT_BOLD_MASK); @@ -97,7 +105,8 @@ PUBLIC void lynx_setup_colors NOARGS SLtt_set_mono(7, NULL, SLTT_ULINE_MASK | SLTT_BOLD_MASK | SLTT_REV_MASK); } -PRIVATE void sl_suspend ARGS1(int, sig) +PRIVATE void sl_suspend ARGS1( + int, sig) { #ifndef VMS #ifdef SIGSTOP @@ -116,7 +125,9 @@ PRIVATE void sl_suspend ARGS1(int, sig) SLtty_set_suspend_state(1); if (sig == SIGTSTP) SLsmg_resume_smg(); - /* Get new window size in case it changed. */ + /* + * Get new window size in case it changed. + */ r = SLtt_Screen_Rows; c = SLtt_Screen_Cols; size_change(0); @@ -147,8 +158,8 @@ PUBLIC void start_curses NOARGS SLtt_add_color_attribute(4, SLTT_ULINE_MASK); SLtt_add_color_attribute(5, SLTT_ULINE_MASK); /* - * If set, the blink escape sequence will turn on high - * intensity background (rxvt and maybe Linux console). + * If set, the blink escape sequence will turn on high + * intensity background (rxvt and maybe Linux console). */ if (Lynx_Color_Flags & SL_LYNX_USE_BLINK) SLtt_Blink_Mode = 1; @@ -262,7 +273,8 @@ PUBLIC void stop_curses NOARGS /* * Check terminal type, start curses & setup terminal. */ -PUBLIC BOOLEAN setup ARGS1(char *,terminal) +PUBLIC BOOLEAN setup ARGS1( + char *, terminal) { int c; int status; @@ -333,9 +345,10 @@ PUBLIC BOOLEAN setup ARGS1(char *,terminal) #else /* Not VMS: */ /* - * check terminal type, start curses & setup terminal + * Check terminal type, start curses & setup terminal. */ -PUBLIC BOOLEAN setup ARGS1(char *,terminal) +PUBLIC BOOLEAN setup ARGS1( + char *, terminal) { static char term_putenv[120]; char buffer[120]; @@ -352,7 +365,9 @@ PUBLIC BOOLEAN setup ARGS1(char *,terminal) (void) putenv(term_putenv); } - /* query the terminal type */ + /* + * Query the terminal type. + */ if (dumbterm(getenv("TERM"))) { char *s; @@ -367,7 +382,7 @@ PUBLIC BOOLEAN setup ARGS1(char *,terminal) strcpy(buffer,"vt100"); sprintf(term_putenv,"TERM=%s", buffer); - putenv(term_putenv); /* */ + putenv(term_putenv); printf("\nTERMINAL TYPE IS SET TO %s\n",getenv("TERM")); sleep(MESSAGESECS); } @@ -389,7 +404,8 @@ PUBLIC BOOLEAN setup ARGS1(char *,terminal) return(1); } -PRIVATE int dumbterm ARGS1(char *,terminal) +PRIVATE int dumbterm ARGS1( + char *, terminal) { int dumb = FALSE; @@ -491,7 +507,9 @@ static short trap_flag = FALSE; /* TRUE if AST is set */ BOOLEAN DidCleanup = FALSE; /* Exit handler flag */ static char VersionVMS[20]; /* Version of VMS */ -PUBLIC int VMSVersion ARGS2(char *,VerString, int,VerLen) +PUBLIC int VMSVersion ARGS2( + char *, VerString, + int, VerLen) { unsigned long status, itm_cod = SYI$_VERSION; int i, verlen = 0; @@ -507,8 +525,10 @@ PUBLIC int VMSVersion ARGS2(char *,VerString, int,VerLen) if (!(status&1) || verlen == 0) return 0; - /* Cut out trailing spaces */ - for (m=VerString+verlen, i=verlen-1; i > 0 && VerString[i] == ' '; --i) + /* + * Cut out trailing spaces + */ + for (m = VerString+verlen, i = verlen-1; i > 0 && VerString[i] == ' '; --i) *(--m) = '\0'; return strlen(VerString)+1; /* Transmit ending 0 too */ @@ -517,28 +537,37 @@ PUBLIC int VMSVersion ARGS2(char *,VerString, int,VerLen) PUBLIC void VMSexit NOARGS { /* - * If we get here and DidCleanup is not set, it was via an - * ACCVIO, so make *sure* we attempt a cleanup and reset - * the terminal. + * If we get here and DidCleanup is not set, it was via an + * ACCVIO, or outofmemory forced exit, so make *sure* we + * attempt a cleanup and reset the terminal. */ - if (!DidCleanup) { - fprintf(stderr, + if (!DidCleanup) { + if (LYOutOfMemory == FALSE) { + fprintf(stderr, "\nA Fatal error has occured in %s Ver. %s\n", LYNX_NAME, LYNX_VERSION); - fprintf(stderr, + fprintf(stderr, "\nPlease notify your system administrator to confirm a bug, and if\n"); - fprintf(stderr, + fprintf(stderr, "confirmed, to notify the lynx-dev list. Bug reports should have concise\n"); - fprintf(stderr, + fprintf(stderr, "descriptions of the command and/or URL which causes the problem, the\n"); - fprintf(stderr, + fprintf(stderr, "operating system name with version number, the TCPIP implementation, the\n"); - fprintf(stderr, + fprintf(stderr, "TRACEBACK if it can be captured, and any other relevant information.\n"); - fprintf(stderr,"\nPress RETURN to clean up: "); - (void) getchar(); - cleanup(); - } + fprintf(stderr,"\nPress RETURN to clean up: "); + (void) getchar(); + } else if (LYCursesON) { + _statusline(MEMORY_EXHAUSTED_ABORT); + sleep(AlertSecs); + } + cleanup(); + } + if (LYOutOfMemory == TRUE) { + printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT); + fflush(stdout); + } } /* @@ -549,7 +578,6 @@ PUBLIC void VMSexit NOARGS * to EDIT, and sets up the Ctrl-C and Ctrl-Y interrupt * handling. */ - PUBLIC int ttopen NOARGS { extern void cleanup_sig(); @@ -589,7 +617,9 @@ PUBLIC int ttopen NOARGS if( status != SS$_NORMAL ) exit( status ); - /* declare the exit handler block */ + /* + * Declare the exit handler block. + */ exit_handler_block.forward = 0; exit_handler_block.address = (unsigned long) &VMSexit; exit_handler_block.zero = 0; @@ -598,7 +628,9 @@ PUBLIC int ttopen NOARGS if (status != SS$_NORMAL) exit( status ); - /* set the AST */ + /* + * Set the AST. + */ lib$disable_ctrl(&mask, &old_msk); trap_flag = TRUE; status = sys$qiow ( EFN, iochan, @@ -610,9 +642,13 @@ PUBLIC int ttopen NOARGS exit ( status ); } - /* Get the version of VMS */ + /* + * Get the version of VMS. + */ if (VMSVersion(VersionVMS, 20) < 3) - /* Load zeros on error */ + /* + * Load zeros on error. + */ strcpy(VersionVMS, "V0.0-0"); return(0); @@ -624,7 +660,6 @@ PUBLIC int ttopen NOARGS * to the command interpreter. It puts the terminal back * in a reasonable state. */ - PUBLIC int ttclose NOARGS { int status; @@ -648,30 +683,31 @@ PUBLIC int ttclose NOARGS * TTGETC -- * Read a character from the terminal, with NOECHO and NOFILTR. */ - PUBLIC int ttgetc NOARGS { - int status; - unsigned short iosb[4]; - - if (in_pos < in_len) - return(buffer[in_pos++]); - - status = sys$qiow (EFN, iochan, - IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR, - &iosb, 0, 0, - &buffer, 1, 0, 0, 0, 0); - if ((status&1) == 1) - status = iosb[0]; - if (status == SS$_PARTESCAPE) { - /* escape sequence in progress, fake a successful read */ - status = 1; - } - if ((status&1) != 1) - exit(status); - in_pos = 1; - in_len = iosb[1] + iosb[3]; - return (buffer[0]); + int status; + unsigned short iosb[4]; + + if (in_pos < in_len) + return(buffer[in_pos++]); + + status = sys$qiow(EFN, iochan, + IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR, + &iosb, 0, 0, + &buffer, 1, 0, 0, 0, 0); + if ((status&1) == 1) + status = iosb[0]; + if (status == SS$_PARTESCAPE) { + /* + * Escape sequence in progress. Fake a successful read. + */ + status = 1; + } + if ((status&1) != 1 && status != SS$_DATAOVERUN) + exit(status); + in_pos = 1; + in_len = iosb[1] + iosb[3]; + return(buffer[0]); } /* @@ -679,35 +715,36 @@ PUBLIC int ttgetc NOARGS * Check whether a keystroke has been entered, and return * it, or -1 if none was entered. */ - PUBLIC int typeahead NOARGS { - int status; - unsigned short iosb[4]; - - if (dump_output_immediately) - return -1; + int status; + unsigned short iosb[4]; - if (in_pos < in_len) - return(buffer[in_pos++]); + if (dump_output_immediately) + return -1; + + if (in_pos < in_len) + return(buffer[in_pos++]); again: - status = sys$qiow (EFN, iochan, - IO$_READVBLK|IO$M_TIMED|IO$M_NOECHO|IO$M_NOFILTR, - &iosb, 0, 0, - &buffer, 1, 0, 0, 0, 0); - if ((status&1) == 1) - status = iosb[0]; - if (status == SS$_PARTESCAPE) { - /* escape sequence in progress, finish reading it */ - goto again; - } - - in_pos = 1; - in_len = iosb[1] + iosb[3]; - if (status == SS$_TIMEOUT) - return(-1); - return (buffer[0]); + status = sys$qiow (EFN, iochan, + IO$_READVBLK|IO$M_TIMED|IO$M_NOECHO|IO$M_NOFILTR, + &iosb, 0, 0, + &buffer, 1, 0, 0, 0, 0); + if ((status&1) == 1) + status = iosb[0]; + if (status == SS$_PARTESCAPE) { + /* + * Escape sequence in progress, finish reading it. + */ + goto again; + } + + in_pos = 1; + in_len = iosb[1] + iosb[3]; + if (status == SS$_TIMEOUT || status == SS$_DATAOVERUN) + return(-1); + return (buffer[0]); } /* @@ -735,32 +772,42 @@ void (*func)(); short iosb[4]; static int SIG_IGN_flag; - /* Pass all signals other than SIGINT to signal() */ - /* Also pass SIGINT to signal() if we're dumping */ + /* + * Pass all signals other than SIGINT to signal(). + * Also pass SIGINT to signal() if we're dumping. + */ if (sig != SIGINT || dump_output_immediately) { signal(sig, func); return; } - /* If func is SIG_DFL, treat it as ttclose() */ + /* + * If func is SIG_DFL, treat it as ttclose(). + */ if (func == SIG_DFL) { ttclose(); return; } - /* Clear any previous AST */ + /* + * Clear any previous AST. + */ if (trap_flag) { status = sys$dassgn (iochan); status = lib$enable_ctrl(&old_msk); trap_flag = FALSE; } - /* If func is SIG_IGN, leave the TT channel closed and the */ - /* system response to interrupts enabled for system() calls */ + /* + * If func is SIG_IGN, leave the TT channel closed and the + * system response to interrupts enabled for system() calls. + */ if (func == SIG_IGN) return; - /* If we get to here, we have a LYNX func, so set the AST */ + /* + * If we get to here, we have a LYNX func, so set the AST. + */ lib$disable_ctrl(&mask, &old_msk); trap_flag = TRUE; status = sys$assign (&term_nam_dsc, &iochan, 0, 0 ); @@ -781,12 +828,15 @@ void (*func)(); * to Lynx instead of breaking out to DCL if a user issues interrupts * or generates an ACCVIO during spawns. */ - #ifdef __DECC -PRIVATE unsigned int DCLspawn_exception ARGS2(void *,sigarr, void *,mecharr) +PRIVATE unsigned int DCLspawn_exception ARGS2( + void *, sigarr, + void *, mecharr) { #else -PRIVATE int DCLspawn_exception ARGS2(void *,sigarr, void *,mecharr) +PRIVATE int DCLspawn_exception ARGS2( + void *, sigarr, + void *, mecharr) { #endif /* __DECC */ int status; @@ -795,11 +845,14 @@ PRIVATE int DCLspawn_exception ARGS2(void *,sigarr, void *,mecharr) return(SS$_UNWIND); } -PRIVATE int spawn_DCLprocess ARGS1(char *,command) +PRIVATE int spawn_DCLprocess ARGS1( + char *, command) { int status; unsigned long Status = 0; - /** Keep DECC from complaining **/ + /* + * Keep DECC from complaining. + */ struct dsc$descriptor_s command_desc; command_desc.dsc$w_length = strlen(command); command_desc.dsc$b_class = DSC$K_CLASS_S; @@ -815,25 +868,34 @@ PRIVATE int spawn_DCLprocess ARGS1(char *,command) #else if (VersionVMS[1] >= '6') { #endif /* __ALPHA */ - /** Include TRUSTED flag **/ + /* + * Include TRUSTED flag. + */ unsigned long trusted = CLI$M_TRUSTED; status = lib$spawn(&command_desc,0,0,&trusted, 0,0,&Status); - /** If it was invalid, try again without the flag **/ + /* + * If it was invalid, try again without the flag. + */ if (status == LIB$_INVARG) status = lib$spawn(&command_desc,0,0,0, 0,0,&Status ); } else status = lib$spawn(&command_desc,0,0,0, 0,0,&Status); - /** Return -1 on error. **/ + /* + * Return -1 on error. + */ if ((status&1) != 1 || (Status&1) != 1) return(-1); - /** Return 0 on success. **/ + /* + * Return 0 on success. + */ return(0); } -PUBLIC int DCLsystem ARGS1(char *,command) +PUBLIC int DCLsystem ARGS1( + char *, command) { int status; extern void controlc(); @@ -841,7 +903,9 @@ PUBLIC int DCLsystem ARGS1(char *,command) VMSsignal(SIGINT, SIG_IGN); status = spawn_DCLprocess(command); VMSsignal(SIGINT, cleanup_sig); - /** Returns 0 on success, -1 any error. **/ + /* + * Returns 0 on success, -1 any error. + */ return(status); } @@ -851,9 +915,9 @@ PUBLIC int DCLsystem ARGS1(char *,command) ** Pass it the window, it's height, and it's width. - FM */ PUBLIC void VMSbox ARGS3( - WINDOW *, win, - int, height, - int, width) + WINDOW *, win, + int, height, + int, width) { int i; @@ -876,4 +940,3 @@ PUBLIC void VMSbox ARGS3( } #endif /* !USE_SLANG */ #endif /* VMS */ - diff --git a/src/LYForms.c b/src/LYForms.c index b7cd64ee..8474dc12 100644 --- a/src/LYForms.c +++ b/src/LYForms.c @@ -181,6 +181,7 @@ PUBLIC int change_form_link ARGS6(struct link *, form_link, int, mode, break; case F_SUBMIT_TYPE: + case F_IMAGE_SUBMIT_TYPE: if (form->disabled == YES) break; if (form->no_cache && diff --git a/src/LYGetFile.c b/src/LYGetFile.c index cd8ef577..fa6b0c3e 100644 --- a/src/LYGetFile.c +++ b/src/LYGetFile.c @@ -50,7 +50,8 @@ extern BOOLEAN LYDidRename; #ifdef DIRED_SUPPORT -PRIVATE char * LYSanctify ARGS1(char *, href) +PRIVATE char * LYSanctify ARGS1( + char *, href) { int i; char *p, *cp, *tp; @@ -81,34 +82,44 @@ PRIVATE char * LYSanctify ARGS1(char *, href) #endif /* DIRED_SUPPORT */ -PUBLIC BOOLEAN getfile ARGS1(document *,doc) +PUBLIC BOOLEAN getfile ARGS1( + document *, doc) { - int url_type; - char *cp; + int url_type = 0; + char *cp = NULL; + char *temp = NULL; DocAddress WWWDoc; /* a WWW absolute doc address struct */ Try_Redirected_URL: - /* load the WWWDoc struct in case we need to use it */ + /* + * Load the WWWDoc struct in case we need to use it. + */ WWWDoc.address = doc->address; WWWDoc.post_data = doc->post_data; WWWDoc.post_content_type = doc->post_content_type; WWWDoc.bookmark = doc->bookmark; WWWDoc.isHEAD = doc->isHEAD; + WWWDoc.safe = doc->safe; - /* reset WWW_Download_File just in case */ + /* + * Reset WWW_Download_File just in case. + */ FREE(WWW_Download_File); - /* reset redirect_post_content just in case */ + /* + * Reset redirect_post_content just in case. + */ redirect_post_content = FALSE; if (TRACE) { fprintf(stderr,"LYGetFile: getting %s\n\n",doc->address); } - /* check to see if this is a universal document ID - * that lib WWW wants to handle + /* + * Check to see if this is a universal document ID + * that lib WWW wants to handle. * - * some special URL's we handle ourselves :) + * Some special URL's we handle ourselves. :) */ if ((url_type = is_url(doc->address)) != 0) { if (LYValidate && !LYPermitURL) { @@ -117,6 +128,7 @@ Try_Redirected_URL: url_type == LYNXHIST_URL_TYPE || url_type == LYNXKEYMAP_URL_TYPE || url_type == LYNXIMGMAP_URL_TYPE || + url_type == LYNXCOOKIE_URL_TYPE || 0==strncasecomp(WWWDoc.address, helpfilepath, strlen(helpfilepath)) || 0==strncasecomp(WWWDoc.address, aboutfilepath, @@ -124,6 +136,9 @@ Try_Redirected_URL: (lynxlistfile != NULL && 0==strncasecomp(WWWDoc.address, lynxlistfile, strlen(lynxlistfile))) || + (lynxlinksfile != NULL && + 0==strncasecomp(WWWDoc.address, lynxlinksfile, + strlen(lynxlinksfile))) || (lynxjumpfile != NULL && 0==strncasecomp(WWWDoc.address, lynxjumpfile, strlen(lynxjumpfile))))) { @@ -133,7 +148,9 @@ Try_Redirected_URL: } } if (traversal) { - /* only traverse http URLs */ + /* + * Only traverse http URLs. + */ if (url_type != HTTP_URL_TYPE && url_type != LYNXIMGMAP_URL_TYPE) return(NULLFILE); @@ -143,6 +160,7 @@ Try_Redirected_URL: url_type == LYNXHIST_URL_TYPE || url_type == LYNXKEYMAP_URL_TYPE || url_type == LYNXIMGMAP_URL_TYPE || + url_type == LYNXCOOKIE_URL_TYPE || url_type == LYNXPRINT_URL_TYPE || url_type == LYNXDOWNLOAD_URL_TYPE || url_type == MAILTO_URL_TYPE || @@ -152,6 +170,8 @@ Try_Redirected_URL: (url_type == LYNXEXEC_URL_TYPE || url_type == LYNXPROG_URL_TYPE || url_type == LYNXCGI_URL_TYPE)) || + (WWWDoc.bookmark != NULL && + *WWWDoc.bookmark != '\0') || 0==strncasecomp(WWWDoc.address, helpfilepath, strlen(helpfilepath)) || 0==strncasecomp(WWWDoc.address, aboutfilepath, @@ -159,9 +179,6 @@ Try_Redirected_URL: (lynxlistfile != NULL && 0==strncasecomp(WWWDoc.address, lynxlistfile, strlen(lynxlistfile))) || - (lynxbookfile != NULL && - 0==strncasecomp(WWWDoc.address, lynxbookfile, - strlen(lynxbookfile))) || (lynxjumpfile != NULL && 0==strncasecomp(WWWDoc.address, lynxjumpfile, strlen(lynxjumpfile))))) { @@ -215,10 +232,10 @@ Try_Redirected_URL: #ifdef VMS if (LYDidRename) { /* - * The temporary file was saved to disk via a - * rename(), so we can't access the temporary - * file again via the download menu. Clear the - * flag, and return NULLFILE to pop. - FM + * The temporary file was saved to disk via a + * rename(), so we can't access the temporary + * file again via the download menu. Clear the + * flag, and return NULLFILE to pop. - FM */ LYDidRename = FALSE; return(NULLFILE); @@ -241,6 +258,7 @@ Try_Redirected_URL: WWWDoc.post_content_type = doc->post_content_type; WWWDoc.bookmark = doc->bookmark; WWWDoc.isHEAD = doc->isHEAD; + WWWDoc.safe = doc->safe; if (!HTLoadAbsolute(&WWWDoc)) return(NOT_FOUND); @@ -255,12 +273,14 @@ Try_Redirected_URL: } else if (url_type == LYNXHIST_URL_TYPE) { /* * 'doc' will change to the new file - * if we had a successful pop. - FM + * if we had a successful LYpop_num(), + * and the return value will be FALSE + * if we had a cancel. - FM */ - historytarget(doc); - if (!doc || !doc->address) { - HTMLSetCharacterHandling(current_char_set); - return(NOT_FOUND); + if ((historytarget(doc) == FALSE) || + !doc || !doc->address) { + HTMLSetCharacterHandling(current_char_set); + return(NOT_FOUND); } /* @@ -271,6 +291,7 @@ Try_Redirected_URL: WWWDoc.post_content_type = doc->post_content_type; WWWDoc.bookmark = doc->bookmark; WWWDoc.isHEAD = doc->isHEAD; + WWWDoc.safe = doc->safe; if (!HTLoadAbsolute(&WWWDoc)) { HTMLSetCharacterHandling(current_char_set); @@ -297,13 +318,17 @@ Try_Redirected_URL: char *p, addressbuf[1024]; - /* Bug puts slash on end if none is in the string */ + /* + * Bug puts slash on end if none is in the string. + */ char *last_slash = strrchr(doc->address,'/'); if (last_slash-doc->address==strlen(doc->address)-1) doc->address[strlen(doc->address)-1] = '\0'; p = doc->address; - /** Convert '~' to $HOME **/ + /* + * Convert '~' to $HOME. + */ if ((cp = strchr(doc->address, '~'))) { strncpy(addressbuf, doc->address, cp-doc->address); addressbuf[cp - doc->address] = '\0'; @@ -316,17 +341,23 @@ Try_Redirected_URL: strcat(addressbuf, cp+1); p = addressbuf; } - /* Show URL before executing it */ + /* + * Show URL before executing it. + */ statusline(doc->address); sleep(InfoSecs); stop_curses(); - /* run the command */ + /* + * Run the command. + */ if (strstr(p,"//") == p+9) system(p+11); else system(p+9); if (url_type != LYNXPROG_URL_TYPE) { - /* Make sure user gets to see screen output */ + /* + * Make sure user gets to see screen output. + */ #ifndef VMS signal(SIGINT, SIG_IGN); #endif /* !VMS */ @@ -341,6 +372,7 @@ Try_Redirected_URL: #endif /* VMS */ } start_curses(); + LYAddVisitedLink(doc); } else { char buf[512]; @@ -382,13 +414,15 @@ Try_Redirected_URL: } return(NULLFILE); - /* from here on we could have a remote host, - * so check if that's allowed. - */ + /* + * From here on we could have a remote host, + * so check if that's allowed. + */ } else if (local_host_only && url_type != NEWS_URL_TYPE && url_type != LYNXKEYMAP_URL_TYPE && url_type != LYNXIMGMAP_URL_TYPE && + url_type != LYNXCOOKIE_URL_TYPE && url_type != LYNXCGI_URL_TYPE && !(LYisLocalHost(doc->address) || LYisLocalAlias(doc->address))) { @@ -396,11 +430,12 @@ Try_Redirected_URL: sleep(MessageSecs); return(NULLFILE); - /* disable www telnet access if not telnet_ok */ + /* + * Disable www telnet access if not telnet_ok. + */ } else if (url_type == TELNET_URL_TYPE || url_type == TN3270_URL_TYPE || url_type == TELNET_GOPHER_URL_TYPE) { - if (!telnet_ok) { _statusline(TELNET_DISABLED); sleep(MessageSecs); @@ -412,19 +447,19 @@ Try_Redirected_URL: HTLoadAbsolute(&WWWDoc); start_curses(); fflush(stdout); - + LYAddVisitedLink(doc); } - return(NULLFILE); - /* disable www news access if not news_ok */ + /* + * Disable www news access if not news_ok. + */ } else if (url_type == NEWS_URL_TYPE && !news_ok) { _statusline(NEWS_DISABLED); sleep(MessageSecs); return(NULLFILE); } else if (url_type == RLOGIN_URL_TYPE) { - if (!rlogin_ok) { statusline(RLOGIN_DISABLED); sleep(MessageSecs); @@ -433,13 +468,14 @@ Try_Redirected_URL: HTLoadAbsolute(&WWWDoc); fflush(stdout); start_curses(); + LYAddVisitedLink(doc); } return(NULLFILE); /* * If its a gopher index type and there isn't a search * term already attached then do this. Otherwise - * just load it! + * just load it! */ } else if (url_type == INDEX_GOPHER_URL_TYPE && strchr(doc->address,'?') == NULL) { @@ -450,7 +486,6 @@ Try_Redirected_URL: * the search term. - FM */ if ((cp = strstr(doc->address, "%09")) != NULL) { - char *temp = NULL; *cp = '\0'; StrAllocCopy(temp, doc->address); cp += 3; @@ -480,6 +515,7 @@ Try_Redirected_URL: WWWDoc.post_content_type = doc->post_content_type; WWWDoc.bookmark = doc->bookmark; WWWDoc.isHEAD = doc->isHEAD; + WWWDoc.safe = doc->safe; status = HTLoadAbsolute(&WWWDoc); } return(status); @@ -495,7 +531,7 @@ Try_Redirected_URL: if (url_type == HTML_GOPHER_URL_TYPE) { char *tmp=NULL; /* - * If tuple's Path=GET%20/... convert to an http URL + * If tuple's Path=GET%20/... convert to an http URL. */ if ((cp=strchr(doc->address+9, '/')) != NULL && 0==strncmp(++cp, "hGET%20/", 8)) { @@ -507,7 +543,7 @@ Try_Redirected_URL: *cp = '\0'; StrAllocCat(tmp, doc->address+9); /* - * If the port is defaulted, it should stay 70 + * If the port is defaulted, it should stay 70. */ if (strchr(tmp+6, ':') == NULL) { StrAllocCat(tmp, "70/"); @@ -538,7 +574,6 @@ Try_Redirected_URL: #else if (url_type == FILE_URL_TYPE && (cp=strstr(doc->address, "/~")) != NULL) { - char *temp=NULL; *cp = '\0'; cp += 2; StrAllocCopy(temp, doc->address); @@ -556,7 +591,7 @@ Try_Redirected_URL: #endif /* DIRED_SUPPORT */ if (TRACE) sleep(MessageSecs); - user_message(WWW_WAIT_MESSAGE,doc->address); + user_message(WWW_WAIT_MESSAGE, doc->address); #ifdef NOTDEFINED sleep(InfoSecs); #endif /* NOTDEFINED */ @@ -593,21 +628,22 @@ Try_Redirected_URL: * the RIGHT thing and returning an invalid * address message. - FM */ - char *temp = HTParse(use_this_url_instead, - WWWDoc.address, - PARSE_ALL); + HTAlert(LOCATION_NOT_ABSOLUTE); + temp = HTParse(use_this_url_instead, + WWWDoc.address, + PARSE_ALL); if (temp && *temp) { StrAllocCopy(use_this_url_instead, temp); } FREE(temp); } HTMLSetCharacterHandling(current_char_set); - if(TRACE) + if (TRACE) sleep(MessageSecs); _user_message("Using %s", use_this_url_instead); sleep(InfoSecs); if (TRACE) - fprintf(stderr,"\n"); + fprintf(stderr, "\n"); StrAllocCopy(doc->address, use_this_url_instead); FREE(use_this_url_instead); @@ -632,13 +668,14 @@ Try_Redirected_URL: lynx_mode = NORMAL_LYNX_MODE; - /* some URL's don't actually return a document - * compare doc->address with the document that is - * actually loaded and return NULL if not - * loaded. If www_search_result is not -1 - * then this is a reference to a named anchor - * within the same document. Do NOT return - * NULL + /* + * Some URL's don't actually return a document + * compare doc->address with the document that is + * actually loaded and return NULL if not + * loaded. If www_search_result is not -1 + * then this is a reference to a named anchor + * within the same document. Do NOT return + * NULL. */ { char *pound; @@ -674,6 +711,7 @@ Try_Redirected_URL: FREE(fname); return(NOT_FOUND); } + LYAddVisitedLink(doc); StrAllocCopy(doc->address, fname); FREE(fname); WWWDoc.address = doc->address; @@ -681,6 +719,7 @@ Try_Redirected_URL: FREE(WWWDoc.post_content_type); WWWDoc.bookmark = doc->bookmark; WWWDoc.isHEAD = FALSE; + WWWDoc.safe = doc->safe; HTOutputFormat = WWW_PRESENT; if (!HTLoadAbsolute(&WWWDoc)) return(NOT_FOUND); @@ -689,27 +728,28 @@ Try_Redirected_URL: } else if (pound == NULL && /* - * HTAnchor hash-table searches are now - * case-sensitive (hopefully, without - * anchor deletion problems), so this - * is too. - FM + * HTAnchor hash-table searches are now + * case-sensitive (hopefully, without + * anchor deletion problems), so this + * is too. - FM */ (strcmp(doc->address, HTLoadedDocumentURL()) || /* - * Also check the post_data elements. - FM + * Also check the post_data elements. - FM */ strcmp((doc->post_data ? doc->post_data : ""), HTLoadedDocumentPost_data()) || /* - * Also check the isHEAD element. - FM + * Also check the isHEAD element. - FM */ doc->isHEAD != HTLoadedDocumentIsHEAD())) { HTMLSetCharacterHandling(current_char_set); /* * Nothing needed to be shown. */ + LYAddVisitedLink(doc); return(NULLFILE); } else { @@ -734,16 +774,20 @@ Try_Redirected_URL: } } -/* the user wants to select a link by number - * if follow_link_number returns DO_LINK_STUFF do_link will be - * run immeditely following its execution. - * if follow_link_number returns PRINT_ERROR an error message will - * be given to the user, if follow_link_number returns DO_FORMS_STUFF - * some forms stuff will be done, and if follow_link_number returns - * DO_NOTHING nothing special will run after it. +/* + * The user wants to select a link by number. + * If follow_link_number returns DO_LINK_STUFF do_link + * will be run immeditely following its execution. + * If follow_link_number returns PRINT_ERROR an error message + * will be given to the user. + * If follow_link_number returns DO_FORMS_STUFF some forms stuff + * will be done. + * If follow_link_number returns DO_NOTHING nothing special + * will run after it. */ - -PUBLIC int follow_link_number ARGS2(int,c, int,cur) +PUBLIC int follow_link_number ARGS2( + int, c, + int, cur) { char temp[120]; int link_number; @@ -751,7 +795,9 @@ PUBLIC int follow_link_number ARGS2(int,c, int,cur) temp[0] = c; temp[1] = '\0'; _statusline(FOLLOW_LINK_NUMBER); - /* get the number from the user */ + /* + * Get the number from the user. + */ if (LYgetstr(temp, VISIBLE, sizeof(temp), NORECALL) < 0 || *temp == 0) { _statusline(CANCELLED); sleep(InfoSecs); @@ -760,28 +806,26 @@ PUBLIC int follow_link_number ARGS2(int,c, int,cur) link_number = atoi(temp); - if (link_number > 0) { - /* get the lname, and hightext, - * direct from - * www structures and add it to the cur link - * so that we can pass it transparently on to - * get_file() - * this is done so that you may select a link - * anywhere in the document, whether it is displayed - * on the screen or not! - */ - if (HTGetLinkInfo(link_number, &links[cur].hightext, - &links[cur].lname)) { - links[cur].type = WWW_LINK_TYPE; - - return(DO_LINK_STUFF); - } else { - return(PRINT_ERROR); - } + if (link_number > 0) { + /* + * Get the lname, and hightext, direct from + * www structures and add it to the cur link + * so that we can pass it transparently on to + * get_file(). This is done so that you may select a link + * anywhere in the document, whether it is displayed + * on the screen or not! + */ + if (HTGetLinkInfo(link_number, + &links[cur].hightext, + &links[cur].lname)) { + links[cur].type = WWW_LINK_TYPE; + return(DO_LINK_STUFF); + } else { + return(PRINT_ERROR); + } } else { - return(PRINT_ERROR); + return(PRINT_ERROR); } - } #if defined(EXEC_LINKS) || defined(LYNXCGI_LINKS) @@ -848,7 +892,9 @@ PRIVATE void LYTrusted_free NOARGS return; } -PUBLIC void add_trusted ARGS2 (char *,str, int,type) +PUBLIC void add_trusted ARGS2( + char *, str, + int, type) { struct trust *tp; char *path; @@ -899,17 +945,26 @@ PUBLIC void add_trusted ARGS2 (char *,str, int,type) } /* - * Check to see if the supplied paths is allowed to be executed. + * Check to see if the supplied paths is allowed to be executed. */ -PUBLIC BOOLEAN exec_ok ARGS3(CONST char *,source, CONST char *,link, int, type) +PUBLIC BOOLEAN exec_ok ARGS3( + CONST char *, source, + CONST char *, link, + int, type) { struct trust *tp; - char CONST *cp; + CONST char *cp; int Type = type; + /* + * Always OK if it is a jump file shortcut. + */ if (LYJumpFileURL) return TRUE; + /* + * Choose the trust structure based on the type. + */ if (Type == EXEC_PATH) { tp = trusted_exec; } else if (Type == ALWAYS_EXEC_PATH) { @@ -920,8 +975,36 @@ PUBLIC BOOLEAN exec_ok ARGS3(CONST char *,source, CONST char *,link, int, type) HTAlert(MALFORMED_EXEC_REQUEST); return FALSE; } -#ifndef VMS - /* security: reject on strange character */ + +#ifdef VMS + /* + * Security: reject on relative path. + */ + if ((cp = strchr(link, '[')) != NULL) { + char *cp1; + if (((cp1 = strchr(cp, '-')) != NULL) && + strchr(cp1, ']') != NULL) { + while (cp1[1] == '-') + cp1++; + if (cp1[1] == ']' || + cp1[1] == '.') { + HTAlert(RELPATH_IN_EXEC_LINK); + return FALSE; + } + } + } +#else + /* + * Security: reject on relative path. + */ + if (strstr(link, "../") != NULL) { + HTAlert(RELPATH_IN_EXEC_LINK); + return FALSE; + } + + /* + * Security: reject on strange character. + */ for (cp = link; *cp != '\0'; cp++) { if (!isalnum(*cp) && *cp != '_' && *cp != '-' && *cp != ' ' && *cp != ':' && *cp != '.' && @@ -936,7 +1019,7 @@ PUBLIC BOOLEAN exec_ok ARGS3(CONST char *,source, CONST char *,link, int, type) return FALSE; } } -#endif /* !VMS */ +#endif /* VMS */ check_tp_for_entry: while (tp) { @@ -969,11 +1052,14 @@ check_tp_for_entry: } #endif /* EXEC_LINKS || LYNXCGI_LINKS */ -PRIVATE int fix_http_urls ARGS1(document *,doc) +PRIVATE int fix_http_urls ARGS1( + document *, doc) { char *slash; - /* if it's an ftp URL with a trailing slash, trim it off */ + /* + * If it's an ftp URL with a trailing slash, trim it off. + */ if (!strncmp(doc->address, "ftp", 3) && doc->address[strlen(doc->address)-1] == '/') { char *path = HTParse(doc->address, "", PARSE_PATH|PARSE_PUNCTUATION); @@ -993,7 +1079,9 @@ PRIVATE int fix_http_urls ARGS1(document *,doc) } } - /* if there isn't a slash besides the two at the beginning, append one */ + /* + * If there isn't a slash besides the two at the beginning, append one. + */ if ((slash = strrchr(doc->address, '/')) != NULL) { if (*(slash-1) != '/' || *(slash-2) != ':') { return(0); diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h index 5f2577c5..bff9785e 100644 --- a/src/LYGlobalDefs.h +++ b/src/LYGlobalDefs.h @@ -44,6 +44,10 @@ extern char *no_proxy_putenv_cmd; extern char *list_format; #endif /* !VMS */ +#ifdef VMS +extern char *LYCSwingPath; +#endif /* VMS */ + #ifdef DIRED_SUPPORT extern BOOLEAN lynx_edit_mode; extern BOOLEAN no_dired_support; @@ -88,7 +92,7 @@ extern char star_string[MAX_LINE + 1]; /* from GridText.c */ extern BOOLEAN LYShowCursor; /* show the cursor or hide it */ extern BOOLEAN LYCursesON; /* start_curses()->TRUE, stop_curses()->FALSE */ extern BOOLEAN LYUserSpecifiedURL; /* URL from a goto or document? */ -extern BOOLEAN LYJumpFileURL; /* URL from the jump file shorcuts? */ +extern BOOLEAN LYJumpFileURL; /* URL from the jump file shortcuts? */ extern BOOLEAN jump_buffer; /* TRUE if offering default shortcut */ extern BOOLEAN goto_buffer; /* TRUE if offering default goto URL */ extern char *LYRequestTitle; /* newdoc.title in calls to getfile() */ @@ -101,13 +105,14 @@ extern char *unchecked_box; /* form boxes */ extern char *checked_radio; /* form radio buttons */ extern char *unchecked_radio; /* form radio buttons */ extern char *empty_string; +extern char *LynxHome; extern char *startfile; extern char *helpfile; extern char *helpfilepath; extern char *aboutfilepath; extern char *lynxjumpfile; extern char *lynxlistfile; -extern char *lynxbookfile; +extern char *lynxlinksfile; extern char *display; extern char *language; extern char *pref_charset; /* Lynx's preferred character set - MM */ @@ -256,5 +261,8 @@ extern BOOLEAN LYUseDefSelPop; /* Command line -popup toggle */ extern int LYMultiBookmarks; /* Multi bookmark support on? */ extern BOOLEAN LYMBMBlocked; /* Force MBM support off? */ extern BOOLEAN LYMBMAdvanced; /* MBM statusline for ADVANCED? */ +extern int LYStatusLine; /* Line for statusline() or -1 */ +extern BOOLEAN LYCollapseBRs; /* Collapse serial BRs? */ +extern BOOLEAN LYSetCookies; /* Process Set-Cookie headers? */ #endif /* LYGLOBALDEFS_H */ diff --git a/src/LYHistory.c b/src/LYHistory.c index 8ad69cb3..eb57db8e 100644 --- a/src/LYHistory.c +++ b/src/LYHistory.c @@ -2,11 +2,14 @@ #include "tcp.h" #include "HTAlert.h" #include "HText.h" +#include "LYGlobalDefs.h" #include "LYUtils.h" #include "LYHistory.h" #include "LYPrint.h" #include "LYDownload.h" -#include "LYGlobalDefs.h" +#include "LYKeymap.h" +#include "LYList.h" +#include "LYShowInfo.h" #include "LYSignal.h" #include "LYStrings.h" #include "LYCharUtils.h" @@ -21,49 +24,178 @@ #define FREE(x) if (x) {free(x); x = NULL;} -/* - * Push the current filename, link and line number onto the history list. +PUBLIC HTList * Visited_Links = NULL; /* List of safe popped docs. */ + +/* + * Utility for freeing the list of visited links. - FM */ -PUBLIC void LYpush ARGS1(document *,doc) +PRIVATE void Visited_Links_free NOARGS { + VisitedLink *vl; + HTList *cur = Visited_Links; - if( *doc->address == '\0') /* dont push null file names */ - return; + if (!cur) + return; - /* don't push the history, download, or printer lists */ - if(!strcmp(doc->title, HISTORY_PAGE_TITLE) || - !strcmp(doc->title, PRINT_OPTIONS_TITLE) || - !strcmp(doc->title, DOWNLOAD_OPTIONS_TITLE) ) { - if (!LYforce_no_cache) - LYoverride_no_cache = TRUE; - return; + while (NULL != (vl = (VisitedLink *)HTList_nextObject(cur))) { + FREE(vl->address); + FREE(vl->title); + FREE(vl); } + HTList_delete(Visited_Links); + Visited_Links = NULL; + return; +} + +/* + * Utility for listing visited links, making any repeated + * links the most current in the list. - FM + */ +PUBLIC void LYAddVisitedLink ARGS1( + document *, doc) +{ + VisitedLink *new; + VisitedLink *old; + HTList *cur; + + if (!(doc->address && *doc->address)) + return; + /* + * Exclude POST or HEAD replies, and bookmark, menu + * or list files. - FM + */ + if (doc->post_data || doc->isHEAD || doc->bookmark || + !strcmp((doc->title ? doc->title : ""), HISTORY_PAGE_TITLE) || + !strcmp((doc->title ? doc->title : ""), PRINT_OPTIONS_TITLE) || + !strcmp((doc->title ? doc->title : ""), DOWNLOAD_OPTIONS_TITLE) || #ifdef DIRED_SUPPORT - if(!strcmp(doc->title, DIRED_MENU_TITLE) || - !strcmp(doc->title, UPLOAD_OPTIONS_TITLE) || - !strcmp(doc->title, PERMIT_OPTIONS_TITLE)) { - if (!LYforce_no_cache) - LYoverride_no_cache = TRUE; + !strcmp((doc->title ? doc->title : ""), DIRED_MENU_TITLE) || + !strcmp((doc->title ? doc->title : ""), UPLOAD_OPTIONS_TITLE) || + !strcmp((doc->title ? doc->title : ""), PERMIT_OPTIONS_TITLE) || +#endif /* DIRED_SUPPORT */ + !strcmp((doc->title ? doc->title : ""), CURRENT_KEYMAP_TITLE) || + !strcmp((doc->title ? doc->title : ""), LIST_PAGE_TITLE) || + !strcmp((doc->title ? doc->title : ""), SHOWINFO_TITLE) || + !strcmp((doc->title ? doc->title : ""), COOKIE_JAR_TITLE) || + !strcmp((doc->title ? doc->title : ""), VISITED_LINKS_TITLE)) { + return; + } + + if ((new = (VisitedLink *)calloc(1, sizeof(*new))) == NULL) + outofmem(__FILE__, "HTAddVisitedLink"); + StrAllocCopy(new->address, doc->address); + StrAllocCopy(new->title, (doc->title ? doc->title : "(no title)")); + + if (!Visited_Links) { + Visited_Links = HTList_new(); + atexit(Visited_Links_free); + HTList_addObject(Visited_Links, new); return; } + + cur = Visited_Links; + while (NULL != (old = (VisitedLink *)HTList_nextObject(cur))) { + if (!strcmp((old->address ? old->address : ""), + (new->address ? new->address : "")) && + !strcmp((old->title ? new->title : ""), + (new->title ? new->title : ""))) { + FREE(old->address); + FREE(old->title); + HTList_removeObject(Visited_Links, old); + FREE(old); + break; + } + } + HTList_addObject(Visited_Links, new); + + return; +} + +/* + * Push the current filename, link and line number onto the history list. + */ +PUBLIC void LYpush ARGS2( + document *, doc, + BOOLEAN, force_push) +{ + /* + * Don't push NULL file names. + */ + if (*doc->address == '\0') + return; + + /* + * Check whether this is a document we + * don't push unless forced. - FM + */ + if (!force_push) { + /* + * Don't push the history, printer, or download lists. + */ + if (!strcmp(doc->title, HISTORY_PAGE_TITLE) || + !strcmp(doc->title, PRINT_OPTIONS_TITLE) || + !strcmp(doc->title, DOWNLOAD_OPTIONS_TITLE)) { + if (!LYforce_no_cache) + LYoverride_no_cache = TRUE; + return; + } + +#ifdef DIRED_SUPPORT + /* + * Don't push DIRED menu, upload or permit lists. + */ + if (!strcmp(doc->title, DIRED_MENU_TITLE) || + !strcmp(doc->title, UPLOAD_OPTIONS_TITLE) || + !strcmp(doc->title, PERMIT_OPTIONS_TITLE)) { + if (!LYforce_no_cache) + LYoverride_no_cache = TRUE; + return; + } #endif /* DIRED_SUPPORT */ + } + + /* + * If file is identical to one before it, don't push it. + */ + if (nhist> 1 && + STREQ(history[nhist-1].address, doc->address) && + !strcmp(history[nhist-1].post_data ? + history[nhist-1].post_data : "", + doc->post_data ? + doc->post_data : "") && + !strcmp(history[nhist-1].bookmark ? + history[nhist-1].bookmark : "", + doc->bookmark ? + doc->bookmark : "") && + history[nhist-1].isHEAD == doc->isHEAD) + return; - if(nhist>1 && STREQ(history[nhist-1].address, doc->address) && - !strcmp(history[nhist-1].post_data ? history[nhist-1].post_data : "", - doc->post_data ? doc->post_data : "") && - history[nhist-1].isHEAD == doc->isHEAD) - return; /* file is identical to one before it don't push it */ - - if(nhist>2 && STREQ(history[nhist-2].address, doc->address) && - !strcmp(history[nhist-2].post_data ? history[nhist-2].post_data : "", - doc->post_data ? doc->post_data : "") && - history[nhist-2].isHEAD == doc->isHEAD) { - nhist--; /* pop one off the stack */ - return; /* file is identical to one two before it don't push it */ + /* + * If file is identical to one two before it, don't push it. + */ + if (nhist > 2 && + STREQ(history[nhist-2].address, doc->address) && + !strcmp(history[nhist-2].post_data ? + history[nhist-2].post_data : "", + doc->post_data ? + doc->post_data : "") && + !strcmp(history[nhist-2].bookmark ? + history[nhist-2].bookmark : "", + doc->bookmark ? + doc->bookmark : "") && + history[nhist-2].isHEAD == doc->isHEAD) { + /* + * Pop one off the stack. + */ + nhist--; + return; } - if (nhist<MAXHIST) { + /* + * OK, push it if we have stack space. + */ + if (nhist < MAXHIST) { history[nhist].link = doc->link; history[nhist].page = doc->line; history[nhist].title = NULL; @@ -77,40 +209,53 @@ PUBLIC void LYpush ARGS1(document *,doc) history[nhist].bookmark = NULL; StrAllocCopy(history[nhist].bookmark, doc->bookmark); history[nhist].isHEAD = doc->isHEAD; + history[nhist].safe = doc->safe; nhist++; - - if(TRACE) - fprintf(stderr,"\nLYpush: address:%s\n title:%s\n", - doc->address,doc->title); + if (TRACE) { + fprintf(stderr, + "\nLYpush: address:%s\n title:%s\n", + doc->address, doc->title); + } + } else { + if (LYCursesON) { + _statusline(MAXHIST_REACHED); + sleep(AlertSecs); + } + if (TRACE) { + fprintf(stderr, + "\nLYpush: MAXHIST reached for:\n address:%s\n title:%s\n", + doc->address, doc->title); + } } } /* * Pop the previous filename, link and line number from the history list. */ -PUBLIC void LYpop ARGS1(document *,doc) +PUBLIC void LYpop ARGS1( + document *, doc) { - - if (nhist>0) { + if (nhist > 0) { nhist--; doc->link = history[nhist].link; doc->line = history[nhist].page; FREE(doc->title); - doc->title = history[nhist].title; /* will be freed later */ + doc->title = history[nhist].title; /* will be freed later */ FREE(doc->address); - doc->address = history[nhist].address; /* will be freed later */ + doc->address = history[nhist].address; /* will be freed later */ FREE(doc->post_data); doc->post_data = history[nhist].post_data; FREE(doc->post_content_type); doc->post_content_type = history[nhist].post_content_type; FREE(doc->bookmark); - doc->bookmark = history[nhist].bookmark; + doc->bookmark = history[nhist].bookmark; /* will be freed later */ doc->isHEAD = history[nhist].isHEAD; - - if(TRACE) - fprintf(stderr,"LYpop: address:%s\n title:%s\n", - doc->address,doc->title); - + doc->safe = history[nhist].safe; + if (TRACE) { + fprintf(stderr, + "LYpop: address:%s\n title:%s\n", + doc->address, doc->title); + } } } @@ -119,7 +264,9 @@ PUBLIC void LYpop ARGS1(document *,doc) * list but don't actually remove the entry, just return it. * (This procedure is badly named :) */ -PUBLIC void LYpop_num ARGS2(int,number, document *,doc) +PUBLIC void LYpop_num ARGS2( + int, number, + document *, doc) { if (number >= 0 && nhist >= number) { doc->link = history[number].link; @@ -130,14 +277,15 @@ PUBLIC void LYpop_num ARGS2(int,number, document *,doc) StrAllocCopy(doc->post_content_type, history[number].post_content_type); StrAllocCopy(doc->bookmark, history[number].bookmark); doc->isHEAD = history[number].isHEAD; + doc->safe = history[number].safe; } } /* * This procedure outputs the history buffer into a temporary file. - * */ -PUBLIC int showhistory ARGS1(char **,newfile) +PUBLIC int showhistory ARGS1( + char **, newfile) { static char tempfile[256]; static BOOLEAN first = TRUE; @@ -155,7 +303,7 @@ PUBLIC int showhistory ARGS1(char **,newfile) #endif /* VMS */ } - if ((fp0 = fopen(tempfile,"w")) == NULL) { + if ((fp0 = fopen(tempfile, "w")) == NULL) { HTAlert(CANNOT_OPEN_TEMP); return(-1); } @@ -181,7 +329,7 @@ PUBLIC int showhistory ARGS1(char **,newfile) for (x = nhist-1; x >= 0; x--) { /* * The number of the document in the hist stack, - * its name in a link, and its address. - FM + * its title in a link, and its address. - FM */ if (history[x].title != NULL) { StrAllocCopy(Title, history[x].title); @@ -210,53 +358,155 @@ PUBLIC int showhistory ARGS1(char **,newfile) } /* - * This is a kludge to make the history page seem like any other type of - * file since more info is needed than can be provided by the normal link - * structure. I saved out the history number to a special URL. The info - * looks like: LYNXHIST:# + * This function makes the history page seem like any other type of + * file since more info is needed than can be provided by the normal + * link structure. We saved out the history number to a special URL. + * The info looks like: LYNXHIST:# */ -PUBLIC void historytarget ARGS1(document *,newdoc) +PUBLIC BOOLEAN historytarget ARGS1( + document *, newdoc) { int number, c; DocAddress WWWDoc; + HTParentAnchor *tmpanchor; + HText *text; if ((!newdoc || !newdoc->address) || strlen(newdoc->address) < 10 || !isdigit(*(newdoc->address+9))) - return; + return(FALSE); if ((number = atoi(newdoc->address+9)) > nhist || number < 0) - return; + return(FALSE); LYpop_num(number, newdoc); /* - * If we have POST content, aren't forcing no_cache, - * and still have the text cached, ask the user whether - * to resubmit the form. - FM + * If we have POST content, and have LYresubmit_posts set + * or have no_cache set or do not still have the text cached, + * ask the user whether to resubmit the form. - FM */ - if (newdoc->post_data != NULL && LYforce_no_cache == FALSE) { - if (LYresubmit_posts == TRUE) { + if (newdoc->post_data != NULL) { + WWWDoc.address = newdoc->address; + WWWDoc.post_data = newdoc->post_data; + WWWDoc.post_content_type = newdoc->post_content_type; + WWWDoc.bookmark = newdoc->bookmark; + WWWDoc.isHEAD = newdoc->isHEAD; + WWWDoc.safe = newdoc->safe; + tmpanchor = HTAnchor_parent(HTAnchor_findAddress(&WWWDoc)); + text = (HText *)HTAnchor_document(tmpanchor); + if (((LYresubmit_posts == TRUE) || + (LYforce_no_cache == TRUE && + LYoverride_no_cache == FALSE) || + text == NULL) && + HTConfirm(CONFIRM_POST_RESUBMISSION) == TRUE) { + LYforce_no_cache == TRUE; LYoverride_no_cache = FALSE; + } else if (text != NULL) { + LYforce_no_cache == FALSE; + LYoverride_no_cache = TRUE; } else { - WWWDoc.address = newdoc->address; - WWWDoc.post_data = newdoc->post_data; - WWWDoc.post_content_type = newdoc->post_content_type; - WWWDoc.bookmark = newdoc->bookmark; - WWWDoc.isHEAD = newdoc->isHEAD; - if ((HText *)HTAnchor_document( - HTAnchor_parent(HTAnchor_findAddress(&WWWDoc)) - )) { - LYoverride_no_cache = TRUE; - _statusline( - "Document from Form with POST content. Resubmit? (y/n) "); - c = LYgetch(); - if (TOUPPER(c) == 'Y') { - LYoverride_no_cache = FALSE; - } - } + _statusline(CANCELLED); + sleep(InfoSecs); + return(FALSE); } } if (number != 0) StrAllocCat(newdoc->title," (From History)"); + return(TRUE); +} + +/* + * This procedure outputs the Visited Links + * list into a temporary file. - FM + */ +PUBLIC int LYShowVisitedLinks ARGS1( + char **, newfile) +{ + static char tempfile[256]; + static BOOLEAN first = TRUE; + static char vl_filename[256]; + char *Title = NULL; + char *Address = NULL; + int x; + FILE *fp0; + VisitedLink *vl; + HTList *cur = Visited_Links; + + if (!cur) + return(-1); + + if (first) { + tempname(tempfile, NEW_FILE); + first = FALSE; +#ifdef VMS + } else { + remove(tempfile); /* Remove duplicates on VMS. */ +#endif /* VMS */ + } + + if ((fp0 = fopen(tempfile, "w")) == NULL) { + HTAlert(CANNOT_OPEN_TEMP); + return(-1); + } + + /* + * Make the file a URL now. + */ +#ifdef VMS + sprintf(vl_filename,"file://localhost/%s", tempfile); +#else + sprintf(vl_filename,"file://localhost%s", tempfile); +#endif /* VMS */ + StrAllocCopy(*newfile, vl_filename); + LYforce_HTML_mode = TRUE; /* force this file to be HTML */ + LYforce_no_cache = TRUE; /* force this file to be new */ + + fprintf(fp0, "<head>\n<title>%s</title>\n</head>\n<body>\n", + VISITED_LINKS_TITLE); + + fprintf(fp0, "<h1>You have reached the Visited Links Page</h1>\n"); + fprintf(fp0, "<h2>%s Version %s</h2>\n<pre>", LYNX_NAME, LYNX_VERSION); + fprintf(fp0, + "<em>You visited (POSTs, bookmark, menu and list files excluded):</em>\n"); + x = HTList_count(Visited_Links); + while (NULL != (vl = (VisitedLink *)HTList_nextObject(cur))) { + /* + * The number of the document (most recent highest), + * its title in a link, and its address. - FM + */ + x--; + if (vl->title != NULL && *vl->title != '\0') { + StrAllocCopy(Title, vl->title); + LYEntify(&Title, TRUE); + } else { + StrAllocCopy(Title , "(no title)"); + } + if (vl->address != NULL && *vl->address != '\0') { + StrAllocCopy(Address, vl->address); + LYEntify(&Address, FALSE); + fprintf(fp0, + "%s<em>%d</em>. <tab id=t%d><a href=\"%s\">%s</a>\n", + (x > 99 ? "" : x < 9 ? " " : " "), + x, x, Address, Title); + } else { + fprintf(fp0, + "%s<em>%d</em>. <tab id=t%d><em>%s</em>\n", + (x > 99 ? "" : x < 9 ? " " : " "), + x, x, Title); + } + if (Address != NULL) { + StrAllocCopy(Address, vl->address); + LYEntify(&Address, TRUE); + } + fprintf(fp0, "<tab to=t%d>%s\n", x, + ((Address != NULL) ? Address : "(no address)")); + } + + fprintf(fp0,"</pre>\n</body>\n"); + + fclose(fp0); + FREE(Title); + FREE(Address); + return(0); } diff --git a/src/LYHistory.h b/src/LYHistory.h index 1271259b..caac9605 100644 --- a/src/LYHistory.h +++ b/src/LYHistory.h @@ -6,12 +6,15 @@ #include "LYStructs.h" #endif /* LYSTRUCTS_H */ -extern void LYpush PARAMS((document *doc)); +extern void LYAddVisitedLink PARAMS((document *doc)); +extern void LYpush PARAMS((document *doc, BOOLEAN force_push)); extern void LYpop PARAMS((document *doc)); extern void LYpop_num PARAMS((int number, document *doc)); extern int showhistory PARAMS((char **newfile)); -extern void historytarget PARAMS((document *newdoc)); +extern BOOLEAN historytarget PARAMS((document *newdoc)); +extern int LYShowVisitedLinks PARAMS((char **newfile)); #define HISTORY_PAGE_TITLE "Lynx History Page" +#define VISITED_LINKS_TITLE "Lynx Visited Links Page" #endif /* LYHISTORY_H */ diff --git a/src/LYKeymap.c b/src/LYKeymap.c index 5ba5f6a1..2545f6a6 100644 --- a/src/LYKeymap.c +++ b/src/LYKeymap.c @@ -30,7 +30,7 @@ char keymap[] = { LYK_ABORT, LYK_END, LYK_NEXT_PAGE, 0, /* ^D */ /* ^E */ /* ^F */ /* ^G */ -LYK_HISTORY, LYK_NEXT_LINK, LYK_ACTIVATE, 0, +LYK_HISTORY, LYK_NEXT_LINK, LYK_ACTIVATE, LYK_COOKIE_JAR, /* bs */ /* ht */ /* nl */ /* ^K */ LYK_REFRESH, LYK_ACTIVATE, LYK_DOWN_TWO, 0, @@ -82,11 +82,11 @@ LYK_RAW_TOGGLE, LYK_ADD_BOOKMARK, LYK_PREV_PAGE, LYK_COMMENT, LYK_DOWNLOAD, LYK_EDIT, /* D */ /* E */ -#ifdef DIRED_SUPPORT +#if defined(DIRED_SUPPORT) || defined(VMS) LYK_DIRED_MENU, #else 0, -#endif /* DIRED_SUPPORT */ +#endif /* DIRED_SUPPORT || VMS */ /* F */ LYK_GOTO, @@ -108,7 +108,7 @@ LYK_TAG_LINK, #endif /* DIRED_SUPPORT */ /* T */ - LYK_PREV_DOC, LYK_VIEW_BOOKMARK, 0, + LYK_PREV_DOC, LYK_VLINKS, 0, /* U */ /* V */ /* W */ #ifdef NOT_USED @@ -127,11 +127,11 @@ LYK_MINIMAL, LYK_ADD_BOOKMARK, LYK_PREV_PAGE, LYK_COMMENT, LYK_DOWNLOAD, LYK_EDIT, /* d */ /* e */ -#ifdef DIRED_SUPPORT +#if defined(DIRED_SUPPORT) || defined(VMS) LYK_DIRED_MENU, #else 0, -#endif /* DIRED_SUPPORT */ +#endif /* DIRED_SUPPORT || VMS */ /* f */ LYK_GOTO, @@ -436,6 +436,7 @@ PRIVATE struct rmap revmap[] = { { "ADD_BOOKMARK", "add to your personal bookmark list" }, { "DEL_BOOKMARK", "delete from your personal bookmark list" }, { "VIEW_BOOKMARK", "view your personal bookmark list" }, +{ "VLINKS", "list links visited during the current Lynx session" }, { "SHELL", "escape from the browser to the system" }, { "DOWNLOAD", "download the current link to your computer" }, { "TRACE_TOGGLE", "toggle tracing of browser operations" }, @@ -446,21 +447,26 @@ PRIVATE struct rmap revmap[] = { { "TOGGLE_HELP", "show other commands in the novice help menu" }, { "JUMP", "go directly to a target document or action" }, { "KEYMAP", "display the current key map" }, -{ "LIST", "list references (links) in the current document" }, +{ "LIST", "list the references (links) in the current document" }, { "TOOLBAR", "go to Toolbar or Banner in the current document" }, { "HISTORICAL", "toggle historical vs. valid/minimal comment parsing" }, { "MINIMAL", "toggle minimal vs. valid comment parsing" }, { "SOFT_DQUOTES", "toggle valid vs. soft double-quote parsing" }, { "RAW_TOGGLE", "toggle raw 8-bit translations or CJK mode ON or OFF" }, +{ "COOKIE_JAR", "Examine the Cookie Jar" }, +#ifdef VMS +{ "DIRED_MENU", "invoke File/Directory Manager, if available" }, +#else #ifdef DIRED_SUPPORT +{ "DIRED_MENU", "display a full menu of file operations" }, { "CREATE", "create a new file or directory" }, { "REMOVE", "remove a file or directory" }, { "MODIFY", "modify the name or location of a file or directory" }, { "TAG_LINK", "tag a file or directory for later action" }, -{ "DIRED_MENU", "display a full menu of file operations" }, { "UPLOAD", "upload from your computer to the current directory" }, { "INSTALL", "install file or tagged files into a system area" }, #endif /* DIRED_SUPPORT */ +#endif /* VMS */ #ifdef NOT_USED { "VERSION", "report version of lynx"}, { "FORM_UP", "toggle a checkbox" }, @@ -512,9 +518,6 @@ PRIVATE char *pretty ARGS1 (int, c) return buf; } - -#define KEYTITLE "Current Key Map" - PRIVATE void print_binding ARGS3(HTStream *, target, char *, buf, int, i) { #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) @@ -556,11 +559,12 @@ PRIVATE int LYLoadKeymap ARGS4 ( return(HT_NOT_LOADED); } - sprintf(buf, "<head>\n<title>%s</title>\n</head>\n<body>\n", KEYTITLE); + sprintf(buf, "<head>\n<title>%s</title>\n</head>\n<body>\n", + CURRENT_KEYMAP_TITLE); (*target->isa->put_block)(target, buf, strlen(buf)); sprintf(buf, "<h1>%s (%s Version %s)</h1>\n<pre>", - KEYTITLE, LYNX_NAME, LYNX_VERSION); + CURRENT_KEYMAP_TITLE, LYNX_NAME, LYNX_VERSION); (*target->isa->put_block)(target, buf, strlen(buf)); for (i = 'a'+1; i <= 'z'+1; i++) { diff --git a/src/LYKeymap.h b/src/LYKeymap.h index 99c38fd2..1ed08cf2 100644 --- a/src/LYKeymap.h +++ b/src/LYKeymap.h @@ -20,6 +20,8 @@ extern char keymap[]; /* main keymap matrix */ extern char override[]; #endif +#define CURRENT_KEYMAP_TITLE "Current Key Map" + #define LYK_1 1 #define LYK_2 2 #define LYK_3 3 @@ -69,36 +71,41 @@ extern char override[]; #define LYK_ADD_BOOKMARK 47 #define LYK_DEL_BOOKMARK 48 #define LYK_VIEW_BOOKMARK 49 -#define LYK_SHELL 50 -#define LYK_DOWNLOAD 51 -#define LYK_TRACE_TOGGLE 52 -#define LYK_IMAGE_TOGGLE 53 -#define LYK_INLINE_TOGGLE 54 -#define LYK_HEAD 55 -#define LYK_DO_NOTHING 56 -#define LYK_TOGGLE_HELP 57 -#define LYK_JUMP 58 -#define LYK_KEYMAP 59 -#define LYK_LIST 60 -#define LYK_TOOLBAR 61 -#define LYK_HISTORICAL 62 -#define LYK_MINIMAL 63 -#define LYK_SOFT_DQUOTES 64 -#define LYK_RAW_TOGGLE 65 +#define LYK_VLINKS 50 +#define LYK_SHELL 51 +#define LYK_DOWNLOAD 52 +#define LYK_TRACE_TOGGLE 53 +#define LYK_IMAGE_TOGGLE 54 +#define LYK_INLINE_TOGGLE 55 +#define LYK_HEAD 56 +#define LYK_DO_NOTHING 57 +#define LYK_TOGGLE_HELP 58 +#define LYK_JUMP 59 +#define LYK_KEYMAP 60 +#define LYK_LIST 61 +#define LYK_TOOLBAR 62 +#define LYK_HISTORICAL 63 +#define LYK_MINIMAL 64 +#define LYK_SOFT_DQUOTES 65 +#define LYK_RAW_TOGGLE 66 +#define LYK_COOKIE_JAR 67 +#ifdef VMS +#define LYK_DIRED_MENU 68 +#endif /* VMS */ #ifdef DIRED_SUPPORT -#define LYK_CREATE 66 -#define LYK_REMOVE 67 -#define LYK_MODIFY 68 -#define LYK_TAG_LINK 69 -#define LYK_DIRED_MENU 70 -#define LYK_UPLOAD 71 -#define LYK_INSTALL 72 +#define LYK_DIRED_MENU 68 +#define LYK_CREATE 69 +#define LYK_REMOVE 70 +#define LYK_MODIFY 71 +#define LYK_TAG_LINK 72 +#define LYK_UPLOAD 73 +#define LYK_INSTALL 74 #endif /* DIRED_SUPPORT */ #ifdef NOT_USED -#define LYK_VERSION 73 -#define LYK_FORM_UP 74 -#define LYK_FORM_DOWN 75 +#define LYK_VERSION 75 +#define LYK_FORM_UP 76 +#define LYK_FORM_DOWN 77 #endif /* NOT_USED */ #endif /* LYKEYMAP_H */ diff --git a/src/LYLocal.c b/src/LYLocal.c index 95a49abc..d7d36052 100644 --- a/src/LYLocal.c +++ b/src/LYLocal.c @@ -25,6 +25,7 @@ #include "LYGlobalDefs.h" #include "LYUtils.h" #include "LYStrings.h" +#include "LYCharUtils.h" #include "LYStructs.h" #include "LYGetFile.h" #include "LYHistory.h" @@ -105,6 +106,9 @@ struct dired_menu { #if defined(OK_TAR) && defined(OK_GZIP) && !defined(ARCHIVE_ONLY) { DE_FILE, ".tar.gz", "Expand", "(current selection)", "LYNXDIRED://UNTAR_GZ%p", NULL }, + +{ DE_FILE, ".tgz", "Expand", + "(current selection)", "LYNXDIRED://UNTAR_GZ%p", NULL }, #endif /* OK_TAR && OK_GZIP && !ARCHIVE_ONLY */ #ifndef ARCHIVE_ONLY @@ -161,6 +165,9 @@ struct dired_menu { { DE_TAG, "", "Remove all tagged files and directories.", "", "LYNXDIRED://REMOVE_TAGGED", NULL }, +{ DE_TAG, "", "Untag all tagged files and directories.", + "", "LYNXDIRED://CLEAR_TAGGED", NULL }, + { 0, NULL, NULL, NULL, NULL, NULL } }; @@ -214,7 +221,7 @@ PRIVATE BOOLEAN remove_tagged NOARGS sprintf(tmpbuf, "remove %s", testpath); if (my_spawn(RM_PATH, args, tmpbuf) <= 0) { FREE(testpath); - return count; + return ((count == 0) ? -1 : count); } ++count; } @@ -379,8 +386,11 @@ PRIVATE BOOLEAN modify_tagged ARGS1( args[1] = srcpath; args[2] = savepath; args[3] = (char *) 0; - if (my_spawn(MV_PATH, args, tmpbuf) <= 0) + if (my_spawn(MV_PATH, args, tmpbuf) <= 0) { + if (count == 0) + count = -1; break; + } ++count; } FREE(srcpath); @@ -466,7 +476,7 @@ PRIVATE BOOLEAN modify_name ARGS1( args[2] = newpath; args[3] = (char *) 0; if (my_spawn(MV_PATH, args, tmpbuf) <= 0) - return 0; + return (-1); return 1; } } else if ((dir_info.st_mode & S_IFMT) == S_IFDIR) { @@ -587,7 +597,7 @@ PRIVATE BOOLEAN modify_location ARGS1( args[2] = newpath; args[3] = (char *) 0; if (my_spawn(MV_PATH, args, tmpbuf) <= 0) - return 0; + return (-1); return 1; } else { _statusline("Destination has different owner! Request denied. "); @@ -719,7 +729,7 @@ PRIVATE BOOLEAN create_file ARGS1( args[1] = testpath; args[2] = (char *) 0; if (my_spawn(TOUCH_PATH, args, tmpbuf) <= 0) - return 0; + return (-1); return 1; } else if ((dir_info.st_mode & S_IFMT) == S_IFDIR) { _statusline( @@ -782,7 +792,7 @@ PRIVATE BOOLEAN create_directory ARGS1( args[1] = testpath; args[2] = (char *) 0; if (my_spawn(MKDIR_PATH, args, tmpbuf) <= 0) - return 0; + return (-1); return 1; } else if ((dir_info.st_mode & S_IFMT) == S_IFDIR) { _statusline( @@ -888,7 +898,7 @@ PRIVATE BOOLEAN remove_single ARGS1( args[2] = testpath; args[3] = (char *) 0; if (my_spawn(RM_PATH, args, tmpbuf) <= 0) - return 0; + return (-1); return 1; } return 0; @@ -1178,7 +1188,7 @@ PRIVATE BOOLEAN permit_location ARGS3( args[2] = destpath; args[3] = (char *) 0; if (my_spawn(CHMOD_PATH, args, tmpbuf) <= 0) { - return 0; + return (-1); } ++LYforce_no_cache; /* Force update of dired listing */ return 1; @@ -1259,16 +1269,6 @@ PUBLIC void showtags ARGS1( } } -PUBLIC char * strip_trailing_slash ARGS1( - char *, dirname) -{ - int i; - - i = strlen(dirname) - 1; - while (i && dirname[i] == '/') dirname[i--] = '\0'; - return dirname; -} - /* ** Perform file management operations for LYNXDIRED URL's. ** Attempt to be consistent. These are (pseudo) URLs - i.e. they should @@ -1301,9 +1301,11 @@ PUBLIC int local_dired ARGS1( */ tp = NULL; if (!strncmp(line,"LYNXDIRED://NEW_FILE",20)) { - if (create_file(&line[20])) ++LYforce_no_cache; + if (create_file(&line[20]) > 0) + ++LYforce_no_cache; } else if (!strncmp(line,"LYNXDIRED://NEW_FOLDER",22)) { - if (create_directory(&line[22])) ++LYforce_no_cache; + if (create_directory(&line[22]) > 0) + ++LYforce_no_cache; } else if (!strncmp(line,"LYNXDIRED://INSTALL_SRC",23)) { local_install(NULL, &line[23], &tp); StrAllocCopy(doc->address, tp); @@ -1313,11 +1315,14 @@ PUBLIC int local_dired ARGS1( local_install(&line[24], NULL, &tp); LYpop(doc); } else if (!strncmp(line,"LYNXDIRED://MODIFY_NAME",23)) { - if (modify_name(&line[23])) ++LYforce_no_cache; + if (modify_name(&line[23]) > 0) + ++LYforce_no_cache; } else if (!strncmp(line,"LYNXDIRED://MODIFY_LOCATION",27)) { - if (modify_location(&line[27])) ++LYforce_no_cache; + if (modify_location(&line[27]) > 0) + ++LYforce_no_cache; } else if (!strncmp(line,"LYNXDIRED://MOVE_TAGGED",23)) { - if (modify_tagged(&line_url[23])) ++LYforce_no_cache; + if (modify_tagged(&line_url[23]) > 0) + ++LYforce_no_cache; #ifdef OK_PERMIT } else if (!strncmp(line,"LYNXDIRED://PERMIT_SRC",22)) { permit_location(NULL, &line[22], &tp); @@ -1329,9 +1334,12 @@ PUBLIC int local_dired ARGS1( permit_location(&line_url[27], NULL, &tp); #endif /* OK_PERMIT */ } else if (!strncmp(line,"LYNXDIRED://REMOVE_SINGLE",25)) { - if (remove_single(&line[25])) ++LYforce_no_cache; + if (remove_single(&line[25]) > 0) + ++LYforce_no_cache; } else if (!strncmp(line,"LYNXDIRED://REMOVE_TAGGED",25)) { if (remove_tagged()) ++LYforce_no_cache; + } else if (!strncmp(line,"LYNXDIRED://CLEAR_TAGGED",24)) { + clear_tags(); } else if (!strncmp(line,"LYNXDIRED://UPLOAD",18)) { /* * They're written by LYUpload_options() HTUnEscaped, @@ -1549,11 +1557,11 @@ PUBLIC int dired_options ARGS2( cp += 5; strcpy(path,cp); StrAllocCopy(path_url,cp); - if (path_url[strlen(path_url)-1] == '/') + if (*path_url && path_url[1] && path_url[strlen(path_url)-1] == '/') path_url[strlen(path_url)-1] = '\0'; HTUnEscape(path); - if (path[strlen(path)-1] == '/') - path[strlen(path)-1] = '\0'; + if (*path && path[1] && path[strlen(path)-1] == '/') + path[strlen(path)-1] = '\0'; if (lstat(path,&dir_info) == -1 && stat(path,&dir_info) == -1) { sprintf(tmpbuf,"Unable to get status of %s ",path); @@ -1588,8 +1596,35 @@ PUBLIC int dired_options ARGS2( fprintf(fp0,"Current selection is %s <p>\n",path); else fprintf(fp0,"Nothing currently selected. <p>\n"); - else - fprintf(fp0,"Current selection is all tagged items. <p>\n"); + else { /* write out number of tagged items, and names of first + few of them relative to current (in the DIRED sense) directory */ + int n = HTList_count(tagged); + char * cp1 = NULL; + char * cd = NULL; + int i, m; +#define NUM_TAGS_TO_WRITE 10 + fprintf(fp0,"Current selection is %d tagged item%s", + n, (n==1 ? ":" : "s:")); + StrAllocCopy(cd, doc->address); + HTUnEscapeSome(cd, "/"); + if (*cd && cd[strlen(cd)-1] != '/') + StrAllocCat(cd, "/"); + m = (n < NUM_TAGS_TO_WRITE) ? n : NUM_TAGS_TO_WRITE; + for (i=1; i <= m; i++) { + cp1 = HTRelative(HTList_objectAt(tagged, i-1), + (*cd ? cd : "file://localhost")); + HTUnEscape(cp1); + LYEntify(&cp1, TRUE); /* _should_ do this everywhere... */ + fprintf(fp0,"%s <br>\n %s", + (i==1 ? "" : " ,"), cp1); + FREE(cp1); + } + if (n > m) { + fprintf(fp0," , ..."); + } + fprintf(fp0, " <p>\n"); + FREE(cd); + } /* * if menu_head is NULL then use defaults and link them together now @@ -1674,7 +1709,7 @@ PRIVATE int my_spawn ARGS3( waitpid(pid, &wstatus, 0); /* wait for child */ #endif /* NeXT || AIX4 || sony_news */ if (WEXITSTATUS(wstatus) != 0 || - WTERMSIG(wstatus) != 0) { /* error return */ + WTERMSIG(wstatus) > 0) { /* error return */ sprintf(tmpbuf, "Probable failure to %s due to system error!", msg); rc = 0; @@ -1805,7 +1840,7 @@ PUBLIC BOOLEAN local_install ARGS3( if (HTList_isEmpty(tagged)) { args[1] = savepath; if (my_spawn(INSTALL_PATH, args, tmpbuf) <= 0) - return count; + return (-1); count++; } else { char * name; @@ -1815,7 +1850,7 @@ PUBLIC BOOLEAN local_install ARGS3( args[1] = name + 16; if (my_spawn(INSTALL_PATH, args, tmpbuf) <= 0) - return count; + return ((count == 0) ? -1 : count); count++; } clear_tags(); diff --git a/src/LYLocal.h b/src/LYLocal.h index 66dbff4d..6a042e60 100644 --- a/src/LYLocal.h +++ b/src/LYLocal.h @@ -33,7 +33,7 @@ #endif /* !S_ISUID */ /* Special return code for LYMainLoop.c */ -#define PERMIT_FORM_RESULT 2 +#define PERMIT_FORM_RESULT (-99) extern BOOLEAN local_create PARAMS((document *doc)); extern BOOLEAN local_modify PARAMS((document *doc, char **newpath)); @@ -56,7 +56,6 @@ extern BOOLEAN is_a_file PARAMS((char *testname)); */ extern void tagflag PARAMS((int flag, int cur)); extern void showtags PARAMS((HTList *tag)); -extern char * strip_trailing_slash PARAMS((char * dirname)); extern int local_dired PARAMS((document *doc)); extern int dired_options PARAMS ((document *doc, char ** newfile)); diff --git a/src/LYMail.c b/src/LYMail.c index 094e6da8..a0855064 100644 --- a/src/LYMail.c +++ b/src/LYMail.c @@ -30,9 +30,12 @@ PUBLIC void mailform ARGS4( { FILE *fd; char *address = NULL; - char cmd[512], *cp, *cp0, *cp1; - int len, i, ch, recall; + char *searchpart = NULL; + char *cp = NULL, *cp0 = NULL, *cp1 = NULL; char subject[80]; + char self[80]; + char cmd[512]; + int len, i, ch; #ifdef VMS char tmpfile[256]; char *address_ptr1, *address_ptr2; @@ -43,30 +46,77 @@ PUBLIC void mailform ARGS4( HTAlert(BAD_FORM_MAILTO); return; } + subject[0] = '\0'; + self[0] = '\0'; if ((cp = (char *)strchr(mailto_address,'\n')) != NULL) *cp = '\0'; StrAllocCopy(address, mailto_address); /* - * Check for a ?searchpart with subject=foo. - FM + * Check for a ?searchpart. - FM */ - subject[0] = '\0'; if ((cp = strchr(address, '?')) != NULL) { - *cp++ = '\0'; - while (*cp != '\0' && strncasecomp(cp, "subject=", 8)) - cp++; - cp0 = (cp - 1); - if ((*cp != '\0') && - (*cp0 == '\0' || *cp0 == '&' || *cp0 == ';')) { - if ((cp1 = strchr(cp, '&')) != NULL) { - *cp1 = '\0'; - } else if ((cp1 = strchr(cp, ';')) != NULL) { - *cp1 = '\0'; + StrAllocCopy(searchpart, cp); + *cp = '\0'; + cp = (searchpart + 1); + if (*cp != '\0') { + /* + * Seek and handle a subject=foo. - FM + */ + while (*cp != '\0') { + if ((*(cp - 1) == '?' || *(cp - 1) == '&') && + !strncasecomp(cp, "subject=", 8)) + break; + cp++; + } + if (*cp) { + cp += 8; + if ((cp1 = strchr(cp, '&')) != NULL) { + *cp1 = '\0'; + } + if (*cp) { + strncpy(subject, cp, 70); + subject[70] = '\0'; + HTUnEscape(subject); + } + if (cp1) { + *cp1 = '&'; + cp1 = NULL; + } + } + + /* + * Seek and handle cc=foo fields. Excludes Bcc=foo + * and appends to address, so we can use our own cc + * field for the actual mailing. - FM + */ + cp = (searchpart + 1); + while (*cp != '\0') { + if ((*(cp - 1) == '?' || *(cp - 1) == '&') && + !strncasecomp(cp, "cc=", 3)) { + cp += 3; + if ((cp1 = strchr(cp, '&')) != NULL) { + *cp1 = '\0'; + } + while (*cp == ',') + cp++; + if (*cp) { + StrAllocCat(address, ","); + StrAllocCat(address, cp); + } + if (cp1) { + *cp1 = '&'; + cp = cp1; + cp1 = NULL; + } else { + break; + } + } + cp++; } - strncpy(subject, cp, 70); - subject[70] = '\0'; - HTUnEscape(subject); + + FREE(searchpart); } } @@ -90,7 +140,8 @@ PUBLIC void mailform ARGS4( } /* - * Allow user to edit the default Subject. - FM + * Allow user to edit the default Subject + * and enter a cc to self. - FM */ if (subject[0] == '\0') { if (mailto_subject && *mailto_subject) { @@ -101,9 +152,21 @@ PUBLIC void mailform ARGS4( } subject[70] = '\0'; } - recall = 0; _statusline(SUBJECT_PROMPT); - if ((ch = LYgetstr(subject, VISIBLE, 71, recall)) < 0) { + if ((ch = LYgetstr(subject, VISIBLE, 71, NORECALL)) < 0) { + /* + * User cancelled via ^G. - FM + */ + _statusline(FORM_MAILTO_CANCELLED); + sleep(InfoSecs); + FREE(address); + return; + } + sprintf(self,"%.79s", (personal_mail_address ? + personal_mail_address : "")); + self[79] = '\0'; + _statusline("Cc: "); + if ((ch = LYgetstr(self, VISIBLE, sizeof(self), NORECALL)) < 0) { /* * User cancelled via ^G. - FM */ @@ -113,7 +176,32 @@ PUBLIC void mailform ARGS4( return; } -#ifdef UNIX +#ifdef VMS + sprintf(tmpfile, "%s%s", lynx_temp_space, "temp_mail.txt"); + if ((fd = fopen(tmpfile,"w")) == NULL) { + HTAlert(FORM_MAILTO_FAILED); + FREE(address); + return; + } + if (*self) { + cp = self; + while (*cp == ' ' || *cp == ',') + cp++; + if (*cp) { + StrAllocCat(address, ","); + StrAllocCat(address, cp); + } + } + if (mailto_type && + !strncasecomp(mailto_type, "multipart/form-data", 19)) { + /* + * Ugh! There's no good way to include headers while + * we're still using "generic" VMS MAIL, so we'll put + * this in the body of the message. - FM + */ + fprintf(fd, "X-Content-Type: %s\n\n", mailto_type); + } +#else #ifdef MMDF sprintf(cmd, "%s -mlruxto,cc\\*",system_mail); #else @@ -133,25 +221,11 @@ PUBLIC void mailform ARGS4( fprintf(fd,"To: %s\n", address); if (personal_mail_address && *personal_mail_address) fprintf(fd,"From: %s\n", personal_mail_address); + remove_tildes(self); + if (*self) + fprintf(fd,"Cc: %s\n", self); fprintf(fd,"Subject: %.70s\n\n", subject); _statusline(SENDING_FORM_CONTENT); -#endif /* UNIX */ -#ifdef VMS - sprintf(tmpfile,"%s%s",lynx_temp_space, "temp_mail.txt"); - if ((fd = fopen(tmpfile,"w")) == NULL) { - HTAlert(FORM_MAILTO_FAILED); - FREE(address); - return; - } - if (mailto_type && - !strncasecomp(mailto_type, "multipart/form-data", 19)) { - /* - * Ugh! There's no good way to include headers while - * we're still using "generic" VMS MAIL, so we'll put - * this in the body of the message. - FM - */ - fprintf(fd, "X-Content-Type: %s\n\n", mailto_type); - } #endif /* VMS */ /* @@ -192,7 +266,10 @@ PUBLIC void mailform ARGS4( #endif /* UNIX */ #ifdef VMS fclose(fd); - sprintf(cmd, "%s /subject=\"%.70s\" %s ",system_mail, subject,tmpfile); + sprintf(cmd, "%s %s/subject=\"%.70s\" %s ", + system_mail, + (strncasecomp(system_mail, "MAIL", 4) ? "" : "/noself"), + subject, tmpfile); address_ptr1 = address; do { @@ -204,7 +281,7 @@ PUBLIC void mailform ARGS4( if (strlen(address) > 3) { if (!first) - strcat(cmd, ", "); /* add a comma and a space */ + strcat(cmd, ","); /* add a comma */ sprintf( &cmd[strlen(cmd)], mail_adrs, address_ptr1); first = FALSE; } @@ -248,7 +325,7 @@ PUBLIC void mailmsg ARGS4(int,cur, char *,owner_address, /* * Check for a ?searchpart and trim it. - FM */ - if ((cp = strchr(address, '?')) != NULL && strchr(cp+1, '=') != NULL) + if ((cp = strchr(address, '?')) != NULL) *cp = '\0'; /* @@ -324,7 +401,7 @@ PUBLIC void mailmsg ARGS4(int,cur, char *,owner_address, if (strlen(address) > 3) { if (!first) - strcat(cmd, ", "); /* add a comma and a space */ + strcat(cmd, ","); /* add a comma */ sprintf(&cmd[strlen(cmd)], mail_adrs, address_ptr1); first = FALSE; } @@ -375,8 +452,12 @@ PUBLIC void reply_by_mail ARGS3( { char user_input[1000]; FILE *fd; - char *address = NULL, *cp, *cp0, *cp1; - int i; + char *address = NULL; + char *searchpart = NULL; + char *body = NULL; + char *cp = NULL, *cp0 = NULL, *cp1 = NULL; + char *temp = NULL; + int i, len; int c = 0; /* user input */ char tmpfile[256], cmd[512]; static char *personal_name = NULL; @@ -413,26 +494,139 @@ PUBLIC void reply_by_mail ARGS3( HTAlert(MAILTO_URL_TEMPOPEN_FAILED); return; } + subject[0] = '\0'; /* - * Check for a ?searchpart with subject=foo. - FM + * Check for a ?searchpart. - FM */ - subject[0] = '\0'; if ((cp = strchr(address, '?')) != NULL) { - *cp++ = '\0'; - while (*cp != '\0' && strncasecomp(cp, "subject=", 8)) - cp++; - cp0 = (cp - 1); - if ((*cp != '\0') && - (*cp0 == '\0' || *cp0 == '&' || *cp0 == ';')) { - if ((cp1 = strchr(cp, '&')) != NULL) { - *cp1 = '\0'; - } else if ((cp1 = strchr(cp, ';')) != NULL) { - *cp1 = '\0'; + StrAllocCopy(searchpart, cp); + *cp = '\0'; + cp = (searchpart + 1); + if (*cp != '\0') { + /* + * Seek and handle a subject=foo. - FM + */ + while (*cp != '\0') { + if ((*(cp - 1) == '?' || *(cp - 1) == '&') && + !strncasecomp(cp, "subject=", 8)) + break; + cp++; + } + if (*cp) { + cp += 8; + if ((cp1 = strchr(cp, '&')) != NULL) { + *cp1 = '\0'; + } + if (*cp) { + strncpy(subject, cp, 70); + subject[70] = '\0'; + HTUnEscape(subject); + } + if (cp1) { + *cp1 = '&'; + cp1 = NULL; + } } - strncpy(subject, cp, 70); - subject[70] = '\0'; - HTUnEscape(subject); + + /* + * Seek and handle cc=foo fields. Excludes Bcc=foo + * and appends to address, so we can use our own cc + * field for the actual mailing. - FM + */ + cp = (searchpart + 1); + while (*cp != '\0') { + if ((*(cp - 1) == '?' || *(cp - 1) == '&') && + !strncasecomp(cp, "cc=", 3)) { + cp += 3; + if ((cp1 = strchr(cp, '&')) != NULL) { + *cp1 = '\0'; + } + while (*cp == ',') + cp++; + if (*cp) { + StrAllocCat(address, ","); + StrAllocCat(address, cp); + } + if (cp1) { + *cp1 = '&'; + cp = cp1; + cp1 = NULL; + } else { + break; + } + } + cp++; + } + + /* + * Seek and handle body=foo fields. - FM + */ + cp = (searchpart + 1); + while (*cp != '\0') { + if ((*(cp - 1) == '?' || *(cp - 1) == '&') && + !strncasecomp(cp, "body=", 5)) { + cp += 5; + if ((cp1 = strchr(cp, '&')) != NULL) { + *cp1 = '\0'; + } + if (*cp) { + /* + * Break up the value into lines with + * a maximimum length of 78. - FM + */ + StrAllocCopy(temp, cp); + HTUnEscape(temp); + cp0 = temp; + while((cp = strchr(cp0, '\n')) != NULL) { + *cp = '\0'; + if (cp > cp0) { + if (*(cp - 1) == '\r') { + *(cp - 1) = '\0'; + } + } + i = 0; + len = strlen(cp0); + while (len > 78) { + strncpy(cmd, (char *)&cp0[i], 78); + cmd[78] = '\0'; + strcat(cmd, "\n"); + StrAllocCat(body, cmd); + i += 78; + len = strlen((char *)&cp0[i]); + } + sprintf(cmd, "%s\n", (char *)&cp0[i]); + StrAllocCat(body, cmd); + cp0 = (cp + 1); + } + i = 0; + len = strlen(cp0); + while (len > 78) { + strncpy(cmd, (char *)&cp0[i], 78); + cmd[78] = '\0'; + strcat(cmd, "\n"); + StrAllocCat(body, cmd); + i += 78; + len = strlen((char *)&cp0[i]); + } + if (len) { + sprintf(cmd, "%s\n", (char *)&cp0[i]); + StrAllocCat(body, cmd); + } + FREE(temp); + } + if (cp1) { + *cp1 = '&'; + cp = cp1; + cp1 = NULL; + } else { + break; + } + } + cp++; + } + + FREE(searchpart); } } if (subject[0] == '\0' && title && *title) { @@ -458,8 +652,11 @@ PUBLIC void reply_by_mail ARGS3( } cp = cp1; } + if (address[(strlen(address) - 1)] == ',') + address[(strlen(address) - 1)] == '\0'; if (*address == '\0') { FREE(address); + FREE(body); fclose(fd); /* Close the tmpfile. */ remove(tmpfile); /* Delete the tmpfile. */ HTAlert(NO_ADDRESS_IN_MAILTO_URL); @@ -474,16 +671,18 @@ PUBLIC void reply_by_mail ARGS3( #ifdef VMS - /* - * Put the X-URL and X-Mailer lines in the tmpfile. - */ - fprintf(fd, "X-URL: %s%s\n", - (filename && *filename) ? filename : "mailto:", - (filename && *filename) ? "" : address); - fprintf(fd,"X-Mailer: Lynx, Version %s\n",LYNX_VERSION); + if (!body) { + /* + * Put the X-URL and X-Mailer lines in the tmpfile. + */ + fprintf(fd, "X-URL: %s%s\n", + (filename && *filename) ? filename : "mailto:", + (filename && *filename) ? "" : address); + fprintf(fd,"X-Mailer: Lynx, Version %s\n",LYNX_VERSION); #ifdef NO_ANONYMOUS_MAIL - fprintf(fd,"\n"); + fprintf(fd,"\n"); #endif /* NO_ANONYMOUS_MAIL */ + } #else /* Unix: */ /* * Put the To: line in the header. @@ -502,26 +701,43 @@ PUBLIC void reply_by_mail ARGS3( #endif /* VMS */ /* - * Cear the screen and inform the user. + * Clear the screen and inform the user. */ clear(); move(2,0); - scrollok(stdscr,TRUE); /* Enable scrolling. */ - addstr("You are now sending a comment to:"); - addstr("\n "); - addstr(address); - addstr("\n\nUse Ctrl-G to cancel if you do not want to send a message\n"); + scrollok(stdscr, TRUE); /* Enable scrolling. */ + if (body) + addstr(SENDING_MESSAGE_WITH_BODY_TO); + else + addstr(SENDING_COMMENT_TO); + cp = address; + while ((cp1 = strchr(cp, ',')) != NULL) { + *cp1 = '\0'; + while (*cp == ' ') + cp++; + if (*cp) { + addstr(cp); + addstr(",\n "); + } + *cp1 = ','; + cp = (cp1 + 1); + } + if (*cp) + addstr(cp); + addstr(CTRL_G_TO_CANCEL_SEND); +#ifdef VMS + if (!body) { +#endif /* VMS */ #ifndef NO_ANONYMOUS_EMAIL /* * Get the user's personal name. */ - addstr("\n Please enter your name, "); - addstr("or leave it blank if you wish to remain anonymous\n"); + addstr(ENTER_NAME_OR_BLANK); if (personal_name == NULL) *user_input = '\0'; else { - addstr(" Use Control-U to erase the default.\n"); + addstr(CTRL_U_TO_ERASE); strcpy(user_input, personal_name); } #ifdef VMS @@ -554,10 +770,10 @@ PUBLIC void reply_by_mail ARGS3( /* * Get the user's return address. */ - addstr("\n Please enter a mail address or some other\n"); - addstr(" means to contact you, if you desire a response.\n"); + addstr(ENTER_MAIL_ADDRESS_OR_OTHER); + addstr(MEANS_TO_CONTACT_FOR_RESPONSE); if (personal_mail_address) - addstr(" Use Control-U to erase the default.\n"); + addstr(CTRL_U_TO_ERASE); #ifdef VMS addstr("X-From: "); #else @@ -587,12 +803,15 @@ PUBLIC void reply_by_mail ARGS3( StrAllocCat(header, buf); #endif /* VMS */ #endif /* !NO_ANONYMOUS_EMAIL */ +#ifdef VMS + } +#endif /* VMS */ /* * Get the subject line. */ - addstr("\n Please enter a subject line.\n"); - addstr(" Use Control-U to erase the default.\n"); + addstr(ENTER_SUBJECT_LINE); + addstr(CTRL_U_TO_ERASE); addstr("Subject: "); /* Add the default subject. */ sprintf(user_input, "%.70s%.63s", @@ -622,14 +841,13 @@ PUBLIC void reply_by_mail ARGS3( StrAllocCat(header, buf); #endif /* VMS */ -#ifndef VMS /* * Offer a CC line. */ - addstr("\n Enter a mail address for a CC of your message.\n"); + addstr(ENTER_ADDRESS_FOR_CC); if (personal_mail_address) - addstr(" Use Control-U to erase the default.\n"); - addstr(" (Leave blank if you don't want a copy.)\n"); + addstr(CTRL_U_TO_ERASE); + addstr(BLANK_FOR_NO_COPY); addstr("Cc: "); /* Add the mail address if there is one. */ sprintf(user_input,"%s", (personal_mail_address ? @@ -645,6 +863,17 @@ PUBLIC void reply_by_mail ARGS3( } addstr("\n"); remove_tildes(user_input); +#ifdef VMS + if (*user_input) { + cp = user_input; + while (*cp == ' ' || *cp == ',') + cp++; + if (*cp) { + StrAllocCat(address, ","); + StrAllocCat(address, cp); + } + } +#else if (*user_input) { sprintf(buf,"Cc: %s\n",user_input); StrAllocCat(header, buf); @@ -655,7 +884,7 @@ PUBLIC void reply_by_mail ARGS3( */ sprintf(buf,"\n"); StrAllocCat(header, buf); -#endif /* !VMS */ +#endif /* VMS */ if (!no_editor && editor && *editor != '\0') { /* @@ -663,7 +892,14 @@ PUBLIC void reply_by_mail ARGS3( */ char *editor_arg = ""; - if (strcmp(HTLoadedDocumentURL(),"")) { + if (body) { + cp1 = body; + while((cp = strchr(cp1, '\n')) != NULL) { + *cp++ = '\0'; + fprintf(fd, "%s\n", cp1); + cp1 = cp; + } + } else if (strcmp(HTLoadedDocumentURL(), "")) { /* * Ask if the user wants to include the original message. */ @@ -674,7 +910,7 @@ PUBLIC void reply_by_mail ARGS3( c = LYgetch(); if (TOUPPER(c) == 'Y') { /* the 1 will add the reply ">" in front of every line */ - print_wwwfile_to_fd(fd,1); + print_wwwfile_to_fd(fd, 1); } } fclose(fd); /* Close the tmpfile. */ @@ -700,13 +936,53 @@ PUBLIC void reply_by_mail ARGS3( start_curses(); } + } else if (body) { + /* + * Let user review the body. - FM + */ + clear(); + move(0,0); + addstr(REVIEW_MESSAGE_BODY); + refresh(); + cp1 = body; + i = (LYlines - 5); + while((cp = strchr(cp1, '\n')) != NULL) { + if (i <= 0) { + addstr(RETURN_TO_CONTINUE); + refresh(); + c = LYgetch(); + addstr("\n"); + if (term_letter || c == 7 || c == 3) { + addstr(CANCELLED); + sleep(InfoSecs); + fclose(fd); /* Close the tmpfile. */ + scrollok(stdscr, FALSE); /* Stop scrolling. */ + goto cleanup; + } + i = (LYlines - 2); + } + *cp++ = '\0'; + sprintf(cmd, "%s\n", cp1); + fprintf(fd, cmd); + addstr(cmd); + cp1 = cp; + i--; + } + while (i >= 0) { + addstr("\n"); + i--; + } + refresh(); + fclose(fd); /* Close the tmpfile. */ + scrollok(stdscr,FALSE); /* Stop scrolling. */ + } else { /* * Use the internal line editor for the message. */ - addstr("\n Please enter your message below."); - addstr("\n When you are done, press enter and put a single period (.)"); - addstr("\n on a line and press enter again."); + addstr(ENTER_MESSAGE_BELOW); + addstr(ENTER_PERIOD_WHEN_DONE_A); + addstr(ENTER_PERIOD_WHEN_DONE_B); addstr("\n\n"); refresh(); *user_input = '\0'; @@ -745,7 +1021,12 @@ PUBLIC void reply_by_mail ARGS3( */ signal(SIGINT, SIG_IGN); #endif /* !VMS */ - _statusline(SEND_COMMENT_PROMPT); + LYStatusLine = (LYlines - 1); + if (body) + _statusline(SEND_MESSAGE_PROMPT); + else + _statusline(SEND_COMMENT_PROMPT); + LYStatusLine = -1; c = 0; while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' && !term_letter && c != 7 && c != 3) @@ -764,7 +1045,10 @@ PUBLIC void reply_by_mail ARGS3( /* * Set the mail command. */ - sprintf(cmd, "%s /subject=\"%s\" %s ", system_mail, subject, tmpfile); + sprintf(cmd, "%s %s/subject=\"%s\" %s ", + system_mail, + (strncasecomp(system_mail, "MAIL", 4) ? "" : "/noself"), + subject, tmpfile); /* * Now add all the people in the address field. @@ -784,7 +1068,7 @@ PUBLIC void reply_by_mail ARGS3( */ if (strlen(address_ptr1) > 3) { if (!first) - strcat(cmd, ", "); /* add a comma and a space */ + strcat(cmd, ","); /* add a comma */ sprintf( &cmd[strlen(cmd)], mail_adrs, address_ptr1); first = FALSE; } @@ -847,6 +1131,7 @@ cleandown: term_letter = FALSE; remove(tmpfile); /* Delete the tmpfile. */ FREE(address); + FREE(body); return; } diff --git a/src/LYMain.c b/src/LYMain.c index 963a528a..6c45c54d 100644 --- a/src/LYMain.c +++ b/src/LYMain.c @@ -81,6 +81,10 @@ PUBLIC char *syslog_txt = NULL; /* syslog arb text for session */ #endif /* SYSLOG_REQUESTED_URLS */ #endif /* !VMS */ +#ifdef VMS +PUBLIC char *LYCSwingPath = NULL; +#endif /* VMS */ + #ifdef DIRED_SUPPORT PUBLIC BOOLEAN lynx_edit_mode = FALSE; PUBLIC BOOLEAN no_dired_support = FALSE; @@ -225,13 +229,14 @@ PUBLIC char *jumpfile = NULL; /* the name of the default jumps file */ PUBLIC char *jumpprompt = NULL; /* the default jumps prompt */ PUBLIC char *bookmark_page = NULL; /* the name of the default bookmark page */ PUBLIC char *BookmarkPage = NULL; /* the name of the current bookmark page */ +PUBLIC char *LynxHome = NULL; /* the default Home HREF. */ PUBLIC char *startfile = NULL; /* the first file */ PUBLIC char *helpfile = NULL; /* the main help file */ PUBLIC char *helpfilepath = NULL; /* the path to the help file set */ PUBLIC char *aboutfilepath = NULL; /* the path to the about lynx file */ PUBLIC char *lynxjumpfile = NULL; /* the current jump file URL */ PUBLIC char *lynxlistfile = NULL; /* the current list file URL */ -PUBLIC char *lynxbookfile = NULL; /* the current bookmark file URL */ +PUBLIC char *lynxlinksfile = NULL; /* the current visited links file URL */ PUBLIC char *startrealm = NULL; /* the startfile realm */ PUBLIC char *indexfile = NULL; /* an index file if there is one */ PUBLIC char *personal_mail_address = NULL; /* the users mail address */ @@ -296,7 +301,10 @@ PUBLIC BOOLEAN LYSelectPopups = USE_SELECT_POPUPS; PUBLIC BOOLEAN LYUseDefSelPop = TRUE; /* Command line -popup toggle */ PUBLIC int LYMultiBookmarks = MULTI_BOOKMARK_SUPPORT; PUBLIC BOOLEAN LYMBMBlocked = BLOCK_MULTI_BOOKMARKS; -PUBLIC BOOLEAN LYMBMAdvanced = ADVANCED_MULTI_BOOKMARKS; +PUBLIC BOOLEAN LYMBMAdvanced = TRUE; +PUBLIC int LYStatusLine = -1; /* Line for statusline() if > -1 */ +PUBLIC BOOLEAN LYCollapseBRs = COLLAPSE_BR_TAGS; /* Collapse serial BRs? */ +PUBLIC BOOLEAN LYSetCookies = SET_COOKIES; /* Process Set-Cookie headers? */ /* These are declared in cutil.h for current freeWAIS libraries. - FM */ #ifdef DECLARE_WAIS_LOGFILES @@ -310,12 +318,11 @@ extern int HTNewsMaxChunk; /* Max news articles before chunking (HTNews.c) */ extern int mainloop NOPARAMS; - -PRIVATE BOOLEAN anon_restrictions_set=FALSE; -PRIVATE BOOLEAN stack_dump=FALSE; -PRIVATE char *terminal=NULL; +PRIVATE BOOLEAN anon_restrictions_set = FALSE; +PRIVATE BOOLEAN stack_dump = FALSE; +PRIVATE char *terminal = NULL; PRIVATE char *pgm; -PRIVATE BOOLEAN number_links=FALSE; +PRIVATE BOOLEAN number_links = FALSE; PRIVATE void parse_arg PARAMS((char **arg, int *i, int argc)); #ifndef VMS @@ -349,8 +356,10 @@ PRIVATE void free_lynx_globals NOARGS #ifdef VMS Define_VMSLogical("LYNX_VERSION", ""); FREE(mail_adrs); + FREE(LYCSwingPath); #endif /* VMS */ + FREE(LynxHome); FREE(startfile); FREE(helpfile); FREE(jumpprompt); @@ -366,7 +375,6 @@ PRIVATE void free_lynx_globals NOARGS FREE(pref_charset); FREE(inews_path); FREE(system_mail); - FREE(lynx_temp_space); FREE(LYUserAgent); FREE(LYUserAgentDefault); FREE(LYHostName); @@ -389,28 +397,26 @@ PRIVATE void free_lynx_globals NOARGS FREE(personal_mail_address); FREE(URLDomainPrefixes); FREE(URLDomainSuffixes); - for (i = 0; i < MAXLINKS; i++) { + for (i = 0; i < nlinks; i++) { FREE(links[i].lname); } - for (i = 0; i < nhist; i++) { - FREE(history[i].title); - FREE(history[i].address); - FREE(history[i].post_data); - FREE(history[i].post_content_type); - } + nlinks = 0; return; } - /* * Wow! Someone wants to start up Lynx. */ -PUBLIC int main ARGS2(int,argc, char **,argv) +PUBLIC int main ARGS2( + int, argc, + char **, argv) { - int i; /* indexing variable */ - int status=0; /* exit status */ - char *lynx_cfg_file=NULL; + int i; /* indexing variable */ + int status = 0; /* exit status */ + int len; + char *lynx_cfg_file = NULL; + char *temp = NULL; char *cp; FILE *fp; @@ -477,7 +483,7 @@ PUBLIC int main ARGS2(int,argc, char **,argv) #ifdef JUMPFILE StrAllocCopy(jumpfile, JUMPFILE); { - char *temp = (char *)malloc(strlen(jumpfile) + 10); + temp = (char *)malloc(strlen(jumpfile) + 10); if (!temp) { outofmem(__FILE__, "main"); } else { @@ -499,16 +505,14 @@ PUBLIC int main ARGS2(int,argc, char **,argv) StrAllocCopy(pref_charset, PREFERRED_CHARSET); StrAllocCopy(inews_path, INEWS); StrAllocCopy(system_mail, SYSTEM_MAIL); - if ((cp=getenv("LYNX_TEMP_SPACE")) != NULL) + if ((cp = getenv("LYNX_TEMP_SPACE")) != NULL) StrAllocCopy(lynx_temp_space, cp); else StrAllocCopy(lynx_temp_space, TEMP_SPACE); if ((cp = strchr(lynx_temp_space, '~'))) { - char *temp = NULL; - int len; *(cp++) = '\0'; StrAllocCopy(temp, lynx_temp_space); - if ((len=strlen(temp)) > 0 && temp[len-1] == '/') + if (((len = strlen(temp)) > 0) && temp[len-1] == '/') temp[len-1] = '\0'; #ifdef VMS StrAllocCat(temp, HTVMS_wwwName((char *)Home_Dir())); @@ -523,7 +527,7 @@ PUBLIC int main ARGS2(int,argc, char **,argv) StrAllocCat(LYUserAgent, "/"); StrAllocCat(LYUserAgent, LYNX_VERSION); if (HTLibraryVersion) { - StrAllocCat(LYUserAgent, " libwww-FM/"); + StrAllocCat(LYUserAgent, " libwww-FM/"); StrAllocCat(LYUserAgent, HTLibraryVersion); } StrAllocCopy(LYUserAgentDefault, LYUserAgent); @@ -538,10 +542,7 @@ PUBLIC int main ARGS2(int,argc, char **,argv) for (i = 0; lynx_temp_space[i]; i++) lynx_temp_space[i] = TOLOWER(lynx_temp_space[i]); if (strchr(lynx_temp_space, '/') != NULL) { - char *temp = NULL; - int len = strlen(lynx_temp_space); - - if (len == 1) { + if ((len = strlen(lynx_temp_space)) == 1) { StrAllocCopy(lynx_temp_space, "sys$scratch:"); } else { if (lynx_temp_space[len-1] != '/') @@ -557,14 +558,18 @@ PUBLIC int main ARGS2(int,argc, char **,argv) } #else { - int len = strlen(lynx_temp_space); - if (len > 1 && lynx_temp_space[len-1] != '/') { + len; + if (((len = strlen(lynx_temp_space)) > 1) && + lynx_temp_space[len-1] != '/') { StrAllocCat(lynx_temp_space, "/"); } } #endif /* VMS */ #ifdef VMS StrAllocCopy(mail_adrs, MAIL_ADRS); +#ifdef CSWING_PATH + StrAllocCopy(LYCSwingPath, CSWING_PATH); +#endif /* CSWING_PATH */ #endif /* VMS */ #ifdef LYNX_HOST_NAME StrAllocCopy(LYHostName, LYNX_HOST_NAME); @@ -665,12 +670,9 @@ PUBLIC int main ARGS2(int,argc, char **,argv) * Convert a '~' in the configuration file path to $HOME. */ if ((cp = strchr(lynx_cfg_file, '~'))) { - char *temp = NULL; - int len; - *(cp++) = '\0'; StrAllocCopy(temp, lynx_cfg_file); - if ((len=strlen(temp)) > 0 && temp[len-1] == '/') + if (((len = strlen(temp)) > 0) && temp[len-1] == '/') temp[len-1] = '\0'; #ifdef VMS StrAllocCat(temp, HTVMS_wwwName((char *)Home_Dir())); @@ -730,12 +732,9 @@ PUBLIC int main ARGS2(int,argc, char **,argv) } if (lynx_save_space) { if ((cp = strchr(lynx_save_space, '~')) != NULL) { - char *temp = NULL; - int len; - *(cp++) = '\0'; StrAllocCopy(temp, lynx_save_space); - if ((len=strlen(temp)) > 0 && temp[len-1] == '/') + if (((len = strlen(temp)) > 0) && temp[len-1] == '/') temp[len-1] = '\0'; #ifdef VMS StrAllocCat(temp, HTVMS_wwwName((char *)Home_Dir())); @@ -750,11 +749,8 @@ PUBLIC int main ARGS2(int,argc, char **,argv) for (i = 0; lynx_save_space[i]; i++) lynx_save_space[i] = TOLOWER(lynx_save_space[i]); if (strchr(lynx_save_space, '/') != NULL) { - char *temp = NULL; - int len = strlen(lynx_save_space); - - if (len == 1) { - StrAllocCopy(lynx_save_space, "sys$scratch:"); + if ((len = strlen(lynx_save_space)) == 1) { + StrAllocCopy(lynx_save_space, "sys$login:"); } else { if (lynx_save_space[len-1] != '/') StrAllocCat(lynx_save_space, "/"); @@ -769,9 +765,8 @@ PUBLIC int main ARGS2(int,argc, char **,argv) } #else { - int len = strlen(lynx_save_space); - - if (len > 1 && lynx_save_space[len-1] != '/') { + if (((len = strlen(lynx_save_space)) > 1) && + lynx_save_space[len-1] != '/') { StrAllocCat(lynx_save_space, "/"); } } @@ -795,6 +790,15 @@ PUBLIC int main ARGS2(int,argc, char **,argv) StrAllocCopy(startfile, cp); /* + * Set the LynxHome URL. If it's a file URL and the + * host is defaulted, force in "//localhost", and if + * it's not an absolute URL, make it one. - FM + */ + StrAllocCopy(LynxHome, startfile); + LYFillLocalFileURL((char **)&LynxHome, "file://localhost"); + LYEnsureAbsoluteURL((char **)&LynxHome, "LynxHome"); + + /* * Process arguments - with none, look for the database in STARTDIR, * starting with STARTFILE. * @@ -823,7 +827,7 @@ PUBLIC int main ARGS2(int,argc, char **,argv) parse_arg(argv, NULL, -1); } } else { - for (i=1; i<argc; i++) { + for (i = 1; i < argc; i++) { parse_arg(&argv[i], &i, argc); } } @@ -933,136 +937,32 @@ PUBLIC int main ARGS2(int,argc, char **,argv) /* * If startfile is a file URL and the host is defaulted, - * force in "//localhost". We need this until all the - * other Lynx code which performs security checks based - * on the "localhost" string is changed to assume - * "//localhost" when a host field is not present in file - * URLs - FM - */ - if (!strncmp(startfile, "file:", 5)) { - char *temp=NULL; - if (startfile[5] == '\0') { - StrAllocCat(startfile, "//localhost"); - } else if (!strcmp(startfile, "file://")) { - StrAllocCat(startfile, "localhost"); - } else if (!strncmp(startfile, "file:///", 8)) { - StrAllocCopy(temp, (startfile+7)); - StrAllocCopy(startfile, "file://localhost"); - StrAllocCat(startfile, temp); - FREE(temp); - } else if (!strncmp(startfile, "file:/", 6) && startfile[6] != '/') { - StrAllocCopy(temp, (startfile+5)); - StrAllocCopy(startfile, "file://localhost"); - StrAllocCat(startfile, temp); - FREE(temp); - } - } - - /* - * No path in a file://localhost URL for startfile means - * a directory listing for the current default. - FM - */ - if (!strcmp(startfile, "file://localhost")) { -#ifdef VMS - StrAllocCat(startfile, HTVMS_wwwName(getenv("PATH"))); -#else - char curdir[DIRNAMESIZE]; -#ifdef NO_GETCWD - getwd (curdir); -#else - getcwd (curdir, DIRNAMESIZE); -#endif /* NO_GETCWD */ - StrAllocCat(startfile, curdir); -#endif /* VMS */ - } - -#ifdef VMS - /* - * On VMS, a file://localhost/ URL for startfile - * means a listing for the login directory. - FM - */ - if (!strcmp(startfile, "file://localhost/")) - StrAllocCat(startfile, (HTVMS_wwwName((char *)Home_Dir())+1)); -#endif /* VMS */ - - /* - * If it is not a URL then make it one. - */ - if (!is_url(startfile)) { - if (TRACE) - fprintf(stderr, "STARTFILE '%s' is not a URL\n", startfile); - LYConvertToURL(&startfile); - } - - /* - * If homepage is a file URL and the host is defaulted, - * force in "//localhost". We need this until all the - * other Lynx code which performs security checks based - * on the "localhost" string is changed to assume - * "//localhost" when a host field is not present in file - * URLs - FM - */ - if (homepage && !strncmp(homepage, "file:", 5)) { - char *temp=NULL; - if (homepage[5] == '\0') { - StrAllocCat(homepage, "//localhost"); - } else if (!strcmp(homepage, "file://")) { - StrAllocCat(homepage, "localhost"); - } else if (!strncmp(homepage, "file:///", 8)) { - StrAllocCopy(temp, (homepage+7)); - StrAllocCopy(homepage, "file://localhost"); - StrAllocCat(homepage, temp); - FREE(temp); - } else if (!strncmp(homepage, "file:/", 6) && homepage[6] != '/') { - StrAllocCopy(temp, (homepage+5)); - StrAllocCopy(homepage, "file://localhost"); - StrAllocCat(homepage, temp); - FREE(temp); - } - } - - /* - * No path in a file://localhost URL for homepage means - * a directory listing for the current default. - FM - */ - if (homepage && !strcmp(homepage, "file://localhost")) { -#ifdef VMS - StrAllocCat(homepage, HTVMS_wwwName(getenv("PATH"))); -#else - char curdir[DIRNAMESIZE]; -#ifdef NO_GETCWD - getwd (curdir); -#else - getcwd (curdir, DIRNAMESIZE); -#endif /* NO_GETCWD */ - StrAllocCat(homepage, curdir); -#endif /* VMS */ - } - -#ifdef VMS - /* - * On VMS, a file://localhost/ URL for homepage - * means a listing for the login directory. - FM + * force in "//localhost", and if it's not an absolute URL, + * make it one. - FM */ - if (homepage && !strcmp(homepage, "file://localhost/")) - StrAllocCat(homepage, (HTVMS_wwwName((char *)Home_Dir())+1)); -#endif /* VMS */ + LYFillLocalFileURL((char **)&startfile, "file://localhost"); + LYEnsureAbsoluteURL((char **)&startfile, "STARTFILE"); /* - * If it is not a URL then make it one. + * If homepage was specified and is a file URL with the + * host defaulted, force in "//localhost", and if it's + * not an absolute URL, make it one. - FM */ - if (homepage && !is_url(homepage)) { - if (TRACE) - fprintf(stderr, "HOMEPAGE '%s' is not a URL\n", homepage); - LYConvertToURL(&homepage); + if (homepage) { + LYFillLocalFileURL((char **)&homepage, "file://localhost"); + LYEnsureAbsoluteURL((char **)&homepage, "HOMEPAGE"); } /* * If we don't have a homepage specified, - * set it to startfile. + * set it to startfile. Otherwise, reset + * LynxHome. - FM */ - if (!homepage) + if (!(homepage && *homepage)) { StrAllocCopy(homepage, startfile); + } else { + StrAllocCopy(LynxHome, homepage); + } /* * Set up the inside/outside domain restriction flags. - FM @@ -1233,16 +1133,18 @@ PUBLIC int main ARGS2(int,argc, char **,argv) /* * Called by HTAccessInit to register any protocols supported by lynx. * Protocols added by lynx: - * LYNXKEYMAP, lynxcgi, LYNXIMGMAP + * LYNXKEYMAP, lynxcgi, LYNXIMGMAP, LYNXCOOKIE */ #ifdef GLOBALREF_IS_MACRO extern GLOBALREF (HTProtocol,LYLynxKeymap); extern GLOBALREF (HTProtocol,LYLynxCGI); extern GLOBALREF (HTProtocol,LYLynxIMGmap); +extern GLOBALREF (HTProtocol,LYLynxCookies); #else GLOBALREF HTProtocol LYLynxKeymap; GLOBALREF HTProtocol LYLynxCGI; GLOBALREF HTProtocol LYLynxIMGmap; +GLOBALREF HTProtocol LYLynxCookies; #endif /* GLOBALREF_IS_MACRO */ PUBLIC void LYRegisterLynxProtocols NOARGS @@ -1250,6 +1152,7 @@ PUBLIC void LYRegisterLynxProtocols NOARGS HTRegisterProtocol(&LYLynxKeymap); HTRegisterProtocol(&LYLynxCGI); HTRegisterProtocol(&LYLynxIMGmap); + HTRegisterProtocol(&LYLynxCookies); } /* @@ -1257,7 +1160,9 @@ PUBLIC void LYRegisterLynxProtocols NOARGS * appropriate). */ -PRIVATE char * scan3D ARGS2(char **,argv, int *,i) +PRIVATE char * scan3D ARGS2( + char **, argv, + int *, i) { char *result; @@ -1268,7 +1173,10 @@ PRIVATE char * scan3D ARGS2(char **,argv, int *,i) return argv[1]; } -PRIVATE void parse_arg ARGS3(char **, argv, int *, i, int, argc) +PRIVATE void parse_arg ARGS3( + char **, argv, + int *, i, + int, argc) { char *cp; #ifndef VMS @@ -1276,6 +1184,17 @@ PRIVATE void parse_arg ARGS3(char **, argv, int *, i, int, argc) #endif /* !VMS */ #define nextarg ((cp=scan3D(&argv[0], i))!=NULL) + /* + * Check for a command line startfile. - FM + */ + if (argv[0][0] != '-') { + StrAllocCopy(startfile, argv[0]); + return; + } + + switch (TOLOWER(argv[0][1])) { + + case 'a': if (strncmp(argv[0], "-anonymous", 10) == 0) { /* * Should already have been set, so we don't @@ -1285,7 +1204,454 @@ PRIVATE void parse_arg ARGS3(char **, argv, int *, i, int, argc) if (!anon_restrictions_set) parse_restrictions("default"); anon_restrictions_set = TRUE; + + } else if (strncmp(argv[0], "-auth", 5) == 0) { + /* + * Authentication information for protected forms. + */ + char *auth_info = NULL; + if (nextarg) { + StrAllocCopy(auth_info, cp); + memset(cp, ' ', strlen(cp));/* Let's not show too much */ + } + if (auth_info != NULL) { + if ((cp = strchr(auth_info, ':')) != NULL) { /* Pw */ + *cp++ = '\0'; /* Terminate ID */ + if (*cp) { + HTUnEscape(cp); + StrAllocCopy(authentication_info[1], cp); + } + } + if (*auth_info) { /* Id */ + HTUnEscape(auth_info); + StrAllocCopy(authentication_info[0], auth_info); + } + FREE(auth_info); + } + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'b': + if (strcmp(argv[0], "-book") == 0) { + /* + * Use bookmarks as startfile. + */ + bookmark_start = TRUE; + + } else if (strcmp(argv[0], "-buried_news") == 0) { + /* + * Toggle scans for buried news references. + */ + if (scan_for_buried_news_references) + scan_for_buried_news_references = FALSE; + else + scan_for_buried_news_references = TRUE; + +#ifdef USE_SLANG + } else if (strncmp(argv[0], "-blink", 6) == 0) { + Lynx_Color_Flags |= SL_LYNX_USE_BLINK; +#endif /* USE_SLANG */ + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'c': + if (strncmp(argv[0], "-cache", 6) == 0) { + if (nextarg) + HTCacheSize = atoi(cp); + /* + * Limit size. + */ + if (HTCacheSize < 2) HTCacheSize = 2; + + } else if (strncmp(argv[0], "-case", 5) == 0) { + case_sensitive = TRUE; + + } else if (strncmp(argv[0], "-cfg", 4) == 0) { + /* + * Already read the alternate configuration file + * so just check whether we need to increment i + */ + if (nextarg) + ; /* do nothing */ + + } else if (strncmp(argv[0], "-child", 6) == 0) { + child_lynx = TRUE; + no_disk_save = TRUE; + +#ifdef USE_SLANG + } else if (strncmp(argv[0], "-color", 6) == 0) { + Lynx_Color_Flags |= SL_LYNX_USE_COLOR; +#endif /* USE_SLANG */ + + } else if (strncmp(argv[0], "-crawl", 6) == 0) { + crawl = TRUE; + LYcols = 80; + + } else if (strncmp(argv[0], "-cookies", 8) == 0) { + if (LYSetCookies) + LYSetCookies = FALSE; + else + LYSetCookies = TRUE; + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'd': + if (strncmp(argv[0], "-display", 8) == 0) { + if (nextarg) { +#ifdef VMS + int j; + for (j = 0; cp[j]; j++) + cp[j] = TOUPPER(cp[j]); + Define_VMSLogical(DISPLAY, cp ? cp : ""); +#else + sprintf(display_putenv_command, "DISPLAY=%s", cp ? cp : ""); + putenv(display_putenv_command); +#endif /* VMS */ + if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') { + display = cp; + } + } + + } else if (strncmp(argv[0], "-dump", 5) == 0) { + dump_output_immediately = TRUE; + LYcols=80; + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'e': + if (strncmp(argv[0], "-editor", 7) == 0) { + if (nextarg) + StrAllocCopy(editor,cp); + system_editor = TRUE; + + } else if (strncmp(argv[0], "-emacskeys", 10) == 0) { + emacs_keys = TRUE; + + } else if (strncmp(argv[0], "-enable_scrollback", 18) == 0) { + if (enable_scrollback) + enable_scrollback = FALSE; + else + enable_scrollback = TRUE; + + } else if (strncmp(argv[0], "-error_file", 11) == 0) { + /* + * Output return (success/failure) code + * of an HTTP transaction. + */ + if (nextarg) + http_error_file = cp; + +#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) + } else if (strncmp(argv[0], "-exec", 5) == 0) { +#ifndef NEVER_ALLOW_REMOTE_EXEC + local_exec = TRUE; +#else + local_exec_on_local_files = TRUE; +#endif /* NEVER_ALLOW_REMOTE_EXEC */ +#endif /* EXEC_LINKS || EXEC_SCRIPTS */ + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'f': + if (strncmp(argv[0], "-force_html", 11) == 0) { + LYforce_HTML_mode = TRUE; + + } else if (strncmp(argv[0], "-fileversions", 13) == 0) { +#ifdef VMS + HTVMSFileVersions = TRUE; +#else + break;; +#endif /* VMS */ + + } else if (strncmp(argv[0], "-ftp", 4) == 0) { + ftp_ok = FALSE; + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'g': + if (strcmp(argv[0], "-get_data") == 0) { + /* + * User data for GET form. + */ + char **get_data; + char buf[1024]; + + /* + * On Unix, conflicts with curses when interactive + * so let's force a dump. - CL + * + * On VMS, mods have been made in LYCurses.c to deal with + * potential conflicts, so don't force the dump here. - FM + */ +#ifndef VMS + dump_output_immediately = TRUE; + LYcols = 80; +#endif /* VMS */ + + StrAllocCopy(form_get_data, "?"); /* Prime the pump */ + get_data = &form_get_data; + + /* + * Build GET data for later. Stop reading when we see a line + * with "---" as its first three characters. + */ + while (fgets(buf, sizeof(buf), stdin) && + strncmp(buf, "---", 3) != 0) { + int j; + + for (j = strlen(buf) - 1; j >= 0 && /* Strip line terminators */ + (buf[j] == CR || buf[j] == LF); j--) { + buf[j] = '\0'; + } + StrAllocCat(*get_data, buf); + } + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'h': + if (strcmp(argv[0], "-help") == 0) { + goto Output_Help_List; + + } else if (strcmp(argv[0], "-head") == 0) { + /* + * Return mime headers. + */ + HEAD_request = TRUE; + + } else if (strncmp(argv[0], "-historical", 11) == 0) { + if (historical_comments) + historical_comments = FALSE; + else + historical_comments = TRUE; + + } else if (strncmp(argv[0], "-homepage", 9) == 0) { + if (nextarg) + StrAllocCopy(homepage,cp); + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'i': + if (strncmp(argv[0], "-image_links", 12) == 0) { + if (clickable_images) + clickable_images = FALSE; + else + clickable_images = TRUE; + + } else if (strncmp(argv[0], "-index", 6) == 0) { + if (nextarg) + StrAllocCopy(indexfile, cp); + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'l': + if (strncmp(argv[0], "-link", 5) == 0) { + if (nextarg) + ccount = atoi(cp); + + } else if (strncmp(argv[0], "-localhost", 10) == 0) { + local_host_only = TRUE; + +#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) + } else if (strncmp(argv[0], "-locexec", 8) == 0) { + local_exec_on_local_files = TRUE; +#endif /* EXEC_LINKS || EXEC_SCRIPTS */ + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'm': + if (strcmp(argv[0], "-mime_header") == 0) { + /* + * Include mime headers and force source dump. + */ + keep_mime_headers = TRUE; + dump_output_immediately = TRUE; + HTOutputFormat = HTAtom_for("www/dump"); + LYcols=999; + + } else if (strncmp(argv[0], "-minimal", 11) == 0) { + if (minimal_comments) + minimal_comments = FALSE; + else + minimal_comments = TRUE; + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'n': + if (strncmp(argv[0], "-newschunksize", 14) == 0) { + if (nextarg) { + HTNewsChunkSize = atoi(cp); + /* + * If the new HTNewsChunkSize exceeds the maximum, + * increase HTNewsMaxChunk to this size. - FM + */ + if (HTNewsChunkSize > HTNewsMaxChunk) { + HTNewsMaxChunk = HTNewsChunkSize; + } + } + + } else if (strncmp(argv[0], "-newsmaxchunk", 13) == 0) { + if (nextarg) { + HTNewsMaxChunk = atoi(cp); + /* + * If HTNewsChunkSize exceeds the new maximum, + * reduce HTNewsChunkSize to this maximum. - FM + */ + if (HTNewsChunkSize > HTNewsMaxChunk) { + HTNewsChunkSize = HTNewsMaxChunk; + } + } + + } else if (strncmp(argv[0], "-nobrowse", 9) == 0) { + HTDirAccess = HT_DIR_FORBID; + +#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) + } else if (strncmp(argv[0], "-noexec", 7) == 0) { + local_exec = FALSE; +#endif /* EXEC_LINKS || EXEC_SCRIPTS */ + + } else if (strncmp(argv[0], "-nofilereferer", 14) == 0) { + no_filereferer = TRUE; + + } else if (strncmp(argv[0], "-nofrom", 7) == 0) { + LYNoFromHeader = TRUE; + + } else if (strncmp(argv[0], "-nolist", 7) == 0) { + nolist = TRUE; + + } else if (strncmp(argv[0], "-nolog", 6) == 0) { + error_logging = FALSE; + + } else if (strcmp(argv[0], "-nopause") == 0) { /* No statusline pauses */ + InfoSecs = 0; + MessageSecs = 0; + AlertSecs = 0; + + } else if (strncmp(argv[0], "-noprint", 8) == 0) { + no_print = TRUE; + + } else if (strcmp(argv[0], "-noredir") == 0) { + /* + * Don't follow URL redirections. + */ + no_url_redirection = TRUE; + + } else if (strncmp(argv[0], "-noreferer", 10) == 0) { + LYNoRefererHeader = TRUE; + +#ifdef SOCKS + } else if (strncmp(argv[0], "-nosocks", 8) == 0) { + socks_flag = FALSE; +#endif /* SOCKS */ + + } else if (strncmp(argv[0], "-nostatus", 9) == 0) { + no_statusline = TRUE; + + } else if (strncmp(argv[0], "-number_links", 9) == 0) { + number_links = TRUE; + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'p': + if (strncmp(argv[0], "-popup", 6) == 0) { + LYUseDefSelPop = FALSE; + + } else if (strcmp(argv[0], "-post_data") == 0) { + /* + * User data for POST form. + */ + char **post_data; + char buf[1024]; + + /* + * On Unix, conflicts with curses when interactive + * so let's force a dump. - CL + * + * On VMS, mods have been made in LYCurses.c to deal with + * potential conflicts, so don't force a dump here. - FM + */ +#ifndef VMS + dump_output_immediately = TRUE; + LYcols = 80; +#endif /* VMS */ + + post_data = &form_post_data; + + /* + * Build post data for later. Stop reading when we see a line + * with "---" as its first three characters. + */ + while (fgets(buf, sizeof(buf), stdin) && + strncmp(buf, "---", 3) != 0) { + int j; + + for (j = strlen(buf) - 1; j >= 0 && /* Strip line terminators */ + (buf[j] == CR || buf[j] == LF); j--) { + buf[j] = '\0'; + } + StrAllocCat(*post_data, buf); + } + + } else if (strncmp(argv[0], "-print", 6) == 0) { + no_print=FALSE; + + } else if (strncmp(argv[0], "-pseudo_inlines", 15) == 0) { + if (pseudo_inline_alts) + pseudo_inline_alts = FALSE; + else + pseudo_inline_alts = TRUE; + + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'r': + if (strncmp(argv[0], "-raw", 4) == 0) { + LYUseDefaultRawMode = FALSE; + + } else if (strncmp(argv[0], "-realm", 6) == 0) { + check_realm = TRUE; + + } else if (strncmp(argv[0], "-reload", 7) == 0) { + reloading = TRUE; + } else if (strncmp(argv[0], "-restrictions", 13) == 0) { if ((cp=strchr(argv[0],'=')) != NULL) parse_restrictions(cp+1); @@ -1378,110 +1744,29 @@ PRIVATE void parse_arg ARGS3(char **, argv, int *, i, int, argc) exit(0); } - } else if (strncmp(argv[0], "-homepage", 9) == 0) { - if (nextarg) - StrAllocCopy(homepage,cp); - - } else if (strncmp(argv[0], "-editor", 7) == 0) { - if (nextarg) - StrAllocCopy(editor,cp); - system_editor = TRUE; - -#ifndef VMS -#ifdef SYSLOG_REQUESTED_URLS - } else if (strncmp(argv[0], "-syslog", 7) == 0) { - if (nextarg) - StrAllocCopy(syslog_txt, cp); -#endif /* SYSLOG_REQUESTED_URLS */ -#endif /* !VMS */ - - } else if (strncmp(argv[0], "-display", 8) == 0) { - if (nextarg) { -#ifdef VMS - int j; - for (j = 0; cp[j]; j++) - cp[j] = TOUPPER(cp[j]); - Define_VMSLogical(DISPLAY, cp ? cp : ""); -#else - sprintf(display_putenv_command, "DISPLAY=%s", cp ? cp : ""); - putenv(display_putenv_command); -#endif /* VMS */ - if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') { - display = cp; - } - } - - } else if (strncmp(argv[0], "-index", 6) == 0) { - if (nextarg) - StrAllocCopy(indexfile, cp); - - } else if (strncmp(argv[0], "-cfg", 4) == 0) { - /* - * Already read the alternate configuration file - * so just check whether we need to increment i - */ - if (nextarg) - ; /* do nothing */ - - } else if (strncmp(argv[0], "-stack_dump", 11) == 0) { - stack_dump = TRUE; - - } else if (strncmp(argv[0], "-cache", 6) == 0) { - if (nextarg) - HTCacheSize = atoi(cp); - - /* limit size */ - if (HTCacheSize < 2) HTCacheSize = 2; - - } else if (strncmp(argv[0], "-vikeys", 7) == 0) { - vi_keys = TRUE; - - } else if (strncmp(argv[0], "-emacskeys", 10) == 0) { - emacs_keys = TRUE; - - } else if (strncmp(argv[0], "-version", 8) == 0) { - printf("\n%s Version %s\n(c)1996 GNU General Public License\n\ -<URL:http://lynx.browser.org/>\n\n", - LYNX_NAME, LYNX_VERSION); - exit(0); - - } else if (strncmp(argv[0], "-case", 5) == 0) { - case_sensitive = TRUE; - - } else if (strncmp(argv[0], "-dump", 5) == 0) { - dump_output_immediately = TRUE; - LYcols=80; - - } else if (strncmp(argv[0], "-nofrom", 7) == 0) { - LYNoFromHeader = TRUE; - - } else if (strncmp(argv[0], "-nofilereferer", 14) == 0) { - no_filereferer = TRUE; - - } else if (strncmp(argv[0], "-nolist", 7) == 0) { - nolist = TRUE; - - } else if (strncmp(argv[0], "-noreferer", 10) == 0) { - LYNoRefererHeader = TRUE; - - } else if (strncmp(argv[0], "-popup", 6) == 0) { - LYUseDefSelPop = FALSE; + } else if (strncmp(argv[0], "-resubmit_posts", 14) == 0) { + if (LYresubmit_posts) + LYresubmit_posts = FALSE; + else + LYresubmit_posts = TRUE; - } else if (strncmp(argv[0], "-crawl", 6) == 0) { - crawl = TRUE; - LYcols=80; + } else if (strncmp(argv[0], "-rlogin", 7) == 0) { + rlogin_ok = FALSE; - } else if (strncmp(argv[0], "-historical", 11) == 0) { - if (historical_comments) - historical_comments = FALSE; - else - historical_comments = TRUE; + } else { + goto Output_Error_and_Help_List; + } + break; - } else if (strncmp(argv[0], "-minimal", 11) == 0) { - if (minimal_comments) - minimal_comments = FALSE; + case 's': + if (strncmp(argv[0], "-selective", 10) == 0) { + HTDirAccess = HT_DIR_SELECTIVE; + + } else if (strncmp(argv[0], "-show_cursor", 12) == 0) { + if (LYShowCursor) + LYShowCursor = FALSE; else - minimal_comments = TRUE; + LYShowCursor = TRUE; } else if (strncmp(argv[0], "-soft_dquotes", 13) == 0) { if (soft_dquotes) @@ -1489,425 +1774,277 @@ PRIVATE void parse_arg ARGS3(char **, argv, int *, i, int, argc) else soft_dquotes = TRUE; - } else if (strncmp(argv[0], "-enable_scrollback", 18) == 0) { - if (enable_scrollback) - enable_scrollback = FALSE; - else - enable_scrollback = TRUE; - - } else if (strncmp(argv[0], "-link", 5) == 0) { - if (nextarg) - ccount = atoi(cp); - - } else if (strncmp(argv[0], "-traversal", 10) == 0) { - traversal = TRUE; -#ifdef USE_SLANG - LYcols=80; -#else - LYcols=999; -#endif /* USE_SLANG */ - - } else if (strncmp(argv[0], "-realm", 6) == 0) { - check_realm = TRUE; - } else if (strncmp(argv[0], "-source", 7) == 0) { dump_output_immediately = TRUE; HTOutputFormat = HTAtom_for("www/dump"); LYcols=999; - - } else if (strncmp(argv[0], "-reload", 7) == 0) { - reloading = TRUE; - } else if (strncmp(argv[0], "-force_html", 11) == 0) { - LYforce_HTML_mode = TRUE; - -#ifdef SOCKS - } else if (strncmp(argv[0], "-nosocks", 8) == 0) { - socks_flag = FALSE; -#endif /* SOCKS */ + } else if (strncmp(argv[0], "-stack_dump", 11) == 0) { + stack_dump = TRUE; - } else if (strncmp(argv[0], "-trace", 6) == 0) { - WWW_TraceFlag = TRUE; - - } else if (strncmp(argv[0], "-number_links", 9) == 0) { - number_links = TRUE; - - } else if (strncmp(argv[0], "-image_links", 12) == 0) { - if (clickable_images) - clickable_images = FALSE; - else - clickable_images = TRUE; + } else if (strncmp(argv[0], "-startfile_ok", 13) == 0) { + startfile_ok = TRUE; - } else if (strncmp(argv[0], "-pseudo_inlines", 15) == 0) { - if (pseudo_inline_alts) - pseudo_inline_alts = FALSE; - else - pseudo_inline_alts = TRUE; +#ifndef VMS +#ifdef SYSLOG_REQUESTED_URLS + } else if (strncmp(argv[0], "-syslog", 7) == 0) { + if (nextarg) + StrAllocCopy(syslog_txt, cp); +#endif /* SYSLOG_REQUESTED_URLS */ +#endif /* !VMS */ - } else if (strncmp(argv[0], "-resubmit_posts", 14) == 0) { - if (LYresubmit_posts) - LYresubmit_posts = FALSE; - else - LYresubmit_posts = TRUE; + } else { + goto Output_Error_and_Help_List; + } + break; - } else if (strncmp(argv[0], "-underscore", 15) == 0) { - if (use_underscore) - use_underscore = FALSE; - else - use_underscore = TRUE; + case 't': + if (strncmp(argv[0], "-telnet", 7) == 0) { + telnet_ok = FALSE; - } else if (strncmp(argv[0], "-localhost", 10) == 0) { - local_host_only = TRUE; - - } else if (strncmp(argv[0], "-nobrowse", 9) == 0) { - HTDirAccess = HT_DIR_FORBID; - - } else if (strncmp(argv[0], "-selective", 10) == 0) { - HTDirAccess = HT_DIR_SELECTIVE; - - } else if (strncmp(argv[0], "-noprint", 8) == 0) { - no_print=TRUE; - - } else if (strncmp(argv[0], "-print", 6) == 0) { - no_print=FALSE; - -#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) - } else if (strncmp(argv[0], "-exec", 5) == 0) { -#ifndef NEVER_ALLOW_REMOTE_EXEC - local_exec=TRUE; -#else - local_exec_on_local_files=TRUE; -#endif /* NEVER_ALLOW_REMOTE_EXEC */ - - } else if (strncmp(argv[0], "-locexec", 8) == 0) { - local_exec_on_local_files=TRUE; - - } else if (strncmp(argv[0], "-noexec", 7) == 0) { - local_exec=FALSE; -#endif /* EXEC_LINKS || EXEC_SCRIPTS */ - - } else if (strncmp(argv[0], "-child", 6) == 0) { - child_lynx=TRUE; - no_disk_save=TRUE; - - } else if (strncmp(argv[0], "-nolog", 6) == 0) { - error_logging=FALSE; - - } else if (strncmp(argv[0], "-nostatus", 9) == 0) { - no_statusline = TRUE; - - } else if (strncmp(argv[0], "-show_cursor", 12) == 0) { - LYShowCursor = TRUE; - } else if (strncmp(argv[0], "-term", 5) == 0) { if (nextarg) terminal = cp; - - } else if (strncmp(argv[0], "-telnet", 7) == 0) { - telnet_ok=FALSE; - - } else if (strncmp(argv[0], "-ftp", 4) == 0) { - ftp_ok=FALSE; - - } else if (strncmp(argv[0], "-rlogin", 7) == 0) { - rlogin_ok=FALSE; - -#ifdef USE_SLANG - } else if (strncmp(argv[0], "-color", 6) == 0) { - Lynx_Color_Flags |= SL_LYNX_USE_COLOR; - } else if (strncmp(argv[0], "-blink", 6) == 0) { - Lynx_Color_Flags |= SL_LYNX_USE_BLINK; -#endif /* USE_SLANG */ + } else if (strncmp(argv[0], "-trace", 6) == 0) { + WWW_TraceFlag = TRUE; - } else if (strncmp(argv[0], "-fileversions", 13) == 0) { -#ifdef VMS - HTVMSFileVersions=TRUE; + } else if (strncmp(argv[0], "-traversal", 10) == 0) { + traversal = TRUE; +#ifdef USE_SLANG + LYcols=80; #else - return; -#endif /* VMS */ - - } else if (strcmp(argv[0], "-post_data") == 0 || - strcmp(argv[0], "-get_data") == 0) { /* User data for post - or get form. */ - char **post_data; - char buf[1024]; + LYcols=999; +#endif /* USE_SLANG */ - /* -post_data and -get_data conflict with curses when interactive - * so let's force them to dump. - CL - * - * On VMS, mods have been made in LYCurses.c to deal with - * potential conflicts, so don't force them to dump here. - FM - */ -#ifndef VMS - dump_output_immediately = TRUE; - LYcols = 80; -#endif /* VMS */ - - if (strcmp(argv[0], "-get_data") == 0) { - StrAllocCopy(form_get_data, "?"); /* Prime the pump */ - post_data = &form_get_data; - } else { - post_data = &form_post_data; - } - - /* Build post data for later. Stop reading when we see a line with - * "---" as its first three characters. - */ - while (fgets(buf, sizeof(buf), stdin) && strncmp(buf, "---", 3) != 0) { - int j; - - for (j = strlen(buf) - 1; j >= 0 && /* Strip line terminators */ - (buf[j] == CR || buf[j] == LF); j--) { - buf[j] = '\0'; - } - StrAllocCat(*post_data, buf); - } - - } else if (strcmp(argv[0], "-head") == 0) {/* Return mime headers */ - HEAD_request = TRUE; - - } else if (strcmp(argv[0], "-book") == 0) {/* Use bookmarks as startfile */ - bookmark_start = TRUE; - - } else if (strcmp(argv[0], "-buried_news") == 0) { - /* Toggle scans for buried news references */ - if (scan_for_buried_news_references) - scan_for_buried_news_references = FALSE; + } else { + goto Output_Error_and_Help_List; + } + break; + + case 'u': + if (strncmp(argv[0], "-underscore", 15) == 0) { + if (use_underscore) + use_underscore = FALSE; else - scan_for_buried_news_references = TRUE; - - } else if (strcmp(argv[0], "-mime_header") == 0) { - /* Include mime headers and force source dump */ - keep_mime_headers = TRUE; - dump_output_immediately = TRUE; - HTOutputFormat = HTAtom_for("www/dump"); - LYcols=999; + use_underscore = TRUE; - } else if (strncmp(argv[0], "-error_file", 11) == 0) { /* Output return - (success/failure) - code of an HTTP - transaction */ - if (nextarg) - http_error_file = cp; + } else { + goto Output_Error_and_Help_List; + } + break; - - } else if (strncmp(argv[0], "-auth", 5) == 0) { /* Authentication - information for - protected forms */ - char *auth_info = NULL; - - if (nextarg) { - StrAllocCopy(auth_info, cp); - memset(cp, ' ', strlen(cp));/* Let's not show too much */ - } - if (auth_info != NULL) { - if ((cp = strchr(auth_info, ':')) != NULL) { /* Pw */ - *cp++ = '\0'; /* Terminate ID */ - if (*cp) { - HTUnEscape(cp); - StrAllocCopy(authentication_info[1], cp); - } - } - if (*auth_info) { /* Id */ - HTUnEscape(auth_info); - StrAllocCopy(authentication_info[0], auth_info); - } - FREE(auth_info); - } - - } else if (strcmp(argv[0], "-noredir") == 0) { /* Don't follow URL - Redirections */ - no_url_redirection = TRUE; - - } else if (strcmp(argv[0], "-validate") == 0) { /* Follow only http URLs */ + case 'v': + if (strcmp(argv[0], "-validate") == 0) { + /* + * Follow only http URLs. + */ LYValidate = TRUE; parse_restrictions("all"); - } else if (strncmp(argv[0], "-raw", 4) == 0) { - LYUseDefaultRawMode = FALSE; - - } else if (strncmp(argv[0], "-newschunksize", 14) == 0) { - if (nextarg) { - HTNewsChunkSize = atoi(cp); - /* - * If the new HTNewsChunkSize exceeds the maximum, - * increase HTNewsMaxChunk to this size. - FM - */ - if (HTNewsChunkSize > HTNewsMaxChunk) { - HTNewsMaxChunk = HTNewsChunkSize; - } - } + } else if (strncmp(argv[0], "-version", 8) == 0) { + printf("\n%s Version %s\n(c)1996 GNU General Public License\n\ +<URL:http://lynx.browser.org/>\n\n", + LYNX_NAME, LYNX_VERSION); + exit(0); - } else if (strncmp(argv[0], "-newsmaxchunk", 13) == 0) { - if (nextarg) { - HTNewsMaxChunk = atoi(cp); - /* - * If HTNewsChunkSize exceeds the new maximum, - * reduce HTNewsChunkSize to this maximum. - FM - */ - if (HTNewsChunkSize > HTNewsMaxChunk) { - HTNewsChunkSize = HTNewsMaxChunk; - } - } + } else if (strncmp(argv[0], "-vikeys", 7) == 0) { + vi_keys = TRUE; - } else if (strncmp(argv[0], "-startfile_ok", 13) == 0) { - startfile_ok = TRUE; + } else { + goto Output_Error_and_Help_List; + } + break; - } else if (strncmp(argv[0], "-", 1) == 0) { - if (strncmp(argv[0], "-help", 5) != 0) + default: +Output_Error_and_Help_List: +#ifdef VMS + printf(" LYNX: Invalid Option: %s\n", argv[0]); +#else + printf("%s: Invalid Option: %s\n", pgm, argv[0]); +#endif /* VMS */ +Output_Help_List: #ifdef VMS - printf(" LYNX: Invalid Option: %s\n", argv[0]); - printf("USAGE: lynx [options] [file]\n"); + printf("USAGE: lynx [options] [file]\n"); #else - printf("%s: Invalid Option: %s\n", pgm, argv[0]); - printf("USAGE: %s [options] [file]\n",pgm); + printf("USAGE: %s [options] [file]\n",pgm); #endif /* VMS */ - printf("Options are:\n"); - printf(" - receive the arguments from stdin (enclose\n"); - printf(" in double-quotes (\"-\") on VMS)\n"); - printf(" -anonymous used to specify the anonymous account\n"); - printf(" -auth=id:pw authentication information for protected forms\n"); - printf(" -book use the bookmark page as the startfile\n"); - printf(" -buried_news toggles scanning of news articles for buried references\n"); - printf(" -cache=NUMBER NUMBER of documents cached in memory (default is %d)\n",DEFAULT_CACHE_SIZE); - printf(" -case enable case sensitive user searching\n"); - printf(" -cfg=FILENAME specifies a lynx.cfg file other than the default\n"); - printf(" -child exit on left-arrow in startfile, and disable save to disk\n"); + printf("Options are:\n"); + printf(" - receive the arguments from stdin (enclose\n"); + printf(" in double-quotes (\"-\") on VMS)\n"); + printf(" -anonymous used to specify the anonymous account\n"); + printf(" -auth=id:pw authentication information for protected forms\n"); + printf(" -book use the bookmark page as the startfile\n"); + printf(" -buried_news toggles scanning of news articles for buried references\n"); + printf(" -cache=NUMBER NUMBER of documents cached in memory (default is %d)\n",DEFAULT_CACHE_SIZE); + printf(" -case enable case sensitive user searching\n"); + printf(" -cfg=FILENAME specifies a lynx.cfg file other than the default\n"); + printf(" -child exit on left-arrow in startfile, and disable save to disk\n"); #ifdef USE_SLANG - printf(" -color force color mode on with standard bg colors\n"); - printf(" -blink force color mode on with high intensity bg colors\n"); + printf(" -color force color mode on with standard bg colors\n"); + printf(" -blink force color mode on with high intensity bg colors\n"); #endif /* USE_SLANG */ - printf(" -crawl with -traversal, output each page to a file\n"); - printf(" with -dump, format output as with -traversal, but to stdout\n"); - printf(" -display=DISPLAY set the display variable for X execed programs\n"); - printf(" -dump dump the first file to stdout and exit\n"); - printf(" -editor=EDITOR enable edit mode with specified editor\n"); - printf(" -emacskeys enable emacs-like key movement\n"); - printf(" -enable_scrollback toggle compatibility with comm programs' scrollback\n"); - printf(" keys (may be incompatible with some curses packages)\n"); - printf(" -error_file=FILE write the HTTP status code here\n"); + printf(" -cookies toggles handling of Set-Cookie headers\n"); + printf(" -crawl with -traversal, output each page to a file\n"); + printf(" with -dump, format output as with -traversal, but to stdout\n"); + printf(" -display=DISPLAY set the display variable for X execed programs\n"); + printf(" -dump dump the first file to stdout and exit\n"); + printf(" -editor=EDITOR enable edit mode with specified editor\n"); + printf(" -emacskeys enable emacs-like key movement\n"); + printf(" -enable_scrollback toggles compatibility with comm programs' scrollback\n"); + printf(" keys (may be incompatible with some curses packages)\n"); + printf(" -error_file=FILE write the HTTP status code here\n"); #if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) #ifndef NEVER_ALLOW_REMOTE_EXEC - printf(" -exec enable local program execution\n"); + printf(" -exec enable local program execution\n"); #endif /* !NEVER_ALLOW_REMOTE_EXEC */ - printf(" -locexec enable local program execution from local files only\n"); - printf(" -noexec disable local program execution (DEFAULT)\n"); + printf(" -locexec enable local program execution from local files only\n"); + printf(" -noexec disable local program execution (DEFAULT)\n"); #endif /* EXEC_LINKS || EXEC_SCRIPTS */ - printf(" -fileversions include all versions of files in local VMS directory\n"); - printf(" listings\n"); - printf(" -force_html forces the first document to be interpreted as HTML\n"); - printf(" -ftp disable ftp access\n"); - printf(" -get_data user data for get forms, read from stdin,\n"); - printf(" terminated by '---' on a line\n"); - printf(" -head send a HEAD request\n"); - printf(" -help print this usage message\n"); - printf(" -historical toggles use of '>' or '-->' as a terminator for comments\n"); - printf(" -homepage=URL set homepage separate from start page\n"); - printf(" -image_links toggles inclusion of links for all images\n"); - printf(" -index=URL set the default index file to URL\n"); - printf(" -link=NUMBER starting count for lnk#.dat files produced by -crawl\n"); - printf(" -localhost disable URLs that point to remote hosts\n"); - printf(" -mime_header include mime headers and force source dump\n"); - printf(" -minimal toggles minimal versus valid comment parsing\n"); - printf(" -newschunksize=NUMBER number of articles in chunked news listings\n"); - printf(" -newsmaxchunk=NUMBER maximum news articles in listings before chunking\n"); - printf(" -nobrowse disable directory browsing\n"); - printf(" -nofilereferer disable transmissions of Referer headers for file URLs\n"); - printf(" -nofrom disable transmissions of From headers\n"); - printf(" -nolist disable the link list feature in dumps\n"); - printf(" -nolog disable mailing of error messages to document owners\n"); - printf(" -noprint disable print functions\n"); - printf(" -noredir don't follow Location: redirection\n"); - printf(" -noreferer disable transmissions of Referer headers\n"); + printf(" -fileversions include all versions of files in local VMS directory\n"); + printf(" listings\n"); + printf(" -force_html forces the first document to be interpreted as HTML\n"); + printf(" -ftp disable ftp access\n"); + printf(" -get_data user data for get forms, read from stdin,\n"); + printf(" terminated by '---' on a line\n"); + printf(" -head send a HEAD request\n"); + printf(" -help print this usage message\n"); + printf(" -historical toggles use of '>' or '-->' as a terminator for comments\n"); + printf(" -homepage=URL set homepage separate from start page\n"); + printf(" -image_links toggles inclusion of links for all images\n"); + printf(" -index=URL set the default index file to URL\n"); + printf(" -link=NUMBER starting count for lnk#.dat files produced by -crawl\n"); + printf(" -localhost disable URLs that point to remote hosts\n"); + printf(" -mime_header include mime headers and force source dump\n"); + printf(" -minimal toggles minimal versus valid comment parsing\n"); + printf(" -newschunksize=NUMBER number of articles in chunked news listings\n"); + printf(" -newsmaxchunk=NUMBER maximum news articles in listings before chunking\n"); + printf(" -nobrowse disable directory browsing\n"); + printf(" -nofilereferer disable transmissions of Referer headers for file URLs\n"); + printf(" -nofrom disable transmissions of From headers\n"); + printf(" -nolist disable the link list feature in dumps\n"); + printf(" -nolog disable mailing of error messages to document owners\n"); + printf(" -nopause disable forced pauses for statusline messages\n"); + printf(" -noprint disable print functions\n"); + printf(" -noredir don't follow Location: redirection\n"); + printf(" -noreferer disable transmissions of Referer headers\n"); #ifdef SOCKS - printf(" -nosocks don't use SOCKS proxy for this session\n"); + printf(" -nosocks don't use SOCKS proxy for this session\n"); #endif /* SOCKS */ - printf(" -nostatus disable the miscellaneous information messages\n"); - printf(" -number_links force numbering of links\n"); - printf(" -popup toggles handling of single-choice SELECT options via\n"); - printf(" popup windows or as lists of radio buttons\n"); - printf(" -post_data user data for post forms, read from stdin,\n"); - printf(" terminated by '---' on a line\n"); - printf(" -print enable print functions (DEFAULT)\n"); - printf(" -pseudo_inlines toggles pseudo-ALTs for inlines with no ALT string\n"); - printf(" -raw toggles default setting of 8-bit character translations\n"); - printf(" or CJK mode for the startup character set\n"); - printf(" -realm restricts access to URLs in the starting realm\n"); - printf(" -reload flushes the cache on a proxy server\n"); - printf(" (only the first document affected)\n"); - printf(" -restrictions=[options] use -restrictions to see list\n"); - printf(" -resubmit_posts toggles forced resubmissions (no-cache) of forms with\n"); - printf(" method POST when the documents they returned are sought\n"); - printf(" with the PREV_DOC command or from the History List\n"); - printf(" -rlogin disable rlogins\n"); - printf(" -selective require .www_browsable files to browse directories\n"); - printf(" -show_cursor don't hide the curser in the lower right corner\n"); - printf(" -soft_dquotes toggles emulation of the old Netscape and Mosaic bug which\n"); - printf(" treated '>' as a co-terminator for double-quotes and tags\n"); - printf(" -source dump the source of the first file to stdout and exit\n"); - printf(" -startfile_ok allow non-http startfile and homepage with -validate\n"); + printf(" -nostatus disable the miscellaneous information messages\n"); + printf(" -number_links force numbering of links\n"); + printf(" -popup toggles handling of single-choice SELECT options via\n"); + printf(" popup windows or as lists of radio buttons\n"); + printf(" -post_data user data for post forms, read from stdin,\n"); + printf(" terminated by '---' on a line\n"); + printf(" -print enable print functions (DEFAULT)\n"); + printf(" -pseudo_inlines toggles pseudo-ALTs for inlines with no ALT string\n"); + printf(" -raw toggles default setting of 8-bit character translations\n"); + printf(" or CJK mode for the startup character set\n"); + printf(" -realm restricts access to URLs in the starting realm\n"); + printf(" -reload flushes the cache on a proxy server\n"); + printf(" (only the first document affected)\n"); + printf(" -restrictions=[options] use -restrictions to see list\n"); + printf(" -resubmit_posts toggles forced resubmissions (no-cache) of forms with\n"); + printf(" method POST when the documents they returned are sought\n"); + printf(" with the PREV_DOC command or from the History List\n"); + printf(" -rlogin disable rlogins\n"); + printf(" -selective require .www_browsable files to browse directories\n"); + printf(" -show_cursor toggles hiding of the curser in the lower right corner\n"); + printf(" -soft_dquotes toggles emulation of the old Netscape and Mosaic bug which\n"); + printf(" treated '>' as a co-terminator for double-quotes and tags\n"); + printf(" -source dump the source of the first file to stdout and exit\n"); + printf(" -startfile_ok allow non-http startfile and homepage with -validate\n"); #ifndef VMS #ifdef SYSLOG_REQUESTED_URLS - printf(" -syslog=text information for syslog call\n"); + printf(" -syslog=text information for syslog call\n"); #endif /* SYSLOG_REQUESTED_URLS */ #endif /* !VMS */ - printf(" -telnet disable telnets\n"); - printf(" -term=TERM set terminal type to TERM\n"); - printf(" -trace turns on WWW trace mode\n"); - printf(" -traversal traverse all http links derived from startfile\n"); - printf(" -underscore toggles use of _underline_ format in dumps\n"); - printf(" -validate accept only http URLs (for validation)\n"); - printf(" -version print Lynx version information\n"); - printf(" -vikeys enable vi-like key movement\n"); - if (strncmp(argv[0], "-help", 5) != 0) - exit(-1); - exit(0); - } else { /* alternate database path */ - - StrAllocCopy(startfile, argv[0]); - } + printf(" -telnet disable telnets\n"); + printf(" -term=TERM set terminal type to TERM\n"); + printf(" -trace turns on WWW trace mode\n"); + printf(" -traversal traverse all http links derived from startfile\n"); + printf(" -underscore toggles use of _underline_ format in dumps\n"); + printf(" -validate accept only http URLs (for validation)\n"); + printf(" -version print Lynx version information\n"); + printf(" -vikeys enable vi-like key movement\n"); + if (strncmp(argv[0], "-help", 5) != 0) + exit(-1); + exit(0); + break; + + } /* end of switch. */ } #ifndef VMS -static void FatalProblem ARGS1(int,sig) +PRIVATE void FatalProblem ARGS1( + int, sig) { - fprintf (stderr, "\r\n\ + /* + * Ignore further interrupts. - mhc: 11/2/91 + */ + (void) signal (SIGHUP, SIG_IGN); + (void) signal (SIGTERM, SIG_IGN); + (void) signal (SIGINT, SIG_IGN); +#ifndef __linux__ + (void) signal(SIGBUS, SIG_IGN); +#endif /* !__linux__ */ + (void) signal(SIGSEGV, SIG_IGN); + (void) signal(SIGILL, SIG_IGN); + + /* + * Flush all messages. - FM + */ + fflush(stderr); + fflush(stdout); + + /* + * Deal with curses, if on, and clean up. - FM + */ + if (LYOutOfMemory && LYCursesON) { + sleep(AlertSecs); + } + cleanup_sig(0); +#ifndef __linux__ + signal(SIGBUS, SIG_DFL); +#endif /* !__linux__ */ + signal(SIGSEGV, SIG_DFL); + signal(SIGILL, SIG_DFL); + + /* + * Issue appropriate messages and abort or exit. - FM + */ + if (LYOutOfMemory == FALSE) { + fprintf (stderr, "\r\n\ A Fatal error has occurred in %s Ver. %s\r\n", LYNX_NAME, LYNX_VERSION); - fprintf(stderr, "\r\n\ + fprintf(stderr, "\r\n\ Please notify your system administrator to confirm a bug, and\r\n\ if confirmed, to notify the lynx-dev list. Bug reports should\r\n\ have concise descriptions of the command and/or URL which causes\r\n\ the problem, the operating system name with version number, the\r\n\ TCPIP implementation, and any other relevant information.\r\n"); - fprintf(stderr, "\r\n\ + fprintf(stderr, "\r\n\ Do NOT mail the core file if one was generated.\r\n"); - fprintf(stderr, "\r\n\ + fprintf(stderr, "\r\n\ Lynx now exiting with signal: %d\r\n\r\n", sig); - /* ignore further interrupts */ /* mhc: 11/2/91 */ - (void) signal (SIGHUP, SIG_IGN); - (void) signal (SIGTERM, SIG_IGN); -#ifndef VMS /* use ttclose() from cleanup() for VMS */ - (void) signal (SIGINT, SIG_IGN); -#endif /* !VMS */ -#ifndef __linux__ - (void) signal(SIGBUS, SIG_IGN); -#endif /* !__linux__ */ - (void) signal(SIGSEGV, SIG_IGN); - (void) signal(SIGILL, SIG_IGN); + /* + * Exit and dump core. + */ + abort(); - if (LYCursesON) - sleep(AlertSecs); - cleanup_sig(0); -#ifndef __linux__ - signal(SIGBUS, 0); -#endif /* !__linux__ */ - signal(SIGSEGV, 0); - signal(SIGILL, 0); - abort(); /* exit and dump core */ + } else { + LYOutOfMemory = FALSE; + printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT); + fflush(stdout); + + /* + * Exit without dumping core. + */ + exit(0); + } } #endif /* !VMS */ diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c index 83567743..bce1652c 100644 --- a/src/LYMainLoop.c +++ b/src/LYMainLoop.c @@ -4,6 +4,7 @@ #include "HTParse.h" #include "HTList.h" #include "HTFTP.h" +#include "HTFile.h" #include "HTTP.h" #include "LYCurses.h" #include "LYGlobalDefs.h" @@ -32,6 +33,7 @@ #include "LYTraversal.h" #include "LYCharSets.h" #include "LYCharUtils.h" +#include "LYCookie.h" #ifdef VMS #include "HTVMSUtils.h" @@ -53,7 +55,10 @@ PUBLIC void HTAddGotoURL PARAMS((char *url)); #define FASTTAB #ifdef FASTTAB -PRIVATE int sametext ARGS2(char *,een, char *,twee) { +PRIVATE int sametext ARGS2( + char *, een, + char *, twee) +{ if (een && twee) return (strcmp(een, twee) == 0); return TRUE; @@ -98,25 +103,26 @@ PRIVATE void free_mainloop_variables NOARGS } /* - * Here's where we do all the work. - * mainloop is basically just a big switch dependent on the users input. - * I have tried to offload most of the work done here to procedures to - * make it more modular, but this procedure still does a lot of variable - * manipulation. This needs some work to make it neater. - Lou Moutilli + * Here's where we do all the work. + * mainloop is basically just a big switch dependent on the users input. + * I have tried to offload most of the work done here to procedures to + * make it more modular, but this procedure still does a lot of variable + * manipulation. This needs some work to make it neater. - Lou Moutilli * (memoir from the original Lynx - FM) */ int mainloop NOARGS { - int c=0, real_c=0, old_c=0, cmd, arrowup=FALSE, show_help=FALSE; - int lines_in_file= -1; - int newline=0; + int c = 0, real_c = 0, old_c = 0, cmd; + int arrowup = FALSE, show_help = FALSE; + int lines_in_file = -1; + int Newline = 0; char prev_target[512]; char user_input_buffer[1024]; - char *owner_address=NULL; /* holds the responsible owner's address */ - char *ownerS_address=NULL; /* holds owner's address during source fetch */ - BOOLEAN first_file=TRUE; - BOOLEAN refresh_screen=FALSE; + char *owner_address = NULL; /* Holds the responsible owner's address */ + char *ownerS_address = NULL; /* Holds owner's address during source fetch */ + BOOLEAN first_file = TRUE; + BOOLEAN refresh_screen = FALSE; BOOLEAN force_load = FALSE; BOOLEAN crawl_ok = FALSE; BOOLEAN rlink_exists; @@ -124,6 +130,7 @@ int mainloop NOARGS BOOLEAN vi_keys_flag = vi_keys; BOOLEAN emacs_keys_flag = emacs_keys; BOOLEAN keypad_mode_flag = keypad_mode; + BOOLEAN user_mode_flag = user_mode; BOOLEAN HTfileSortMethod_flag = HTfileSortMethod; int CurrentCharSet_flag = current_char_set; BOOLEAN show_dotfiles_flag = show_dotfiles; @@ -140,6 +147,8 @@ int mainloop NOARGS int URLNum; BOOLEAN FirstURLRecall = TRUE; char *temp = NULL; + BOOLEAN ForcePush = FALSE; + int i, len; #ifdef DIRED_SUPPORT char *tp; @@ -148,12 +157,12 @@ int mainloop NOARGS #endif /* DIRED_SUPPORT */ /* - * curdoc.address contains the name of the file that is currently open + * curdoc.address contains the name of the file that is currently open. * newdoc.address contains the name of the file that will soon be - * opened if it exits - * prev_target contains the last search string the user searched for - * newdoc.title contains the link name that the user last chose to get into - * the current link (file) + * opened if it exits. + * prev_target contains the last search string the user searched for. + * newdoc.title contains the link name that the user last chose to get + * into the current link (file). */ /* initalize some variables*/ newdoc.address = NULL; @@ -166,22 +175,21 @@ int mainloop NOARGS curdoc.post_data = NULL; curdoc.post_content_type = NULL; curdoc.bookmark = NULL; + nhist = 0; + user_input_buffer[(sizeof(user_input_buffer) - 1)] = '\0'; + *prev_target = '\0'; + *user_input_buffer = '\0'; + StrAllocCopy(CurrentUserAgent, (LYUserAgent ? + LYUserAgent : "")); atexit(free_mainloop_variables); - if (startfile && homepage && strcmp(startfile, homepage)) - HTAddGotoURL(homepage); - HTAddGotoURL(startfile); initialize: - nhist = 0; StrAllocCopy(newdoc.address, startfile); StrAllocCopy(startrealm, startfile); StrAllocCopy(newdoc.title, "Entry into main screen"); - newdoc.isHEAD=FALSE; - newdoc.line=1; - newdoc.link=0; - *prev_target='\0'; - *user_input_buffer='\0'; - StrAllocCopy(CurrentUserAgent, (LYUserAgent ? - LYUserAgent : "")); + newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; + newdoc.line = 1; + newdoc.link = 0; #ifdef USE_SLANG if (TRACE && LYCursesON) { @@ -220,13 +228,13 @@ initialize: */ if ((cp = get_bookmark_filename(&newdoc.address)) != NULL && *cp != '\0' && strcmp(cp, " ")) { - LYforce_HTML_mode = TRUE; /* force HTML */ StrAllocCopy(newdoc.title, BOOKMARK_TITLE); StrAllocCopy(newdoc.bookmark, BookmarkPage); StrAllocCopy(startrealm, newdoc.address); FREE(newdoc.post_data); FREE(newdoc.post_content_type); newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; if (TRACE) fprintf(stderr, "Using bookmarks=%s\n", newdoc.address); } else { @@ -238,20 +246,18 @@ initialize: } } - if (form_post_data) { - FREE(form_post_data); - } else if (form_get_data) { - FREE(form_get_data); - } + FREE(form_post_data); + FREE(form_get_data); - if (user_mode==NOVICE_MODE) + if (user_mode == NOVICE_MODE) display_lines = LYlines-4; else display_lines = LYlines-2; while (TRUE) { - /* if newdoc.address is different then curdoc.address then we need - * to go out and find and load newdoc.address + /* + * If newdoc.address is different then curdoc.address then + * we need to go out and find and load newdoc.address. */ if (LYforce_no_cache || force_load || are_different(&curdoc, &newdoc)) { @@ -266,17 +272,21 @@ initialize: } try_again: /* - * Push the old file onto the history stack. + * Push the old file onto the history stack. */ if (curdoc.address && newdoc.address) { - LYpush(&curdoc); + LYpush(&curdoc, ForcePush); } else if (!newdoc.address) { /* - * If newdoc.address is empty then pop a file and load it. + * If newdoc.address is empty then pop a file + * and load it. Force a no_cache override unless + * it's a bookmark file or it has POST content + * and LYresubmit_posts is set. - FM */ LYpop(&newdoc); - if (newdoc.post_data != NULL && LYresubmit_posts) { + if ((newdoc.bookmark != NULL) || + (newdoc.post_data != NULL && LYresubmit_posts)) { LYoverride_no_cache = FALSE; } else { LYoverride_no_cache = TRUE; @@ -350,15 +360,15 @@ try_again: /* * Fall through to do the NULL stuff and reload the * old file, unless the first file wasn't found or - * has gone missing + * has gone missing. */ if (!nhist) { /* - * If nhist = 0 then it must be the first file. + * If nhist = 0 then it must be the first file. */ if (!dump_output_immediately) cleanup(); - printf("\nlynx: Can't access start file %s\n", + printf("\nlynx: Can't access startfile %s\n", startfile); if (!dump_output_immediately) { (void) signal(SIGHUP, SIG_DFL); @@ -377,7 +387,7 @@ try_again: case NULLFILE: /* - * Not supposed to return any file. + * Not supposed to return any file. */ LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */ FREE(newdoc.address); /* to pop last doc */ @@ -386,13 +396,14 @@ try_again: reloading = FALSE; LYPermitURL = FALSE; LYCancelledFetch = FALSE; + ForcePush = FALSE; if (traversal) { crawl_ok = FALSE; if (traversal_link_to_add) { /* - * It's a binary file, or the fetch attempt - * failed. Add it to TRAVERSE_REJECT_FILE - * so we don't try again in this run. + * It's a binary file, or the fetch attempt + * failed. Add it to TRAVERSE_REJECT_FILE + * so we don't try again in this run. */ if (!lookup_reject(traversal_link_to_add)) { add_to_reject_list(traversal_link_to_add); @@ -401,12 +412,12 @@ try_again: } } /* - * Make sure the first file was found and - * has not gone missing. + * Make sure the first file was found and + * has not gone missing. */ if (!nhist) { /* - * If nhist = 0 then it must be the first file. + * If nhist = 0 then it must be the first file. */ if (first_file && homepage && #ifdef VMS @@ -416,14 +427,14 @@ try_again: #endif /* VMS */ { /* - * Couldn't return to the first file but there is a - * homepage we can use instead. Useful for when the - * first URL causes a program to be invoked. - GL + * Couldn't return to the first file but there is a + * homepage we can use instead. Useful for when the + * first URL causes a program to be invoked. - GL * - * But first make sure homepage is different from - * startfile (above), then make it the same (below) - * so we don't enter an infinite getfile() loop on - * on failures to find the files. - FM + * But first make sure homepage is different from + * startfile (above), then make it the same (below) + * so we don't enter an infinite getfile() loop on + * on failures to find the files. - FM */ StrAllocCopy(newdoc.address, homepage); FREE(newdoc.post_data); @@ -431,6 +442,7 @@ try_again: FREE(newdoc.bookmark); StrAllocCopy(startfile, homepage); newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; } else { if (!dump_output_immediately) cleanup(); @@ -458,11 +470,111 @@ try_again: case NORMAL: /* - * Marvelously, we got the document! + * Marvelously, we got the document! */ LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */ *prev_target = '\0'; /* Reset for this document. - FM */ + /* + * If it's the first file and we're interactive, + * check whether it's a bookmark file which was + * not accessed via the -book switch. - FM + */ + if (((first_file == TRUE) && + (dump_output_immediately == FALSE) && + !(newdoc.bookmark && *newdoc.bookmark)) && + ((LYisLocalFile(newdoc.address) == TRUE) && + !(strcmp((HText_getTitle() ? HText_getTitle() : ""), + BOOKMARK_TITLE))) && + (temp = HTParse(newdoc.address, "", + PARSE_PATH+PARSE_PUNCTUATION)) != NULL) { +#ifdef VMS + cp = HTVMS_wwwName((char *)Home_Dir()); +#else + cp = (char *)Home_Dir(); +#endif /* VMS */ + len = strlen(cp); +#ifdef VMS + if (!strncasecomp(temp, cp, len) && +#else + if (!strncmp(temp, cp, len) && +#endif /* VMS */ + strlen(temp) > len) { + /* + * We're interactive and this might be a + * bookmark file entered as a startfile + * rather than invoked via -book. Check + * if it's in our bookmark file list, and + * if so, reload if with the relevant + * bookmark elements set. - FM + */ + if ((cp = (char *)calloc(1, + (strlen((char *)&temp[len]) + 2))) == NULL) + outofmem(__FILE__, "mainloop"); + if (temp[len] == '/') + sprintf(cp, ".%s", (char *)&temp[len]); + else + strcpy(cp, (char *)&temp[len]); + for (i = 0; i <= MBM_V_MAXFILES; i++) { + if (MBM_A_subbookmark[i] && +#ifdef VMS + !strcasecomp(cp, MBM_A_subbookmark[i])) +#else + !strcmp(cp, MBM_A_subbookmark[i])) +#endif /* VMS */ + { + StrAllocCopy(BookmarkPage, + MBM_A_subbookmark[i]); + break; + } + } + FREE(cp); + if (i <= MBM_V_MAXFILES) { + FREE(temp); + if (LYValidate) { + _statusline(BOOKMARKS_DISABLED); + sleep(AlertSecs); + return(-1); + } + if (temp = HTParse(newdoc.address, "", + PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION)) { + StrAllocCopy(newdoc.address, temp); + HTuncache_current_document(); + FREE(curdoc.address); +#ifdef VMS + StrAllocCat(newdoc.address, + HTVMS_wwwName((char *)Home_Dir())); +#else + StrAllocCat(newdoc.address, Home_Dir()); +#endif /* VMS */ + StrAllocCat(newdoc.address, "/"); + StrAllocCat(newdoc.address, + (strncmp(BookmarkPage, "./", 2) ? + BookmarkPage : + (BookmarkPage + 2))); + StrAllocCopy(newdoc.title, BOOKMARK_TITLE); + StrAllocCopy(newdoc.bookmark, BookmarkPage); + StrAllocCopy(startrealm, newdoc.address); + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); + newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; + FREE(temp); + if (!strcmp(homepage, startfile)) + StrAllocCopy(homepage, newdoc.address); + StrAllocCopy(startfile, newdoc.address); + if (TRACE) + fprintf(stderr, + "Reloading as bookmarks=%s\n", + newdoc.address); + goto try_again; + } + } + } + cp = NULL; + } + FREE(temp); + if (traversal) { /* * During traversal build up lists of all links @@ -470,14 +582,18 @@ try_again: * feature for traversing http links in the web. */ if (traversal_link_to_add) { - /* Add the address we sought to TRAVERSE_FILE */ + /* + * Add the address we sought to TRAVERSE_FILE. + */ if (!lookup(traversal_link_to_add)) add_to_table(traversal_link_to_add); FREE(traversal_link_to_add); } if (curdoc.address && curdoc.title && strncasecomp(curdoc.address, "LYNXIMGMAP:", 11)) - /* Add the address we got to TRAVERSE_FOUND_FILE */ + /* + * Add the address we got to TRAVERSE_FOUND_FILE. + */ add_to_traverse_list(curdoc.address, curdoc.title); } @@ -497,48 +613,67 @@ try_again: } /* - * Set newline to the saved line. It contains the - * line the user was on if s/he has been in the file - * before, or it is 1 if this is a new file. + * Set Newline to the saved line. It contains the + * line the user was on if s/he has been in the file + * before, or it is 1 if this is a new file. */ - newline = newdoc.line; + Newline = newdoc.line; /* - * If we are going to a target line, - * override any www_search line result. + * If we are going to a target line, + * override any www_search line result. */ - if (newline > 1) + if (Newline > 1) www_search_result = -1; /* - * Make sure curdoc.line will not be equal - * to newline, so we get a redraw. + * Make sure curdoc.line will not be equal + * to Newline, so we get a redraw. */ curdoc.line = -1; break; } /* end switch */ - if (TRACE) - sleep(AlertSecs); /* allow me to look at the results */ + if (TRACE) + sleep(AlertSecs); /* allow me to look at the results */ + + /* + * Set the files the same. + */ + StrAllocCopy(curdoc.address, newdoc.address); + StrAllocCopy(curdoc.post_data, newdoc.post_data); + StrAllocCopy(curdoc.post_content_type, newdoc.post_content_type); + StrAllocCopy(curdoc.bookmark, newdoc.bookmark); + curdoc.isHEAD = newdoc.isHEAD; + + /* + * Set the remaining document elements and add to + * the visitied links list. - FM + */ + if (ownerS_address != NULL) { + if (HTOutputFormat == WWW_SOURCE && !HText_getOwner()) + HText_setMainTextOwner(ownerS_address); + FREE(ownerS_address); + } + if (HText_getTitle()) { + StrAllocCopy(curdoc.title, HText_getTitle()); + } else if (!dump_output_immediately) { + StrAllocCopy(curdoc.title, newdoc.title); + } + owner_address = HText_getOwner(); + curdoc.safe = HTLoadedDocumentIsSafe(); + if (!dump_output_immediately) { + LYAddVisitedLink(&curdoc); + } - /* set the files the same */ - StrAllocCopy(curdoc.address, newdoc.address); - StrAllocCopy(curdoc.post_data, newdoc.post_data); - StrAllocCopy(curdoc.post_content_type, newdoc.post_content_type); - StrAllocCopy(curdoc.bookmark, newdoc.bookmark); - curdoc.isHEAD = newdoc.isHEAD; /* * Reset WWW present mode so that if we were getting * the source, we get rendered HTML from now on. */ - if (ownerS_address != NULL) { - if (HTOutputFormat == WWW_SOURCE && !HText_getOwner()) - HText_setMainTextOwner(ownerS_address); - FREE(ownerS_address); - } HTOutputFormat = WWW_PRESENT; + /* * Reset all of the other relevant flags. - FM */ @@ -548,28 +683,28 @@ try_again: reloading = FALSE; /* only set for RELOAD and RESUBMIT */ HEAD_request = FALSE; /* only set for HEAD requests */ LYPermitURL = FALSE; /* only set for LYValidate */ + ForcePush = FALSE; /* only set for some PRINT requests. */ - } /* end if (STREQ(newdoc.address,curdoc.address) */ + } /* end if (STREQ(newdoc.address, curdoc.address) */ if (dump_output_immediately) { if (crawl) { - if (HText_getTitle()) - StrAllocCopy(curdoc.title, HText_getTitle()); - print_crawl_to_fd(stdout,curdoc.address,curdoc.title); + print_crawl_to_fd(stdout, curdoc.address, curdoc.title); } else { print_wwwfile_to_fd(stdout,0); } return(0); } - /* if the resent_sizechange variable is set to true - then the window size changed recently. - */ + /* + * If the resent_sizechange variable is set to TRUE + * then the window size changed recently. + */ if (recent_sizechange) { stop_curses(); start_curses(); clear(); - refresh_screen = TRUE; /*to force a redraw */ + refresh_screen = TRUE; /* to force a redraw */ recent_sizechange=FALSE; if (user_mode==NOVICE_MODE) { display_lines = LYlines-4; @@ -579,17 +714,18 @@ try_again: } if (www_search_result != -1) { - /* This was a WWW search, set the line - * to the result of the search + /* + * This was a WWW search, set the line + * to the result of the search. */ - newline = www_search_result; + Newline = www_search_result; www_search_result = -1; /* reset */ more = HText_canScrollDown(); } if (first_file == TRUE) { /* - * We can never again have the first file. + * We can never again have the first file. */ first_file = FALSE; @@ -618,7 +754,7 @@ try_again: } if (traversal) { /* - * Set up the crawl output stuff. + * Set up the crawl output stuff. */ if (curdoc.address && !lookup(curdoc.address)) { if (strncasecomp(curdoc.address, "LYNXIMGMAP:", 11)) @@ -626,7 +762,7 @@ try_again: add_to_table(curdoc.address); } /* - * Set up the traversal_host comparison string. + * Set up the traversal_host comparison string. */ if (strncmp((curdoc.address ? curdoc.address : "NULL"), "http", 4)) { @@ -651,65 +787,81 @@ try_again: "Traversal host is '%s'\n\n", traversal_host); } } + if (startfile) { + if (homepage && strcmp(startfile, homepage)) + HTAddGotoURL(homepage); + if (strcmp(startfile, newdoc.address) || + newdoc.post_data == NULL); + HTAddGotoURL(startfile); + } if (TRACE) { refresh_screen = TRUE; sleep(AlertSecs); } } - /* if the curdoc.line is different than newline then there must - * have been a change since last update. Run showpage. - * showpage will put a fresh screen of text out. - * If this is a WWW document then use the - * WWW routine HText_pageDisplay to put the page on - * the screen + /* + * If the curdoc.line is different than Newline then there + * must have been a change since last update. Run showpage. + * showpage will put a fresh screen of text out. If this is + * a WWW document then use the WWW routine HText_pageDisplay + * to put the page on the screen. */ - if (curdoc.line != newline) { + if (curdoc.line != Newline) { refresh_screen = FALSE; - HText_pageDisplay(newline, prev_target); + HText_pageDisplay(Newline, prev_target); #ifdef DIRED_SUPPORT if (lynx_edit_mode && nlinks > 0 && !HTList_isEmpty(tagged)) showtags(tagged); #endif /* DIRED_SUPPORT */ - /* if more equals true then there is more - * info below this page + /* + * If more equals TRUE, then there is more + * info below this page . */ more = HText_canScrollDown(); - curdoc.line = newline = HText_getTopOfScreen()+1; + curdoc.line = Newline = HText_getTopOfScreen()+1; lines_in_file = HText_getNumOfLines(); - if (HText_getTitle()) { - StrAllocCopy(curdoc.title, HText_getTitle()); - } else { - StrAllocCopy(curdoc.title, newdoc.title); + if (curdoc.title == NULL) { + /* + * If we don't yet have a title, try to get it, + * or set to that for newdoc.title. - FM + */ + if (HText_getTitle()) { + StrAllocCopy(curdoc.title, HText_getTitle()); + } else { + StrAllocCopy(curdoc.title, newdoc.title); + } } - owner_address = HText_getOwner(); - if (arrowup) { - /* arrow up is set if we just came up from - * a page below + if (arrowup) { + /* + * arrowup is set if we just came up from + * a page below. */ curdoc.link = nlinks - 1; arrowup = FALSE; - } else { + } else { curdoc.link = newdoc.link; if (curdoc.link >= nlinks) curdoc.link = nlinks - 1; - } + } - show_help = FALSE; /* reset */ - newdoc.line = 1; - newdoc.link = 0; - curdoc.line = newline; /* set */ + show_help = FALSE; /* reset */ + newdoc.line = 1; + newdoc.link = 0; + curdoc.line = Newline; /* set */ } - /* refesh the screen if neccessary */ + /* + * Refesh the screen if neccessary. + */ if (refresh_screen) { clear(); - HText_pageDisplay(newline, prev_target); + HText_pageDisplay(Newline, prev_target); #ifdef DIRED_SUPPORT if (lynx_edit_mode && nlinks > 0 && !HTList_isEmpty(tagged)) @@ -721,25 +873,33 @@ try_again: } - /* report unread or new mail, if appropriate */ + /* + * Report unread or new mail, if appropriate. + */ if (check_mail && !no_mail && LYCheckMail()) sleep(MessageSecs); - /* if help is not on the screen - * then put a message on the screen - * to tell the user other misc info + /* + * If help is not on the screen, + * then put a message on the screen + * to tell the user other misc info. */ if (!show_help) { - /* make sure form novice lines are replaced */ + /* + * Make sure form novice lines are replaced. + */ if (user_mode == NOVICE_MODE) { noviceline(more); } - /* if we are in forms mode then explicitly - * tell the user what each kind of link is + /* + * If we are in forms mode then explicitly + * tell the user what each kind of link is. */ if (HTisDocumentSource()) { - /* currently displaying HTML source */ + /* + * Currently displaying HTML source. + */ _statusline(SOURCE_HELP); #ifdef INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE @@ -797,6 +957,7 @@ try_again: } break; case F_SUBMIT_TYPE: + case F_IMAGE_SUBMIT_TYPE: if (links[curdoc.link].form->disabled == YES) { statusline(FORM_LINK_SUBMIT_DIS_MSG); } else if (links[curdoc.link].form->submit_method == @@ -829,7 +990,9 @@ try_again: else statusline(NORMAL_LINK_MESSAGE); - /* let them know if it's an index -- very rare*/ + /* + * Let them know if it's an index -- very rare. + */ if (is_www_index) { move(LYlines-1,LYcols-8); start_reverse(); @@ -838,7 +1001,9 @@ try_again: } } else if (user_mode == ADVANCED_MODE && nlinks > 0) { - /* show the URL */ + /* + * Show the URL. + */ if (more) if (is_www_index) _user_message("-more- -index- %s", @@ -880,8 +1045,8 @@ try_again: if (traversal) { /* - * Don't go interactively into forms, - * or accept keystrokes from the user + * Don't go interactively into forms, + * or accept keystrokes from the user */ if (crawl && crawl_ok) { crawl_ok = FALSE; @@ -912,7 +1077,7 @@ try_again: } } else { /* - * Normal, non-traversal handling + * Normal, non-traversal handling. */ if (nlinks > 0 && links[curdoc.link].type == WWW_FORM_LINK_TYPE && @@ -921,7 +1086,7 @@ try_again: links[curdoc.link].form->type == F_PASSWORD_TYPE || links[curdoc.link].form->type == F_TEXTAREA_TYPE)) { /* - * Replace novice lines if in NOVICE_MODE + * Replace novice lines if in NOVICE_MODE. */ if (user_mode==NOVICE_MODE) { move(LYlines-2,0); clrtoeol(); @@ -937,25 +1102,28 @@ try_again: if (c == '\n' || c == '\r') #ifdef FASTTAB /* - * Make return act like downarrow + * Make return act like down-arrow. */ c = DNARROW; #else /* - * Make return act like tab + * Make return act like tab. */ c = '\t'; #endif /* FASTTAB */ } else { - /* Get a keystroke from the user - * Save the last keystroke to avoid redundant - * error reporting. +get_keyboard_input: + /* + * Get a keystroke from the user. + * Save the last keystroke to avoid + * redundant error reporting. */ real_c = c = LYgetch(); /* get user input */ #ifndef VMS if (c == 3) { /* ^C */ - /* This shouldn't happen. We'll try to - * deal with whatever bug caused it. - FM + /* + * This shouldn't happen. We'll try to + * deal with whatever bug caused it. - FM */ signal(SIGINT, cleanup_sig); old_c = 0; @@ -982,16 +1150,17 @@ try_again: #endif /* VMS */ new_keyboard_input: - /* a goto point for new input without going - * back through the getch() loop + /* + * A goto point for new input without going + * back through the getch() loop. */ if (traversal) { /* - * This is a special feature to traverse every http link - * derived from startfile and check for errors or create - * crawl ouput files. Only URL's that begin with - * "traversal_host" are searched - this keeps the search - * from crossing to other servers (a feature, not a bug!) + * This is a special feature to traverse every http link + * derived from startfile and check for errors or create + * crawl ouput files. Only URL's that begin with + * "traversal_host" are searched - this keeps the search + * from crossing to other servers (a feature, not a bug!). */ rlink_exists = (nlinks > 0 && links[curdoc.link].lname != NULL); if (rlink_exists) { @@ -1048,8 +1217,8 @@ new_keyboard_input: c=DNARROW; else { /* - * curdoc.title doesn't always work, so - * bail out if the history list is empty. + * curdoc.title doesn't always work, so + * bail out if the history list is empty. */ if (STREQ(curdoc.title,"Entry into main screen") || (nhist <= 0 )) { @@ -1080,8 +1249,9 @@ new_keyboard_input: cmd = override[c+1]; #endif /* DIRED_SUPPORT && OK_OVERRIDE */ -new_cmd: /* a goto point for new input without going - * back through the getch() loop +new_cmd: /* + * A goto point for new input without going + * back through the getch() loop. */ switch(cmd) { @@ -1093,12 +1263,17 @@ new_cmd: /* a goto point for new input without going _statusline(HELP); show_help = TRUE; - if (TRACE) - printw("%d", c); /* show the user input */ + if (TRACE) { + sprintf(cfile, "%d", c); + addstr(cfile); /* show the user input */ + cfile[0] = '\0'; + } break; case LYK_INTERRUPT: - /* No network transmission to interrupt - 'til we multithread */ + /* + * No network transmission to interrupt - 'til we multithread. + */ break; case LYK_1: @@ -1110,23 +1285,28 @@ new_cmd: /* a goto point for new input without going case LYK_7: case LYK_8: case LYK_9: - /* get a number from the user and follow that link number */ + /* + * Get a number from the user and follow that link number. + */ switch(follow_link_number(c, ((nlinks > 0) ? curdoc.link : 0))) { case DO_LINK_STUFF: - /* follow a normal link */ + /* + * Follow a normal link. + */ if (nlinks > 0) StrAllocCopy(newdoc.address, links[curdoc.link].lname); else StrAllocCopy(newdoc.address, links[0].lname); /* - * Might be an anchor in the same doc from a POST - * form. If so, don't free the content. -- FM + * Might be an anchor in the same doc from a POST + * form. If so, don't free the content. -- FM */ if (are_different(&curdoc, &newdoc)) { FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; } force_load = TRUE; /* force MainLoop to reload */ break; @@ -1142,6 +1322,18 @@ new_cmd: /* a goto point for new input without going break; case LYK_SOURCE: /* toggle view source mode */ + /* + * Check if this is a reply from a POST, and if so, + * seek confirmation if the safe element is not set. - FM + */ + if ((curdoc.post_data != NULL && + curdoc.safe != TRUE) && + HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + _statusline(CANCELLED); + sleep(InfoSecs); + break; + } + if (HTisDocumentSource()) { HTOutputFormat = WWW_PRESENT; } else { @@ -1155,7 +1347,19 @@ new_cmd: /* a goto point for new input without going case LYK_RELOAD: /* control-R to reload and refresh */ /* - * Check to see if should reload source, or load html + * Check if this is a reply from a POST, and if so, + * seek confirmation if the safe element is not set. - FM + */ + if ((curdoc.post_data != NULL && + curdoc.safe != TRUE) && + HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + _statusline(CANCELLED); + sleep(InfoSecs); + break; + } + + /* + * Check to see if should reload source, or load html */ if (HTisDocumentSource()) { HTOutputFormat = WWW_SOURCE; @@ -1164,22 +1368,22 @@ new_cmd: /* a goto point for new input without going HTuncache_current_document(); #ifdef NO_ASSUME_SAME_DOC /* - * Don't assume the reloaded document will be the same. - FM + * Don't assume the reloaded document will be the same. - FM */ newdoc.line=1; newdoc.link=0; #else /* - * Do assume the reloaded document will be the same. - FM - * (I don't remember all the reasons why we couldn't assume - * this. As the problems show up, we'll try to fix them, - * or add warnings. - FM) + * Do assume the reloaded document will be the same. - FM + * (I don't remember all the reasons why we couldn't assume + * this. As the problems show up, we'll try to fix them, + * or add warnings. - FM) */ if (lynx_mode == FORMS_LYNX_MODE) { /* - * Note that if there are no form links on the current - * page, lynx_mode won't have this setting and we won't - * know that this warning should be issued. - FM + * Note that if there are no form links on the current + * page, lynx_mode won't have this setting and we won't + * know that this warning should be issued. - FM */ _statusline(RELOADING_FORM); sleep(AlertSecs); @@ -1192,16 +1396,28 @@ new_cmd: /* a goto point for new input without going clearok(curscr, TRUE); #endif /* VMS */ /* - * Reload should force a cache refresh on a proxy + * Reload should force a cache refresh on a proxy. * -- Ari L. <luotonen@dxcern.cern.ch> */ reloading = TRUE; break; case LYK_HISTORICAL: - HTuncache_current_document(); - StrAllocCopy(newdoc.address, curdoc.address); - FREE(curdoc.address); + /* + * Check if this is a reply from a POST, and if so, + * seek confirmation of reload if the safe element + * is not set. - FM + */ + if ((curdoc.post_data != NULL && + curdoc.safe != TRUE) && + HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + _statusline(WILL_NOT_RELOAD_DOC); + sleep(InfoSecs); + } else { + HTuncache_current_document(); + StrAllocCopy(newdoc.address, curdoc.address); + FREE(curdoc.address); + } if (historical_comments) historical_comments = FALSE; else @@ -1218,9 +1434,21 @@ new_cmd: /* a goto point for new input without going case LYK_MINIMAL: if (!historical_comments) { - HTuncache_current_document(); - StrAllocCopy(newdoc.address, curdoc.address); - FREE(curdoc.address); + /* + * Check if this is a reply from a POST, and if so, + * seek confirmation of reload if the safe element + * is not set. - FM + */ + if ((curdoc.post_data != NULL && + curdoc.safe != TRUE) && + HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + _statusline(WILL_NOT_RELOAD_DOC); + sleep(InfoSecs); + } else { + HTuncache_current_document(); + StrAllocCopy(newdoc.address, curdoc.address); + FREE(curdoc.address); + } } if (minimal_comments) minimal_comments = FALSE; @@ -1237,9 +1465,21 @@ new_cmd: /* a goto point for new input without going break; case LYK_SOFT_DQUOTES: - HTuncache_current_document(); - StrAllocCopy(newdoc.address, curdoc.address); - FREE(curdoc.address); + /* + * Check if this is a reply from a POST, and if so, + * seek confirmation of reload if the safe element + * is not set. - FM + */ + if ((curdoc.post_data != NULL && + curdoc.safe != TRUE) && + HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + _statusline(WILL_NOT_RELOAD_DOC); + sleep(InfoSecs); + } else { + HTuncache_current_document(); + StrAllocCopy(newdoc.address, curdoc.address); + FREE(curdoc.address); + } if (soft_dquotes) soft_dquotes = FALSE; else @@ -1270,13 +1510,13 @@ new_cmd: /* a goto point for new input without going } break; - case LYK_ABORT: - return(0); /* dont ask the user about quitting */ + case LYK_ABORT: /* don't ask the user about quitting */ + return(0); break; case LYK_NEXT_PAGE: /* next page */ if (more) { - newline += display_lines; + Newline += display_lines; } else if (curdoc.link < nlinks-1) { highlight(OFF,curdoc.link); curdoc.link = nlinks-1; /* put on last link */ @@ -1288,8 +1528,8 @@ new_cmd: /* a goto point for new input without going break; case LYK_PREV_PAGE: /* page up */ - if (newline > 1) { - newline -= display_lines; + if (Newline > 1) { + Newline -= display_lines; } else if (curdoc.link > 0) { highlight(OFF,curdoc.link); curdoc.link = 0; /* put on last link */ @@ -1301,13 +1541,13 @@ new_cmd: /* a goto point for new input without going break; case LYK_UP_TWO: - if (newline > 1) { - newline -= 2; + if (Newline > 1) { + Newline -= 2; if (nlinks > 0 && curdoc.link > -1) { if (links[curdoc.link].ly <= (display_lines - 2)) { newdoc.link = curdoc.link + HText_LinksInLines(HTMainText, - newline, 2); + Newline, 2); } else { arrowup = TRUE; } @@ -1321,10 +1561,9 @@ new_cmd: /* a goto point for new input without going case LYK_DOWN_TWO: if (more) { - newline += 2; + Newline += 2; if (nlinks > 0 && curdoc.link > -1 && links[curdoc.link].ly > 2) { - int i; newdoc.link = curdoc.link; for (i = 0; links[i].ly <= 2; i++) --newdoc.link; @@ -1337,13 +1576,13 @@ new_cmd: /* a goto point for new input without going break; case LYK_UP_HALF: - if (newline > 1) { - newline -= display_lines/2; + if (Newline > 1) { + Newline -= display_lines/2; if (nlinks > 0 && curdoc.link > -1) { if (links[curdoc.link].ly <= (display_lines/2)) { newdoc.link = curdoc.link + HText_LinksInLines(HTMainText, - newline, + Newline, (display_lines/2)); } else { arrowup = TRUE; @@ -1358,10 +1597,9 @@ new_cmd: /* a goto point for new input without going case LYK_DOWN_HALF: if (more) { - newline += (display_lines/2); + Newline += (display_lines/2); if (nlinks > 0 && curdoc.link > -1 && links[curdoc.link].ly > display_lines/2) { - int i; newdoc.link = curdoc.link; for (i = 0; links[i].ly <= (display_lines/2); i++) --newdoc.link; @@ -1382,7 +1620,7 @@ new_cmd: /* a goto point for new input without going case LYK_HOME: if (curdoc.line > 1) - newline = 1; + Newline = 1; else { cmd = LYK_PREV_PAGE; goto new_cmd; @@ -1391,8 +1629,8 @@ new_cmd: /* a goto point for new input without going case LYK_END: if (more) { - newline = MAXINT; /* go to end of file */ - arrowup = TRUE; /* position on last link */ + Newline = MAXINT; /* go to end of file */ + arrowup = TRUE; /* position on last link */ } else { cmd = LYK_NEXT_PAGE; goto new_cmd; @@ -1400,21 +1638,25 @@ new_cmd: /* a goto point for new input without going break; case LYK_PREV_LINK: - if (curdoc.link > 0) { /* previous link */ - highlight(OFF, curdoc.link); /* unhighlight the current link */ + if (curdoc.link > 0) { /* previous link */ + highlight(OFF, curdoc.link); /* unhighlight the current link */ curdoc.link--; - } else if (!more && curdoc.link==0 && newline==1) { /* at the top of list */ - /* if there is only one page of data and the user - * goes off the top, then just move the cursor to - * last link on the page + } else if (!more && + curdoc.link==0 && Newline==1) { /* at the top of list */ + /* + * If there is only one page of data and the user + * goes off the top, then just move the cursor to + * last link on the page. */ highlight(OFF,curdoc.link); /* unhighlight the current link */ curdoc.link = nlinks-1; /* the last link */ } else if (curdoc.line > 1) { /* previous page */ - /* go back to the previous page */ - newline -= (display_lines); + /* + * Go back to the previous page. + */ + Newline -= (display_lines); arrowup = TRUE; } else if (old_c != real_c) { @@ -1429,7 +1671,7 @@ new_cmd: /* a goto point for new input without going highlight(OFF, curdoc.link); #ifdef FASTTAB /* - * Move to different textarea if TAB in textarea. + * Move to different textarea if TAB in textarea. */ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && links[curdoc.link].form->type == F_TEXTAREA_TYPE && @@ -1450,15 +1692,15 @@ new_cmd: /* a goto point for new input without going curdoc.link++; #endif /* FASTTAB */ /* - * At the bottom of list and there is only one page. - * Move to the top link on the page. + * At the bottom of list and there is only one page. + * Move to the top link on the page. */ - } else if (!more && newline == 1 && curdoc.link == nlinks-1) { + } else if (!more && Newline == 1 && curdoc.link == nlinks-1) { highlight(OFF,curdoc.link); curdoc.link = 0; } else if (more) { /* next page */ - newline += (display_lines); + Newline += (display_lines); } else if (old_c != real_c) { old_c = real_c; @@ -1469,7 +1711,7 @@ new_cmd: /* a goto point for new input without going case LYK_UP_LINK: if (curdoc.link > 0) { /* more links above? */ - int i, newlink = -1; + int newlink = -1; for (i = curdoc.link; i >= 0; i--) { if (links[i].ly < links[curdoc.link].ly) { newlink = i; @@ -1480,11 +1722,11 @@ new_cmd: /* a goto point for new input without going highlight(OFF, curdoc.link); curdoc.link = newlink; #ifdef NOTDEFINED - } else if (!more && newline == 1 && curdoc.link == 0) { + } else if (!more && Newline == 1 && curdoc.link == 0) { highlight(OFF, curdoc.link); curdoc.link = (nlinks-1); } else if (more) { /* next page */ - newline += (display_lines); + Newline += (display_lines); } #else } else if (old_c != real_c) { @@ -1495,16 +1737,17 @@ new_cmd: /* a goto point for new input without going #endif /* NOTDEFINED */ #ifdef NOTDEFINED - /* at the bottom of list and there is only one page - * move to the top link on the page + /* + * At the bottom of list and there is only one page. + * Move to the top link on the page. */ - } else if (!more && newline == 1 && curdoc.link == (nlinks-1)) { + } else if (!more && Newline == 1 && curdoc.link == (nlinks-1)) { highlight(OFF, curdoc.link); curdoc.link = 0; #endif /* NOTDEFINED */ - } else if (curdoc.line > 1 && newline > 1) { /* previous page */ - newline -= (display_lines); + } else if (curdoc.line > 1 && Newline > 1) { /* previous page */ + Newline -= (display_lines); arrowup = TRUE; } else if (old_c != real_c) { @@ -1516,7 +1759,7 @@ new_cmd: /* a goto point for new input without going case LYK_DOWN_LINK: if (curdoc.link < (nlinks-1)) { /* more links? */ - int i, newlink = -1; + int newlink = -1; for (i = curdoc.link; i < nlinks; i++) if (links[i].ly > links[curdoc.link].ly) { newlink = i; @@ -1528,12 +1771,12 @@ new_cmd: /* a goto point for new input without going curdoc.link = newlink; #ifdef NOTDEFINED } else if (!more && - newline == 1 && curdoc.link == (nlinks-1)) { + Newline == 1 && curdoc.link == (nlinks-1)) { highlight(OFF, curdoc.link); curdoc.link = 0; #endif /* NOTDEFINED */ } else if (more) { /* next page */ - newline += (display_lines); + Newline += (display_lines); } else if (old_c != real_c) { old_c = real_c; _statusline(NO_LINKS_BELOW); @@ -1541,15 +1784,16 @@ new_cmd: /* a goto point for new input without going break; } #ifdef NOTDEFINED - /* at the bottom of list and there is only one page - * move to the top link on the page + /* + * At the bottom of list and there is only one page. + * Move to the top link on the page. */ - } else if (!more && newline == 1 && curdoc.link == (nlinks-1)) { + } else if (!more && Newline == 1 && curdoc.link == (nlinks-1)) { highlight(OFF, curdoc.link); curdoc.link = 0; #endif /* NOTDEFINED */ } else if (more) { /* next page */ - newline += (display_lines); + Newline += (display_lines); } else if (old_c != real_c) { old_c = real_c; @@ -1574,6 +1818,30 @@ new_cmd: /* a goto point for new input without going } break; + case LYK_COOKIE_JAR: /* show the cookie jar */ + /* + * Don't do if already viewing the cookie jar. + */ + if (strcmp(curdoc.title, COOKIE_JAR_TITLE)) { + StrAllocCopy(newdoc.address, "LYNXCOOKIE:/"); + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); + FREE(newdoc.bookmark); + newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; + LYforce_no_cache = TRUE; + if (LYValidate || check_realm) { + LYPermitURL = TRUE; + } + } else { + /* + * If already in the cookie jar, get out. + */ + cmd = LYK_PREV_DOC; + goto new_cmd; + } + break; + case LYK_HISTORY: /* show the history page */ if (curdoc.title && strcmp(curdoc.title, HISTORY_PAGE_TITLE)) { /* @@ -1590,22 +1858,23 @@ new_cmd: /* a goto point for new input without going #endif /* USE_SLANG */ refresh(); } - LYpush(&curdoc); + LYpush(&curdoc, ForcePush); /* * Print history options to file. */ - if (showhistory(&newdoc.address) < 0) + if (showhistory(&newdoc.address) < 0) { + LYpop(&curdoc); break; - FREE(curdoc.address); /* so it doesn't get pushed */ + } FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; + FREE(curdoc.address); /* so it doesn't get pushed */ - LYpop(&curdoc); - - refresh_screen=TRUE; + refresh_screen = TRUE; if (LYValidate || check_realm) { LYPermitURL = TRUE; } @@ -1619,6 +1888,54 @@ new_cmd: /* a goto point for new input without going case LYK_PREV_DOC: /* back up a level */ if (nhist > 0) { /* if there is anything to go back to */ + /* + * Check if the previous document is a reply from a POST, + * and if so, seek confirmation of resubmission if the safe + * element is not set and the document is not still in the + * cache or LYresubmit_posts is set. If not confirmed and + * it is not the startfile, pop it so we go to the yet + * previous document, until we're OK or reach the startfile. + * If we reach the startfile and its not OK or we don't get + * confirmation, cancel. - FM + */ + DocAddress WWWDoc; + HTParentAnchor *tmpanchor; + + while (nhist > 0) { + if (history[(nhist - 1)].post_data == NULL) { + break; + } + WWWDoc.address = history[(nhist - 1)].address; + WWWDoc.post_data = history[(nhist - 1)].post_data; + WWWDoc.post_content_type = + history[(nhist - 1)].post_content_type; + WWWDoc.bookmark = history[(nhist - 1)].bookmark; + WWWDoc.isHEAD = history[(nhist - 1)].isHEAD; + WWWDoc.safe = history[(nhist - 1)].safe; + tmpanchor = HTAnchor_parent(HTAnchor_findAddress(&WWWDoc)); + if (HTAnchor_safe(tmpanchor)) { + break; + } + if ((LYresubmit_posts || + (HText *)HTAnchor_document(tmpanchor) == NULL) && + HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + if (nhist == 1) { + _statusline(CANCELLED); + sleep(InfoSecs); + old_c = 0; + cmd = LYK_DO_NOTHING; + goto new_cmd; + } else { + _user_message(WWW_SKIP_MESSAGE, WWWDoc.address); + sleep(MessageSecs); + LYpop(&curdoc); + continue; + } + } else { + break; + } + } + /* * Set newdoc.address to empty to pop a file. */ @@ -1640,7 +1957,8 @@ new_cmd: /* a goto point for new input without going case LYK_NOCACHE: /* Force submission of form or link with no-cache */ if (nlinks > 0) { if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && - links[curdoc.link].form->type != F_SUBMIT_TYPE) { + links[curdoc.link].form->type != F_SUBMIT_TYPE && + links[curdoc.link].form->type != F_IMAGE_SUBMIT_TYPE) { if (old_c == real_c) break; old_c = real_c; @@ -1656,89 +1974,111 @@ new_cmd: /* a goto point for new input without going case LYK_ACTIVATE: /* follow a link */ if (nlinks > 0) { if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) { - /* - * Don't try to submit forms with bad actions. - FM + /* + * Don't try to submit forms with bad actions. - FM + */ + if (links[curdoc.link].form->type == F_SUBMIT_TYPE || + links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE || + links[curdoc.link].form->type == + F_TEXT_SUBMIT_TYPE) { + /* + * Do nothing if it's disabled. - FM */ - if (links[curdoc.link].form->type == F_SUBMIT_TYPE || - links[curdoc.link].form->type == - F_TEXT_SUBMIT_TYPE) { - /* - * Do nothing if it's disabled. - FM - */ - if (links[curdoc.link].form->disabled == YES) { - HTOutputFormat = WWW_PRESENT; - LYforce_no_cache = FALSE; - break; - } - /* - * Make sure we have an action. - FM - */ - if (!links[curdoc.link].form->submit_action || - *links[curdoc.link].form->submit_action + if (links[curdoc.link].form->disabled == YES) { + HTOutputFormat = WWW_PRESENT; + LYforce_no_cache = FALSE; + break; + } + /* + * Make sure we have an action. - FM + */ + if (!links[curdoc.link].form->submit_action || + *links[curdoc.link].form->submit_action == '\0') { - _statusline(NO_FORM_ACTION); - sleep(MessageSecs); - HTOutputFormat = WWW_PRESENT; - LYforce_no_cache = FALSE; - break; - } - /* - * Check for no_mail if the form action - * is a mailto URL. - FM - */ - if (links[curdoc.link].form->submit_method + _statusline(NO_FORM_ACTION); + sleep(MessageSecs); + HTOutputFormat = WWW_PRESENT; + LYforce_no_cache = FALSE; + break; + } + /* + * Check for no_mail if the form action + * is a mailto URL. - FM + */ + if (links[curdoc.link].form->submit_method == URL_MAIL_METHOD && no_mail) { - HTAlert(FORM_MAILTO_DISALLOWED); - HTOutputFormat = WWW_PRESENT; - LYforce_no_cache = FALSE; - break; - } - /* - * Make sure this isn't a spoof in an account - * with restrictions on file URLs. - FM - */ - if (no_file_url && - !strncasecomp( + HTAlert(FORM_MAILTO_DISALLOWED); + HTOutputFormat = WWW_PRESENT; + LYforce_no_cache = FALSE; + break; + } + /* + * Make sure this isn't a spoof in an account + * with restrictions on file URLs. - FM + */ + if (no_file_url && + !strncasecomp( links[curdoc.link].form->submit_action, - "file:", 5)) { - HTAlert(FILE_ACTIONS_DISALLOWED); + "file:", 5)) { + HTAlert(FILE_ACTIONS_DISALLOWED); + HTOutputFormat = WWW_PRESENT; + LYforce_no_cache = FALSE; + break; + } +#ifdef NOTDEFINED /* We're disabling form inputs instead of using this. - FM */ + /* + * Check for enctype and let user know we + * don't yet support multipart/form-data - FM + */ + if (links[curdoc.link].form->submit_enctype) { + if (!strcmp( + links[curdoc.link].form->submit_enctype, + "multipart/form-data")) { + HTAlert( + "Enctype multipart/form-data not yet supported! Cannot submit."); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; break; - } -#ifdef NOTDEFINED /* We're disabling form inputs instead of using this. - FM */ - /* - * Check for enctype and let user know we - * don't yet support multipart/form-data - FM - */ - if (links[curdoc.link].form->submit_enctype) { - if (!strcmp( - links[curdoc.link].form->submit_enctype, - "multipart/form-data")) { - HTAlert( - "Enctype multipart/form-data not yet supported! Cannot submit."); - HTOutputFormat = WWW_PRESENT; - LYforce_no_cache = FALSE; - break; - } - } + } + } #endif /* NOTDEFINED */ - if (check_realm) { - LYPermitURL = TRUE; - } - if (no_filereferer == TRUE && - !strncasecomp(curdoc.address, "file:", 5)) { - LYNoRefererForThis = TRUE; - } + if (check_realm) { + LYPermitURL = TRUE; } - c = change_form_link(&links[curdoc.link], - FORM_UP, &newdoc, &refresh_screen, - links[curdoc.link].form->name, - links[curdoc.link].form->value); - goto new_keyboard_input; - - } else { /* Not a forms link */ + if (no_filereferer == TRUE && + !strncasecomp(curdoc.address, "file:", 5)) { + LYNoRefererForThis = TRUE; + } + } + c = change_form_link(&links[curdoc.link], + FORM_UP, &newdoc, &refresh_screen, + links[curdoc.link].form->name, + links[curdoc.link].form->value); + if (HTOutputFormat == HTAtom_for("www/download") && + newdoc.post_data != NULL && + newdoc.safe == FALSE) { + if ((HText_POSTReplyLoaded(&newdoc) == TRUE) && + HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + _statusline(CANCELLED); + sleep(InfoSecs); + HTOutputFormat = WWW_PRESENT; + LYforce_no_cache = FALSE; + StrAllocCopy(newdoc.address, curdoc.address); + StrAllocCopy(newdoc.title, curdoc.title); + StrAllocCopy(newdoc.post_data, curdoc.post_data); + StrAllocCopy(newdoc.post_content_type, + curdoc.post_content_type); + StrAllocCopy(newdoc.bookmark, curdoc.bookmark); + newdoc.isHEAD = curdoc.isHEAD; + newdoc.safe = curdoc.safe; + break; + } + } + goto new_keyboard_input; + } else { /* + * Not a forms link. + * * Make sure this isn't a spoof in an account * with restrictions on file URLs. - FM */ @@ -1758,8 +2098,8 @@ new_cmd: /* a goto point for new input without going StrAllocCopy(newdoc.address, links[curdoc.link].lname); StrAllocCopy(newdoc.title, links[curdoc.link].hightext); /* - * Might be an anchor in the same doc from a POST - * form. If so, dont't free the content. -- FM + * Might be an anchor in the same doc from a POST + * form. If so, dont't free the content. -- FM */ if (are_different(&curdoc, &newdoc)) { FREE(newdoc.post_data); @@ -1785,7 +2125,8 @@ new_cmd: /* a goto point for new input without going #ifdef DIRED_SUPPORT if (lynx_edit_mode) { HTuncache_current_document(); - /* Unescaping any slash chars in the URL, + /* + * Unescaping any slash chars in the URL, * but avoid double unescaping and too-early * unescaping of other chars. - KW */ @@ -1793,12 +2134,14 @@ new_cmd: /* a goto point for new input without going strip_trailing_slash(newdoc.address); } #endif /* DIRED_SUPPORT */ + if (!strncasecomp(curdoc.address, "LYNXCOOKIE:", 11)) { + HTuncache_current_document(); + } } } break; case LYK_GOTO: /* 'g' to goto a random URL */ - if (no_goto && !LYValidate) { if (old_c != real_c) { old_c = real_c; @@ -1824,14 +2167,14 @@ new_cmd: /* a goto point for new input without going } /* - * Ask the user. + * Ask the user. */ _statusline(URL_TO_OPEN); if ((ch = LYgetstr(user_input_buffer, VISIBLE, sizeof(user_input_buffer), recall)) < 0 ) { /* - * User cancelled the Goto via ^G. - * Restore user_input_buffer and break. - FM + * User cancelled the Goto via ^G. + * Restore user_input_buffer and break. - FM */ strcpy(user_input_buffer, temp); FREE(temp); @@ -1842,7 +2185,7 @@ new_cmd: /* a goto point for new input without going check_recall: /* - * Get rid of leading spaces (and any other spaces). + * Get rid of leading spaces (and any other spaces). */ collapse_spaces(user_input_buffer); if (*user_input_buffer == '\0' && @@ -1856,19 +2199,19 @@ check_recall: if (recall && ch == UPARROW) { if (FirstURLRecall) { /* - * Use last URL in the list. - FM + * Use last URL in the list. - FM */ FirstURLRecall = FALSE; URLNum = 0; } else { /* - * Go back to the previous URL in the list. - FM + * Go back to the previous URL in the list. - FM */ URLNum++; } if (URLNum >= URLTotal) /* - * Roll around to the last URL in the list. - FM + * Roll around to the last URL in the list. - FM */ URLNum = 0; if ((cp = (char *)HTList_objectAt(Goto_URLs, @@ -1887,8 +2230,8 @@ check_recall: sizeof(user_input_buffer), recall)) < 0) { /* - * User cancelled the Goto via ^G. - * Restore user_input_buffer and break. - FM + * User cancelled the Goto via ^G. + * Restore user_input_buffer and break. - FM */ strcpy(user_input_buffer, temp); FREE(temp); @@ -1901,19 +2244,19 @@ check_recall: } else if (recall && ch == DNARROW) { if (FirstURLRecall) { /* - * Use the first URL in the list. - FM + * Use the first URL in the list. - FM */ FirstURLRecall = FALSE; URLNum = URLTotal - 1; } else { /* - * Advance to the next URL in the list. - FM + * Advance to the next URL in the list. - FM */ URLNum--; } if (URLNum < 0) /* - * Roll around to the first URL in the list. - FM + * Roll around to the first URL in the list. - FM */ URLNum = URLTotal - 1; if ((cp=(char *)HTList_objectAt(Goto_URLs, @@ -1932,8 +2275,8 @@ check_recall: sizeof(user_input_buffer), recall)) < 0) { /* - * User cancelled the Goto via ^G. - * Restore user_input_buffer and break. - FM + * User cancelled the Goto via ^G. + * Restore user_input_buffer and break. - FM */ strcpy(user_input_buffer, temp); FREE(temp); @@ -1946,18 +2289,14 @@ check_recall: } /* - * If its not a URL then make it one. + * If its not a URL then make it one. */ - if (!is_url(user_input_buffer)) { - char *user_input_string = NULL; - if (TRACE) - fprintf(stderr, "\n'%s' is not a URL\n", - user_input_buffer); - StrAllocCopy(user_input_string, user_input_buffer); - LYConvertToURL(&user_input_string); - strcpy(user_input_buffer, user_input_string); - FREE(user_input_string); - } + StrAllocCopy(temp, user_input_buffer); + LYFillLocalFileURL((char **)&temp, "file://localhost"); + LYEnsureAbsoluteURL((char **)&temp, ""); + sprintf(user_input_buffer, "%.*s", + (sizeof(user_input_buffer) - 1), temp); + FREE(temp); if ((no_file_url || no_goto_file) && !strncmp(user_input_buffer,"file:",5)) { _statusline(GOTO_FILE_DISALLOWED); @@ -2065,64 +2404,6 @@ check_recall: sleep(MessageSecs); } else { - /* make a name for this new URL */ - StrAllocCopy(newdoc.title, "A URL specified by the user"); - - /* - * If it's a file URL and the host is defaulted, - * force in "//localhost". We need this until - * all the other Lynx code which performs security - * checks based on the "localhost" string is changed - * to assume "//localhost" when a host field is not - * present in file URLs - FM - */ - if (!strncmp(user_input_buffer, "file:", 5)) { - if (user_input_buffer[5] == '\0') { - strcat(user_input_buffer, "//localhost"); - } else if (!strcmp(user_input_buffer, "file://")) { - strcat(user_input_buffer, "localhost"); - } else if (!strncmp(user_input_buffer, "file:///", 8)) { - StrAllocCopy(temp, (user_input_buffer+7)); - strcpy(user_input_buffer, "file://localhost"); - strcat(user_input_buffer, temp); - FREE(temp); - } else if (!strncmp(user_input_buffer, "file:/", 6) && - user_input_buffer[6] != '/') { - StrAllocCopy(temp, (user_input_buffer+5)); - strcpy(user_input_buffer, "file://localhost"); - strcat(user_input_buffer, temp); - FREE(temp); - } - } - - /* - * No path in a file://localhost URL means a - * directory listing for the current default. - FM - */ - if (!strcmp(user_input_buffer, "file://localhost")) { -#ifdef VMS - strcat(user_input_buffer, HTVMS_wwwName(getenv("PATH"))); -#else - char curdir[DIRNAMESIZE]; -#ifdef NO_GETCWD - getwd (curdir); -#else - getcwd (curdir, DIRNAMESIZE); -#endif /* NO_GETCWD */ - strcat(user_input_buffer, curdir); -#endif /* VMS */ - } - -#ifdef VMS - /* - * On VMS, a file://localhost/ URL means - * a listing for the login directory. - FM - */ - if (!strcmp(user_input_buffer, "file://localhost/")) - strcat(user_input_buffer, - (HTVMS_wwwName((char *)Home_Dir())+1)); -#endif /* VMS */ - StrAllocCopy(newdoc.address, user_input_buffer); newdoc.isHEAD = FALSE; /* @@ -2130,41 +2411,54 @@ check_recall: * form. If so, dont't free the content. -- FM */ if (are_different(&curdoc, &newdoc)) { + /* + * Make a name for this new URL. + */ + StrAllocCopy(newdoc.title, "A URL specified by the user"); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); - } - force_load = TRUE; - LYUserSpecifiedURL = TRUE; + newdoc.safe = FALSE; + force_load = TRUE; + LYUserSpecifiedURL = TRUE; #ifdef DIRED_SUPPORT - if (lynx_edit_mode) - HTuncache_current_document(); + if (lynx_edit_mode) + HTuncache_current_document(); #endif /* DIRED_SUPPORT */ - HTAddGotoURL(user_input_buffer); + HTAddGotoURL(newdoc.address); + } } break; case LYK_HELP: /* show help file */ if (!STREQ(curdoc.address, helpfile)) { - StrAllocCopy(newdoc.address, helpfile); /* set the filename */ - /* make a name for this help file */ + /* + * Set the filename. + */ + StrAllocCopy(newdoc.address, helpfile); + /* + * Make a name for this help file. + */ StrAllocCopy(newdoc.title, "Help Screen"); FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; } break; case LYK_INDEX: /* index file */ - /* make sure we are not in the index already */ + /* + * Make sure we are not in the index already. + */ if (!STREQ(curdoc.address, indexfile)) { if (indexfile[0]=='\0') { /* no defined index */ if (old_c != real_c) { - old_c = real_c; - _statusline(NO_INDEX_FILE); - sleep(MessageSecs); + old_c = real_c; + _statusline(NO_INDEX_FILE); + sleep(MessageSecs); } } else { @@ -2174,6 +2468,7 @@ check_recall: FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; } /* end else */ } /* end if */ break; @@ -2190,7 +2485,8 @@ check_recall: /* * Code to handle multiple submit buttons? * Taken out due to bug it causes. - if (links[curdoc.link].form->type == F_SUBMIT_TYPE) { + if (links[curdoc.link].form->type == F_SUBMIT_TYPE || + links[curdoc.link].form->type == F_IMAGESUBMIT_TYPE) { curdoc.address = NULL; } */ @@ -2222,7 +2518,9 @@ check_recall: #endif /* NOT_USED */ case LYK_MAIN_MENU: /* return to main screen */ - /* if its already the homepage then don't reload it */ + /* + * If its already the homepage then don't reload it. + */ if (!STREQ(curdoc.address,homepage)) { _statusline(CONFIRM_MAIN_SCREEN); @@ -2234,6 +2532,7 @@ check_recall: FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; highlight(OFF,curdoc.link); #ifdef DIRED_SUPPORT if (lynx_edit_mode) @@ -2254,27 +2553,64 @@ check_recall: break; case LYK_OPTIONS: /* options screen */ - #ifdef DIRED_SUPPORT c = dir_list_style; #endif /* DIRED_SUPPORT */ options(); /* do the options stuff */ if (keypad_mode_flag != keypad_mode || + (user_mode_flag != user_mode && + (user_mode_flag == NOVICE_MODE || + user_mode == NOVICE_MODE)) || + (((HTfileSortMethod_flag != HTfileSortMethod) || #ifdef DIRED_SUPPORT - c != dir_list_style || + (c != dir_list_style) || #endif /* DIRED_SUPPORT */ - HTfileSortMethod_flag != HTfileSortMethod || + (show_dotfiles_flag != show_dotfiles)) && + (!strncmp(curdoc.address, "file:", 5) || + !strncmp(curdoc.address, "ftp:", 4))) || CurrentCharSet_flag != current_char_set || - show_dotfiles_flag != show_dotfiles || LYRawMode_flag != LYRawMode || LYSelectPopups_flag != LYSelectPopups || - strcmp(CurrentUserAgent, (LYUserAgent ? - LYUserAgent : ""))) { - HTuncache_current_document(); - StrAllocCopy(newdoc.address, curdoc.address); - FREE(curdoc.address); + (strcmp(CurrentUserAgent, (LYUserAgent ? + LYUserAgent : "")) && + !strncmp(curdoc.address, "http", 4))) { + /* + * Check if this is a reply from a POST, and if so, + * seek confirmation of reload if the safe element + * is not set. - FM + */ + if ((curdoc.post_data != NULL && + curdoc.safe != TRUE) && + HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + _statusline(WILL_NOT_RELOAD_DOC); + sleep(InfoSecs); + + } else { + LYforce_no_cache = TRUE; + StrAllocCopy(newdoc.address, curdoc.address); + if (keypad_mode_flag != keypad_mode || + (user_mode_flag != user_mode && + (user_mode_flag == NOVICE_MODE || + user_mode == NOVICE_MODE)) || + (((HTfileSortMethod_flag != HTfileSortMethod) || +#ifdef DIRED_SUPPORT + (c != dir_list_style) || +#endif /* DIRED_SUPPORT */ + (show_dotfiles_flag != show_dotfiles)) && + (!strncmp(curdoc.address, "file:", 5) || + !strncmp(curdoc.address, "ftp:", 4))) || + LYSelectPopups_flag != LYSelectPopups || + (strcmp(CurrentUserAgent, (LYUserAgent ? + LYUserAgent : "")) && + !strncmp(curdoc.address, "http", 4))) { + HTuncache_current_document(); + FREE(curdoc.address); + } else { + } + } keypad_mode_flag = keypad_mode; + user_mode_flag = user_mode; HTfileSortMethod_flag = HTfileSortMethod; CurrentCharSet_flag = current_char_set; show_dotfiles_flag = show_dotfiles; @@ -2287,91 +2623,110 @@ check_recall: break; case LYK_INDEX_SEARCH: /* search for a user string */ - if (is_www_index) { - /* perform a database search */ - - /* do_www_search will try to go out and get the document - * if it returns yes a new document was returned and is - * named in the newdoc.address + if (is_www_index) { + /* + * Perform a database search. + * + * do_www_search will try to go out and get the document. + * If it returns TRUE, a new document was returned and is + * named in the newdoc.address. */ newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; if (do_www_search(&newdoc) == NORMAL) { - /* Yah, the search succeeded. */ - if (TRACE && LYCursesON) { - move(LYlines-1, LYcols-1); /* make sure cursor is down */ + /* + * Yah, the search succeeded. + */ + if (TRACE && LYCursesON) { + /* + * Make sure cursor is down. + */ + move(LYlines-1, LYcols-1); #ifdef USE_SLANG - addstr("\n"); + addstr("\n"); #endif /* USE_SLANG */ - refresh(); - } - LYpush(&curdoc); - /* Make the curdoc.address the newdoc.address so that - * getfile doesn't try to get the newdoc.address. - * Since we have already gotton it. - */ - StrAllocCopy(curdoc.address, newdoc.address); - StrAllocCopy(newdoc.post_data, curdoc.post_data); - curdoc.line = -1; - newline = 0; - refresh_screen = TRUE; /* redisplay it */ + refresh(); + } + LYpush(&curdoc, ForcePush); + /* + * Make the curdoc.address the newdoc.address so that + * getfile doesn't try to get the newdoc.address. + * Since we have already gotton it. + */ + StrAllocCopy(curdoc.address, newdoc.address); + StrAllocCopy(newdoc.post_data, curdoc.post_data); + curdoc.line = -1; + Newline = 0; + refresh_screen = TRUE; /* redisplay it */ } else if (use_this_url_instead != NULL) { - /* Got back a redirecting URL. Check it out. */ - _user_message("Using %s", use_this_url_instead); - /* Make a name for this URL */ - StrAllocCopy(newdoc.title, "A URL specified by redirection"); - StrAllocCopy(newdoc.address, use_this_url_instead); - FREE(newdoc.post_data); - FREE(newdoc.post_content_type); - FREE(newdoc.bookmark); - newdoc.isHEAD = FALSE; - FREE(use_this_url_instead); - force_load = TRUE; - break; + /* + * Got back a redirecting URL. Check it out. + */ + _user_message("Using %s", use_this_url_instead); + /* + * Make a name for this URL. + */ + StrAllocCopy(newdoc.title, + "A URL specified by redirection"); + StrAllocCopy(newdoc.address, use_this_url_instead); + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); + FREE(newdoc.bookmark); + newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; + FREE(use_this_url_instead); + force_load = TRUE; + break; } else { - /* Yuk, the search failed. Restore the old file. */ - StrAllocCopy(newdoc.address, curdoc.address); - StrAllocCopy(newdoc.post_data, curdoc.post_data); - newdoc.isHEAD = curdoc.isHEAD; + /* + * Yuk, the search failed. Restore the old file. + */ + StrAllocCopy(newdoc.address, curdoc.address); + StrAllocCopy(newdoc.post_data, curdoc.post_data); + StrAllocCopy(newdoc.post_content_type, + curdoc.post_content_type); + StrAllocCopy(newdoc.bookmark, curdoc.bookmark); + newdoc.isHEAD = curdoc.isHEAD; + newdoc.safe = curdoc.safe; } - } else if (old_c != real_c) { + } else if (old_c != real_c) { old_c = real_c; _statusline(NOT_ISINDEX); sleep(MessageSecs); - } - break; + } + break; case LYK_WHEREIS: /* search within the document */ - /* search for the next occurrence of the user string */ - case LYK_NEXT: + case LYK_NEXT: /* search for the next occurrence in the document */ /* user search */ if (cmd != LYK_NEXT) { /* - * Reset prev_target to force prompting - * for a new search string and to turn - * off highlighting in no search string - * is entered by the user. + * Reset prev_target to force prompting + * for a new search string and to turn + * off highlighting in no search string + * is entered by the user. */ *prev_target = '\0'; textsearch(&curdoc, prev_target, FALSE); } else { /* - * When the third argument is TRUE, the previous - * search string, if any, will be recalled from - * a buffer, loaded into prev_target, and used - * for the search without prompting for a new - * search string. This allows the LYK_NEXT - * command to repeat a search in a new document, - * after prev_target was reset on fetch of that - * document. + * When the third argument is TRUE, the previous + * search string, if any, will be recalled from + * a buffer, loaded into prev_target, and used + * for the search without prompting for a new + * search string. This allows the LYK_NEXT + * command to repeat a search in a new document, + * after prev_target was reset on fetch of that + * document. */ textsearch(&curdoc, prev_target, TRUE); } /* - * Force a redraw to ensure highlighting of hits - * even when found on the same page, or clearing - * of highlighting is the default search string - * was erased without replacement. - FM + * Force a redraw to ensure highlighting of hits + * even when found on the same page, or clearing + * of highlighting is the default search string + * was erased without replacement. - FM */ refresh_screen = TRUE; break; @@ -2401,6 +2756,7 @@ check_recall: */ char *address = NULL; char *path = HTParse(curdoc.address, "", PARSE_PATH); + if (path != NULL) { HTUnEscape(path); if (*path == '~' && strlen(path) > 1) { @@ -2467,7 +2823,7 @@ check_recall: if (dir_list_style == MIXED_STYLE) { if (!strcmp(links[curdoc.link].hightext, "../")) break; - } else if (!strncmp(links[curdoc.link].hightext,"Up to ",6)) + } else if (!strncmp(links[curdoc.link].hightext, "Up to ", 6)) break; { /* @@ -2478,7 +2834,7 @@ check_recall: BOOLEAN found = FALSE; while ((tagname = (char *)HTList_nextObject(t1)) != NULL) { - if (!strcmp(links[curdoc.link].lname,tagname)) { + if (!strcmp(links[curdoc.link].lname, tagname)) { found = TRUE; HTList_removeObject(tagged, tagname); FREE(tagname); @@ -2495,39 +2851,59 @@ check_recall: tagflag(ON,curdoc.link); } } - } - break; + if (curdoc.link < nlinks-1) { + highlight(OFF, curdoc.link); + curdoc.link++; + } else if (!more && Newline == 1 && curdoc.link == nlinks-1) { + highlight(OFF,curdoc.link); + curdoc.link = 0; + } else if (more) { /* next page */ + Newline += (display_lines); + } + } + break; case LYK_MODIFY: /* rename a file or directory */ - if (lynx_edit_mode && nlinks > 0 && !no_dired_support) { - int ret; - - ret = local_modify(&curdoc, &newdoc.address); - if (ret == PERMIT_FORM_RESULT) { /* Permit form thrown up */ - refresh_screen=TRUE; - } else if (ret) { - HTuncache_current_document(); - StrAllocCopy(newdoc.address, curdoc.address); - FREE(curdoc.address); - newdoc.line = curdoc.line; - newdoc.link = curdoc.link; - clear(); - } - } - break; + if (lynx_edit_mode && nlinks > 0 && !no_dired_support) { + int ret; + + ret = local_modify(&curdoc, &newdoc.address); + if (ret == PERMIT_FORM_RESULT) { /* Permit form thrown up */ + refresh_screen=TRUE; + } else if (ret) { + HTuncache_current_document(); + StrAllocCopy(newdoc.address, curdoc.address); + FREE(curdoc.address); + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); + FREE(newdoc.bookmark); + newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; + newdoc.line = curdoc.line; + newdoc.link = curdoc.link; + clear(); + } + } + break; case LYK_CREATE: /* create a new file or directory */ - if (lynx_edit_mode && !no_dired_support) { - if (local_create(&curdoc)) { - HTuncache_current_document(); - StrAllocCopy(newdoc.address, curdoc.address); - FREE(curdoc.address); - newdoc.line = curdoc.line; - newdoc.link = curdoc.link > -1 ? curdoc.link : 0; - clear(); - } - } - break; + if (lynx_edit_mode && !no_dired_support) { + if (local_create(&curdoc)) { + HTuncache_current_document(); + StrAllocCopy(newdoc.address, curdoc.address); + FREE(curdoc.address); + FREE(curdoc.address); + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); + FREE(newdoc.bookmark); + newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; + newdoc.line = curdoc.line; + newdoc.link = curdoc.link > -1 ? curdoc.link : 0; + clear(); + } + } + break; #endif /* DIRED_SUPPORT */ case LYK_EDIT: /* edit */ @@ -2541,99 +2917,108 @@ check_recall: } #ifdef DIRED_SUPPORT - -/* Allow the user to edit the link rather than curdoc in edit mode */ - - if (lynx_edit_mode && editor && *editor != '\0' && - !no_dired_support) { - if (nlinks > 0) { - cp = links[curdoc.link].lname; - if (is_url(cp) == FILE_URL_TYPE) { - tp = cp; - if (!strncmp(tp,"file://localhost",16)) - tp += 16; - else if (!strncmp(tp,"file:",5)) - tp += 5; - strcpy(tmpbuf,tp); - HTUnEscape(tmpbuf); - if (stat(tmpbuf,&dir_info) == -1) { - _statusline(NO_STATUS); - sleep(AlertSecs); - } else { - if (((dir_info.st_mode) & S_IFMT) == S_IFREG) { - strcpy(tmpbuf,cp); - HTUnEscapeSome(tmpbuf,"/"); - if (edit_current_file(tmpbuf,curdoc.link,newline)) - { - HTuncache_current_document(); - StrAllocCopy(newdoc.address, curdoc.address); - FREE(curdoc.address); + /* + * Allow the user to edit the link rather + * than curdoc in edit mode. + */ + if (lynx_edit_mode && + editor && *editor != '\0' && !no_dired_support) { + if (nlinks > 0) { + cp = links[curdoc.link].lname; + if (is_url(cp) == FILE_URL_TYPE) { + tp = cp; + if (!strncmp(tp, "file://localhost", 16)) + tp += 16; + else if (!strncmp(tp, "file:", 5)) + tp += 5; + strcpy(tmpbuf, tp); + HTUnEscape(tmpbuf); + if (stat(tmpbuf, &dir_info) == -1) { + _statusline(NO_STATUS); + sleep(AlertSecs); + } else { + if (((dir_info.st_mode) & S_IFMT) == S_IFREG) { + strcpy(tmpbuf, cp); + HTUnEscapeSome(tmpbuf, "/"); + if (edit_current_file(tmpbuf, + curdoc.link, Newline)) { + HTuncache_current_document(); + StrAllocCopy(newdoc.address, + curdoc.address); + FREE(curdoc.address); #ifdef NO_SEEK_OLD_POSITION - /* Go to top of file */ - newdoc.line = 1; - newdoc.link = 0; + /* + * Go to top of file. + */ + newdoc.line = 1; + newdoc.link = 0; #else - /* Seek old position, which probably changed */ - newdoc.line = + /* + * Seek old position, + * which probably changed. + */ + newdoc.line = ((curdoc.line > 0) ? curdoc.line : 1); - newdoc.link = + newdoc.link = ((curdoc.link > -1) ? curdoc.link : 0); #endif /* NO_SEEK_OLD_POSITION */ - clear(); /* clear the screen */ - } - } + clear(); /* clear the screen */ + } + } + } } - } - } - } else + } + } else #endif /* DIRED_SUPPORT */ - if (editor && *editor != '\0') { - if (edit_current_file(newdoc.address, curdoc.link, newline)) - { - HTuncache_current_document(); - LYforce_no_cache = TRUE; /*force the document to be reloaded*/ - FREE(curdoc.address); /* so it doesn't get pushed */ + if (editor && *editor != '\0') { + if (edit_current_file(newdoc.address, curdoc.link, Newline)) { + HTuncache_current_document(); + LYforce_no_cache = TRUE; /*force reload of document */ + FREE(curdoc.address); /* so it doesn't get pushed */ #ifdef NO_SEEK_OLD_POSITION - /* Go to top of file */ - newdoc.line = 1; - newdoc.link = 0; + /* + * Go to top of file. + */ + newdoc.line = 1; + newdoc.link = 0; #else - /* Seek old position, which probably changed */ - newdoc.line = curdoc.line; - newdoc.link = curdoc.link; + /* + * Seek old position, which probably changed. + */ + newdoc.line = curdoc.line; + newdoc.link = curdoc.link; #endif /* NO_SEEK_OLD_POSITION */ - clear(); /* clear the screen */ + clear(); /* clear the screen */ } - } else { - if (old_c != real_c) { - old_c = real_c; - _statusline(NO_EDITOR); - sleep(MessageSecs); + } else { + if (old_c != real_c) { + old_c = real_c; + _statusline(NO_EDITOR); + sleep(MessageSecs); } - } - break; + } + break; - case LYK_DEL_BOOKMARK: /* delete home page link */ + case LYK_DEL_BOOKMARK: /* remove a bookmark file link */ #ifdef DIRED_SUPPORT - case LYK_REMOVE: /* remove files and directories */ - c = 'N'; - if (lynx_edit_mode && nlinks > 0 && !no_dired_support) { + case LYK_REMOVE: /* remove files and directories */ + c = 'N'; + if (lynx_edit_mode && nlinks > 0 && !no_dired_support) { local_remove(&curdoc); c = 'Y'; - } else + } else #endif /* DIRED_SUPPORT */ - if (curdoc.bookmark != NULL) { _statusline(CONFIRM_BOOKMARK_DELETE); - c = LYgetch(); - if (TOUPPER(c) != 'Y') - break; - remove_bookmark_link(links[curdoc.link].anchor_number-1, + c = LYgetch(); + if (TOUPPER(c) != 'Y') + break; + remove_bookmark_link(links[curdoc.link].anchor_number-1, curdoc.bookmark); } else { /* behave like REFRESH for backward compatability */ refresh_screen = TRUE; - break; + break; } if (TOUPPER(c) == 'Y') { HTuncache_current_document(); @@ -2653,20 +3038,31 @@ check_recall: #ifdef DIRED_SUPPORT case LYK_INSTALL: /* install a file into system area */ - if (lynx_edit_mode && nlinks > 0 && !no_dired_support) - local_install(NULL, links[curdoc.link].lname, &newdoc.address); - break; + if (lynx_edit_mode && nlinks > 0 && !no_dired_support) + local_install(NULL, links[curdoc.link].lname, &newdoc.address); + break; #endif /* DIRED_SUPPORT */ case LYK_INFO: /* show document info */ - /* don't do if already viewing info page */ - if (strcmp((curdoc.title ? curdoc.title : ""), SHOWINFO_TITLE)) { - showinfo(&curdoc, lines_in_file, &newdoc, owner_address); + /* + * Don't do if already viewing info page. + */ + if (strcmp((curdoc.title ? curdoc.title : ""), SHOWINFO_TITLE)) { + if (!showinfo(&curdoc, lines_in_file, + &newdoc, owner_address)) + break; + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); + FREE(newdoc.bookmark); + newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; LYforce_no_cache = TRUE; if (LYValidate || check_realm) LYPermitURL = TRUE; } else { - /* if already in info page; get out */ + /* + * If already in info page, get out. + */ cmd = LYK_PREV_DOC; goto new_cmd; } @@ -2682,12 +3078,22 @@ check_recall: break; } - /* don't do if already viewing print options page */ + /* + * Don't do if already viewing print options page. + */ if (strcmp((curdoc.title ? curdoc.title : ""), PRINT_OPTIONS_TITLE)) { if (print_options(&newdoc.address, lines_in_file) < 0) break; + if (!strcmp((curdoc.title ? curdoc.title : ""), + HISTORY_PAGE_TITLE)) + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); + FREE(newdoc.bookmark); + newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; + ForcePush = TRUE; if (check_realm) LYPermitURL = TRUE; refresh_screen=TRUE; /* redisplay */ @@ -2695,19 +3101,64 @@ check_recall: break; case LYK_LIST: /* list links in the current document */ - /* don't do if already viewing list page */ - if (strcmp((curdoc.title ? curdoc.title : ""), - LIST_PAGE_TITLE)) { - if (showlist(&newdoc.address, TRUE) < 0) - break; - refresh_screen=TRUE; /* redisplay */ - if (LYValidate || check_realm) { - LYPermitURL = TRUE; - StrAllocCopy(lynxlistfile, newdoc.address); - } + /* + * Don't do if already viewing list page. + */ + if (!strcmp((curdoc.title ? curdoc.title : ""), + LIST_PAGE_TITLE)) { + /* + * Already viewing list page, so get out. + */ + cmd = LYK_PREV_DOC; + goto new_cmd; + } + + /* + * Print list page to file. + */ + if (showlist(&newdoc.address, TRUE) < 0) + break; + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); + FREE(newdoc.bookmark); + newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; + refresh_screen = TRUE; /* redisplay */ + if (LYValidate || check_realm) { + LYPermitURL = TRUE; + StrAllocCopy(lynxlistfile, newdoc.address); } break; + case LYK_VLINKS: /* list links visited during the current session */ + if (!strcmp(curdoc.title, VISITED_LINKS_TITLE)) { + /* + * Already viewing visited links page, so get out. + */ + cmd = LYK_PREV_DOC; + goto new_cmd; + } + + /* + * Print visited links page to file. + */ + if (LYShowVisitedLinks(&newdoc.address) < 0) { + _statusline(VISITED_LINKS_EMPTY); + sleep(MessageSecs); + break; + } + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); + FREE(newdoc.bookmark); + newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; + refresh_screen = TRUE; + if (LYValidate || check_realm) { + LYPermitURL = TRUE; + StrAllocCopy(lynxlinksfile, newdoc.address); + } + break; + case LYK_TOOLBAR: /* go to Toolbar or Banner in current document */ if (!HText_hasToolbar(HTMainText)) { if (old_c != real_c) { @@ -2730,19 +3181,142 @@ check_recall: } break; -#ifdef DIRED_SUPPORT +#if defined(DIRED_SUPPORT) || defined(VMS) case LYK_DIRED_MENU: /* provide full file management menu */ - /* don't do if not allowed or already viewing the menu */ +#ifdef VMS + /* + * Check if the CSwing Directory/File Manager is available. + * Will be disabled if LYCSwingPath is NULL, zero-length, + * or "none" (case insensitive), if no_file_url was set via + * the file_url restriction, if no_goto_file was set for + * the anonymous account, or if HTDirAccess was set to + * HT_DIR_FORBID or HT_DIR_SELECTIVE via the -nobrowse + * or -selective switches. - FM + */ + if (!(LYCSwingPath && *LYCSwingPath) || + !strcasecomp(LYCSwingPath, "none") || + no_file_url || no_goto_file || + HTDirAccess == HT_DIR_FORBID || + HTDirAccess == HT_DIR_SELECTIVE) { + if (old_c != real_c) { + old_c = real_c; + _statusline(DFM_NOT_AVAILABLE); + sleep(MessageSecs); + } + break; + } + + /* + * If we are viewing a local directory listing or a + * local file which is not temporary, invoke CSwing + * with the URL's directory converted to VMS path specs + * and passed as the argument, so we start up CSwing + * positioned on that node of the directory tree. + * Otherwise, pass the current default directory as + * the argument. - FM + */ + if (LYisLocalFile(curdoc.address) && + strncasecomp(curdoc.address, + lynx_temp_space, strlen(lynx_temp_space))) { + /* + * We are viewing a local directory or a local file + * which is not temporary. - FM + */ + struct stat stat_info; + + cp = HTParse(curdoc.address, "", PARSE_PATH|PARSE_PUNCTUATION); + HTUnEscape(cp); + if (HTStat(cp, &stat_info) == -1) { + if (TRACE) + fprintf(stderr, "mainloop: Can't stat %s\n", cp); + FREE(cp); + temp = (char *)calloc(1, (strlen(LYCSwingPath) + 4)); + if (temp == NULL) + outofmem(__FILE__, "mainloop"); + sprintf(temp, "%s []", LYCSwingPath); + refresh_screen = TRUE; /* redisplay */ + } else { + char *VMSdir = NULL; + + if (((stat_info.st_mode) & S_IFMT) == S_IFDIR) { + /* + * We're viewing a local directory. Make + * that the CSwing argument. - FM + */ + if (cp[(strlen(cp) - 1)] != '/') + StrAllocCat(cp, "/"); + StrAllocCopy(VMSdir, HTVMS_name("", cp)); + FREE(cp); + } else { + /* + * We're viewing a local file. Make it's + * directory the CSwing argument. - FM + */ + StrAllocCopy(VMSdir, HTVMS_name("", cp)); + FREE(cp); + if ((cp = strrchr(VMSdir, ']')) != NULL) { + *(cp + 1) = '\0'; + cp == NULL; + } else if ((cp = strrchr(VMSdir, ':')) != NULL) { + *(cp + 1) = '\0'; + cp == NULL; + } + } + temp = (char *)calloc(1, + (strlen(LYCSwingPath) + + strlen(VMSdir) + + 2)); + if (temp == NULL) + outofmem(__FILE__, "mainloop"); + sprintf(temp, "%s %s", LYCSwingPath, VMSdir); + FREE(VMSdir); + /* + * Uncache the current document in case we + * change, move, or delete it during the + * CSwing session. - FM + */ + HTuncache_current_document(); + StrAllocCopy(newdoc.address, curdoc.address); + StrAllocCopy(newdoc.title, + curdoc.title ? curdoc.title : ""); + StrAllocCopy(newdoc.bookmark, curdoc.bookmark); + FREE(curdoc.address); + newdoc.line = curdoc.line; + newdoc.link = curdoc.link; + } + } else { + /* + * We're not viewing a local directory or file. + * Pass CSwing the current default directory as + * an argument and don't uncache the current + * document. - FM + */ + temp = (char *)calloc(1, (strlen(LYCSwingPath) + 4)); + if (temp == NULL) + outofmem(__FILE__, "mainloop"); + sprintf(temp, "%s []", LYCSwingPath); + refresh_screen = TRUE; /* redisplay */ + } + stop_curses(); + system(temp); + start_curses(); + FREE(temp); + break; +#else + /* + * Don't do if not allowed or already viewing the menu. + */ if (lynx_edit_mode && !no_dired_support && strcmp((curdoc.title ? curdoc.title : ""), DIRED_MENU_TITLE)) { dired_options(&curdoc,&newdoc.address); - refresh_screen=TRUE; /* redisplay */ + refresh_screen = TRUE; /* redisplay */ } break; -#endif /* DIRED_SUPPORT */ +#endif /* VMS */ +#endif /* DIRED_SUPPORT || VMS*/ - case LYK_ADD_BOOKMARK: /* a to add link to bookmark file */ + case LYK_ADD_BOOKMARK: /* add link to bookmark file */ if (LYValidate) { if (old_c != real_c) { old_c = real_c; @@ -2769,6 +3343,8 @@ check_recall: strcmp((curdoc.title ? curdoc.title : ""), DOWNLOAD_OPTIONS_TITLE) && strcmp((curdoc.title ? curdoc.title : ""), + COOKIE_JAR_TITLE) && + strcmp((curdoc.title ? curdoc.title : ""), LIST_PAGE_TITLE)) { if (nlinks > 0) { if (curdoc.post_data == NULL && @@ -2787,7 +3363,11 @@ check_recall: } } else { if (LYMultiBookmarks == FALSE && - curdoc.bookmark != NULL) { + curdoc.bookmark != NULL && + strstr(curdoc.address, + (*bookmark_page == '.' + ? + (bookmark_page+1) : bookmark_page)) != NULL) { /* * If multiple bookmarks are disabled, offer * the L)ink or C)ancel, but with wording @@ -2813,10 +3393,14 @@ check_recall: if (links[curdoc.link].type != WWW_FORM_LINK_TYPE) { save_bookmark_link(links[curdoc.link].lname, links[curdoc.link].hightext); + refresh_screen = TRUE; /* MultiBookmark support */ } else { _statusline(NOBOOK_FORM_FIELD); sleep(MessageSecs); + break; } + } else { + break; } } else if (curdoc.post_data != NULL) { /* @@ -2824,11 +3408,24 @@ check_recall: */ _statusline(NOBOOK_POST_FORM); sleep(MessageSecs); + break; + } else if (curdoc.bookmark != NULL) { + /* + * It's a bookmark file from which all + * of the links were deleted. - FM + */ + _statusline(BOOKMARKS_NOLINKS); + sleep(MessageSecs); + break; } else { _statusline(BOOK_D_OR_CANCEL); c = LYgetch(); - if (TOUPPER(c) == 'D') + if (TOUPPER(c) == 'D') { save_bookmark_link(curdoc.address, curdoc.title); + refresh_screen = TRUE; /* MultiBookmark support */ + } else { + break; + } } check_add_bookmark_to_self: if (curdoc.bookmark && BookmarkPage && @@ -2848,7 +3445,6 @@ check_add_bookmark_to_self: sleep(MessageSecs); } } - refresh_screen = TRUE; /* MultiBookmark support */ break; case LYK_VIEW_BOOKMARK: /* v to view home page */ @@ -2868,27 +3464,27 @@ check_add_bookmark_to_self: if ((cp = get_bookmark_filename(&newdoc.address)) != NULL) { if (*cp == '\0' || !strcmp(cp, " ") || !strcmp(curdoc.address, newdoc.address)) { - refresh_screen = TRUE; /* MultiBookmark support */ + if (LYMultiBookmarks == TRUE) + refresh_screen = TRUE; break; } - LYforce_HTML_mode = TRUE; /* force HTML */ LYforce_no_cache = TRUE; /*force the document to be reloaded*/ StrAllocCopy(newdoc.title, BOOKMARK_TITLE); StrAllocCopy(newdoc.bookmark, BookmarkPage); FREE(newdoc.post_data); FREE(newdoc.post_content_type); newdoc.isHEAD = FALSE; - if (check_realm) { - StrAllocCopy(lynxbookfile, newdoc.address); - } + newdoc.safe = FALSE; } else { - if (old_c != real_c) { - old_c = real_c; - _statusline(BOOKMARKS_NOT_OPEN); - sleep(MessageSecs); + if (old_c != real_c) { + old_c = real_c; + LYMBM_statusline(BOOKMARKS_NOT_OPEN); + sleep(AlertSecs); + if (LYMultiBookmarks == TRUE) { + refresh_screen = TRUE; + } } } - refresh_screen = TRUE; /* MultiBookmark support */ break; case LYK_SHELL: /* shell escape */ @@ -2913,7 +3509,9 @@ check_add_bookmark_to_self: break; case LYK_DOWNLOAD: - /* don't do if both download and disk_save are restricted */ + /* + * Don't do if both download and disk_save are restricted. + */ if (LYValidate || (no_download && !override_no_download && no_disk_save)) { if (old_c != real_c) { @@ -2924,14 +3522,17 @@ check_add_bookmark_to_self: break; } - /* don't do if already viewing download options page */ - if (0==strcmp((curdoc.title ? curdoc.title : ""), - DOWNLOAD_OPTIONS_TITLE)) + /* + * Don't do if already viewing download options page. + */ + if (!strcmp((curdoc.title ? curdoc.title : ""), + DOWNLOAD_OPTIONS_TITLE)) break; if (nlinks > 0) { if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) { - if (links[curdoc.link].form->type == F_SUBMIT_TYPE) { + if (links[curdoc.link].form->type == F_SUBMIT_TYPE || + links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE) { if (links[curdoc.link].form->submit_method == URL_MAIL_METHOD) { if (old_c != real_c) { @@ -2952,8 +3553,16 @@ check_add_bookmark_to_self: sleep(MessageSecs); } - } else if (0==strcmp((curdoc.title ? curdoc.title : ""), - PRINT_OPTIONS_TITLE)) { + } else if (!strcmp((curdoc.title ? curdoc.title : ""), + COOKIE_JAR_TITLE)) { + if (old_c != real_c) { + old_c = real_c; + _statusline(NO_DOWNLOAD_COOKIES); + sleep(MessageSecs); + } + + } else if (!strcmp((curdoc.title ? curdoc.title : ""), + PRINT_OPTIONS_TITLE)) { if (old_c != real_c) { old_c = real_c; _statusline(NO_DOWNLOAD_PRINT_OP); @@ -2961,16 +3570,16 @@ check_add_bookmark_to_self: } #ifdef DIRED_SUPPORT - } else if (0==strcmp((curdoc.title ? curdoc.title : ""), - UPLOAD_OPTIONS_TITLE)) { + } else if (!strcmp((curdoc.title ? curdoc.title : ""), + UPLOAD_OPTIONS_TITLE)) { if (old_c != real_c) { old_c = real_c; _statusline(NO_DOWNLOAD_UPLOAD_OP); sleep(MessageSecs); } - } else if (0==strcmp((curdoc.title ? curdoc.title : ""), - PERMIT_OPTIONS_TITLE)) { + } else if (!strcmp((curdoc.title ? curdoc.title : ""), + PERMIT_OPTIONS_TITLE)) { if (old_c != real_c) { old_c = real_c; _statusline(NO_DOWNLOAD_PERMIT_OP); @@ -2978,7 +3587,9 @@ check_add_bookmark_to_self: } } else if (lynx_edit_mode && !no_dired_support) { - /* Don't bother making a /tmp copy of the local file */ + /* + * Don't bother making a /tmp copy of the local file. + */ StrAllocCopy(temp, newdoc.address); StrAllocCopy(newdoc.address, links[curdoc.link].lname); if (LYdownload_options(&newdoc.address, @@ -2987,12 +3598,19 @@ check_add_bookmark_to_self: FREE(temp); #endif /* DIRED_SUPPORT */ - } else if (0==strcmp((curdoc.title ? curdoc.title : ""), - HISTORY_PAGE_TITLE)) { + } else if (!strcmp((curdoc.title ? curdoc.title : ""), + HISTORY_PAGE_TITLE)) { int number = atoi(links[curdoc.link].lname+9); + if ((history[number].post_data != NULL && + history[number].safe != TRUE) && + HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + _statusline(CANCELLED); + sleep(InfoSecs); + break; + } StrAllocCopy(newdoc.address, history[number].address); StrAllocCopy(newdoc.title, links[curdoc.link].hightext); - StrAllocCopy(newdoc.address, history[number].bookmark); + StrAllocCopy(newdoc.bookmark, history[number].bookmark); FREE(newdoc.post_data); FREE(newdoc.post_content_type); if (history[number].post_data) @@ -3002,12 +3620,14 @@ check_add_bookmark_to_self: StrAllocCopy(newdoc.post_content_type, history[number].post_content_type); newdoc.isHEAD = history[number].isHEAD; + newdoc.safe = history[number].safe; newdoc.link = 0; HTOutputFormat = HTAtom_for("www/download"); LYUserSpecifiedURL = TRUE; - /*force the document to be reloaded*/ + /* + * Force the document to be reloaded. + */ LYforce_no_cache = TRUE; - force_load = TRUE; /* force MainLoop to reload */ } else if (!strncasecomp(links[curdoc.link].lname, "data:", 5)) { @@ -3018,27 +3638,29 @@ check_add_bookmark_to_self: } else { /* Not a forms, options or history link */ /* - * Follow a normal link or anchor. Note that - * if it's an anchor within the same document, - * entire document will be downloaded + * Follow a normal link or anchor. Note that + * if it's an anchor within the same document, + * entire document will be downloaded. */ StrAllocCopy(newdoc.address, links[curdoc.link].lname); StrAllocCopy(newdoc.title, links[curdoc.link].hightext); /* - * Might be an anchor in the same doc from a POST - * form. If so, don't free the content. -- FM + * Might be an anchor in the same doc from a POST + * form. If so, don't free the content. -- FM */ if (are_different(&curdoc, &newdoc)) { FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; } newdoc.link = 0; HTOutputFormat = HTAtom_for("www/download"); - /*force the document to be reloaded*/ + /* + * Force the document to be reloaded. + */ LYforce_no_cache = TRUE; - force_load = TRUE; /* force MainLoop to reload */ } } else if (old_c != real_c) { old_c = real_c; @@ -3049,14 +3671,22 @@ check_add_bookmark_to_self: #ifdef DIRED_SUPPORT case LYK_UPLOAD: - /* don't do if already viewing upload options page */ - if (0==strcmp((curdoc.title ? curdoc.title : ""), - UPLOAD_OPTIONS_TITLE)) + /* + * Don't do if already viewing upload options page. + */ + if (!strcmp((curdoc.title ? curdoc.title : ""), + UPLOAD_OPTIONS_TITLE)) break; if (lynx_edit_mode && !no_dired_support) { LYUpload_options((char **)&newdoc.address, (char *)curdoc.address); + FREE(curdoc.address); + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); + FREE(newdoc.bookmark); + newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; } break; #endif /* DIRED_SUPPORT */ @@ -3113,7 +3743,8 @@ check_add_bookmark_to_self: case LYK_HEAD: if (nlinks > 0 && (links[curdoc.link].type != WWW_FORM_LINK_TYPE || - links[curdoc.link].form->type == F_SUBMIT_TYPE)) { + links[curdoc.link].form->type == F_SUBMIT_TYPE || + links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE)) { _statusline(HEAD_D_L_OR_CANCEL); c = LYgetch(); if (TOUPPER(c) == 'D') { @@ -3121,6 +3752,18 @@ check_add_bookmark_to_self: _statusline(DOC_NOT_HTTP_URL); sleep(MessageSecs); } else { + /* + * Check if this is a reply from a POST, + * and if so, seek confirmation if the + * safe element is not set. - FM + */ + if ((curdoc.post_data != NULL && + curdoc.safe != TRUE) && + HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + _statusline(CANCELLED); + sleep(InfoSecs); + break; + } HEAD_request = TRUE; LYforce_no_cache = TRUE; if (HTLoadedDocumentIsHEAD()) { @@ -3153,6 +3796,17 @@ check_add_bookmark_to_self: } break; } else { + /* + * Check if this is a reply from a POST, and if so, + * seek confirmation if the safe element is not set. - FM + */ + if ((curdoc.post_data != NULL && + curdoc.safe != TRUE) && + HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + _statusline(CANCELLED); + sleep(InfoSecs); + break; + } if (nlinks > 0) { _statusline(HEAD_D_OR_CANCEL); c = LYgetch(); @@ -3175,10 +3829,6 @@ check_add_bookmark_to_self: } break; - case LYK_DO_NOTHING: - /* pretty self explanitory */ - break; - case LYK_TOGGLE_HELP: if (user_mode==NOVICE_MODE) { toggle_novice_line(); @@ -3194,9 +3844,10 @@ check_add_bookmark_to_self: FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; /* - * If vi_keys changed, the keymap did too, - * so force no cache, and reset the flag. - FM + * If vi_keys changed, the keymap did too, + * so force no cache, and reset the flag. - FM */ if (vi_keys_flag != vi_keys || emacs_keys_flag != emacs_keys) { @@ -3205,9 +3856,10 @@ check_add_bookmark_to_self: emacs_keys_flag = emacs_keys; } #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) - /* Remember whether we are in dired menu - * so we can display the right keymap. - * Don't cache the keymap because it changes. - EF + /* + * Remember whether we are in dired menu + * so we can display the right keymap. + * Don't cache the keymap because it changes. - EF */ if (!no_dired_support) { prev_lynx_edit_mode = lynx_edit_mode; @@ -3264,6 +3916,7 @@ check_add_bookmark_to_self: FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; + newdoc.safe = FALSE; FREE(ret); LYUserSpecifiedURL = TRUE; } else { @@ -3286,16 +3939,21 @@ check_add_bookmark_to_self: break; #endif /* NOT_USED */ + case LYK_DO_NOTHING: /* pretty self explanatory */ + break; + } /* end of BIG switch */ } } -PRIVATE int are_different ARGS2(document *,doc1, document *,doc2) +PRIVATE int are_different ARGS2( + document *, doc1, + document *, doc2) { char *cp1, *cp2; /* - * Do we have two addresses? + * Do we have two addresses? */ if (!doc1->address || !doc2->address) return (TRUE); @@ -3307,16 +3965,16 @@ PRIVATE int are_different ARGS2(document *,doc1, document *,doc2) return (TRUE); /* - * See if the addresses are different, making sure - * we're not tripped up by multiple anchors in the - * the same document from a POST form. -- FM + * See if the addresses are different, making sure + * we're not tripped up by multiple anchors in the + * the same document from a POST form. -- FM */ if ((cp1 = strchr(doc1->address, '#')) != NULL) *cp1 = '\0'; if ((cp2 = strchr(doc2->address, '#')) != NULL) *cp2 = '\0'; /* - * Are the base addresses different? + * Are the base addresses different? */ if (strcmp(doc1->address, doc2->address)) { @@ -3332,7 +3990,7 @@ PRIVATE int are_different ARGS2(document *,doc1, document *,doc2) *cp2 = '#'; /* - * Do the docs have different contents? + * Do the docs have different contents? */ if (doc1->post_data) { @@ -3349,13 +4007,13 @@ PRIVATE int are_different ARGS2(document *,doc1, document *,doc2) return(TRUE); /* - * We'll assume the two documents in fact are the same. + * We'll assume the two documents in fact are the same. */ return(FALSE); } /* - * Utility for freeing the list of goto URLs. - FM + * Utility for freeing the list of goto URLs. - FM */ PUBLIC void HTGotoURLs_free NOARGS { @@ -3374,10 +4032,11 @@ PUBLIC void HTGotoURLs_free NOARGS } /* - * Utility for listing Goto URLs, making any - * repeated URLs the most current in the list. - FM + * Utility for listing Goto URLs, making any + * repeated URLs the most current in the list. - FM */ -PUBLIC void HTAddGotoURL ARGS1(char *, url) +PUBLIC void HTAddGotoURL ARGS1( + char *, url) { char *new; char *old; diff --git a/src/LYMap.c b/src/LYMap.c index 9720586b..3126611c 100644 --- a/src/LYMap.c +++ b/src/LYMap.c @@ -214,6 +214,7 @@ PRIVATE int LYLoadIMGmap ARGS4 ( WWWDoc.post_content_type = NULL; WWWDoc.bookmark = NULL; WWWDoc.isHEAD = FALSE; + WWWDoc.safe = FALSE; LYforce_no_cache = TRUE; reloading = TRUE; HTOutputFormat = WWW_PRESENT; @@ -249,6 +250,7 @@ PRIVATE int LYLoadIMGmap ARGS4 ( WWWDoc.post_content_type = NULL; WWWDoc.bookmark = NULL; WWWDoc.isHEAD = FALSE; + WWWDoc.safe = FALSE; LYforce_no_cache = TRUE; reloading = TRUE; HTOutputFormat = WWW_PRESENT; diff --git a/src/LYNews.c b/src/LYNews.c index 2bdab054..eb1da221 100644 --- a/src/LYNews.c +++ b/src/LYNews.c @@ -51,6 +51,7 @@ PUBLIC int LYNewsPost ARGS2(document *,newdoc, BOOLEAN,followup) WWWDoc.post_content_type = newdoc->post_content_type; WWWDoc.bookmark = newdoc->bookmark; WWWDoc.isHEAD = newdoc->isHEAD; + WWWDoc.safe = newdoc->safe; if(!HTLoadAbsolute(&WWWDoc)) { FREE(newsgroups); return(NOT_FOUND); diff --git a/src/LYOptions.c b/src/LYOptions.c index 345c7d0e..a795fcfb 100644 --- a/src/LYOptions.c +++ b/src/LYOptions.c @@ -35,31 +35,27 @@ PRIVATE int boolean_choice PARAMS((int status, int line, #define MAXCHOICES 10 -PRIVATE void option_statusline ARGS1(char *,text) +PRIVATE void option_statusline ARGS1( + char *, text) { - char buffer[256]; - - if (!text || text == NULL) + /* + * Make sure we have a pointer to a string. + */ + if (text == NULL) return; - /* don't print statusline messages if dumping to stdout - */ + /* + * Don't print statusline messages if dumping to stdout. + */ if (dump_output_immediately) return; - /* make sure text is not longer than COLS */ - LYstrncpy(buffer, text, LYcols-1); - - move(LYlines-1, 0); - - clrtoeol(); - if (text != NULL && *buffer) { - start_reverse(); - addstr(buffer); - stop_reverse(); - } - - refresh(); + /* + * Use _statusline() set to output on the bottom line. - FM + */ + LYStatusLine = (LYlines - 1); + _statusline(text); + LYStatusLine = -1; } PUBLIC void options NOARGS @@ -108,119 +104,129 @@ PUBLIC void options NOARGS signal(SIGINT, terminate_options); draw_options: + /* + * NOTE that printw() should be avoided for strings that + * might have non-ASCII or multibyte/CJK characters. - FM + */ response = 0; clear(); move(0, 5); if (bold_H1 || bold_headers) start_bold(); - printw(" Options Menu (%s Version %s)", - LYNX_NAME, LYNX_VERSION); + addstr(" Options Menu ("); + addstr(LYNX_NAME); + addstr(" Version "); + addstr(LYNX_VERSION); + addch(')'); if (bold_H1 || bold_headers) stop_bold(); move(L_EDITOR, 5); - printw("E)ditor : %s", - ((editor && *editor) ? editor : "NONE")); - - move(L_DISPLAY, 5); - printw("D)ISPLAY variable : %s", - ((display && *display) ? display : "NONE")); + addstr("E)ditor : "); + addstr((editor && *editor) ? editor : "NONE"); - move(L_MAIL_ADDRESS, 5); - printw("P)ersonal mail address : %s", - ((personal_mail_address && *personal_mail_address) ? - personal_mail_address : "NONE")); + move(L_DISPLAY, 5); + addstr("D)ISPLAY variable : "); + addstr((display && *display) ? display : "NONE"); move(L_HOME, 5); - printw("mu(L)ti-bookmarks: %s", - (LYMultiBookmarks ? (LYMBMAdvanced ? - "ADVANCED" : "STANDARD") : "OFF")); + addstr("mu(L)ti-bookmarks: "); + addstr((LYMultiBookmarks ? + (LYMBMAdvanced ? "ADVANCED" + : "STANDARD") + : "OFF")); move(L_HOME, B_BOOK); if (LYMultiBookmarks) { - printw("review/edit B)ookmarks files"); + addstr("review/edit B)ookmarks files"); } else { - printw("B)ookmark file: %s", - ((bookmark_page && *bookmark_page) ? bookmark_page : "NONE")); + addstr("B)ookmark file: "); + addstr((bookmark_page && *bookmark_page) ? bookmark_page : "NONE"); } move(L_FTPSTYPE, 5); - printw("F)TP sort criteria : %s",(HTfileSortMethod==FILE_BY_NAME ? - "By Filename" : - (HTfileSortMethod==FILE_BY_SIZE ? - "By Size" : - (HTfileSortMethod==FILE_BY_TYPE ? - "By Type" : "By Date")))); + addstr("F)TP sort criteria : "); + addstr((HTfileSortMethod==FILE_BY_NAME ? "By Filename" : + (HTfileSortMethod==FILE_BY_SIZE ? "By Size" : + (HTfileSortMethod==FILE_BY_TYPE ? "By Type" : + "By Date")))); + + move(L_MAIL_ADDRESS, 5); + addstr("P)ersonal mail address : "); + addstr((personal_mail_address && *personal_mail_address) ? + personal_mail_address : "NONE"); + move(L_SSEARCH, 5); - printw("S)earching type : %s",(case_sensitive ? - "CASE SENSITIVE" : "CASE INSENSITIVE")); + addstr("S)earching type : "); + addstr(case_sensitive ? "CASE SENSITIVE" : "CASE INSENSITIVE"); move(L_CHARSET, 5); - printw("display (C)haracter set : %s", - LYchar_set_names[current_char_set]); + addstr("display (C)haracter set : "); + addstr(LYchar_set_names[current_char_set]); move(L_RAWMODE, 5); - printw("Raw 8-bit or CJK m(O)de : %s", (LYRawMode ? "ON" : "OFF")); + addstr("Raw 8-bit or CJK m(O)de : "); + addstr(LYRawMode ? "ON" : "OFF"); move(L_LANGUAGE, 5); - printw("preferred document lan(G)uage: %s", - ((language && *language) ? language : "NONE")); + addstr("preferred document lan(G)uage: "); + addstr((language && *language) ? language : "NONE"); move(L_PREF_CHARSET, 5); - printw("preferred document c(H)arset : %s", - ((pref_charset && *pref_charset) ? pref_charset : "NONE")); + addstr("preferred document c(H)arset : "); + addstr((pref_charset && *pref_charset) ? pref_charset : "NONE"); move(L_BOOL_A, B_VIKEYS); - printw("V)I keys: %s", (vi_keys ? "ON" : "OFF")); + addstr("V)I keys: "); + addstr(vi_keys ? "ON" : "OFF"); move(L_BOOL_A, B_EMACSKEYS); - printw("e(M)acs keys: %s", (emacs_keys ? "ON" : "OFF")); + addstr("e(M)acs keys: "); + addstr(emacs_keys ? "ON" : "OFF"); move(L_BOOL_A, B_SHOW_DOTFILES); - printw("sho(W) dot files: %s", - ((!no_dotfiles && show_dotfiles) ? "ON" : "OFF")); + addstr("sho(W) dot files: "); + addstr((!no_dotfiles && show_dotfiles) ? "ON" : "OFF"); move(L_SELECT_POPUPS, 5); - printw("popups for selec(T) fields : %s", - (LYSelectPopups ? "ON" : "OFF")); + addstr("popups for selec(T) fields : "); + addstr(LYSelectPopups ? "ON" : "OFF"); move(L_KEYPAD, 5); - printw("K)eypad mode : %s", - (keypad_mode == NUMBERS_AS_ARROWS ? - "Numbers act as arrows" : - "Links are numbered")); + addstr("K)eypad mode : "); + addstr((keypad_mode == NUMBERS_AS_ARROWS) ? "Numbers act as arrows" : + "Links are numbered"); move(L_LINEED, 5); - printw("li(N)e edit style : %s", - LYLineeditNames[current_lineedit]); + addstr("li(N)e edit style : "); + addstr(LYLineeditNames[current_lineedit]); #ifdef DIRED_SUPPORT move(L_DIRED, 5); - printw("l(I)st directory style : %s", - (dir_list_style == FILES_FIRST ? "Files first " : - (dir_list_style == MIXED_STYLE ? "Mixed style " : - "Directories first "))); + addstr("l(I)st directory style : "); + addstr((dir_list_style == FILES_FIRST) ? "Files first " : + ((dir_list_style == MIXED_STYLE) ? "Mixed style " : + "Directories first ")); #endif /* DIRED_SUPPORT */ move(L_USER_MODE, 5); - printw("U)ser mode : %s", - (user_mode == NOVICE_MODE ? "Novice" : - (user_mode == INTERMEDIATE_MODE ? "Intermediate" : - "Advanced"))); + addstr("U)ser mode : "); + addstr( (user_mode == NOVICE_MODE) ? "Novice" : + ((user_mode == INTERMEDIATE_MODE) ? "Intermediate" : + "Advanced")); move(L_USER_AGENT, 5); - printw("user (A)gent : %s", - ((LYUserAgent && *LYUserAgent) ? LYUserAgent : "NONE")); - + addstr("user (A)gent : "); + addstr((LYUserAgent && *LYUserAgent) ? LYUserAgent : "NONE"); #ifdef ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS move(L_EXEC, 5); - printw("local e(X)ecution links : "); + addstr("local e(X)ecution links : "); #ifndef NEVER_ALLOW_REMOTE_EXEC - addstr((local_exec ? "ALWAYS ON" : - (local_exec_on_local_files ? "FOR LOCAL FILES ONLY" : - "ALWAYS OFF"))); + addstr( local_exec ? "ALWAYS ON" : + (local_exec_on_local_files ? "FOR LOCAL FILES ONLY" : + "ALWAYS OFF")); #else addstr(local_exec_on_local_files ? "FOR LOCAL FILES ONLY" : - "ALWAYS OFF"); + "ALWAYS OFF"); #endif /* NEVER_ALLOW_REMOTE_EXEC */ #endif /* ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */ @@ -422,10 +428,11 @@ draw_options: move(L_HOME, B_BOOK); clrtoeol(); if (LYMultiBookmarks) { - printw("review/edit B)ookmarks files"); + addstr("review/edit B)ookmarks files"); } else { - printw("B)ookmark file: %s", - ((bookmark_page && *bookmark_page) ? bookmark_page : "NONE")); + addstr("B)ookmark file: "); + addstr((bookmark_page && *bookmark_page) ? + bookmark_page : "NONE"); } response = ' '; break; @@ -459,11 +466,19 @@ draw_options: ch == -1 || *display_option == '\0') { addstr((bookmark_page && *bookmark_page) ? bookmark_page : "NONE"); + } else if (!LYPathOffHomeOK(display_option, + sizeof(display_option))) { + addstr((bookmark_page && *bookmark_page) ? + bookmark_page : "NONE"); + clrtoeol(); + option_statusline(USE_PATH_OFF_HOME); + response = ' '; + break; } else { StrAllocCopy(bookmark_page, display_option); StrAllocCopy(MBM_A_subbookmark[0], bookmark_page); - addstr(display_option); + addstr(bookmark_page); } clrtoeol(); option_statusline(VALUE_ACCEPTED); @@ -930,10 +945,10 @@ draw_options: signal(SIGINT, cleanup_sig); } -/* take a boolean status and prompt the user for a new status - * and return it +/* + * Take a boolean status,prompt the user for a new status, + * and return it. */ - PRIVATE int boolean_choice ARGS4( int, status, int, line, @@ -987,7 +1002,8 @@ PRIVATE int boolean_choice ARGS4( } } -PRIVATE void terminate_options ARGS1(int,sig) +PRIVATE void terminate_options ARGS1( + int, sig) { term_options=TRUE; /* Reassert the AST */ @@ -1011,6 +1027,7 @@ PUBLIC void edit_bookmarks NOARGS #define MULTI_OFFSET 8 int a; /* misc counter */ char MBM_tmp_line[256]; /* buffer for LYgetstr */ + char ehead_buffer[265]; /* * We need (MBM_V_MAXFILES + MULTI_OFFSET) lines to display @@ -1022,15 +1039,21 @@ PUBLIC void edit_bookmarks NOARGS signal(SIGINT, terminate_options); draw_bookmark_list: + /* + * Display menu of bookmarks. NOTE that we avoid printw()'s + * to increase the chances that any non-ASCII or multibyte/CJK + * characters will be handled properly. - FM + */ clear(); move(0, 5); if (bold_H1 || bold_headers) start_bold(); - if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET)) - printw("Editing Bookmark DESCRIPTION and FILEPATH (%d of 2)", - MBM_current); - else - printw(" Editing Bookmark DESCRIPTION and FILEPATH"); + if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET)) { + sprintf(ehead_buffer, MULTIBOOKMARKS_EHEAD_MASK, MBM_current); + addstr(ehead_buffer); + } else { + addstr(MULTIBOOKMARKS_EHEAD); + } if (bold_H1 || bold_headers) stop_bold(); @@ -1038,20 +1061,28 @@ draw_bookmark_list: for (a = ((MBM_V_MAXFILES/2 + 1) * (MBM_current - 1)); a <= ((float)MBM_V_MAXFILES/2 * MBM_current); a++) { move((3 + a) - ((MBM_V_MAXFILES/2 + 1)*(MBM_current - 1)), 5); - printw("%c : %s", (a + 'A'), - (!MBM_A_subdescript[a] ? "" : MBM_A_subdescript[a])); + addch((unsigned char)(a + 'A')); + addstr(" : "); + if (MBM_A_subdescript[a]) + addstr(MBM_A_subdescript[a]); move((3 + a) - ((MBM_V_MAXFILES/2 + 1)*(MBM_current - 1)), 35); - printw("| %s", - (!MBM_A_subbookmark[a] ? "" : MBM_A_subbookmark[a])); + addstr("| "); + if (MBM_A_subbookmark[a]) { + addstr(MBM_A_subbookmark[a]); + } } } else { for (a = 0; a <= MBM_V_MAXFILES; a++) { move(3 + a, 5); - printw("%c : %s", (a + 'A'), - (!MBM_A_subdescript[a] ? "" : MBM_A_subdescript[a])); + addch((unsigned char)(a + 'A')); + addstr(" : "); + if (MBM_A_subdescript[a]) + addstr(MBM_A_subdescript[a]); move(3 + a, 35); - printw("| %s", - (!MBM_A_subbookmark[a] ? "" : MBM_A_subbookmark[a])); + addstr("| "); + if (MBM_A_subbookmark[a]) { + addstr(MBM_A_subbookmark[a]); + } } } @@ -1059,10 +1090,19 @@ draw_bookmark_list: * Only needed when we have 2 screens. */ if (LYlines < MBM_V_MAXFILES + MULTI_OFFSET) { - move((LYlines - 4), 0); - start_reverse(); - addstr(MULTIBOOKMARKS_MOVE); - stop_reverse(); + move((LYlines - 4), 0); + addstr("'"); + standout(); + addstr("["); + standend(); + addstr("' "); + addstr(PREVIOUS); + addstr(", '"); + standout(); + addstr("]"); + standend(); + addstr("' "); + addstr(NEXT_SCREEN); } move((LYlines - 3), 0); @@ -1089,7 +1129,7 @@ draw_bookmark_list: move((LYlines - 2), 0); start_reverse(); - addstr("Letter: "); + addstr(MULTIBOOKMARKS_LETTER); stop_reverse(); refresh(); @@ -1200,9 +1240,10 @@ draw_bookmark_list: 5); else move((3 + a), 5); - printw("%c : %s", (a + 'A'), - (!MBM_A_subdescript[a] ? - "" : MBM_A_subdescript[a])); + addch((unsigned char)(a + 'A')); + addstr(" : "); + if (MBM_A_subdescript[a]) + addstr(MBM_A_subdescript[a]); clrtoeol(); refresh(); } @@ -1212,7 +1253,7 @@ draw_bookmark_list: 35); else move((3 + a), 35); - printw("| "); + addstr("| "); standout(); strcpy(MBM_tmp_line, @@ -1226,6 +1267,10 @@ draw_bookmark_list: StrAllocCopy(MBM_A_subbookmark[a], bookmark_page); else FREE(MBM_A_subbookmark[a]); + } else if (!LYPathOffHomeOK(MBM_tmp_line, + sizeof(MBM_tmp_line))) { + LYMBM_statusline(USE_PATH_OFF_HOME); + sleep(AlertSecs); } else { StrAllocCopy(MBM_A_subbookmark[a], MBM_tmp_line); if (a == 0) { @@ -1237,8 +1282,9 @@ draw_bookmark_list: 35); else move((3 + a), 35); - printw("| %s", (!MBM_A_subbookmark[a] ? - "" : MBM_A_subbookmark[a])); + addstr("| "); + if (MBM_A_subbookmark[a]) + addstr(MBM_A_subbookmark[a]); clrtoeol(); move(LYlines-1, 0); clrtoeol(); diff --git a/src/LYOptions.h b/src/LYOptions.h index f89159aa..e7464226 100644 --- a/src/LYOptions.h +++ b/src/LYOptions.h @@ -3,6 +3,7 @@ #define LYOPTIONS_H extern void options NOPARAMS; +extern void edit_bookmarks NOPARAMS; /* values for options */ #define L_EDITOR 2 diff --git a/src/LYPrint.c b/src/LYPrint.c index 8e14c938..3b3a5fe4 100644 --- a/src/LYPrint.c +++ b/src/LYPrint.c @@ -67,6 +67,7 @@ PUBLIC int printfile ARGS1(document *,newdoc) int FnameTotal; int FnameNum; BOOLEAN FirstRecall = TRUE; + char *content_base = NULL, *content_location = NULL; #ifdef VMS extern BOOLEAN HadVMSInterrupt; #endif /* VMS */ @@ -85,10 +86,42 @@ PUBLIC int printfile ARGS1(document *,newdoc) WWWDoc.post_content_type = newdoc->post_content_type; WWWDoc.bookmark = newdoc->bookmark; WWWDoc.isHEAD = newdoc->isHEAD; - if(!HTLoadAbsolute(&WWWDoc)) + WWWDoc.safe = newdoc->safe; + if (!HTLoadAbsolute(&WWWDoc)) return(NOT_FOUND); /* + * If document is source, load the content_base + * and content_location strings. - FM + */ + if (HTisDocumentSource()) { + if (HText_getContentBase()) { + StrAllocCopy(content_base, HText_getContentBase()); + collapse_spaces(content_base); + if (!(content_base && *content_base)) { + FREE(content_base); + } + } + if (HText_getContentLocation()) { + StrAllocCopy(content_location, HText_getContentLocation()); + collapse_spaces(content_location); + if (!(content_location && *content_location)) { + FREE(content_location); + } + } + if (!content_base) { + if ((content_location) && is_url(content_location)) { + StrAllocCopy(content_base, content_location); + } else { + StrAllocCopy(content_base, newdoc->address); + } + } + if (!content_location) { + StrAllocCopy(content_location, newdoc->address); + } + } + + /* * Load the suggested filename string. - FM */ if (HText_getSugFname() != NULL) @@ -113,7 +146,6 @@ PUBLIC int printfile ARGS1(document *,newdoc) pages = lines_in_file/66; } - /* * Determine the type. */ @@ -141,7 +173,6 @@ PUBLIC int printfile ARGS1(document *,newdoc) } } - /* * Set up the sug_filenames recall buffer. */ @@ -149,7 +180,9 @@ PUBLIC int printfile ARGS1(document *,newdoc) recall = ((FnameTotal >= 1) ? RECALL : NORECALL); FnameNum = FnameTotal; - + /* + * Act on the request. - FM + */ switch (type) { case TO_FILE: _statusline(FILENAME_PROMPT); @@ -343,15 +376,16 @@ PUBLIC int printfile ARGS1(document *,newdoc) if (HTisDocumentSource()) { /* - * Added the document's URL as a BASE tag + * Added the document's base as a BASE tag * to the top of the file. May create * technically invalid HTML, but will help * get any partial or relative URLs resolved * properly if no BASE tag is present to * replace it. - FM */ - fprintf(outfile_fp, "<BASE HREF=\"%s\">\n", - newdoc->address); + fprintf(outfile_fp, + "<!-- X-URL: %s -->\n<BASE HREF=\"%s\">\n", + newdoc->address, content_base); } print_wwwfile_to_fd(outfile_fp,0); if (keypad_mode) @@ -419,18 +453,21 @@ PUBLIC int printfile ARGS1(document *,newdoc) break; } - /* write the contents to a temp file */ + /* + * Write the contents to a temp file. + */ if (HTisDocumentSource()) { /* - * Added the document's URL as a BASE tag to + * Added the document's base as a BASE tag to * the top of the message body. May create * technically invalid HTML, but will help * get any partial or relative URLs resolved * properly if no BASE tag is present to * replace it. - FM */ - fprintf(outfile_fp, "<BASE HREF=\"%s\">\n\n", - newdoc->address); + fprintf(outfile_fp, + "<!-- X-URL: %s -->\n<BASE HREF=\"%s\">\n\n", + newdoc->address, content_base); } else { fprintf(outfile_fp, "X-URL: %s\n\n", newdoc->address); } @@ -445,7 +482,9 @@ PUBLIC int printfile ARGS1(document *,newdoc) stop_curses(); printf(MAILING_FILE); + fflush(stdout); system(buffer); + fflush(stdout); sleep(MessageSecs); start_curses(); #else /* Unix: */ @@ -475,30 +514,26 @@ PUBLIC int printfile ARGS1(document *,newdoc) } else { fprintf(outfile_fp, "\n"); } - fprintf(outfile_fp, "Content-Location: %s\n", - newdoc->address); fprintf(outfile_fp, "Content-Base: %s\n", - newdoc->address); - } else { - /* - * Add an X-URL header for rendered HTML or - * plain text. - FM - */ - fprintf(outfile_fp, "X-URL: %s\n", newdoc->address); + content_base); + fprintf(outfile_fp, "Content-Location: %s\n", + content_location); } + fprintf(outfile_fp, "X-URL: %s\n", newdoc->address); fprintf(outfile_fp, "To: %s\nSubject:%s\n\n", user_response, sug_filename); if (HTisDocumentSource()) { /* - * Added the document's URL as a BASE tag to + * Added the document's base as a BASE tag to * the top of the message body. May create * technically invalid HTML, but will help * get any partial or relative URLs resolved * properly if no BASE tag is present to * replace it. - FM */ - fprintf(outfile_fp, "<BASE HREF=\"%s\">\n\n", - newdoc->address); + fprintf(outfile_fp, + "<!-- X-URL: %s -->\n<BASE HREF=\"%s\">\n\n", + newdoc->address, content_base); } print_wwwfile_to_fd(outfile_fp, 0); if (keypad_mode) @@ -553,15 +588,16 @@ PUBLIC int printfile ARGS1(document *,newdoc) if (HTisDocumentSource()) { /* - * Added the document's URL as a BASE tag + * Added the document's base as a BASE tag * to the top of the file. May create * technically invalid HTML, but will help * get any partial or relative URLs resolved * properly if no BASE tag is present to * replace it. - FM */ - fprintf(outfile_fp, "<BASE HREF=\"%s\">\n\n", - newdoc->address); + fprintf(outfile_fp, + "<!-- X-URL: %s -->\n<BASE HREF=\"%s\">\n\n", + newdoc->address, content_base); } print_wwwfile_to_fd(outfile_fp, 0); if (keypad_mode) @@ -639,15 +675,16 @@ PUBLIC int printfile ARGS1(document *,newdoc) if (HTisDocumentSource()) { /* - * Added the document's URL as a BASE tag + * Added the document's base as a BASE tag * to the top of the file. May create * technically invalid HTML, but will help * get any partial or relative URLs resolved * properly if no BASE tag is present to * replace it. - FM */ - fprintf(outfile_fp, "<BASE HREF=\"%s\">\n\n", - newdoc->address); + fprintf(outfile_fp, + "<!-- X-URL: %s -->\n<BASE HREF=\"%s\">\n\n", + newdoc->address, content_base); } print_wwwfile_to_fd(outfile_fp, 0); if (keypad_mode) @@ -816,6 +853,7 @@ PUBLIC int printfile ARGS1(document *,newdoc) if (TRACE) fprintf(stderr, "command: %s\n", buffer); printf(PRINTING_FILE); + fflush(stdout); system(buffer); fflush(stdout); #ifndef VMS @@ -828,6 +866,8 @@ PUBLIC int printfile ARGS1(document *,newdoc) FREE(link_info); FREE(sug_filename); + FREE(content_base); + FREE(content_location); return(NORMAL); } diff --git a/src/LYReadCFG.c b/src/LYReadCFG.c index 686eb13e..c0ede5b9 100644 --- a/src/LYReadCFG.c +++ b/src/LYReadCFG.c @@ -41,7 +41,7 @@ PUBLIC BOOLEAN LYUseNoviceLineTwo=TRUE; PRIVATE int is_true ARGS1( char *, string) { - if(!strncasecomp(string,"TRUE",4)) + if (!strncasecomp(string,"TRUE",4)) return(TRUE); else return(FALSE); @@ -153,7 +153,7 @@ PRIVATE void add_item_to_list ARGS2( * Process name field */ cur_item->name = (char *)calloc((colon-buffer+1),sizeof(char)); - if(cur_item->name == NULL) + if (cur_item->name == NULL) perror("Out of memory in read_cfg"); LYstrncpy(cur_item->name, buffer, (int)(colon-buffer)); remove_backslashes(cur_item->name); @@ -242,8 +242,8 @@ PRIVATE void add_printer_to_list ARGS2( /* * Process name field. */ - cur_item->name = (char *)calloc((colon-buffer+1),sizeof(char)); - if(cur_item->name == NULL) + cur_item->name = (char *)calloc((colon-buffer+1), sizeof(char)); + if (cur_item->name == NULL) perror("Out of memory in read_cfg"); LYstrncpy(cur_item->name, buffer, (int)(colon-buffer)); remove_backslashes(cur_item->name); @@ -385,12 +385,12 @@ PUBLIC void read_cfg ARGS1( * Locate and open the file. */ if (!cfg_filename || strlen(cfg_filename) == 0) { - if(TRACE) + if (TRACE) fprintf(stderr,"No filename following -cfg switch!\n"); return; } - if((fp = fopen(cfg_filename,"r")) == NULL) { - if(TRACE) + if ((fp = fopen(cfg_filename,"r")) == NULL) { + if (TRACE) fprintf(stderr,"lynx.cfg file not found as %s\n",cfg_filename); return; } @@ -403,7 +403,7 @@ PUBLIC void read_cfg ARGS1( /* * Strip off \n at the end. */ - if((line_feed = (char *)strchr(buffer,'\n')) != NULL) + if ((line_feed = (char *)strchr(buffer, '\n')) != NULL) *line_feed = '\0'; /* @@ -424,285 +424,210 @@ PUBLIC void read_cfg ARGS1( /* * Process the string buffer. */ - if (!strncasecomp(buffer,"SUFFIX:",7)) { - char *extention; - char *mime_type; - - if (strlen(buffer) > 9) { - extention = buffer + 7; - if ((mime_type = strchr(extention, ':')) != NULL) { - *mime_type++ = '\0'; - for (i = 0, j = 0; mime_type[i]; i++) { - if (mime_type[i] != ' ') { - mime_type[j++] = TOLOWER(mime_type[i]); - } - } - mime_type[j] = '\0'; - if (strstr(mime_type, "tex") != NULL || - strstr(mime_type, "postscript") != NULL || - strstr(mime_type, "sh") != NULL || - strstr(mime_type, "troff") != NULL || - strstr(mime_type, "rtf") != NULL) - HTSetSuffix(extention, mime_type, "8bit", 1.0); - else - HTSetSuffix(extention, mime_type, "binary", 1.0); - } - } - - } else if (!strncasecomp(buffer,"VIEWER:",7)) { - char *mime_type; - char *viewer; - char *environment; - - if (strlen(buffer) > 9) { - mime_type = buffer + 7; - if ((viewer = strchr(mime_type, ':')) != NULL) { - *viewer++ = '\0'; - for (i = 0, j = 0; mime_type[i]; i++) { - if (mime_type[i] != ' ') { - mime_type[j++] = TOLOWER(mime_type[i]); - } - } - mime_type[j] = '\0'; - environment = strrchr(viewer, ':'); - if ((environment != NULL) && - (strlen(viewer) > 1) && *(environment-1) != '\\') { - *environment++ = '\0'; - remove_backslashes(viewer); - /* - * If environment equals xwindows then only - * assign the presentation if there is a display - * variable. - */ - if (!strcasecomp(environment,"XWINDOWS")) { - if (getenv(DISPLAY)) - HTSetPresentation(mime_type, viewer, - 1.0, 3.0, 0.0, 0); - } else if (!strcasecomp(environment,"NON_XWINDOWS")) { - if (!getenv(DISPLAY)) - HTSetPresentation(mime_type, viewer, - 1.0, 3.0, 0.0, 0); - } else { - HTSetPresentation(mime_type, viewer, - 1.0, 3.0, 0.0, 0); - } - } else { - remove_backslashes(viewer); - HTSetPresentation(mime_type, viewer, - 1.0, 3.0, 0.0, 0); - } + switch (TOUPPER(buffer[0])) { + + case 'A': + if (!strncasecomp(buffer, "ALERTSECS:", 10)) { + strcpy(temp, buffer+10); + for (i = 0; temp[i]; i++) { + if (!isdigit(temp[i])) { + temp[i] = '\0'; + break; } } + if (temp[0]) + AlertSecs = atoi(temp); - } else if(!strncasecomp(buffer,"KEYMAP:",7)) { - char *key; - char *func; - - key = buffer + 7; - if ((func = strchr(key, ':')) != NULL) { - *func++ = '\0'; - /* Allow comments on the ends of key remapping lines. - DT */ - if (!remap(key, strtok(func, " \t\n#"))) - fprintf(stderr, - "key remapping of %s to %s failed\n",key,func); - else if (!strcmp("TOGGLE_HELP", strtok(func, " \t\n#"))) - LYUseNoviceLineTwo = FALSE; - } + } else if (!strncasecomp(buffer, "ALWAYS_RESUBMIT_POSTS:", 22)) { + LYresubmit_posts = is_true(buffer+22); - } else if(!strncasecomp(buffer,"GLOBAL_MAILCAP:",15)) { - - StrAllocCopy(global_type_map, buffer+15); +#ifdef EXEC_LINKS + } else if (!strncasecomp(buffer, "ALWAYS_TRUSTED_EXEC:", 20)) { + add_trusted(&buffer[20], ALWAYS_EXEC_PATH); /* Add exec path */ +#endif /* EXEC_LINKS */ + } + break; - } else if(!strncasecomp(buffer,"GLOBAL_EXTENSION_MAP:",21)) { + case 'B': + if (!strncasecomp(buffer, "BLOCK_MULTI_BOOKMARKS:", 22)) { + LYMBMBlocked = is_true(buffer+22); - StrAllocCopy(global_extension_map, buffer+21); + } else if (!strncasecomp(buffer, "BOLD_H1:", 8)) { + bold_H1 = is_true(buffer+8); - } else if(!strncasecomp(buffer,"PERSONAL_MAILCAP:",17)) { + } else if (!strncasecomp(buffer, "BOLD_HEADERS:", 13)) { + bold_headers = is_true(buffer+13); - StrAllocCopy(personal_type_map, buffer+17); - - } else if(!strncasecomp(buffer,"PERSONAL_EXTENSION_MAP:",23)) { + } else if (!strncasecomp(buffer, "BOLD_NAME_ANCHORS:", 18)) { + bold_name_anchors = is_true(buffer+18); + } + break; - StrAllocCopy(personal_extension_map, buffer+23); + case 'C': + if (!strncasecomp(buffer, "CASE_SENSITIVE_ALWAYS_ON:", 25)) { + case_sensitive = is_true(buffer+25); - } else if(!strncasecomp(buffer,"CHARACTER_SET:",14)) { - for(i = 0; LYchar_set_names[i]; i++) - if(!strncmp(buffer+14,LYchar_set_names[i],strlen(buffer+14))) - { + } else if (!strncasecomp(buffer, "CHARACTER_SET:", 14)) { + for (i = 0; LYchar_set_names[i]; i++) { + if (!strncmp(buffer+14, + LYchar_set_names[i], strlen(buffer+14))) { current_char_set=i; HTMLSetRawModeDefault(i); break; } + } - } else if(!strncasecomp(buffer,"STARTFILE:",10)) { - - StrAllocCopy(startfile, buffer+10); - - } else if(!strncasecomp(buffer,"HELPFILE:",9)) { - - StrAllocCopy(helpfile, buffer+9); - - } else if(!strncasecomp(buffer,"DEFAULT_INDEX_FILE:",19)) { - StrAllocCopy(indexfile, buffer+19); - -#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) - } else if(!strncasecomp(buffer, - "LOCAL_EXECUTION_LINKS_ALWAYS_ON:",32)) { - local_exec = is_true(buffer+32); + } else if (!strncasecomp(buffer, "CHECKMAIL:", 10)) { + check_mail = is_true(buffer+10); - } else if(!strncasecomp(buffer, - "LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE:",40)) { - local_exec_on_local_files = is_true(buffer+40); -#endif /* defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) */ + } else if (!strncasecomp(buffer, "COLLAPSE_BR_TAGS:", 17)) { + LYCollapseBRs = is_true(buffer+17); - } else if(!strncasecomp(buffer,"MAIL_SYSTEM_ERROR_LOGGING:",26)) { - error_logging = is_true(buffer+26); +#ifdef USE_SLANG + } else if (!strncasecomp(buffer, "COLOR:", 6)) { + parse_color(buffer + 6); +#endif /* USE_SLANG */ - } else if(!strncasecomp(buffer,"CHECKMAIL:",10)) { - check_mail = is_true(buffer+10); + } else if (!strncasecomp(buffer, "cso_proxy:", 10)) { + if (getenv("cso_proxy") == NULL) { +#ifdef VMS + strcpy(temp, "cso_proxy"); + Define_VMSLogical(temp, (char *)&buffer[10]); +#else + strcpy(temp, "cso_proxy="); + StrAllocCopy(cso_proxy_putenv_cmd, temp); + StrAllocCat(cso_proxy_putenv_cmd, (char *)&buffer[10]); + putenv(cso_proxy_putenv_cmd); +#endif /* VMS */ + } #ifdef VMS - } else if(!strncasecomp(buffer,"USE_FIXED_RECORDS:",18)) { - UseFixedRecords = is_true(buffer+18); + } else if (!strncasecomp(buffer, "CSWING_PATH:", 12)) { + StrAllocCopy(LYCSwingPath, buffer+12); #endif /* VMS */ + } + break; - } else if(!strncasecomp(buffer,"VI_KEYS_ALWAYS_ON:",18)) { - vi_keys = is_true(buffer+18); + case 'D': + if (!strncasecomp(buffer, "DEFAULT_BOOKMARK_FILE:", 22)) { + StrAllocCopy(bookmark_page, buffer+22); + StrAllocCopy(BookmarkPage, bookmark_page); + StrAllocCopy(MBM_A_subbookmark[0], bookmark_page); + StrAllocCopy(MBM_A_subdescript[0], MULTIBOOKMARKS_DEFAULT); - } else if(!strncasecomp(buffer,"EMACS_KEYS_ALWAYS_ON:",21)) { - emacs_keys = is_true(buffer+21); + } else if (!strncasecomp(buffer, "DEFAULT_CACHE_SIZE:", 19)) { + HTCacheSize = atoi(buffer+19); - } else if(!strncasecomp(buffer, - "DEFAULT_KEYPAD_MODE_IS_NUMBERS_AS_ARROWS:",41)) { - if(is_true(buffer+41)) + } else if (!system_editor && + !strncasecomp(buffer, "DEFAULT_EDITOR:", 15)) { + StrAllocCopy(editor, buffer+15); + + } else if (!strncasecomp(buffer, "DEFAULT_INDEX_FILE:", 19)) { + StrAllocCopy(indexfile, buffer+19); + + } else if (!strncasecomp(buffer, + "DEFAULT_KEYPAD_MODE_IS_NUMBERS_AS_ARROWS:", 41)) { + if (is_true(buffer+41)) keypad_mode = NUMBERS_AS_ARROWS; else keypad_mode = LINKS_ARE_NUMBERED; - } else if(!strncasecomp(buffer,"CASE_SENSITIVE_ALWAYS_ON:",25)) { - case_sensitive = is_true(buffer+25); - - } else if(!strncasecomp(buffer,"DEFAULT_USER_MODE:",18)) { - if(!strncasecomp(buffer+18,"NOVICE",5)) - user_mode = NOVICE_MODE; - else if(!strncasecomp(buffer+18,"INTER",5)) - user_mode = INTERMEDIATE_MODE; - else if(!strncasecomp(buffer+18,"ADVANCE",7)) - user_mode = ADVANCED_MODE; - - } else if(!strncasecomp(buffer,"DEFAULT_BOOKMARK_FILE:",22)) { - StrAllocCopy(bookmark_page, buffer+22); - StrAllocCopy(BookmarkPage, bookmark_page); - StrAllocCopy(MBM_A_subbookmark[0], bookmark_page); - StrAllocCopy(MBM_A_subdescript[0], MULTIBOOKMARKS_DEFAULT); - - } else if(!strncasecomp(buffer,"MULTI_BOOKMARK_SUPPORT:",23)) { - LYMultiBookmarks = is_true(buffer+23); - - } else if(!strncasecomp(buffer,"BLOCK_MULTI_BOOKMARKS:",22)) { - LYMBMBlocked = is_true(buffer+22); - - } else if(!strncasecomp(buffer,"ADVANCED_MULTI_BOOKMARKS:",25)) { - LYMBMAdvanced = is_true(buffer+25); - - } else if(!system_editor && - !strncasecomp(buffer,"DEFAULT_EDITOR:",15)) { - StrAllocCopy(editor,buffer+15); - - } else if(!strncasecomp(buffer,"GOTOBUFFER:",11)) { - goto_buffer = is_true(buffer+11); - - } else if(!strncasecomp(buffer,"JUMPFILE:",9)) { - if (!LYJumpInit(buffer)) { - if (TRACE) - fprintf(stderr, "Failed to register %s\n", buffer); - } - - } else if(!strncasecomp(buffer,"JUMP_PROMPT:",12)) { - StrAllocCopy(jumpprompt,buffer+12); - - } else if(!strncasecomp(buffer,"JUMPBUFFER:",11)) { - jump_buffer = is_true(buffer+11); - - } else if(!strncasecomp(buffer,"NO_DOT_FILES:",13)) { - no_dotfiles = is_true(buffer+13); - - } else if(!strncasecomp(buffer,"NO_FROM_HEADER:",15)) { - LYNoFromHeader = is_true(buffer+15); - - } else if(!strncasecomp(buffer,"NO_REFERER_HEADER:",18)) { - LYNoRefererHeader = is_true(buffer+18); - - } else if(!strncasecomp(buffer,"NO_FILE_REFERER:",16)) { - no_filereferer = is_true(buffer+16); - - } else if(!strncasecomp(buffer,"MAKE_LINKS_FOR_ALL_IMAGES:",26)) { - clickable_images = is_true(buffer+26); - - } else if(!strncasecomp(buffer,"MAKE_PSEUDO_ALTS_FOR_INLINES:",29)) { - pseudo_inline_alts = is_true(buffer+29); + } else if (!strncasecomp(buffer, "DEFAULT_USER_MODE:", 18)) { + if (!strncasecomp(buffer+18, "NOVICE", 5)) + user_mode = NOVICE_MODE; + else if (!strncasecomp(buffer+18, "INTER", 5)) + user_mode = INTERMEDIATE_MODE; + else if (!strncasecomp(buffer+18, "ADVANCE", 7)) + user_mode = ADVANCED_MODE; - } else if(!strncasecomp(buffer,"BOLD_HEADERS:",13)) { - bold_headers = is_true(buffer+13); - - } else if(!strncasecomp(buffer,"BOLD_H1:",8)) { - bold_H1 = is_true(buffer+8); - - } else if(!strncasecomp(buffer,"BOLD_NAME_ANCHORS:",18)) { - bold_name_anchors = is_true(buffer+18); - - } else if(!strncasecomp(buffer,"SYSTEM_EDITOR:",14)) { - StrAllocCopy(editor,buffer+14); - system_editor = TRUE; - - } else if(!strncasecomp(buffer,"PREFERRED_LANGUAGE:",19)) { - StrAllocCopy(language,buffer+19); +#if defined(VMS) && defined(VAXC) && !defined(__DECC) + } else if (!strncasecomp(buffer, + "DEFAULT_VIRTUAL_MEMORY_SIZE:", 28)) { + HTVirtualMemorySize = atoi(buffer+28); +#endif /* VMS && VAXC && !__DECC */ - } else if(!strncasecomp(buffer,"PREFERRED_CHARSET:",18)) { - StrAllocCopy(pref_charset,buffer+18); +#ifdef DIRED_SUPPORT + } else if (!strncasecomp(buffer, "DIRED_MENU:", 11)) { + add_menu_item(&buffer[11]); +#endif /* DIRED_SUPPORT */ - } else if(!strncasecomp(buffer,"URL_DOMAIN_PREFIXES:",20)) { - StrAllocCopy(URLDomainPrefixes, buffer+20); + } else if (!strncasecomp(buffer, "DOWNLOADER:", 11)) { + add_item_to_list(&buffer[11], &downloaders); + } + break; - } else if(!strncasecomp(buffer,"URL_DOMAIN_SUFFIXES:",20)) { - StrAllocCopy(URLDomainSuffixes, buffer+20); + case 'E': + if (!strncasecomp(buffer, "EMACS_KEYS_ALWAYS_ON:", 21)) { + emacs_keys = is_true(buffer+21); - } else if(!strncasecomp(buffer,"INEWS:",6)) { - StrAllocCopy(inews_path,buffer+6); - if (*inews_path == '\0' || !strcasecomp(inews_path,"none")) - no_newspost = TRUE; - else - no_newspost = FALSE; + } else if (!strncasecomp(buffer, "ENABLE_SCROLLBACK:", 18)) { + enable_scrollback = is_true(buffer+18); + } + break; - } else if(!strncasecomp(buffer,"SYSTEM_MAIL:",12)) { - StrAllocCopy(system_mail,buffer+12); + case 'F': + if (!strncasecomp(buffer, "finger_proxy:", 13)) { + if (getenv("finger_proxy") == NULL) { +#ifdef VMS + strcpy(temp, "finger_proxy"); + Define_VMSLogical(temp, (char *)&buffer[13]); +#else + strcpy(temp, "finger_proxy="); + StrAllocCopy(finger_proxy_putenv_cmd, temp); + StrAllocCat(finger_proxy_putenv_cmd, (char *)&buffer[13]); + putenv(finger_proxy_putenv_cmd); +#endif /* VMS */ + } + } else if (!strncasecomp(buffer, "ftp_proxy:", 10)) { + if (getenv("ftp_proxy") == NULL) { #ifdef VMS - } else if(!strncasecomp(buffer,"MAIL_ADRS:",10)) { - StrAllocCopy(mail_adrs,buffer+10); + strcpy(temp, "ftp_proxy"); + Define_VMSLogical(temp, (char *)&buffer[10]); +#else + strcpy(temp, "ftp_proxy="); + StrAllocCopy(ftp_proxy_putenv_cmd, temp); + StrAllocCat(ftp_proxy_putenv_cmd, (char *)&buffer[10]); + putenv(ftp_proxy_putenv_cmd); #endif /* VMS */ + } + } + break; - } else if(!strncasecomp(buffer,"PRINTER:",8)) { - add_printer_to_list (&buffer[8],&printers); + case 'G': + if (!strncasecomp(buffer, "GLOBAL_EXTENSION_MAP:", 21)) { + StrAllocCopy(global_extension_map, buffer+21); - } else if(!strncasecomp(buffer,"DOWNLOADER:",11)) { - add_item_to_list(&buffer[11],&downloaders); + } else if (!strncasecomp(buffer, "GLOBAL_MAILCAP:", 15)) { + StrAllocCopy(global_type_map, buffer+15); - } else if(!strncasecomp(buffer,"NNTPSERVER:",11)) { - if(getenv("NNTPSERVER") == NULL) { + } else if (!strncasecomp(buffer, "gopher_proxy:", 13)) { + if (getenv("gopher_proxy") == NULL) { #ifdef VMS - strcpy(temp, "NNTPSERVER"); - Define_VMSLogical(temp, (char *)&buffer[11]); + strcpy(temp, "gopher_proxy"); + Define_VMSLogical(temp, (char *)&buffer[13]); #else - strcpy(temp, "NNTPSERVER="); - StrAllocCopy(NNTPSERVER_putenv_cmd, temp); - StrAllocCat(NNTPSERVER_putenv_cmd, (char *)&buffer[11]); - putenv(NNTPSERVER_putenv_cmd); + strcpy(temp, "gopher_proxy="); + StrAllocCopy(gopher_proxy_putenv_cmd, temp); + StrAllocCat(gopher_proxy_putenv_cmd, (char *)&buffer[13]); + putenv(gopher_proxy_putenv_cmd); #endif /* VMS */ } - } else if(!strncasecomp(buffer,"http_proxy:",11)) { - if(getenv("http_proxy") == NULL) { + } else if (!strncasecomp(buffer, "GOTOBUFFER:", 11)) { + goto_buffer = is_true(buffer+11); + } + break; + + case 'H': + if (!strncasecomp(buffer, "HELPFILE:", 9)) { + StrAllocCopy(helpfile, buffer+9); + + } else if (!strncasecomp(buffer, "HISTORICAL_COMMENTS:", 20)) { + historical_comments = is_true(buffer+20); + + } else if (!strncasecomp(buffer, "http_proxy:", 11)) { + if (getenv("http_proxy") == NULL) { #ifdef VMS strcpy(temp, "http_proxy"); Define_VMSLogical(temp, (char *)&buffer[11]); @@ -714,8 +639,8 @@ PUBLIC void read_cfg ARGS1( #endif /* VMS */ } - } else if(!strncasecomp(buffer,"https_proxy:",12)) { - if(getenv("https_proxy") == NULL) { + } else if (!strncasecomp(buffer, "https_proxy:", 12)) { + if (getenv("https_proxy") == NULL) { #ifdef VMS strcpy(temp, "https_proxy"); Define_VMSLogical(temp, (char *)&buffer[12]); @@ -726,48 +651,159 @@ PUBLIC void read_cfg ARGS1( putenv(https_proxy_putenv_cmd); #endif /* VMS */ } + } + break; - } else if(!strncasecomp(buffer,"ftp_proxy:",10)) { - if(getenv("ftp_proxy") == NULL) { -#ifdef VMS - strcpy(temp, "ftp_proxy"); - Define_VMSLogical(temp, (char *)&buffer[10]); -#else - strcpy(temp, "ftp_proxy="); - StrAllocCopy(ftp_proxy_putenv_cmd, temp); - StrAllocCat(ftp_proxy_putenv_cmd, (char *)&buffer[10]); - putenv(ftp_proxy_putenv_cmd); -#endif /* VMS */ + case 'I': + if (!strncasecomp(buffer, "INEWS:", 6)) { + StrAllocCopy(inews_path, buffer+6); + if (*inews_path == '\0' || !strcasecomp(inews_path, "none")) + no_newspost = TRUE; + else + no_newspost = FALSE; + + } else if (!strncasecomp(buffer, "INFOSECS:", 9)) { + strcpy(temp, buffer+9); + for (i = 0; temp[i]; i++) { + if (!isdigit(temp[i])) { + temp[i] = '\0'; + break; + } } + if (temp[0]) + InfoSecs = atoi(temp); + } + break; - } else if(!strncasecomp(buffer,"gopher_proxy:",13)) { - if(getenv("gopher_proxy") == NULL) { -#ifdef VMS - strcpy(temp, "gopher_proxy"); - Define_VMSLogical(temp, (char *)&buffer[13]); -#else - strcpy(temp, "gopher_proxy="); - StrAllocCopy(gopher_proxy_putenv_cmd, temp); - StrAllocCat(gopher_proxy_putenv_cmd, (char *)&buffer[13]); - putenv(gopher_proxy_putenv_cmd); -#endif /* VMS */ + case 'J': + if (!strncasecomp(buffer, "JUMP_PROMPT:", 12)) { + StrAllocCopy(jumpprompt, buffer+12); + + } else if (!strncasecomp(buffer, "JUMPBUFFER:", 11)) { + jump_buffer = is_true(buffer+11); + + } else if (!strncasecomp(buffer, "JUMPFILE:", 9)) { + if (!LYJumpInit(buffer)) { + if (TRACE) + fprintf(stderr, "Failed to register %s\n", buffer); } + } + break; + + case 'K': + if (!strncasecomp(buffer, "KEYMAP:", 7)) { + char *key; + char *func; + + key = buffer + 7; + if ((func = strchr(key, ':')) != NULL) { + *func++ = '\0'; + /* Allow comments on the ends of key remapping lines. - DT */ + if (!remap(key, strtok(func, " \t\n#"))) + fprintf(stderr, + "key remapping of %s to %s failed\n",key,func); + else if (!strcmp("TOGGLE_HELP", strtok(func, " \t\n#"))) + LYUseNoviceLineTwo = FALSE; + } + } + break; + + case 'L': + if (!strncasecomp(buffer, "LIST_NEWS_NUMBERS:", 18)) { + LYListNewsNumbers = is_true(buffer+18); + + } else if (!strncasecomp(buffer, "LIST_NEWS_DATES:", 16)) { + LYListNewsDates = is_true(buffer+16); + +#ifndef VMS + } else if (!strncasecomp(buffer, "LIST_FORMAT:", 12)) { + StrAllocCopy(list_format, buffer+12); +#endif /* !VMS */ + + } else if (!strncasecomp(buffer, "LOCALHOST_ALIAS:", 16)) { + LYAddLocalhostAlias(buffer+16); + + } else if (!strncasecomp(buffer, "LOCAL_DOMAIN:", 13)) { + StrAllocCopy(LYLocalDomain, buffer+13); + +#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) + } else if (!strncasecomp(buffer, + "LOCAL_EXECUTION_LINKS_ALWAYS_ON:", 32)) { + local_exec = is_true(buffer+32); + + } else if (!strncasecomp(buffer, + "LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE:", 40)) { + local_exec_on_local_files = is_true(buffer+40); +#endif /* defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) */ + +#ifdef LYNXCGI_LINKS + } else if (!strncasecomp(buffer, "LYNXCGI_ENVIRONMENT:", 20)) { + add_lynxcgi_environment(buffer+20); +#endif /* LYNXCGI_LINKS */ + + } else if (!strncasecomp(buffer, "LYNX_HOST_NAME:", 15)) { + StrAllocCopy(LYHostName, buffer+15); + } + break; + + case 'M': + if (!strncasecomp(buffer, "MAIL_SYSTEM_ERROR_LOGGING:", 26)) { + error_logging = is_true(buffer+26); - } else if(!strncasecomp(buffer,"cso_proxy:",10)) { - if(getenv("cso_proxy") == NULL) { #ifdef VMS - strcpy(temp, "cso_proxy"); - Define_VMSLogical(temp, (char *)&buffer[10]); -#else - strcpy(temp, "cso_proxy="); - StrAllocCopy(cso_proxy_putenv_cmd, temp); - StrAllocCat(cso_proxy_putenv_cmd, (char *)&buffer[10]); - putenv(cso_proxy_putenv_cmd); + } else if (!strncasecomp(buffer, "MAIL_ADRS:", 10)) { + StrAllocCopy(mail_adrs, buffer+10); #endif /* VMS */ + + } else if (!strncasecomp(buffer, "MAKE_LINKS_FOR_ALL_IMAGES:", 26)) { + clickable_images = is_true(buffer+26); + + } else if (!strncasecomp(buffer, + "MAKE_PSEUDO_ALTS_FOR_INLINES:", 29)) { + pseudo_inline_alts = is_true(buffer+29); + + } else if (!strncasecomp(buffer, "MESSAGESECS:", 12)) { + strcpy(temp, buffer+12); + for (i = 0; temp[i]; i++) { + if (!isdigit(temp[i])) { + temp[i] = '\0'; + break; + } } + if (temp[0]) + MessageSecs = atoi(temp); + + } else if (!strncasecomp(buffer, "MINIMAL_COMMENTS:", 17)) { + minimal_comments = is_true(buffer+17); + + } else if (!strncasecomp(buffer, "MULTI_BOOKMARK_SUPPORT:", 23)) { + LYMultiBookmarks = is_true(buffer+23); + } + break; + + case 'N': + if (!strncasecomp(buffer, "NEWS_CHUNK_SIZE:", 16)) { + HTNewsChunkSize = atoi(buffer+16); + /* + * If the new HTNewsChunkSize exceeds the maximum, + * increase HTNewsMaxChunk to this size. - FM + */ + if (HTNewsChunkSize > HTNewsMaxChunk) { + HTNewsMaxChunk = HTNewsChunkSize; + } - } else if(!strncasecomp(buffer,"news_proxy:",11)) { - if(getenv("news_proxy") == NULL) { + } else if (!strncasecomp(buffer, "NEWS_MAX_CHUNK:", 15)) { + HTNewsMaxChunk = atoi(buffer+15); + /* + * If HTNewsChunkSize exceeds the new maximum, + * reduce HTNewsChunkSize to this maximum. - FM + */ + if (HTNewsChunkSize > HTNewsMaxChunk) { + HTNewsChunkSize = HTNewsMaxChunk; + } + + } else if (!strncasecomp(buffer, "news_proxy:", 11)) { + if (getenv("news_proxy") == NULL) { #ifdef VMS strcpy(temp, "news_proxy"); Define_VMSLogical(temp, (char *)&buffer[11]); @@ -779,21 +815,8 @@ PUBLIC void read_cfg ARGS1( #endif /* VMS */ } - } else if(!strncasecomp(buffer,"snews_proxy:",12)) { - if(getenv("snews_proxy") == NULL) { -#ifdef VMS - strcpy(temp, "snews_proxy"); - Define_VMSLogical(temp, (char *)&buffer[12]); -#else - strcpy(temp, "snews_proxy="); - StrAllocCopy(snews_proxy_putenv_cmd, temp); - StrAllocCat(snews_proxy_putenv_cmd, (char *)&buffer[12]); - putenv(snews_proxy_putenv_cmd); -#endif /* VMS */ - } - - } else if(!strncasecomp(buffer,"nntp_proxy:",11)) { - if(getenv("nntp_proxy") == NULL) { + } else if (!strncasecomp(buffer, "nntp_proxy:", 11)) { + if (getenv("nntp_proxy") == NULL) { #ifdef VMS strcpy(temp, "nntp_proxy"); Define_VMSLogical(temp, (char *)&buffer[11]); @@ -805,34 +828,30 @@ PUBLIC void read_cfg ARGS1( #endif /* VMS */ } - } else if(!strncasecomp(buffer,"wais_proxy:",11)) { - if(getenv("wais_proxy") == NULL) { + } else if (!strncasecomp(buffer, "NNTPSERVER:", 11)) { + if (getenv("NNTPSERVER") == NULL) { #ifdef VMS - strcpy(temp, "wais_proxy"); + strcpy(temp, "NNTPSERVER"); Define_VMSLogical(temp, (char *)&buffer[11]); #else - strcpy(temp, "wais_proxy="); - StrAllocCopy(wais_proxy_putenv_cmd, temp); - StrAllocCat(wais_proxy_putenv_cmd, (char *)&buffer[11]); - putenv(wais_proxy_putenv_cmd); + strcpy(temp, "NNTPSERVER="); + StrAllocCopy(NNTPSERVER_putenv_cmd, temp); + StrAllocCat(NNTPSERVER_putenv_cmd, (char *)&buffer[11]); + putenv(NNTPSERVER_putenv_cmd); #endif /* VMS */ } - } else if(!strncasecomp(buffer,"finger_proxy:",13)) { - if(getenv("finger_proxy") == NULL) { -#ifdef VMS - strcpy(temp, "finger_proxy"); - Define_VMSLogical(temp, (char *)&buffer[13]); -#else - strcpy(temp, "finger_proxy="); - StrAllocCopy(finger_proxy_putenv_cmd, temp); - StrAllocCat(finger_proxy_putenv_cmd, (char *)&buffer[13]); - putenv(finger_proxy_putenv_cmd); -#endif /* VMS */ - } + } else if (!strncasecomp(buffer, "NO_DOT_FILES:", 13)) { + no_dotfiles = is_true(buffer+13); - } else if(!strncasecomp(buffer,"no_proxy:",9)) { - if(getenv("no_proxy") == NULL) { + } else if (!strncasecomp(buffer, "NO_FILE_REFERER:", 16)) { + no_filereferer = is_true(buffer+16); + + } else if (!strncasecomp(buffer, "NO_FROM_HEADER:", 15)) { + LYNoFromHeader = is_true(buffer+15); + + } else if (!strncasecomp(buffer, "no_proxy:", 9)) { + if (getenv("no_proxy") == NULL) { #ifdef VMS strcpy(temp, "no_proxy"); Define_VMSLogical(temp, (char *)&buffer[9]); @@ -844,159 +863,221 @@ PUBLIC void read_cfg ARGS1( #endif /* VMS */ } -#ifdef EXEC_LINKS - } else if(!strncasecomp(buffer,"TRUSTED_EXEC:",13)) { - add_trusted(&buffer[13], EXEC_PATH); /* Add exec path */ + } else if (!strncasecomp(buffer, "NO_REFERER_HEADER:", 18)) { + LYNoRefererHeader = is_true(buffer+18); + } + break; - } else if(!strncasecomp(buffer,"ALWAYS_TRUSTED_EXEC:",20)) { - add_trusted(&buffer[20], ALWAYS_EXEC_PATH); /* Add exec path */ -#endif /* EXEC_LINKS */ + case 'P': + if (!strncasecomp(buffer, "PERSONAL_MAILCAP:", 17)) { + StrAllocCopy(personal_type_map, buffer+17); -#ifdef LYNXCGI_LINKS - } else if(!strncasecomp(buffer,"TRUSTED_LYNXCGI:",16)) { - add_trusted(&buffer[16], CGI_PATH); /* Add CGI path */ + } else if (!strncasecomp(buffer, "PERSONAL_EXTENSION_MAP:", 23)) { + StrAllocCopy(personal_extension_map, buffer+23); - } else if(!strncasecomp(buffer,"LYNXCGI_ENVIRONMENT:",20)) { - add_lynxcgi_environment(buffer+20); -#endif /* LYNXCGI_LINKS */ + } else if (!strncasecomp(buffer, "PREFERRED_CHARSET:", 18)) { + StrAllocCopy(pref_charset, buffer+18); -#ifdef DIRED_SUPPORT - } else if(!strncasecomp(buffer,"UPLOADER:",9)) { - add_item_to_list(&buffer[9],&uploaders); + } else if (!strncasecomp(buffer, "PREFERRED_LANGUAGE:", 19)) { + StrAllocCopy(language, buffer+19); - } else if(!strncasecomp(buffer,"DIRED_MENU:",11)) { - add_menu_item(&buffer[11]); -#endif /* DIRED_SUPPORT */ + } else if (!strncasecomp(buffer, "PRINTER:", 8)) { + add_printer_to_list(&buffer[8], &printers); + } + break; - } else if(!strncasecomp(buffer,"LYNX_HOST_NAME:",15)) { - StrAllocCopy(LYHostName,buffer+15); + case 'S': + if (!strncasecomp(buffer, "SAVE_SPACE:", 11)) { + StrAllocCopy(lynx_save_space, buffer+11); - } else if(!strncasecomp(buffer,"LOCALHOST_ALIAS:",16)) { - LYAddLocalhostAlias(buffer+16); + } else if (!strncasecomp(buffer, "SCAN_FOR_BURIED_NEWS_REFS:", 26)) { + scan_for_buried_news_references = is_true(buffer+26); - } else if(!strncasecomp(buffer,"LOCAL_DOMAIN:",13)) { - StrAllocCopy(LYLocalDomain,buffer+13); + } else if (!strncasecomp(buffer, "SET_COOKIES:", 12)) { + LYSetCookies = is_true(buffer+12); - } else if(!strncasecomp(buffer,"SUBSTITUTE_UNDERSCORES:",23)) { - use_underscore = is_true(buffer+23); + } else if (!strncasecomp(buffer, "SHOW_CURSOR:", 12)) { + LYShowCursor = is_true(buffer+12); - } else if(!strncasecomp(buffer,"HISTORICAL_COMMENTS:",20)) { - historical_comments = is_true(buffer+20); + } else if (!strncasecomp(buffer, "snews_proxy:", 12)) { + if (getenv("snews_proxy") == NULL) { +#ifdef VMS + strcpy(temp, "snews_proxy"); + Define_VMSLogical(temp, (char *)&buffer[12]); +#else + strcpy(temp, "snews_proxy="); + StrAllocCopy(snews_proxy_putenv_cmd, temp); + StrAllocCat(snews_proxy_putenv_cmd, (char *)&buffer[12]); + putenv(snews_proxy_putenv_cmd); +#endif /* VMS */ + } - } else if(!strncasecomp(buffer,"MINIMAL_COMMENTS:",17)) { - minimal_comments = is_true(buffer+17); + } else if (!strncasecomp(buffer, "SOFT_DQUOTES:", 13)) { + soft_dquotes = is_true(buffer+13); - } else if(!strncasecomp(buffer,"SOFT_DQUOTES:",13)) { - soft_dquotes = is_true(buffer+13); + } else if (!strncasecomp(buffer, "STARTFILE:", 10)) { + StrAllocCopy(startfile, buffer+10); - } else if(!strncasecomp(buffer,"ENABLE_SCROLLBACK:",18)) { - enable_scrollback = is_true(buffer+18); + } else if (!strncasecomp(buffer, "SUBSTITUTE_UNDERSCORES:", 23)) { + use_underscore = is_true(buffer+23); - } else if(!strncasecomp(buffer,"SCAN_FOR_BURIED_NEWS_REFS:",26)) { - scan_for_buried_news_references = is_true(buffer+26); + } else if (!strncasecomp(buffer, "SUFFIX:", 7)) { + char *extention; + char *mime_type; - } else if(!strncasecomp(buffer,"INFOSECS:",9)) { - strcpy(temp, buffer+9); - for (i = 0; temp[i]; i++) { - if (!isdigit(temp[i])) { - temp[i] = '\0'; - break; - } - } - if (temp[0]) - InfoSecs = atoi(temp); - - } else if(!strncasecomp(buffer,"MESSAGESECS:",12)) { - strcpy(temp, buffer+12); - for (i = 0; temp[i]; i++) { - if (!isdigit(temp[i])) { - temp[i] = '\0'; - break; - } - } - if (temp[0]) - MessageSecs = atoi(temp); - - } else if(!strncasecomp(buffer,"ALERTSECS:",10)) { - strcpy(temp, buffer+10); - for (i = 0; temp[i]; i++) { - if (!isdigit(temp[i])) { - temp[i] = '\0'; - break; + if (strlen(buffer) > 9) { + extention = buffer + 7; + if ((mime_type = strchr(extention, ':')) != NULL) { + *mime_type++ = '\0'; + for (i = 0, j = 0; mime_type[i]; i++) { + if (mime_type[i] != ' ') { + mime_type[j++] = TOLOWER(mime_type[i]); + } } + mime_type[j] = '\0'; + if (strstr(mime_type, "tex") != NULL || + strstr(mime_type, "postscript") != NULL || + strstr(mime_type, "sh") != NULL || + strstr(mime_type, "troff") != NULL || + strstr(mime_type, "rtf") != NULL) + HTSetSuffix(extention, mime_type, "8bit", 1.0); + else + HTSetSuffix(extention, mime_type, "binary", 1.0); } - if (temp[0]) - AlertSecs = atoi(temp); + } -#ifndef VMS - } else if(!strncasecomp(buffer,"LIST_FORMAT:",12)) { - StrAllocCopy(list_format, buffer+12); -#endif /* !VMS */ + } else if (!strncasecomp(buffer, "SYSTEM_EDITOR:", 14)) { + StrAllocCopy(editor, buffer+14); + system_editor = TRUE; - } else if(!strncasecomp(buffer,"ALWAYS_RESUBMIT_POSTS:",22)) { - LYresubmit_posts = is_true(buffer+22); + } else if (!strncasecomp(buffer, "SYSTEM_MAIL:", 12)) { + StrAllocCopy(system_mail, buffer+12); + } + break; - } else if(!strncasecomp(buffer,"SAVE_SPACE:",11)) { - StrAllocCopy(lynx_save_space, buffer+11); + case 'T': +#ifdef EXEC_LINKS + if (!strncasecomp(buffer, "TRUSTED_EXEC:", 13)) { + add_trusted(&buffer[13], EXEC_PATH); /* Add exec path */ + } +#endif /* EXEC_LINKS */ -#ifdef USE_SLANG - } else if (!strncasecomp(buffer, "COLOR:", 6)) { - parse_color(buffer + 6); -#endif /* USE_SLANG */ +#ifdef LYNXCGI_LINKS + if (!strncasecomp(buffer, "TRUSTED_LYNXCGI:", 16)) { + add_trusted(&buffer[16], CGI_PATH); /* Add CGI path */ + } +#endif /* LYNXCGI_LINKS */ + break; - } else if (!strncasecomp(buffer, "LIST_NEWS_NUMBERS:", 18)) { - LYListNewsNumbers = is_true(buffer+18); + case 'U': + if (!strncasecomp(buffer, "URL_DOMAIN_PREFIXES:", 20)) { + StrAllocCopy(URLDomainPrefixes, buffer+20); - } else if (!strncasecomp(buffer, "LIST_NEWS_DATES:", 16)) { - LYListNewsDates = is_true(buffer+16); + } else if (!strncasecomp(buffer, "URL_DOMAIN_SUFFIXES:", 20)) { + StrAllocCopy(URLDomainSuffixes, buffer+20); - } else if (!strncasecomp(buffer, "NEWS_CHUNK_SIZE:", 16)) { - HTNewsChunkSize = atoi(buffer+16); - /* - * If the new HTNewsChunkSize exceeds the maximum, - * increase HTNewsMaxChunk to this size. - FM - */ - if (HTNewsChunkSize > HTNewsMaxChunk) { - HTNewsMaxChunk = HTNewsChunkSize; - } +#ifdef DIRED_SUPPORT + } else if (!strncasecomp(buffer, "UPLOADER:", 9)) { + add_item_to_list(&buffer[9], &uploaders); +#endif /* DIRED_SUPPORT */ - } else if (!strncasecomp(buffer, "NEWS_MAX_CHUNK:", 15)) { - HTNewsMaxChunk = atoi(buffer+15); - /* - * If HTNewsChunkSize exceeds the new maximum, - * reduce HTNewsChunkSize to this maximum. - FM - */ - if (HTNewsChunkSize > HTNewsMaxChunk) { - HTNewsChunkSize = HTNewsMaxChunk; - } +#ifdef VMS + } else if (!strncasecomp(buffer, "USE_FIXED_RECORDS:", 18)) { + UseFixedRecords = is_true(buffer+18); +#endif /* VMS */ - } else if(!strncasecomp(buffer,"USE_SELECT_POPUPS:",17)) { - LYSelectPopups = is_true(buffer+17); + } else if (!strncasecomp(buffer, "USE_SELECT_POPUPS:", 18)) { + LYSelectPopups = is_true(buffer+18); + } + break; -#if defined(VMS) && defined(VAXC) && !defined(__DECC) - } else if (!strncasecomp(buffer, "DEFAULT_VIRTUAL_MEMORY_SIZE:", 28)) { - HTVirtualMemorySize = atoi(buffer+28); -#endif /* VMS && VAXC && !__DECC */ + case 'V': + if (!strncasecomp(buffer, "VI_KEYS_ALWAYS_ON:", 18)) { + vi_keys = is_true(buffer+18); - } else if (!strncasecomp(buffer, "DEFAULT_CACHE_SIZE:", 19)) { - HTCacheSize = atoi(buffer+19); + } else if (!strncasecomp(buffer, "VIEWER:", 7)) { + char *mime_type; + char *viewer; + char *environment; + + if (strlen(buffer) > 9) { + mime_type = buffer + 7; + if ((viewer = strchr(mime_type, ':')) != NULL) { + *viewer++ = '\0'; + for (i = 0, j = 0; mime_type[i]; i++) { + if (mime_type[i] != ' ') { + mime_type[j++] = TOLOWER(mime_type[i]); + } + } + mime_type[j] = '\0'; + environment = strrchr(viewer, ':'); + if ((environment != NULL) && + (strlen(viewer) > 1) && *(environment-1) != '\\') { + *environment++ = '\0'; + remove_backslashes(viewer); + /* + * If environment equals xwindows then only + * assign the presentation if there is a display + * variable. + */ + if (!strcasecomp(environment,"XWINDOWS")) { + if (getenv(DISPLAY)) + HTSetPresentation(mime_type, viewer, + 1.0, 3.0, 0.0, 0); + } else if (!strcasecomp(environment,"NON_XWINDOWS")) { + if (!getenv(DISPLAY)) + HTSetPresentation(mime_type, viewer, + 1.0, 3.0, 0.0, 0); + } else { + HTSetPresentation(mime_type, viewer, + 1.0, 3.0, 0.0, 0); + } + } else { + remove_backslashes(viewer); + HTSetPresentation(mime_type, viewer, + 1.0, 3.0, 0.0, 0); + } + } + } + } + break; + + case 'W': + if (!strncasecomp(buffer, "wais_proxy:", 11)) { + if (getenv("wais_proxy") == NULL) { +#ifdef VMS + strcpy(temp, "wais_proxy"); + Define_VMSLogical(temp, (char *)&buffer[11]); +#else + strcpy(temp, "wais_proxy="); + StrAllocCopy(wais_proxy_putenv_cmd, temp); + StrAllocCat(wais_proxy_putenv_cmd, (char *)&buffer[11]); + putenv(wais_proxy_putenv_cmd); +#endif /* VMS */ + } + } + break; + + default: + break; - } /* end of Huge if */ + } /* end of Huge switch */ } /* end of while */ fclose(fp); /* - * If any DOWNLOADER: commands have always_enabled set (:TRUE), - * make override_no_download TRUE, so that other restriction - * settings will not block presentation of a download menu - * with those always_enabled options still available. - FM + * If any DOWNLOADER: commands have always_enabled set (:TRUE), + * make override_no_download TRUE, so that other restriction + * settings will not block presentation of a download menu + * with those always_enabled options still available. - FM */ if (downloaders != NULL) { int count; lynx_html_item_type *cur_download; - for(count=0, cur_download=downloaders; cur_download != NULL; - cur_download = cur_download->next, count++) { + for (count = 0, cur_download = downloaders; + cur_download != NULL; + cur_download = cur_download->next, count++) { if (cur_download->always_enabled) { override_no_download = TRUE; break; diff --git a/src/LYShowInfo.c b/src/LYShowInfo.c index 9566967e..d2ffc786 100644 --- a/src/LYShowInfo.c +++ b/src/LYShowInfo.c @@ -247,6 +247,10 @@ PUBLIC int showinfo ARGS4( fprintf(fp0, "<dt> <em>URL:</em> %s\n", Address); + if (HTLoadedDocumentCharset()) + fprintf(fp0, "<dt><em> Charset:</em> %s\n", + HTLoadedDocumentCharset()); + if ((cp = HText_getServer()) != NULL && *cp != '\0') fprintf(fp0, "<dt><em> Server:</em> %s\n", cp); diff --git a/src/LYStructs.h b/src/LYStructs.h index 6ef5d8a7..12ad43be 100644 --- a/src/LYStructs.h +++ b/src/LYStructs.h @@ -30,10 +30,11 @@ typedef struct _document { char * address; char * post_data; char * post_content_type; - int link; - int line; + BOOL safe; BOOL isHEAD; char * bookmark; + int link; + int line; } document; #ifndef HTFORMS_H @@ -45,12 +46,18 @@ typedef struct _histstruct { char * address; char * post_data; char * post_content_type; + BOOL safe; + char * bookmark; + BOOL isHEAD; int link; int page; - BOOL isHEAD; - char * bookmark; } histstruct; +typedef struct _VisitedLink { + char * title; + char * address; +} VisitedLink; + extern histstruct history[MAXHIST]; extern int nhist; diff --git a/src/LYTraversal.c b/src/LYTraversal.c index a12c8ebe..255d8dae 100644 --- a/src/LYTraversal.c +++ b/src/LYTraversal.c @@ -100,18 +100,12 @@ PUBLIC void dump_traversal_history NOARGS int x; FILE *ifp; + if (nhist <= 0) + return; + if ((ifp = fopen(TRAVERSE_FILE,"a+")) == NULL) { perror("unable to open traversal file"); - (void) signal(SIGHUP, SIG_DFL); - (void) signal(SIGTERM, SIG_DFL); -#ifndef VMS - (void) signal(SIGINT, SIG_DFL); -#endif /* !VMS */ -#ifdef SIGTSTP - if (no_suspend) - (void) signal(SIGTSTP,SIG_DFL); -#endif /* SIGTSTP */ - exit(-1); + return; } fprintf(ifp, "\n\nTRAVERSAL WAS INTERUPTED\n\n\ diff --git a/src/LYUtils.c b/src/LYUtils.c index d1cf11f7..c003579e 100644 --- a/src/LYUtils.c +++ b/src/LYUtils.c @@ -73,7 +73,9 @@ PUBLIC HTList * sug_filenames = NULL; /* Suggested filenames */ /* * highlight (or unhighlight) a given link */ -PUBLIC void highlight ARGS2(int,flag, int,cur) +PUBLIC void highlight ARGS2( + int, flag, + int, cur) { char buffer[200]; int i; @@ -109,7 +111,8 @@ PUBLIC void highlight ARGS2(int,flag, int,cur) int avail_space = (LYcols-links[cur].lx)-1; LYstrncpy(buffer, - links[cur].hightext, + (links[cur].hightext ? + links[cur].hightext : ""), (avail_space > links[cur].form->size ? links[cur].form->size : avail_space)); addstr(buffer); @@ -123,7 +126,10 @@ PUBLIC void highlight ARGS2(int,flag, int,cur) /* copy into the buffer only what will fit within the * width of the screen */ - LYstrncpy(buffer,links[cur].hightext, LYcols-links[cur].lx-1); + LYstrncpy(buffer, + (links[cur].hightext ? + links[cur].hightext : ""), + LYcols-links[cur].lx-1); addstr(buffer); } @@ -151,7 +157,7 @@ PUBLIC void highlight ARGS2(int,flag, int,cur) start_bold(); } - for (i=0; (tmp[0] = links[cur].hightext2[i]) != '\0' && + for (i = 0; (tmp[0] = links[cur].hightext2[i]) != '\0' && i+links[cur].hightext2_offset < LYcols; i++) { if (!IsSpecialAttrChar(links[cur].hightext2[i])) { /* For CJK strings, by Masanobu Kimura */ @@ -193,7 +199,8 @@ PUBLIC void highlight ARGS2(int,flag, int,cur) * free_and_clear will free a pointer if it is non-zero and * then set it to zero */ -PUBLIC void free_and_clear ARGS1(char **,pointer) +PUBLIC void free_and_clear ARGS1( + char **, pointer) { if (*pointer) { free(*pointer); @@ -205,7 +212,8 @@ PUBLIC void free_and_clear ARGS1(char **,pointer) /* * Collapse (REMOVE) all spaces in the string. */ -PUBLIC void collapse_spaces ARGS1(char *,string) +PUBLIC void collapse_spaces ARGS1( + char *, string) { int i=0; int j=0; @@ -214,7 +222,7 @@ PUBLIC void collapse_spaces ARGS1(char *,string) return; for (; string[i] != '\0'; i++) - if (!isspace(string[i])) + if (!isspace((unsigned char)string[i])) string[j++] = string[i]; string[j] = '\0'; /* terminate */ @@ -226,7 +234,8 @@ PUBLIC void collapse_spaces ARGS1(char *,string) * (ignore newlines if the preceding character is a space) and convert * tabs to single spaces (but don't ignore any explicit tabs or spaces). */ -PUBLIC void convert_to_spaces ARGS1(char *,string) +PUBLIC void convert_to_spaces ARGS1( + char *, string) { char *s = string; char *ns = string; @@ -263,11 +272,26 @@ PUBLIC void convert_to_spaces ARGS1(char *,string) } /* + * Strip trailing slashes from directory paths. + */ +PUBLIC char * strip_trailing_slash ARGS1( + char *, dirname) +{ + int i; + + i = strlen(dirname) - 1; + while (i >= 0 && dirname[i] == '/') + dirname[i--] = '\0'; + return(dirname); +} + +/* * display (or hide) the status line */ BOOLEAN mustshow = FALSE; -PUBLIC void statusline ARGS1(char *,text) +PUBLIC void statusline ARGS1( + char *, text) { char buffer[256]; unsigned char *temp = NULL; @@ -303,7 +327,7 @@ PUBLIC void statusline ARGS1(char *,text) if ((buffer[0] != '\0') && (LYHaveCJKCharacterSet)) { /* - * Translate or filter any escape sequences. + * Translate or filter any escape sequences. - FM */ if ((temp = (unsigned char *)calloc(1, strlen(text) + 1)) == NULL) outofmem(__FILE__, "statusline"); @@ -321,7 +345,7 @@ PUBLIC void statusline ARGS1(char *,text) } /* - * Deal with any newlines or tabs in the string. + * Deal with any newlines or tabs in the string. - FM */ convert_to_spaces((char *)temp); @@ -356,26 +380,34 @@ PUBLIC void statusline ARGS1(char *,text) } buffer[len] = '\0'; /* - * Deal with any newlines or tabs in the string. + * Deal with any newlines or tabs in the string. - FM */ convert_to_spaces(buffer); } /* - * Move to the statusline window and output the text highlighted. + * Move to the desired statusline window and + * output the text highlighted. - FM */ - if (user_mode == NOVICE_MODE) - move(LYlines-3,0); - else - move(LYlines-1,0); + if (LYStatusLine >= 0) { + if (LYStatusLine < LYlines-1) { + move(LYStatusLine, 0); + } else { + move(LYlines-1, 0); + } + } else if (user_mode == NOVICE_MODE) { + move(LYlines-3, 0); + } else { + move(LYlines-1, 0); + } clrtoeol(); if (text != NULL) { start_reverse(); addstr(buffer); stop_reverse(); } - refresh(); + return; } @@ -400,7 +432,8 @@ PUBLIC void toggle_novice_line NOARGS return; } -PUBLIC void noviceline ARGS1(int,more) +PUBLIC void noviceline ARGS1( + int, more) { if (dump_output_immediately) @@ -534,10 +567,11 @@ PUBLIC int HTCheckForInterrupt NOARGS * A file URL for a remote host is an obsolete ftp URL. * Return YES only if we're certain it's a local file. - FM */ -PUBLIC BOOLEAN LYisLocalFile ARGS1(char *,filename) +PUBLIC BOOLEAN LYisLocalFile ARGS1( + char *, filename) { - char *host=NULL; - char *access=NULL; + char *host = NULL; + char *access = NULL; char *cp; if (!filename) @@ -576,9 +610,10 @@ PUBLIC BOOLEAN LYisLocalFile ARGS1(char *,filename) * Utility for checking URLs with a host field. * Return YES only if we're certain it's the local host. - FM */ -PUBLIC BOOLEAN LYisLocalHost ARGS1(char *,filename) +PUBLIC BOOLEAN LYisLocalHost ARGS1( + char *, filename) { - char *host=NULL; + char *host = NULL; char *cp; if (!filename) @@ -590,7 +625,7 @@ PUBLIC BOOLEAN LYisLocalHost ARGS1(char *,filename) return NO; } - if ((cp=strchr(host, ':')) != NULL) + if ((cp = strchr(host, ':')) != NULL) *cp = '\0'; #ifdef VMS @@ -632,7 +667,8 @@ PUBLIC void LYLocalhostAliases_free NOARGS /* * Utility for listing hosts to be treated as local aliases. - FM */ -PUBLIC void LYAddLocalhostAlias ARGS1(char *, alias) +PUBLIC void LYAddLocalhostAlias ARGS1( + char *, alias) { char *LocalAlias; @@ -656,9 +692,10 @@ PUBLIC void LYAddLocalhostAlias ARGS1(char *, alias) * Utility for checking URLs with a host field. * Return YES only if we've listed the host as a local alias. - FM */ -PUBLIC BOOLEAN LYisLocalAlias ARGS1(char *,filename) +PUBLIC BOOLEAN LYisLocalAlias ARGS1( + char *, filename) { - char *host=NULL; + char *host = NULL; char *alias; char *cp; HTList *cur = localhost_aliases; @@ -672,7 +709,7 @@ PUBLIC BOOLEAN LYisLocalAlias ARGS1(char *,filename) return NO; } - if ((cp=strchr(host, ':')) != NULL) + if ((cp = strchr(host, ':')) != NULL) *cp = '\0'; while (NULL != (alias = (char *)HTList_nextObject(cur))) { @@ -701,8 +738,10 @@ PUBLIC BOOLEAN LYisLocalAlias ARGS1(char *,filename) ** it returns UNKNOWN_URL_TYPE. Otherwise, it returns ** 0 (not a URL). - FM */ -PUBLIC int LYCheckForProxyURL ARGS1(char *, filename) { - char *cp=filename; +PUBLIC int LYCheckForProxyURL ARGS1( + char *, filename) +{ + char *cp = filename; char *cp1; char *cp2 = NULL; @@ -713,14 +752,14 @@ PUBLIC int LYCheckForProxyURL ARGS1(char *, filename) { return(0); /* kill beginning spaces */ - while (isspace(*cp)) + while (isspace((unsigned char)*cp)) cp++; /* * Check for a colon, and if present, * see if we have proxying set up. */ - if ((cp1=strchr((cp+1), ':')) != NULL) { + if ((cp1 = strchr((cp+1), ':')) != NULL) { *cp1 = '\0'; StrAllocCopy(cp2, cp); *cp1 = ':'; @@ -731,8 +770,8 @@ PUBLIC int LYCheckForProxyURL ARGS1(char *, filename) { } FREE(cp2); cp1++; - if (isdigit(*cp1)) { - while (*cp1 && isdigit(*cp1)) + if (isdigit((unsigned char)*cp1)) { + while (*cp1 && isdigit((unsigned char)*cp1)) cp1++; if (*cp1 && *cp1 != '/') return(UNKNOWN_URL_TYPE); @@ -754,7 +793,8 @@ PUBLIC int LYCheckForProxyURL ARGS1(char *, filename) { ** Chains to LYCheckForProxyURL() if a colon ** is present but the type is not recognized. */ -PUBLIC int is_url ARGS1(char *,filename) +PUBLIC int is_url ARGS1( + char *, filename) { char *cp = filename; char *cp1; @@ -775,7 +815,7 @@ PUBLIC int is_url ARGS1(char *,filename) /* * Kill beginning spaces. */ - while (isspace(*cp)) + while (isspace((unsigned char)*cp)) cp++; if (!strncasecomp(cp, "news:", 5)) { @@ -785,6 +825,13 @@ PUBLIC int is_url ARGS1(char *,filename) } return(NEWS_URL_TYPE); + } else if (!strncasecomp(cp, "nntp:", 5)) { + if (strncmp(cp, "nntp", 4)) { + for (i = 0; i < 4; i++) + cp[i] = TOLOWER(cp[i]); + } + return(NNTP_URL_TYPE); + } else if (!strncasecomp(cp, "snews:", 6)) { if (strncmp(cp, "snews", 5)) { for (i = 0; i < 5; i++) @@ -799,6 +846,19 @@ PUBLIC int is_url ARGS1(char *,filename) } return(MAILTO_URL_TYPE); + } else if (!strncasecomp(cp, "file:", 5)) { + if (strncmp(cp, "file", 4)) { + for (i = 0; i < 4; i++) + cp[i] = TOLOWER(cp[i]); + } + if (LYisLocalFile(cp)) { + return(FILE_URL_TYPE); + } else if (cp[5] == '/' && cp[6] == '/') { + return(FTP_URL_TYPE); + } else { + return(0); + } + } else if (!strncasecomp(cp, "data:", 5)) { if (strncmp(cp, "data", 4)) { for (i = 0; i < 4; i++) @@ -920,9 +980,19 @@ PUBLIC int is_url ARGS1(char *,filename) } return(LYNXIMGMAP_URL_TYPE); - } else if (strstr((cp+3), ":/") == NULL) { + } else if (!strncasecomp(cp, "LYNXCOOKIE:", 11)) { /* - * If it doesn't contain ":/", and it's not one of the + * Special Internal Lynx type. + */ + if (strncmp(cp, "LYNXCOOKIE", 10)) { + for (i = 0; i < 10; i++) + cp[i] = TOUPPER(cp[i]); + } + return(LYNXCOOKIE_URL_TYPE); + + } else if (strstr((cp+3), "://") == NULL) { + /* + * If it doesn't contain "://", and it's not one of the * the above, it can't be a URL with a scheme we know, * so check if it's an unknown scheme for which proxying * has been set up. - FM @@ -943,25 +1013,6 @@ PUBLIC int is_url ARGS1(char *,filename) } return(HTTP_URL_TYPE); - } else if (!strncasecomp(cp, "file:", 5)) { - if (strncmp(cp, "file", 4)) { - for (i = 0; i < 4; i++) - cp[i] = TOLOWER(cp[i]); - } - /* - * We won't expend the overhead here of - * determining whether it's really an - * ftp URL unless we are restricting - * ftp access, in which case getfile() - * needs to know in order to issue an - * appropriate statusline message and - * and return NULLFILE. - */ - if ((ftp_ok) || LYisLocalFile(cp)) - return(FILE_URL_TYPE); - else - return(FTP_URL_TYPE); - } else if (!strncasecomp(cp, "gopher:", 7)) { if (strncmp(cp, "gopher", 6)) { for (i = 0; i < 6; i++) @@ -1017,13 +1068,6 @@ PUBLIC int is_url ARGS1(char *,filename) } return(RLOGIN_URL_TYPE); - } else if (!strncasecomp(cp, "nntp:", 5)) { - if (strncmp(cp, "nntp", 4)) { - for (i = 0; i < 4; i++) - cp[i] = TOLOWER(cp[i]); - } - return(NNTP_URL_TYPE); - } else if (!strncasecomp(cp, "cso:", 4)) { if (strncmp(cp, "cso", 3)) { for (i = 0; i < 3; i++) @@ -1064,7 +1108,8 @@ PUBLIC int is_url ARGS1(char *,filename) /* * Remove backslashes from any string. */ -PUBLIC void remove_backslashes ARGS1(char *,buf) +PUBLIC void remove_backslashes ARGS1( + char *, buf) { char *cp; @@ -1090,7 +1135,8 @@ PUBLIC void remove_backslashes ARGS1(char *,buf) * string using single quotes, escaping the real single quotes * with double quotes. This may be gross but it seems to work. */ -PUBLIC char * quote_pathname ARGS1(char *, pathname) +PUBLIC char * quote_pathname ARGS1( + char *, pathname) { int i, n = 0; char * result; @@ -1137,7 +1183,7 @@ PUBLIC BOOLEAN inlocaldomain NOARGS int n; FILE *fp; struct utmp me; - char *cp, *mytty=NULL; + char *cp, *mytty = NULL; char *ttyname(); if ((cp=ttyname(0))) @@ -1190,8 +1236,19 @@ PUBLIC BOOLEAN inlocaldomain NOARGS #endif /* HAVE_TERMIO_H */ #endif /* HAVE_TERMIOS_H */ -PUBLIC void size_change ARGS1(int,sig) +PUBLIC void size_change ARGS1( + int, sig) { +#ifdef USE_SLANG + SLtt_get_screen_size(); + LYlines = SLtt_Screen_Rows; + LYcols = SLtt_Screen_Cols; + if (sig == 0) + /* + * Called from start_curses(). + */ + return; +#else /* Curses: */ #ifndef NO_SIZECHANGE #ifdef TIOCGSIZE struct ttysize win; @@ -1204,11 +1261,7 @@ PUBLIC void size_change ARGS1(int,sig) #ifdef TIOCGSIZE if (ioctl(0, TIOCGSIZE, &win) == 0) { if (win.ts_lines != 0) { -#ifdef USE_SLANG - LYlines = win.ts_lines; -#else LYlines = win.ts_lines - 1; -#endif /* USE_SLANG */ } if (win.ts_cols != 0) { LYcols = win.ts_cols; @@ -1218,11 +1271,7 @@ PUBLIC void size_change ARGS1(int,sig) #ifdef TIOCGWINSZ if (ioctl(0, TIOCGWINSZ, &win) == 0) { if (win.ws_row != 0) { -#ifdef USE_SLANG - LYlines = win.ws_row; -#else LYlines = win.ws_row - 1; -#endif /* USE_SLANG */ } if (win.ws_col != 0) { LYcols = win.ws_col; @@ -1236,12 +1285,6 @@ PUBLIC void size_change ARGS1(int,sig) LYlines = 24; if (LYcols <= 0) LYcols = 80; - -#ifdef USE_SLANG - SLtt_Screen_Rows = LYlines; - SLtt_Screen_Cols = LYcols; - if (sig == 0) - return; /* called from start_curses */ #endif /* USE_SLANG */ recent_sizechange = TRUE; @@ -1275,7 +1318,8 @@ PUBLIC void HTSugFilenames_free NOARGS * Utility for listing suggested filenames, making any * repeated filenanmes the most current in the list. - FM */ -PUBLIC void HTAddSugFilename ARGS1(char *, fname) +PUBLIC void HTAddSugFilename ARGS1( + char *, fname) { char *new; char *old; @@ -1312,7 +1356,8 @@ PUBLIC void HTAddSugFilename ARGS1(char *, fname) * CHANGE_SUG_FILENAME -- Foteos Macrides 29-Dec-1993 * Upgraded for use with Lynx2.2 - FM 17-Jan-1994 */ -PUBLIC void change_sug_filename ARGS1(char *,fname) +PUBLIC void change_sug_filename ARGS1( + char *, fname) { char *temp, *cp, *cp1, *end; int len; @@ -1525,11 +1570,12 @@ PUBLIC void change_sug_filename ARGS1(char *,fname) /* * To create standard temporary file names */ -PUBLIC void tempname ARGS2(char *,namebuffer, int,action) +PUBLIC void tempname ARGS2( + char *, namebuffer, + int, action) { static int counter = 0; - if (action == REMOVE_FILES) { /* REMOVE ALL FILES */ for (; counter > 0; counter--) { sprintf(namebuffer, "%sL%d%uTMP.txt", lynx_temp_space, @@ -1552,7 +1598,8 @@ PUBLIC void tempname ARGS2(char *,namebuffer, int,action) /* * Convert 4, 6, 2, 8 to left, right, down, up, etc. */ -PUBLIC int number2arrows ARGS1(int,number) +PUBLIC int number2arrows ARGS1( + int, number) { switch(number) { case '1': @@ -1671,7 +1718,8 @@ PRIVATE BOOLEAN *restrict_flag[] = { #endif /* DIRED_SUPPORT */ (BOOLEAN *) 0 }; -PUBLIC void parse_restrictions ARGS1(char *,s) +PUBLIC void parse_restrictions ARGS1( + char *, s) { char *p; char *word; @@ -1729,7 +1777,7 @@ PUBLIC void parse_restrictions ARGS1(char *,s) p = s; while (*p) { - while (isspace(*p)) + while (isspace((unsigned char)*p)) p++; if (*p == '\0') break; @@ -1797,7 +1845,10 @@ PUBLIC int LYCheckMail NOARGS } user[userlen] = '\0'; while (user[0] && - isspace(user[--userlen])) /* suck up trailing spaces */ + /* + * Suck up trailing spaces. + */ + isspace((unsigned char)user[--userlen])) user[userlen] = '\0'; } @@ -1881,14 +1932,56 @@ PUBLIC int LYCheckMail NOARGS #endif /* VMS */ /* +** This function ensures that an href will be +** converted to a fully resolved, absolute URL, +** with guessing of the host or expansions of +** lead tildes via LYConvertToURL() if needed, +** and tweaking/simplifying via HTParse(). It +** is used for LynxHome, startfile, homepage, +** an 'g'oto entries, after they have been +** passed to LYFillLocalFileURL(). - FM +*/ +PUBLIC void LYEnsureAbsoluteURL ARGS2( + char **, href, + char *, name) +{ + char *temp = NULL; + + if (!(*href && *(*href))) + return; + + /* + * If it is not a URL then make it one. + */ + if (!strcasecomp(*href, "news:")) { + StrAllocCat(*href, "*"); + } else if (!strcasecomp(*href, "nntp:") || + !strcasecomp(*href, "snews:")) { + StrAllocCat(*href, "/*"); + } + if (!is_url(*href)) { + if (TRACE) + fprintf(stderr, "%s%s'%s' is not a URL\n", + (name ? name : ""), (name ? " " : ""), *href); + LYConvertToURL(href); + } + if ((temp = HTParse(*href, "", PARSE_ALL)) != NULL && *temp != '\0') + StrAllocCopy(*href, temp); + FREE(temp); +} + +/* * Rewrite and reallocate a previously allocated string * as a file URL if the string resolves to a file or * directory on the local system, otherwise as an * http URL. - FM */ -PUBLIC void LYConvertToURL ARGS1(char **, AllocatedString) +PUBLIC void LYConvertToURL ARGS1( + char **, AllocatedString) { char *old_string = *AllocatedString; + char *temp = NULL; + char *cp = NULL; if (!old_string || *old_string == '\0') return; @@ -1897,11 +1990,12 @@ PUBLIC void LYConvertToURL ARGS1(char **, AllocatedString) StrAllocCopy(*AllocatedString,"file://localhost"); if (*old_string != '/') { + char *fragment = NULL; #ifdef VMS /* * Not a SHELL pathspec. Get the full VMS spec and convert it. */ - char *cp, *cur_dir=NULL; + char *cur_dir = NULL; static char url_file[256], file_name[256], dir_name[256]; unsigned long context = 0; $DESCRIPTOR(url_file_dsc, url_file); @@ -1909,14 +2003,25 @@ PUBLIC void LYConvertToURL ARGS1(char **, AllocatedString) if (*old_string == '~') { /* * On VMS, we'll accept '~' on the command line as - * $HOME, and assume the rest of the path, if any, - * has SHELL syntax. + * Home_Dir(), and assume the rest of the path, if + * any, has SHELL syntax. */ - StrAllocCat(*AllocatedString, HTVMS_wwwName(getenv("HOME"))); - if (old_string[1]) - StrAllocCat(*AllocatedString, (old_string+1)); + StrAllocCat(*AllocatedString, HTVMS_wwwName((char *)Home_Dir())); + if ((cp = strchr(old_string, '/')) != NULL) { + /* + * Append rest of path, if present, skipping "user" if + * "~user" was entered, simplifying, and eliminating + * any residual relative elements. - FM + */ + StrAllocCopy(temp, cp); + LYTrimRelFromAbsPath(temp); + StrAllocCat(*AllocatedString, temp); + FREE(temp); + } goto have_VMS_URL; } else { + if ((fragment = strchr(old_string, '#')) != NULL) + *fragment = '\0'; strcpy(url_file, old_string); } url_file_dsc.dsc$w_length = (short) strlen(url_file); @@ -1925,36 +2030,52 @@ PUBLIC void LYConvertToURL ARGS1(char **, AllocatedString) /* * We found the file. Convert to a URL pathspec. */ - if ((cp=strchr(file_name, ';')) != NULL) { + if ((cp = strchr(file_name, ';')) != NULL) { *cp = '\0'; } for (cp = file_name; *cp; cp++) { *cp = TOLOWER(*cp); } StrAllocCat(*AllocatedString, HTVMS_wwwName(file_name)); - if ((cp=strchr(old_string, ';')) != NULL) { + if ((cp = strchr(old_string, ';')) != NULL) { StrAllocCat(*AllocatedString, cp); } + if (fragment != NULL) { + *fragment = '#'; + StrAllocCat(*AllocatedString, fragment); + fragment = NULL; + } } else if ((NULL != getcwd(dir_name, 255, 0)) && 0 == chdir(old_string)) { /* * Probably a directory. Try converting that. */ StrAllocCopy(cur_dir, dir_name); + if (fragment != NULL) { + *fragment = '#'; + } if (NULL != getcwd(dir_name, 255, 0)) { /* * Yup, we got it! */ + for (cp = dir_name; *cp; cp++) { + *cp = TOLOWER(*cp); + } StrAllocCat(*AllocatedString, dir_name); + if (fragment != NULL) { + StrAllocCat(*AllocatedString, fragment); + fragment = NULL; + } } else { /* * Nope. Assume it's an http URL with * the "http://" defaulted, if we can't * rule out a bad VMS path. */ + fragment = NULL; if (strchr(old_string, '[') || - ((cp=strchr(old_string, ':')) != NULL && - !isdigit(cp[1])) || + ((cp = strchr(old_string, ':')) != NULL && + !isdigit((unsigned char)cp[1])) || !LYExpandHostForURL((char **)&old_string, URLDomainPrefixes, URLDomainSuffixes)) { @@ -1990,9 +2111,13 @@ PUBLIC void LYConvertToURL ARGS1(char **, AllocatedString) * with the "http://" defaulted, if we can't * rule out a bad VMS path. */ + if (fragment != NULL) { + *fragment = '#'; + fragment = NULL; + } if (strchr(old_string, '[') || - ((cp=strchr(old_string, ':')) != NULL && - !isdigit(cp[1])) || + ((cp = strchr(old_string, ':')) != NULL && + !isdigit((unsigned char)cp[1])) || !LYExpandHostForURL((char **)&old_string, URLDomainPrefixes, URLDomainSuffixes)) { @@ -2031,11 +2156,19 @@ have_VMS_URL: #else /* Unix: */ if (*old_string == '~') { /* - * On Unix, covert '~' to $HOME. + * On Unix, covert '~' to Home_Dir(). */ - StrAllocCat(*AllocatedString, getenv("HOME")); - if (old_string[1]) { - StrAllocCat(*AllocatedString, (old_string+1)); + StrAllocCat(*AllocatedString, Home_Dir()); + if ((cp = strchr(old_string, '/')) != NULL) { + /* + * Append rest of path, if present, skipping "user" if + * "~user" was entered, simplifying, and eliminating + * any residual relative elements. - FM + */ + StrAllocCopy(temp, cp); + LYTrimRelFromAbsPath(temp); + StrAllocCat(*AllocatedString, temp); + FREE(temp); } if (TRACE) { fprintf(stderr, "Converted '%s' to '%s'\n", @@ -2046,22 +2179,64 @@ have_VMS_URL: * Create a full path to the current default directory. */ char curdir[DIRNAMESIZE]; - char *temp=NULL; struct stat st; - FILE *fptemp=NULL; + FILE *fptemp = NULL; + BOOL is_local = FALSE; #ifdef NO_GETCWD getwd (curdir); #else getcwd (curdir, DIRNAMESIZE); #endif /* NO_GETCWD */ + /* + * Concatenate and simplify, trimming any + * residual relative elements. - FM + */ StrAllocCopy(temp, curdir); StrAllocCat(temp, "/"); StrAllocCat(temp, old_string); + LYTrimRelFromAbsPath(temp); if (TRACE) { fprintf(stderr, "Converted '%s' to '%s'\n", old_string, temp); } - if ((stat(temp, &st) < 0) && - !(fptemp=fopen(temp, "r"))) { + if ((stat(temp, &st) > -1) || + (fptemp = fopen(temp, "r")) != NULL) { + /* + * It is a subdirectory or file on the local system. + */ + StrAllocCat(*AllocatedString, temp); + if (TRACE) { + fprintf(stderr, "Converted '%s' to '%s'\n", + old_string, *AllocatedString); + } + is_local = TRUE; + } else { + if ((fragment = strchr(temp, '#')) != NULL) + *fragment = '\0'; + StrAllocCopy(cp, temp); + HTUnEscape(cp); + if ((stat(cp, &st) > -1) || + (fptemp = fopen(cp, "r")) != NULL) { + /* + * It is a subdirectory of file on the local system + * with escaped characters and/or a fragment to be + * appended to the URL. - FM + */ + *fragment = '#'; + fragment = NULL; + StrAllocCat(*AllocatedString, temp); + if (TRACE) { + fprintf(stderr, "Converted '%s' to '%s'\n", + old_string, *AllocatedString); + } + is_local = TRUE; + } + FREE(cp); + if (fragment != NULL) { + *fragment = '#'; + fragment = NULL; + } + } + if (is_local == FALSE) { /* * It's not an accessible subdirectory or file on the * local system, so assume it's a URL request and guess @@ -2085,15 +2260,6 @@ have_VMS_URL: if (TRACE) { fprintf(stderr, "Trying: '%s'\n", *AllocatedString); } - } else { - /* - * It is a subdirectory or file on the local system. - */ - StrAllocCat(*AllocatedString, temp); - if (TRACE) { - fprintf(stderr, "Converted '%s' to '%s'\n", - old_string, *AllocatedString); - } } FREE(temp); if (fptemp) { @@ -2103,17 +2269,56 @@ have_VMS_URL: #endif /* VMS */ } else { /* - * Path begins with a slash. Use it as is. + * Path begins with a slash. Simplify and use it. */ - StrAllocCat(*AllocatedString, old_string); + if (old_string[1] == '\0') { + /* + * Request for root. Respect it on Unix, but + * on VMS we treat that as a listing of the + * login directory. - FM + */ +#ifdef VMS + StrAllocCat(*AllocatedString, HTVMS_wwwName((char *)Home_Dir())); +#else + StrAllocCat(*AllocatedString, "/"); +#endif /* VMS */ + } else if (old_string[1] == '~') { + /* + * Has a Home_Dir() reference. Handle it + * as if there weren't a lead slash. - FM + */ +#ifdef VMS + StrAllocCat(*AllocatedString, HTVMS_wwwName((char *)Home_Dir())); +#else + StrAllocCat(*AllocatedString, Home_Dir()); +#endif /* VMS */ + if ((cp = strchr((old_string + 1), '/')) != NULL) { + /* + * Append rest of path, if present, skipping "user" if + * "~user" was entered, simplifying, and eliminating + * any residual relative elements. - FM + */ + StrAllocCopy(temp, cp); + LYTrimRelFromAbsPath(temp); + StrAllocCat(*AllocatedString, temp); + FREE(temp); + } + } else { + /* + * Normal absolute path. Simplify, trim any + * residual relative elements, and append it. - FM + */ + StrAllocCopy(temp, old_string); + LYTrimRelFromAbsPath(temp); + StrAllocCat(*AllocatedString, temp); + FREE(temp); + } if (TRACE) { fprintf(stderr, "Converted '%s' to '%s'\n", old_string, *AllocatedString); } } - if (old_string) { - FREE(old_string); - } + FREE(old_string); if (TRACE) { /* Pause so we can read the messages before invoking curses */ sleep(AlertSecs); @@ -2146,17 +2351,29 @@ PUBLIC BOOLEAN LYExpandHostForURL ARGS3( char DomainPrefix[80], *StartP, *EndP; char DomainSuffix[80], *StartS, *EndS; char *Str = NULL, *StrColon = NULL, *MsgStr = NULL; - char *Host = NULL, *HostColon = NULL; + char *Host = NULL, *HostColon = NULL, *host = NULL; char *Path = NULL; + char *Fragment = NULL; struct hostent *phost; BOOLEAN GotHost = FALSE; + BOOLEAN Startup = (helpfilepath == NULL); + + /* + * If it's a NULL or zero-length string, + * or if it begins with a slash or hash, + * don't continue pointlessly. - FM + */ + if (!(*AllocatedString) || *AllocatedString[0] == '\0' || + *AllocatedString[0] == '/' || *AllocatedString[0] == '#') { + return GotHost; + } /* - * If we were passed a NULL or zero-length string, or if it - * begins with a slash, don't continue pointlessly. - FM + * If it's a partial or relative path, + * don't continue pointlessly. - FM */ - if (!(*AllocatedString) || - *AllocatedString[0] == '\0' || *AllocatedString[0] == '/') { + if (!strncmp(*AllocatedString, "..", 2) || + !strncmp(*AllocatedString, "./", 2)) { return GotHost; } @@ -2168,7 +2385,18 @@ PUBLIC BOOLEAN LYExpandHostForURL ARGS3( */ StrAllocCopy(Str, *AllocatedString); if ((Path = strchr(Str, '/')) != NULL) { + /* + * Have a path. Any fragment should + * already be included in Path. - FM + */ *Path = '\0'; + } else if ((Fragment = strchr(Str, '#')) != NULL) { + /* + * No path, so check for a fragment and + * trim that, to be restored after filling + * in the Host[:port] field. - FM + */ + *Fragment = '\0'; } /* @@ -2177,7 +2405,8 @@ PUBLIC BOOLEAN LYExpandHostForURL ARGS3( * information so we can restore the port field after * filling in the host field. - FM */ - if ((StrColon = strrchr(Str, ':')) != NULL && isdigit(StrColon[1])) { + if ((StrColon = strrchr(Str, ':')) != NULL && + isdigit((unsigned char)StrColon[1])) { if (StrColon == Str) { FREE(Str); return GotHost; @@ -2189,14 +2418,19 @@ PUBLIC BOOLEAN LYExpandHostForURL ARGS3( * Do a DNS test on the potential host field * as presently trimmed. - FM */ + StrAllocCopy(host, Str); + HTUnEscape(host); if (LYCursesON) { StrAllocCopy(MsgStr, "Looking up "); - StrAllocCat(MsgStr, Str); + StrAllocCat(MsgStr, host); StrAllocCat(MsgStr, " first."); HTProgress(MsgStr); + } else if (Startup && !dump_output_immediately) { + fprintf(stdout, "Looking up '%s' first.\n", host); } - if ((phost = gethostbyname(Str)) != NULL) { + if ((phost = gethostbyname(host)) != NULL) { GotHost = TRUE; + FREE(host); FREE(Str); FREE(MsgStr); return GotHost; @@ -2209,6 +2443,25 @@ PUBLIC BOOLEAN LYExpandHostForURL ARGS3( */ StartP = ((prefix_list && Str[strlen(Str)-1] != '.') ? prefix_list : ""); + /* + ** If we have a prefix, but the allocated string is + ** one of the common host prefixes, make our prefix + ** a zero-length string. - FM + */ + if (*StartP && *StartP != '.') { + if (!strncasecomp(*AllocatedString, "www.", 4) || + !strncasecomp(*AllocatedString, "ftp.", 4) || + !strncasecomp(*AllocatedString, "gopher.", 7) || + !strncasecomp(*AllocatedString, "wais.", 5) || + !strncasecomp(*AllocatedString, "cso.", 4) || + !strncasecomp(*AllocatedString, "ns.", 3) || + !strncasecomp(*AllocatedString, "ph.", 3) || + !strncasecomp(*AllocatedString, "finger.", 7) || + !strncasecomp(*AllocatedString, "news.", 5) || + !strncasecomp(*AllocatedString, "nntp.", 5)) { + StartP = ""; + } + } while ((*StartP) && (WHITE(*StartP) || *StartP == ',')) { StartP++; /* Skip whitespace and separators */ } @@ -2249,16 +2502,20 @@ PUBLIC BOOLEAN LYExpandHostForURL ARGS3( } StrAllocCat(Host, DomainSuffix); if ((HostColon = strrchr(Host, ':')) != NULL && - isdigit(HostColon[1])) { + isdigit((unsigned char)HostColon[1])) { *HostColon = '\0'; } + StrAllocCopy(host, Host); + HTUnEscape(host); if (LYCursesON) { StrAllocCopy(MsgStr, "Looking up "); - StrAllocCat(MsgStr, Host); + StrAllocCat(MsgStr, host); StrAllocCat(MsgStr, ", guessing..."); HTProgress(MsgStr); + } else if (Startup && !dump_output_immediately) { + fprintf(stdout, "Looking up '%s', guessing...\n", host); } - GotHost = ((phost = gethostbyname(Host)) != NULL); + GotHost = ((phost = gethostbyname(host)) != NULL); if (HostColon != NULL) { *HostColon = ':'; } @@ -2270,11 +2527,12 @@ PUBLIC BOOLEAN LYExpandHostForURL ARGS3( if (TRACE) { fprintf(stderr, "*** LYExpandHostForURL interrupted while %s failed to resolve\n", - Host); + host); } FREE(Str); FREE(MsgStr); FREE(Host); + FREE(host); return FALSE; /* We didn't find a valid name. */ } @@ -2323,6 +2581,10 @@ PUBLIC BOOLEAN LYExpandHostForURL ARGS3( if (Path) { *Path = '/'; StrAllocCat(Host, Path); + } else if (Fragment) { + StrAllocCat(Host, "/"); + *Fragment = '#'; + StrAllocCat(Host, Fragment); } StrAllocCopy(*AllocatedString, Host); } @@ -2333,6 +2595,7 @@ PUBLIC BOOLEAN LYExpandHostForURL ARGS3( FREE(Str); FREE(MsgStr); FREE(Host); + FREE(host); return GotHost; } @@ -2442,6 +2705,83 @@ PUBLIC BOOLEAN LYAddSchemeForURL ARGS2( } /* + * This function expects an absolute Unix or VMS SHELL path + * spec as an allocated string, simplifies it, and trims out + * any residual relative elements. It also checks whether + * the path had a terminal slash, and if it didn't, makes + * sure that the simplified path doesn't either. If it's + * a directory, our convention is to exclude "Up to parent" + * links when a terminal slash is present. - FM + */ +PUBLIC void LYTrimRelFromAbsPath ARGS1( + char *, path) +{ + char *cp; + int i; + BOOL TerminalSlash; + + /* + * Make sure we have a pointer to an absolute path. - FM + */ + if (path == NULL || *path != '/') + return; + + /* + * Check whether the path has a terminal slash. - FM + */ + TerminalSlash = (path[(strlen(path) - 1)] == '/'); + + /* + * Simplify the path and then do any necessary trimming. - FM + */ + HTSimplify(path); + cp = path; + while (cp[1] == '.') { + if (cp[2] == '\0') { + /* + * Eliminate trailing dot. - FM + */ + cp[1] = '\0'; + } else if (cp[2] == '/') { + /* + * Skip over the "/." of a "/./". - FM + */ + cp += 2; + } else if (cp[2] == '.' && cp[3] == '\0') { + /* + * Eliminate trailing dotdot. - FM + */ + cp[1] = '\0'; + } else if (cp[2] == '.' && cp[3] == '/') { + /* + * Skip over the "/.." of a "/../". - FM + */ + cp += 3; + } else { + /* + * Done trimming. - FM + */ + break; + } + } + + /* + * Load any shifts into path, and eliminate any + * terminal slash created by HTSimplify() or our + * walk, but not present originally. - FM + */ + if (cp > path) { + for (i = 0; cp[i] != '\0'; i++) + path[i] = cp[i]; + path[i] = '\0'; + } + if (TerminalSlash == FALSE && + path[(strlen(path) - 1)] == '/') { + path[(strlen(path) - 1)] = '\0'; + } +} + +/* * Example Client-Side Include interface. * * This is called from SGML.c and simply returns markup for reporting @@ -2478,7 +2818,9 @@ PUBLIC void LYDoCSI ARGS3( * Define_VMSLogical -- Fote Macrides 04-Apr-1995 * Define VMS logicals in the process table. */ -PUBLIC void Define_VMSLogical ARGS2(char *, LogicalName, char *, LogicalValue) +PUBLIC void Define_VMSLogical ARGS2( + char *, LogicalName, + char *, LogicalValue) { $DESCRIPTOR(lname, ""); $DESCRIPTOR(lvalue, ""); @@ -2532,6 +2874,513 @@ PUBLIC CONST char * Home_Dir NOARGS return homedir; } +/* + * This function checks the acceptability of file paths that + * are intended to be off the home directory. The file path + * should be passed in fbuffer, together with the size of the + * buffer. The function simplifies the file path, and if it + * is acceptible, loads it into fbuffer and returns TRUE. + * Otherwise, it does not modify fbuffer and returns FALSE. + * If a subdirectory is present and the path does not begin + * with "./", that is prefixed to make the situation clear. - FM + */ +PUBLIC BOOLEAN LYPathOffHomeOK ARGS2( + char *, fbuffer, + int, fbuffer_size) +{ + char *file = NULL; + char *cp, *cp1; + + /* + * Make sure we have an fbuffer and a string in it. - FM + */ + if (!fbuffer || fbuffer_size < 2 || fbuffer[0] == '\0') { + return(FALSE); + } + StrAllocCopy(file, fbuffer); + cp = file; + + /* + * Check for an inappropriate reference to the + * home directory, and correct it if we can. - FM + */ +#ifdef VMS + if (!strncasecomp(cp, "sys$login", 9)) { + if (*(cp + 9) == '\0') { + /* + * Reject "sys$login". - FM + */ + FREE(file); + return(FALSE); + } + if (*(cp + 9) == ':') { + cp += 10; + if (*cp == '\0') { + /* + * Reject "sys$login:". Otherwise, we have + * converted "sys$login:file" to "file", or + * have left a strange path for VMS as it + * was originally. - FM + */ + FREE(file); + return(FALSE); + } + } + } +#endif /* VMS */ + if (*cp == '~') { + if (*(cp + 1) == '/') { + if (*(cp + 2) != '\0') { + if ((cp1 = strchr((cp + 2), '/')) != NULL) { + /* + * Convert "~/subdir(s)/file" + * to "./subdir(s)/file". - FM + */ + *cp = '.'; + } else { + /* + * Convert "~/file" to "file". - FM + */ + cp += 2; + } + } else { + /* + * Reject "~/". - FM + */ + FREE(file); + return(FALSE); + } + } else if ((*(cp + 1) != '\0') && + (cp1 = strchr((cp + 1), '/')) != NULL) { + cp = (cp1 - 1) ; + if (*(cp + 2) != '\0') { + if ((cp1 = strchr((cp + 2), '/')) != NULL) { + /* + * Convert "~user/subdir(s)/file" to + * "./subdir(s)/file". If user is someone + * else, we covered a spoof. Otherwise, + * we simplified. - FM + */ + *cp = '.'; + } else { + /* + * Convert "~user/file" to "file". - FM + */ + cp += 2; + } + } else { + /* + * Reject "~user/". - FM + */ + FREE(file); + return(FALSE); + } + } else { + /* + * Reject "~user". - FM + */ + FREE(file); + return(FALSE); + } + } + +#ifdef VMS + /* + * Check for VMS path specs, and reject if still present. - FM + */ + if (strchr(cp, ':') != NULL || strchr(cp, ']') != NULL) { + FREE(file); + return(FALSE); + } +#endif /* VMS */ + + /* + * Check for a URL or absolute path, and reject if present. - FM + */ + if (is_url(cp) || *cp == '/') { + FREE(file); + return(FALSE); + } + + /* + * Simplify it. - FM + */ + HTSimplify(cp); + + /* + * Check if it has a pointless "./". - FM + */ + if (!strncmp(cp, "./", 2)) { + if ((cp1 = strchr((cp + 2), '/')) == NULL) { + cp += 2; + } + } + + /* + * Check for spoofing. - FM + */ + if (*cp == '\0' || *cp == '/' || cp[(strlen(cp) - 1)] == '/' || + strstr(cp, "..") != NULL || !strcmp(cp, ".")) { + FREE(file); + return(FALSE); + } + + /* + * Load what we have at this point into fbuffer, + * trimming if too long, and claim it's OK. - FM + */ + if (fbuffer_size > 3 && strncmp(cp, "./", 2) && strchr(cp, '/')) { + /* + * We have a subdirectory and no lead "./", so + * prefix it to make the situation clear. - FM + */ + strcpy(fbuffer, "./"); + if (strlen(cp) > (fbuffer_size - 3)) + cp[(fbuffer_size - 3)] = '\0'; + strcat(fbuffer, cp); + } else { + if (strlen(cp) > (fbuffer_size - 1)) + cp[(fbuffer_size - 1)] = '\0'; + strcpy(fbuffer, cp); + } + FREE(file); + return(TRUE); +} + +/* + * This function appends fname to the home path and returns + * the full path and filename. The fname string can be just + * a filename (e.g., "lynx_bookmarks.html"), or include a + * subirectory off the home directory, in which case fname + * should begin with "./" (e.g., ./BM/lynx_bookmarks.html) + * Use LYPathOffHomeOK() to check and/or fix up fname before + * calling this function. On VMS, the resultant full path + * and filename are converted to VMS syntax. - FM + */ +PUBLIC void LYAddPathToHome ARGS3( + char *, fbuffer, + int, fbuffer_size, + char *, fname) +{ + char *home = NULL; + char *file = fname; + int len; + + /* + * Make sure we have a buffer. - FM + */ + if (!fbuffer) + return; + if (fbuffer_size < 2) { + fbuffer[0] = '\0'; + return; + } + fbuffer[(fbuffer_size - 1)] = '\0'; + + /* + * Make sure we have a file name. - FM + */ + if (!file) + file = ""; + + /* + * Set up home string and length. - FM + */ + StrAllocCopy(home, Home_Dir()); + if (!(home && *home)) + /* + * Home_Dir() has a bug if this ever happens. - FM + */ +#ifdef VMS + StrAllocCopy(home, "Error:"); +#else + StrAllocCopy(home, "/error"); +#endif /* VMS */ + len = fbuffer_size - (strlen(home) + 1); + if (len <= 0) { + /* + * Buffer is smaller than or only big enough for the home path. + * Load what fits of the home path and return. This will fail, + * but we need something in the buffer. - FM + */ + LYstrncpy(fbuffer, home, (fbuffer_size - 1)); + FREE(home); + return; + } + +#ifdef VMS + /* + * Check whether we have a subdirectory path or just a filename. - FM + */ + if (!strncmp(file, "./", 2)) { + /* + * We have a subdirectory path. - FM + */ + if (home[strlen(home)-1] == ']') { + /* + * We got the home directory, so convert it to + * SHELL syntax and append subdirectory path, + * then convert that to VMS syntax. - FM + */ + char *temp = (char *)calloc(1, + (strlen(home) + strlen(file) + 10)); + sprintf(temp, "%s%s", HTVMS_wwwName(home), (file + 1)); + sprintf(fbuffer, "%.*s", + (fbuffer_size - 1), HTVMS_name("", temp)); + FREE(temp); + } else { + /* + * This will fail, but we need something in the buffer. - FM + */ + sprintf(fbuffer, "%s%.*s", home, len, file); + } + } else { + /* + * We have a file in the home directory. - FM + */ + sprintf(fbuffer, "%s%.*s", home, len, file); + } +#else + /* + * Check whether we have a subdirectory path or just a filename. - FM + */ + sprintf(fbuffer, "%s/%.*s", home, len, + (strncmp(file, "./", 2) ? file : (file + 2))); +#endif /* VMS */ + FREE(home); +} + +/* + * This function takes a string in the format + * "Mon, 01-Jan-96 13:45:35 GMT" or + * "Mon, 1 Jan 1996 13:45:35 GMT"" + * as an argument, and returns its conversion to clock format + * (seconds since 00:00:00 Jan 1 1970), or 0 if the string + * doesn't match the expected pattern. It also returns 0 + * if the time is in the past. It is intended for handling + * 'expires' strings homologously to 'max-age' strings, for + * which 0 is the minimum, and greater values are handled + * as '[max-age seconds] + time(NULL)'. - FM + */ +PUBLIC time_t LYmktime ARGS1( + char *, string) +{ + char *s; + time_t now, clock; + int day, month, year, hour, minutes, seconds; + char *start; + char temp[8]; + + /* + * Make sure we have a string to parse. - FM + */ + if (!(string && *string)) + return(0); + s = string; + if (TRACE) + fprintf(stderr, "LYmktime: Parsing '%s'\n", s); + + /* + * Skip the "Day, " field. - FM + */ + while (*s != '\0' && *s != ',') + s++; + if (*s == '\0') + return(0); + s++; + while (*s != '\0' && isspace((unsigned char)*s)) + s++; + if (*s == '\0' || !isdigit((unsigned char)*s)) + return(0); + + /* + * Get the numeric day and convert to an integer. - FM + */ + start = s; + while (*s != '\0' && isdigit((unsigned char)*s)) + s++; + if (*s == '\0' || (s - start) > 2) + return(0); + LYstrncpy(temp, start, (int)(s - start)); + day = atoi(temp); + if (day < 1 || day > 31) + return(0); + + /* + * Get the month string and convert to an integer. - FM + */ + while (*s != '\0' && !isalpha((unsigned char)*s)) + s++; + if (*s == '\0') + return(0); + start = s; + while (*s != '\0' && isalpha((unsigned char)*s)) + s++; + if (*s == '\0' || (s - start) < 3 || (s - start) > 9) + return(0); + LYstrncpy(temp, start, 3); + switch (TOUPPER(temp[0])) { + case 'A': + if (!strcasecomp(temp, "Apr")) { + month = 4; + } else if (!strcasecomp(temp, "Aug")) { + month = 8; + } else { + return(0); + } + break; + case 'D': + if (!strcasecomp(temp, "Dec")) { + month = 12; + } else { + return(0); + } + break; + case 'F': + if (!strcasecomp(temp, "Feb")) { + month = 2; + } else { + return(0); + } + break; + case 'J': + if (!strcasecomp(temp, "Jan")) { + month = 1; + } else if (!strcasecomp(temp, "Jun")) { + month = 6; + } else if (!strcasecomp(temp, "Jul")) { + month = 7; + } else { + return(0); + } + break; + case 'M': + if (!strcasecomp(temp, "Mar")) { + month = 3; + } else if (!strcasecomp(temp, "May")) { + month = 5; + } else { + return(0); + } + break; + case 'N': + if (!strcasecomp(temp, "Nov")) { + month = 11; + } else { + return(0); + } + break; + case 'O': + if (!strcasecomp(temp, "Oct")) { + month = 10; + } else { + return(0); + } + break; + case 'S': + if (!strcasecomp(temp, "Sep")) { + month = 9; + } else { + return(0); + } + break; + default: + return(0); + } + + /* + * Get the numeric year string and convert to an integer. - FM + */ + while (*s != '\0' && !isdigit((unsigned char)*s)) + s++; + if (*s == '\0') + return(0); + start = s; + while (*s != '\0' && isdigit((unsigned char)*s)) + s++; + if (*s == '\0') + return(0); + if ((s - start) == 4) { + LYstrncpy(temp, start, 4); + } else if ((s - start) == 2) { + now = time(NULL); + LYstrncpy(temp, ((char *)ctime(&now) + 20), 2); + strncat(temp, start, 2); + temp[4] = '\0'; + } else { + return(0); + } + year = atoi(temp); + + /* + * Get the numeric hour string and convert to an integer. - FM + */ + while (*s != '\0' && !isdigit((unsigned char)*s)) + s++; + if (*s == '\0') + return(0); + start = s; + while (*s != '\0' && isdigit((unsigned char)*s)) + s++; + if (*s != ':' || (s - start) > 2) + return(0); + LYstrncpy(temp, start, (int)(s - start)); + hour = atoi(temp); + + /* + * Get the numeric minutes string and convert to an integer. - FM + */ + while (*s != '\0' && !isdigit((unsigned char)*s)) + s++; + if (*s == '\0') + return(0); + start = s; + while (*s != '\0' && isdigit((unsigned char)*s)) + s++; + if (*s != ':' || (s - start) > 2) + return(0); + LYstrncpy(temp, start, (int)(s - start)); + minutes = atoi(temp); + + /* + * Get the numeric seconds string and convert to an integer. - FM + */ + while (*s != '\0' && !isdigit((unsigned char)*s)) + s++; + if (*s == '\0') + return(0); + start = s; + while (*s != '\0' && isdigit((unsigned char)*s)) + s++; + if (*s == '\0' || (s - start) > 2) + return(0); + LYstrncpy(temp, start, (int)(s - start)); + seconds = atoi(temp); + + /* + * Convert to clock format (seconds since 00:00:00 Jan 1 1970), + * but then zero it if it's in the past. - FM + */ + month -= 3; + if (month < 0) { + month += 12; + year--; + } + day += (year - 1968)*1461/4; + day += ((((month*153) + 2)/5) - 672); + clock = (time_t)((day * 60 * 60 * 24) + + (hour * 60 * 60) + + (minutes * 60) + + seconds); + if (clock <= time(NULL)) + clock = (time_t)0; + if (TRACE && clock > 0) + fprintf(stderr, + "LYmktime: clock=%i, ctime=%s", clock, ctime(&clock)); + + return(clock); +} + #ifdef NO_PUTENV /* no putenv on the next so we use this code instead! */ @@ -2581,9 +3430,8 @@ extern int errno; extern char **environ; /* Put STRING, which is of the form "NAME=VALUE", in the environment. */ -int -putenv (string) - const char *string; +PUBLIC int putenv ARGS1( + CONST char *, string) { char *name_end = index (string, '='); register size_t size; @@ -2633,76 +3481,3 @@ putenv (string) return 0; } #endif /* NO_PUTENV */ - -#ifdef VMS -/* - * This function appends fname to the home path and returns - * the full path and filename in VMS syntax. The fname - * string can be just a filename, or include a subirectory - * off the home directory, in which chase fname should - * with "./" (e.g., ./BM/lynx_bookmarks.html). - FM - */ -PUBLIC void LYVMS_HomePathAndFilename ARGS3( - char *, fbuffer, - int, fbuffer_size, - char *, fname) -{ - char *home = NULL; - char *temp = NULL; - int len; - - /* - * Make sure we have a buffer and string. - FM - */ - if (!fbuffer) - return; - if (!(fname && *fname) || fbuffer_size < 1) { - fbuffer[0] = '\0'; - return; - } - - /* - * Set up home string and length. - FM - */ - StrAllocCopy(home, Home_Dir()); - if (!(home && *home)) - StrAllocCopy(home, "Error:"); - len = fbuffer_size - strlen(home) - 1; - if (len < 0) { - len = 0; - home[fbuffer_size] = '\0'; - } - - /* - * Check whether we have a subdirectory path or just a filename. - FM - */ - if (!strncmp(fname, "./", 2)) { - /* - * We have a subdirectory path. - FM - */ - if (home[strlen(home)-1] == ']') { - /* - * We got the home directory, so convert it to - * SHELL syntax and append subdirectory path, - * then convert that to VMS syntax. - FM - */ - temp = (char *)calloc(1, (strlen(home) + strlen(fname) + 10)); - sprintf(temp, "%s%s", HTVMS_wwwName(home), (fname + 1)); - sprintf(fbuffer, "%.*s", - (fbuffer_size - 1), HTVMS_name("", temp)); - FREE(temp); - } else { - /* - * This will fail, but we need something in the buffer. - FM - */ - sprintf(fbuffer,"%s%.*s", home, len, fname); - } - } else { - /* - * We have a file in the home directory. - FM - */ - sprintf(fbuffer,"%s%.*s", home, len, fname); - } - FREE(home); -} -#endif /* VMS */ diff --git a/src/LYUtils.h b/src/LYUtils.h index 7e91f071..05bdff41 100644 --- a/src/LYUtils.h +++ b/src/LYUtils.h @@ -8,13 +8,15 @@ #include "HTList.h" #endif /* HTLIST_H */ -/* for tempname */ -#define NEW_FILE 0 -#define REMOVE_FILES 1 - +extern void highlight PARAMS((int flag, int cur)); +extern void free_and_clear PARAMS((char **obj)); +extern void collapse_spaces PARAMS((char *string)); +extern void convert_to_spaces PARAMS((char *string)); +extern char * strip_trailing_slash PARAMS((char * dirname)); extern void statusline PARAMS((char *text)); -extern void noviceline PARAMS((int more)); extern void toggle_novice_line NOPARAMS; +extern void noviceline PARAMS((int more)); +extern int HTCheckForInterrupt NOPARAMS; extern BOOLEAN LYisLocalFile PARAMS((char *filename)); extern BOOLEAN LYisLocalHost PARAMS((char *filename)); extern void LYLocalhostAliases_free NOPARAMS; @@ -23,43 +25,49 @@ extern BOOLEAN LYisLocalAlias PARAMS((char *filename)); extern int LYCheckForProxyURL PARAMS((char *filename)); extern int is_url PARAMS((char *filename)); extern void remove_backslashes PARAMS((char *buf)); -extern void collapse_spaces PARAMS((char *string)); -extern void convert_to_spaces PARAMS((char *string)); +extern char *quote_pathname PARAMS((char *pathname)); extern BOOLEAN inlocaldomain NOPARAMS; extern void size_change PARAMS((int sig)); -extern HTList * sug_filenames; extern void HTSugFilenames_free NOPARAMS; extern void HTAddSugFilename PARAMS((char *fname)); extern void change_sug_filename PARAMS((char *fname)); extern void tempname PARAMS((char *namebuffer, int action)); -extern int HTCheckForInterrupt NOPARAMS; extern int number2arrows PARAMS((int number)); -extern void highlight PARAMS((int flag, int cur)); -extern CONST char * Home_Dir NOPARAMS; extern void parse_restrictions PARAMS((char *s)); -extern void free_and_clear PARAMS((char **obj)); -extern char * quote_pathname PARAMS((char *pathname)); extern void checkmail NOPARAMS; extern int LYCheckMail NOPARAMS; +extern void LYEnsureAbsoluteURL PARAMS((char **href, char *name)); extern void LYConvertToURL PARAMS((char **AllocatedString)); extern BOOLEAN LYExpandHostForURL PARAMS(( char **AllocatedString, char *prefix_list, char *suffix_list)); extern BOOLEAN LYAddSchemeForURL PARAMS(( char **AllocatedString, char *default_scheme)); +extern void LYTrimRelFromAbsPath PARAMS((char *path)); +extern void LYDoCSI PARAMS((char *url, CONST char *comment, char **csi)); #ifdef VMS extern void Define_VMSLogical PARAMS(( char *LogicalName, char *LogicalValue)); -extern void LYVMS_HomePathAndFilename PARAMS(( - char *fbuffer, int fbuffer_size, char * fname)); #endif /* VMS */ +extern CONST char *Home_Dir NOPARAMS; +extern BOOLEAN LYPathOffHomeOK PARAMS((char *fbuffer, int fbuffer_size)); +extern void LYAddPathToHome PARAMS(( + char *fbuffer, int fbuffer_size, char *fname)); +extern time_t LYmktime PARAMS((char *string)); +#ifdef NO_PUTENV +extern int putenv PARAMS((CONST char *string)); +#endif /* NO_PUTENV */ -/* Whether or not the status line must be shown. +/* + * Whether or not the status line must be shown. */ extern BOOLEAN mustshow; #define _statusline(msg) mustshow = TRUE, statusline(msg) -/* for is_url */ -/* universal document id types */ +/* + * For is_url(). + * + * Universal document id types. + */ #define HTTP_URL_TYPE 1 #define FILE_URL_TYPE 2 #define FTP_URL_TYPE 3 @@ -95,12 +103,27 @@ extern BOOLEAN mustshow; #define LYNXDOWNLOAD_URL_TYPE 29 #define LYNXKEYMAP_URL_TYPE 30 #define LYNXIMGMAP_URL_TYPE 31 -#define LYNXDIRED_URL_TYPE 32 +#define LYNXCOOKIE_URL_TYPE 32 +#define LYNXDIRED_URL_TYPE 33 + +#define PROXY_URL_TYPE 34 -#define PROXY_URL_TYPE 33 +#define UNKNOWN_URL_TYPE 35 -#define UNKNOWN_URL_TYPE 34 +/* + * For change_sug_filename(). + */ +extern HTList *sug_filenames; +/* + * For tempname(). + */ +#define NEW_FILE 0 +#define REMOVE_FILES 1 + +/* + * Miscellaneous. + */ #define ON 1 #define OFF 0 #define STREQ(a,b) (strcmp(a,b) == 0) diff --git a/src/LYexit.c b/src/LYexit.c index 61543393..0429c017 100644 --- a/src/LYexit.c +++ b/src/LYexit.c @@ -5,98 +5,154 @@ #include "tcp.h" #include "LYexit.h" #ifndef VMS +#include "LYGlobalDefs.h" +#include "LYUtils.h" +#include "LYSignal.h" +#include "LYClean.h" #ifdef SYSLOG_REQUESTED_URLS #include <syslog.h> #endif /* SYSLOG_REQUESTED_URLS */ #endif /* !VMS */ +#define FREE(x) if (x) {free(x); x = NULL;} + +/* + * Stack of functions to call upon exit. + */ +PRIVATE void (*callstack[ATEXITSIZE])(); +PRIVATE int topOfStack = 0; + +/* + * Flag for outofmem macro. - FM + */ +PUBLIC BOOL LYOutOfMemory = FALSE; + +/* + * Forward declarations. + */ PRIVATE void LYCompleteExit NOPARAMS; -PUBLIC void LYexit ARGS1(int, status) { /* - * Purpose: Terminates program. - * Arguments: status Exit code. - * Return Value: void - * Remarks/Portability/Dependencies/Restrictions: - * Function calls stdlib.h exit - * Revision History: - * 06-15-94 created Lynx 2-3-1 Garrett Arch Blythe + * Purpose: Terminates program. + * Arguments: status Exit code. + * Return Value: void + * Remarks/Portability/Dependencies/Restrictions: + * Function calls stdlib.h exit + * Revision History: + * 06-15-94 created Lynx 2-3-1 Garrett Arch Blythe */ +PUBLIC void LYexit ARGS1( + int, status) +{ +#ifndef VMS /* On VMS, the VMSexit() handler does these. - FM */ + if (LYOutOfMemory == TRUE) { + /* + * Ignore further interrupts. - FM + */ + (void) signal (SIGHUP, SIG_IGN); + (void) signal (SIGTERM, SIG_IGN); + (void) signal (SIGINT, SIG_IGN); +#ifndef __linux__ + (void) signal(SIGBUS, SIG_IGN); +#endif /* !__linux__ */ + (void) signal(SIGSEGV, SIG_IGN); + (void) signal(SIGILL, SIG_IGN); + + /* + * Flush all messages. - FM + */ + fflush(stderr); + fflush(stdout); /* - * Do functions registered with LYatexit + * Deal with curses, if on, and clean up. - FM */ - LYCompleteExit(); + if (LYCursesON) { + sleep(AlertSecs); + } + cleanup_sig(0); +#ifndef __linux__ + signal(SIGBUS, SIG_DFL); +#endif /* !__linux__ */ + signal(SIGSEGV, SIG_DFL); + signal(SIGILL, SIG_DFL); + } +#endif /* !VMS */ + + /* + * Do functions registered with LYatexit. - GAB + */ + LYCompleteExit(); #ifndef VMS #ifdef SYSLOG_REQUESTED_URLS - syslog(LOG_INFO, "Session over"); - closelog(); + syslog(LOG_INFO, "Session over"); + closelog(); #endif /* SYSLOG_REQUESTED_URLS */ #endif /* !VMS */ #ifdef exit -/* - * Make sure we use stdlib exit and not LYexit. - */ +/* Make sure we use stdlib exit and not LYexit. - GAB +*/ #undef exit #endif /* exit */ - exit(status); +#ifndef VMS /* On VMS, the VMSexit() handler does these. - FM */ + if (LYOutOfMemory == TRUE) { + LYOutOfMemory = FALSE; + printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT); + fflush(stdout); + } +#endif /* !VMS */ + exit(status); } /* - * Stack of functions to call upon exit. + * Purpose: Registers termination function. + * Arguments: function The function to register. + * Return Value: int 0 registered + * !0 no more space to register + * Remarks/Portability/Dependencies/Restrictions: + * Revision History: + * 06-15-94 created Lynx 2-3-1 Garrett Arch Blythe */ -PRIVATE void (*callstack[ATEXITSIZE])(); -PRIVATE int topOfStack = 0; - #ifdef __STDC__ -PUBLIC int LYatexit(void (*function)()) { +PUBLIC int LYatexit(void (*function)()) #else /* Not ANSI, ugh! */ PUBLIC int LYatexit(function) -void (*function)(); { +void (*function)(); #endif /* __STDC__ */ -/* - * Purpose: Registers termination function. - * Arguments: function The function to register. - * Return Value: int 0 registered - * !0 no more space to register - * Remarks/Portability/Dependencies/Restrictions: - * Revision History: - * 06-15-94 created Lynx 2-3-1 Garrett Arch Blythe - */ - /* - * Check for available space - */ - if(topOfStack == ATEXITSIZE) { - return(-1); - } +{ + /* + * Check for available space. + */ + if (topOfStack == ATEXITSIZE) { + return(-1); + } - /* - * Register the function. - */ - callstack[topOfStack] = function; - topOfStack++; - return(0); + /* + * Register the function. + */ + callstack[topOfStack] = function; + topOfStack++; + return(0); } -PRIVATE void LYCompleteExit NOPARAMS { /* - * Purpose: Call the functions registered with LYatexit - * Arguments: void - * Return Value: void - * Remarks/Portability/Dependencies/Restrictions: - * Revision History: - * 06-15-94 created Lynx 2-3-1 Garrett Arch Blythe + * Purpose: Call the functions registered with LYatexit + * Arguments: void + * Return Value: void + * Remarks/Portability/Dependencies/Restrictions: + * Revision History: + * 06-15-94 created Lynx 2-3-1 Garrett Arch Blythe */ - - /* - * Just loop through registered functions. - * This is reentrant if more exits occur in the registered - * functions. - */ - while(--topOfStack >= 0) { - callstack[topOfStack](); - } +PRIVATE void LYCompleteExit NOPARAMS +{ + /* + * Just loop through registered functions. + * This is reentrant if more exits occur in the registered functions. + */ + while (--topOfStack >= 0) { + callstack[topOfStack](); + } } diff --git a/src/LYrcFile.c b/src/LYrcFile.c index 9b8aaa39..4d59e861 100644 --- a/src/LYrcFile.c +++ b/src/LYrcFile.c @@ -10,7 +10,7 @@ #include "LYLeaks.h" -PUBLIC void read_rc() +PUBLIC void read_rc NOPARAMS { char line_buffer[256]; char rcfile[256]; @@ -22,121 +22,111 @@ PUBLIC void read_rc() char *MBM_cp, *MBM_cp2, *MBM_cp1; int MBM_i1, MBM_i2; - /* make a name */ -#ifdef UNIX - sprintf(rcfile,"%s/.lynxrc", Home_Dir()); /* UNIX */ + /* + * Make an RC file name. + */ +#ifdef VMS + sprintf(rcfile, "sys$login:.lynxrc"); #else - sprintf(rcfile,"sys$login:.lynxrc"); /* VMS */ -#endif /* UNIX */ + sprintf(rcfile, "%s/.lynxrc", Home_Dir()); +#endif /* VMS */ - if ((fp = fopen(rcfile,"r")) == NULL) { + /* + * Open the RC file for reading. + */ + if ((fp = fopen(rcfile, "r")) == NULL) { return; } + /* + * Process the entries. + */ while (fgets(line_buffer, 256, fp) != NULL) { - - /* remove the end /n */ + /* + * Remove the /n from the end of the line. + */ if (line_buffer[0] && line_buffer[strlen(line_buffer)-1] == '\n') line_buffer[strlen(line_buffer)-1] = '\0'; - /* remove trailing white space */ + /* + * Remove any trailing white space. + */ while (line_buffer[0] && isspace(line_buffer[strlen(line_buffer)-1])) line_buffer[strlen(line_buffer)-1] = '\0'; - /* skip any comment or blank lines */ + /* + * Skip any comment or blank lines. + */ if (line_buffer[0] == '\0' || line_buffer[0] == '#') continue; - /* find the line position of the number sign if there is one */ - if ((cp = (char *)strchr(line_buffer,'#')) == NULL) + /* + * Find the line position of the number sign if there is one. + */ + if ((cp = (char *)strchr(line_buffer, '#')) == NULL) number_sign = 999; else number_sign = cp - line_buffer; + /* + * File editor. + */ + if (!system_editor && + (cp = LYstrstr(line_buffer, "file_editor")) != NULL && + cp-line_buffer < number_sign) { - /* Character set */ - if ((cp=LYstrstr(line_buffer,"character_set"))!=NULL && - cp-line_buffer < number_sign) { - - int i=0; - - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; - - while (isspace(*cp)) cp++; /* get rid of spaces */ - - for (; LYchar_set_names[i]; i++) - if (!strncmp(cp,LYchar_set_names[i],strlen(cp))) { - current_char_set=i; - HTMLSetRawModeDefault(i); - break; - } - - /* Linedit mode */ - } else if ((cp=LYstrstr(line_buffer,"lineedit_mode"))!=NULL && - cp-line_buffer < number_sign) { - - int i=0; - - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; - - while (isspace(*cp)) cp++; /* get rid of spaces */ - - for (; LYLineeditNames[i]; i++) - if (!strncmp(cp,LYLineeditNames[i],strlen(cp))) { - current_lineedit=i; - break; - } - - /* user mode */ - } else if ((cp=LYstrstr(line_buffer,"user_mode"))!=NULL && - cp-line_buffer < number_sign) { - - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; - - while (isspace(*cp)) cp++; /* get rid of spaces */ - - if (LYstrstr(cp,"ADVANCED") != NULL) - user_mode = ADVANCED_MODE; - else if (LYstrstr(cp,"INTERMEDIATE") != NULL) - user_mode = INTERMEDIATE_MODE; - else - user_mode = NOVICE_MODE; - - /* file editor */ - } else if (!system_editor && - (cp=LYstrstr(line_buffer,"file_editor"))!=NULL && - cp-line_buffer < number_sign) { - - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; - - while (isspace(*cp)) cp++; /* get rid of spaces */ - - StrAllocCopy(editor, cp); + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + StrAllocCopy(editor, cp); - /* bookmark file */ + /* + * Default bookmark file. + */ } else if ((cp = LYstrstr(line_buffer, "bookmark_file")) != NULL && cp-line_buffer < number_sign) { if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; - + cp = cp2 + 1; while (isspace(*cp)) cp++; /* get rid of spaces */ /* - * Since this is the "default" saveto, we save it. + * Since this is the "Default Bookmark File", we save it + * as a globals, and as the first MBM_A_subbookmark entry. */ StrAllocCopy(bookmark_page, cp); StrAllocCopy(BookmarkPage, cp); StrAllocCopy(MBM_A_subbookmark[0], cp); StrAllocCopy(MBM_A_subdescript[0], MULTIBOOKMARKS_DEFAULT); + /* + * Multiple (sub)bookmark support settings. + */ + } else if ((cp = LYstrstr(line_buffer, "sub_bookmarks")) != NULL && + cp-line_buffer < number_sign) { + + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = (cp2 + 1); + while (isspace(*cp)) + cp++; /* get rid of spaces */ + if (!strncasecomp(cp, "standard", 8)) { + LYMultiBookmarks = TRUE; + LYMBMAdvanced = FALSE; + } else if (!strncasecomp(cp, "advanced", 8)) { + LYMultiBookmarks = TRUE; + LYMBMAdvanced = TRUE; + } else { + LYMultiBookmarks = FALSE; + } + + /* + * Multiple (sub)bookmark definitions and descriptions. + */ } else if ((cp = LYstrstr(line_buffer, "multi_bookmark")) != NULL && cp-line_buffer < number_sign) { + /* * Found the root, now cycle through all the * possible spaces and match specific ones. @@ -202,25 +192,17 @@ PUBLIC void read_rc() } } - /* personal_mail_address */ - } else if((cp=LYstrstr(line_buffer,"personal_mail_address"))!=NULL && - cp-line_buffer < number_sign) { - - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; - - while (isspace(*cp)) cp++; /* get rid of spaces */ - - StrAllocCopy(personal_mail_address, cp); - - } else if ((cp = LYstrstr(line_buffer,"file_sorting_method")) != NULL && - cp-line_buffer < number_sign) { - - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; - - while (isspace(*cp)) cp++; /* get rid of spaces */ + /* + * FTP/file sorting method. + */ + } else if ((cp = LYstrstr(line_buffer, + "file_sorting_method")) != NULL && + cp-line_buffer < number_sign) { + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ if (!strncasecomp(cp, "BY_FILENAME", 11)) HTfileSortMethod = FILE_BY_NAME; else if (!strncasecomp(cp, "BY_TYPE", 7)) @@ -230,182 +212,247 @@ PUBLIC void read_rc() else if (!strncasecomp(cp, "BY_DATE", 7)) HTfileSortMethod = FILE_BY_DATE; - } else if ((cp = LYstrstr(line_buffer,"case_sensitive_searching")) - != NULL && - cp-line_buffer < number_sign) { - - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; - - while (isspace(*cp)) cp++; /* get rid of spaces */ - - if (!strncasecomp(cp, "on", 2)) - case_sensitive=TRUE; - else - case_sensitive=FALSE; - -#ifdef ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS - - } else if ((cp = LYstrstr(line_buffer,"run_all_execution_links")) - != NULL && - cp-line_buffer < number_sign) { - - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; - - while (isspace(*cp)) cp++; /* get rid of spaces */ + /* + * Personal mail address. + */ + } else if ((cp = LYstrstr(line_buffer, + "personal_mail_address")) != NULL && + cp-line_buffer < number_sign) { - if (!strncasecomp(cp, "on", 2)) - local_exec=TRUE; - else - local_exec=FALSE; + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + StrAllocCopy(personal_mail_address, cp); + /* + * Searching type. + */ } else if ((cp = LYstrstr(line_buffer, - "run_execution_links_on_local_files")) != NULL && - cp-line_buffer < number_sign) { - - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; - - while (isspace(*cp)) cp++; /* get rid of spaces */ - - if (!strncasecomp(cp, "on", 2)) - local_exec_on_local_files=TRUE; - else - local_exec_on_local_files=FALSE; + "case_sensitive_searching")) != NULL && + cp-line_buffer < number_sign) { -#endif /* ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */ + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + if (!strncasecomp(cp, "on", 2)) + case_sensitive = TRUE; + else + case_sensitive = FALSE; + + /* + * Character set. + */ + } else if ((cp = LYstrstr(line_buffer, "character_set")) != NULL && + cp-line_buffer < number_sign) { - } else if ((cp=LYstrstr(line_buffer,"vi_keys"))!=NULL && - cp-line_buffer < number_sign) { + int i = 0; - if ((cp2 = (char * )strchr(cp,'=')) != NULL) - cp = cp2+1; + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + for (; LYchar_set_names[i]; i++) { + if (!strncmp(cp, LYchar_set_names[i], strlen(cp))) { + current_char_set=i; + HTMLSetRawModeDefault(i); + break; + } + } - while (isspace(*cp)) cp++; /* get rid of spaces */ - - if (!strncasecomp(cp, "on", 2)) - vi_keys=TRUE; - else - vi_keys=FALSE; + /* + * Preferred language. + */ + } else if ((cp = LYstrstr(line_buffer, + "preferred_language")) != NULL && + cp-line_buffer < number_sign) { - } else if ((cp=LYstrstr(line_buffer,"emacs_keys"))!=NULL && - cp-line_buffer < number_sign) { + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + StrAllocCopy(language, cp); - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; + /* + * Preferred charset. + */ + } else if ((cp = LYstrstr(line_buffer, + "preferred_charset")) != NULL && + cp-line_buffer < number_sign) { - while (isspace(*cp)) cp++; /* get rid of spaces */ + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + StrAllocCopy(pref_charset, cp); - if (!strncasecomp(cp, "on", 2)) - emacs_keys=TRUE; - else - emacs_keys=FALSE; + /* + * VI keys. + */ + } else if ((cp = LYstrstr(line_buffer, "vi_keys")) != NULL && + cp-line_buffer < number_sign) { - /* multi bookmarks */ - } else if ((cp = LYstrstr(line_buffer, "sub_bookmarks")) != NULL && + if ((cp2 = (char * )strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + if (!strncasecomp(cp, "on", 2)) + vi_keys = TRUE; + else + vi_keys = FALSE; + + /* + * EMACS keys. + */ + } else if ((cp = LYstrstr(line_buffer, "emacs_keys")) != NULL && cp-line_buffer < number_sign) { - if ((cp2 = (char *)strchr(cp, '=')) != NULL) - cp = (cp2 + 1); - - while (isspace(*cp)) - cp++; /* get rid of spaces */ - - if (!strncmp(cp, "on", 2) || !strncmp(cp, "ON", 2)) - LYMultiBookmarks = TRUE; - else if (!strncmp(cp, "standard", 8) || - !strncmp(cp, "STANDARD", 8)) { - LYMultiBookmarks = TRUE; - LYMBMAdvanced = FALSE; - } else if (!strncmp(cp, "advanced", 8) || - !strncmp(cp, "ADVANCED", 8)) { - LYMultiBookmarks = TRUE; - LYMBMAdvanced = TRUE; - } else - LYMultiBookmarks = FALSE; - - } else if ((cp=LYstrstr(line_buffer,"keypad_mode"))!=NULL && + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + if (!strncasecomp(cp, "on", 2)) + emacs_keys = TRUE; + else + emacs_keys=FALSE; + + /* + * Show dot files. + */ + } else if ((cp = LYstrstr(line_buffer, "show_dotfiles")) != NULL && cp-line_buffer < number_sign) { - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; - - while (isspace(*cp)) cp++; /* get rid of spaces */ - - if (LYstrstr(cp,"LINKS_ARE_NUMBERED")) - keypad_mode = LINKS_ARE_NUMBERED; - else - keypad_mode = NUMBERS_AS_ARROWS; - - /* preferred language */ - } else if ((cp=LYstrstr(line_buffer,"preferred_language"))!=NULL && - cp-line_buffer < number_sign) { - - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; - - while (isspace(*cp)) cp++; /* get rid of spaces */ - - StrAllocCopy(language, cp); - - /* preferred charset */ - } else if ((cp=LYstrstr(line_buffer,"preferred_charset"))!=NULL && - cp-line_buffer < number_sign) { + if ((cp2 = (char * )strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + if (!strncasecomp(cp, "on", 2)) + show_dotfiles = TRUE; + else + show_dotfiles = FALSE; + + /* + * Select popups. + */ + } else if ((cp = LYstrstr(line_buffer, "select_popups")) != NULL && + cp-line_buffer < number_sign) { - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; + if ((cp2 = (char * )strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + if (!strncasecomp(cp, "off", 3)) + LYSelectPopups = FALSE; + else + LYSelectPopups = TRUE; + + /* + * Keypad mode. + */ + } else if ((cp = LYstrstr(line_buffer, "keypad_mode")) != NULL && + cp-line_buffer < number_sign) { - while (isspace(*cp)) cp++; /* get rid of spaces */ + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + if (LYstrstr(cp,"LINKS_ARE_NUMBERED")) + keypad_mode = LINKS_ARE_NUMBERED; + else + keypad_mode = NUMBERS_AS_ARROWS; + + /* + * Linedit mode. + */ + } else if ((cp = LYstrstr(line_buffer, "lineedit_mode")) != NULL && + cp-line_buffer < number_sign) { - StrAllocCopy(pref_charset, cp); + int i = 0; - /* show dot files */ - } else if ((cp=LYstrstr(line_buffer,"show_dotfiles")) != NULL && - cp-line_buffer < number_sign) { + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + for (; LYLineeditNames[i]; i++) { + if (!strncmp(cp, LYLineeditNames[i], strlen(cp))) { + current_lineedit = i; + break; + } + } - if ((cp2 = (char * )strchr(cp,'=')) != NULL) - cp = cp2+1; +#ifdef DIRED_SUPPORT + /* + * List directory style. + */ + } else if ((cp = LYstrstr(line_buffer, "dir_list_style")) != NULL && + cp-line_buffer < number_sign) { - while (isspace(*cp)) cp++; /* get rid of spaces */ - - if (!strncasecomp(cp, "on", 2)) - show_dotfiles=TRUE; - else - show_dotfiles=FALSE; + if ((cp2 = (char *)strchr(cp,'=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + if (LYstrstr(cp, "FILES_FIRST") != NULL) { + dir_list_style = FILES_FIRST; + } else if (LYstrstr(cp,"DIRECTORIES_FIRST") != NULL) { + dir_list_style = 0; + } else { + dir_list_style = MIXED_STYLE; + } +#endif /* DIRED_SUPPORT */ -#ifdef DIRED_SUPPORT - /* list directory style */ - } else if ((cp=LYstrstr(line_buffer,"dir_list_style"))!=NULL && - cp-line_buffer < number_sign) { + /* + * User mode. + */ + } else if ((cp = LYstrstr(line_buffer, "user_mode")) != NULL && + cp-line_buffer < number_sign) { - if ((cp2 = (char *)strchr(cp,'=')) != NULL) - cp = cp2+1; + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + if (LYstrstr(cp, "ADVANCED") != NULL) { + user_mode = ADVANCED_MODE; + } else if (LYstrstr(cp,"INTERMEDIATE") != NULL) { + user_mode = INTERMEDIATE_MODE; + } else { + user_mode = NOVICE_MODE; + } - while (isspace(*cp)) cp++; /* get rid of spaces */ - - if (LYstrstr(cp,"FILES_FIRST") != NULL) - dir_list_style = FILES_FIRST; - else if (LYstrstr(cp,"DIRECTORIES_FIRST") != NULL) - dir_list_style = 0; - else - dir_list_style = MIXED_STYLE; +#ifdef ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS + /* + * Local execution mode - all links. + */ + } else if ((cp = LYstrstr(line_buffer, + "run_all_execution_links")) != NULL && + cp-line_buffer < number_sign) { -#endif /* DIRED_SUPPORT */ + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ - /* select popups */ - } else if ((cp=LYstrstr(line_buffer,"select_popups")) != NULL && - cp-line_buffer < number_sign) { + if (!strncasecomp(cp, "on", 2)) + local_exec = TRUE; + else + local_exec = FALSE; - if ((cp2 = (char * )strchr(cp,'=')) != NULL) - cp = cp2+1; + /* + * Local execution mode - only links in local files. + */ + } else if ((cp = LYstrstr(line_buffer, + "run_execution_links_on_local_files")) != NULL && + cp-line_buffer < number_sign) { - while (isspace(*cp)) cp++; /* get rid of spaces */ - - if (!strncasecomp(cp, "off", 3)) - LYSelectPopups = FALSE; - else - LYSelectPopups = TRUE; + if ((cp2 = (char *)strchr(cp, '=')) != NULL) + cp = cp2 + 1; + while (isspace(*cp)) + cp++; /* get rid of spaces */ + if (!strncasecomp(cp, "on", 2)) + local_exec_on_local_files = TRUE; + else + local_exec_on_local_files=FALSE; +#endif /* ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */ } /* end of if */ @@ -414,219 +461,160 @@ PUBLIC void read_rc() fclose(fp); } /* big end */ -PUBLIC int save_rc () +PUBLIC int save_rc NOPARAMS { char rcfile[256]; FILE *fp; int i; int MBM_c; - /* make a name */ -#ifdef UNIX - sprintf(rcfile,"%s/.lynxrc", Home_Dir()); /* UNIX */ -#else + /* + * Make a name. + */ #ifdef VMS - sprintf(rcfile,"sys$login:.lynxrc"); /* VMS */ + sprintf(rcfile, "sys$login:.lynxrc"); #else - sprintf(rcfile,".lynxrc"); /* anything else */ + sprintf(rcfile, "%s/.lynxrc", Home_Dir()); #endif /* VMS */ -#endif /* UNIX */ - if ((fp = fopen(rcfile,"w")) == NULL) { + /* + * Open the file for write. + */ + if ((fp = fopen(rcfile, "w")) == NULL) { return FALSE; } - /* header */ - fprintf(fp,"# Lynx user defaults file\n\n"); + /* + * Header. + */ + fprintf(fp, "# Lynx User Defaults File\n\n"); - /* user mode */ - fprintf(fp,"\ -# user_mode specifies the users level of knowledge with Lynx.\n\ -# The default is NOVICE which displays two extra lines of help at the\n\ -# bottom of the screen to aid the user in learning the basic Lynx\n\ -# commands. Set user_mode to INTERMEDIATE to turn off the extra info.\n\ -# Use ADVANCED to see the URL of the currently selected link at the\n\ -# bottom of the screen\n"); - fprintf(fp,"user_mode=%s\n\n",(user_mode==NOVICE_MODE ? "NOVICE" : - (user_mode==ADVANCED_MODE ? "ADVANCED" : - "INTERMEDIATE"))); - - /* editor */ - fprintf(fp,"\ -# file editor specifies the editor to be invoked when editing Lynx files.\n\ -# if no editor is specified then file editing is disabled unless it\n\ -# is activated from the command line\n"); - fprintf(fp,"file_editor=%s\n\n", (editor ? editor : "")); - - /* home file */ - fprintf(fp,"\ -# bookmark_file specifies the name and location of a custom file which the\n\ -# user can paste links to for easy access at a later date\n"); - fprintf(fp,"bookmark_file=%s\n\n", (bookmark_page ? bookmark_page : "")); - - /* personal_mail_address */ - fprintf(fp,"\ + /* + * File editor + */ + fprintf(fp, "\ +# file_editor specifies the editor to be invoked when editing local files\n\ +# or sending mail. If no editor is specified, then file editing is disabled\n\ +# unless it is activated from the command line, and the built-in line editor\n\ +# will be used for sending mail.\n"); + fprintf(fp, "file_editor=%s\n\n", (editor ? editor : "")); + + /* + * Default bookmark file. + */ + fprintf(fp, "\ +# bookmark_file specifies the name and location of the default bookmark\n\ +# file into which the user can paste links for easy access at a later\n\ +# date.\n"); + fprintf(fp, "bookmark_file=%s\n\n", (bookmark_page ? bookmark_page : "")); + + /* + * Multiple (sub)bookmark support settings. + */ + fprintf(fp, "\ +# If sub_bookmarks is not turned \"off\", and multiple bookmarks have\n\ +# been defined (see below), then all bookmark operations will first\n\ +# prompt the user to select an active sub-bookmark file. If the default\n\ +# Lynx bookmark_file is defined (see above), it will be used as the\n\ +# default selection. When this option is set to \"advanced\", and the\n\ +# user mode is advanced, the 'v'iew bookmark command will invoke a\n\ +# statusline prompt instead of the menu seen in novice and intermediate\n\ +# user modes. When this option is set to \"standard\", the menu will be\n\ +# presented regardless of user mode.\n"); + fprintf(fp, "sub_bookmarks=%s\n\n", (LYMultiBookmarks ? + (LYMBMAdvanced ? + "advanced" : "standard") + : "off")); + + /* + * Multiple (sub)bookmark definitions and descriptions. + */ + fprintf(fp, "\ +# The following allow you to define sub-bookmark files and descriptions.\n\ +# The format is multi_bookmark<capital_letter>=<filename>,<description>\n\ +# Up to 26 bookmark files (for the English capital letters) are allowed.\n\ +# We start with \"multi_bookmarkB\" since 'A' is the default (see above).\n"); + for (MBM_c = 1; MBM_c <= MBM_V_MAXFILES; MBM_c++) + fprintf(fp, "multi_bookmark%c=%s%s%s\n", + (MBM_c + 'A'), + (MBM_A_subbookmark[MBM_c] ? + MBM_A_subbookmark[MBM_c] : ""), + (MBM_A_subbookmark[MBM_c] ? + "," : ""), + (MBM_A_subdescript[MBM_c] ? + MBM_A_subdescript[MBM_c] : "")); + fprintf(fp, "\n"); + + /* + * FTP/file sorting method. + */ + fprintf(fp, "\ +# The file_sorting_method specifies which value to sort on when viewing\n\ +# file lists such as FTP directories. The options are:\n\ +# BY_FILENAME -- sorts on the name of the file\n\ +# BY_TYPE -- sorts on the type of the file\n\ +# BY_SIZE -- sorts on the size of the file\n\ +# BY_DATE -- sorts on the date of the file\n"); + fprintf(fp, "file_sorting_method=%s\n\n", + (HTfileSortMethod == FILE_BY_NAME ? "BY_FILENAME" + : + (HTfileSortMethod == FILE_BY_SIZE ? "BY_SIZE" + : + (HTfileSortMethod == FILE_BY_TYPE ? "BY_TYPE" + : "BY_DATE")))); + + /* + * Personal mail address. + */ + fprintf(fp, "\ # personal_mail_address specifies your personal mail address. The\n\ # address will be sent during HTTP file transfers for authorization and\n\ # logging purposes, and for mailed comments.\n\ -# If you do not want this information given out, leave this field blank\n"); - fprintf(fp,"personal_mail_address=%s\n\n", (personal_mail_address ? - personal_mail_address : "")); - - /* case sensitive */ - fprintf(fp,"\ -# if case sensitive searching is on then when the user invokes a search\n\ +# If you do not want this information given out, set the NO_FROM_HEADER\n\ +# to TRUE in lynx.cfg, or use the -nofrom command line switch. You also\n\ +# could leave this field blank, but then you won't have if it included in\n\ +# your mailed comments.\n"); + fprintf(fp, "personal_mail_address=%s\n\n", + (personal_mail_address ? personal_mail_address : "")); + + /* + * Searching type. + */ + fprintf(fp, "\ +# If case_sensitive_searching is \"on\" then when the user invokes a search\n\ # using the 's' or '/' keys, the search performed will be case sensitive\n\ -# instead of case INsensitive.\n# the default is usually off\n"); - fprintf(fp,"case_sensitive_searching=%s\n\n",(case_sensitive ? "on" : "off")); +# instead of case INsensitive. The default is usually \"off\".\n"); + fprintf(fp, "case_sensitive_searching=%s\n\n", + (case_sensitive ? "on" : "off")); - /* file sort method */ - fprintf(fp,"\ -# The file sort method specifies which value to sort on when viewing file\n\ -# lists such as FTP directories. The options are:\n\ -# BY_FILENAME -- sorts on the name of the file\n\ -# BY_TYPE -- sorts on the type of the file\n\ -# BY_SIZE -- sorts on the size of the file\n\ -# BY_DATE -- sorts on the date of the file\n"); - fprintf(fp,"file_sorting_method=%s\n\n", - (HTfileSortMethod==FILE_BY_NAME ? "BY_FILENAME" : - (HTfileSortMethod==FILE_BY_SIZE ? "BY_SIZE" : - (HTfileSortMethod==FILE_BY_TYPE ? "BY_TYPE" : - "BY_DATE")))); - - /* Character Set */ - fprintf(fp,"\ -# The character set definition controls the representation of\n\ -# 8 bit characters for your terminal. If 8 bit characters do\n\ -# not show up correctly on your screen you may try changing\n\ -# to a different 8 bit set or using the 7 bit character approximations.\n\ + /* + * Character set. + */ + fprintf(fp, "\ +# The character_set definition controls the representation of 8 bit\n\ +# characters for your terminal. If 8 bit characters do not show up\n\ +# correctly on your screen you may try changing to a different 8 bit\n\ +# set or using the 7 bit character approximations.\n\ # Current valid characters sets are:\n"); - for (i=0;LYchar_set_names[i];i++) - fprintf(fp,"# %s\n",LYchar_set_names[i]); - fprintf(fp,"character_set=%s\n\n",LYchar_set_names[current_char_set]); - + for (i = 0; LYchar_set_names[i]; i++) + fprintf(fp, "# %s\n", LYchar_set_names[i]); + fprintf(fp, "character_set=%s\n\n", LYchar_set_names[current_char_set]); -#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) - /* local_exec */ - fprintf(fp,"\ -# if run all execution links is on then all local exection links will\n\ -# be executed when they are selected.\n\ -#\n\ -# WARNING - this is potentially VERY dangerous. Since you may view\n\ -# information that is written by unknown and untrusted sources\n\ -# there exists the possibility that trojan horse links could be\n\ -# written. Trojan horse links could be written to erase files\n\ -# or compromise security. This should only be set to on if you\n\ -# are viewing trusted source information\n"); - fprintf(fp, "run_all_execution_links=%s\n\n",(local_exec ? "on" : "off")); - - /* local_exec_on_local_files */ - fprintf(fp,"\ -# if run all execution links is on then all local exection links that\n\ -# are found in LOCAL files will be executed when they are selected.\n\ -# This is different from \"run all execution links\" in that only files\n\ -# that reside on the local system will have execution link permissions\n\ -#\n\ -# WARNING - this is potentially dangerous. Since you may view\n\ -# information that is written by unknown and untrusted sources\n\ -# there exists the possibility that trojon horse links could be\n\ -# written. Trojon horse links could be written to erase files\n\ -# or compromise security. This should only be set to on if you\n\ -# are viewing trusted source information\n"); - - fprintf(fp,"run_execution_links_on_local_files=%s\n\n", - (local_exec_on_local_files ? "on" : "off")); - -#endif /* defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) */ - - /* vi keys */ - fprintf(fp,"\ -# if VI keys are turned on then the normal VI movement keys:\n\ -# j - down k - up\n\ -# h - left l - right\n\ -# will be enabled.\n\ -# These keys are only lower case.\n\ -# Capital 'H' will still activate help\n"); - fprintf(fp,"vi_keys=%s\n\n",(vi_keys ? "on" : "off")); - - /* emacs keys */ - fprintf(fp,"\ -# if EMACS keys are turned on then the normal EMACS movement keys:\n\ -# ^N - down ^p - up\n\ -# ^B - left ^F - right\n\ -# will be enabled.\n"); - fprintf(fp, "emacs_keys=%s\n\n", (emacs_keys ? "on" : "off")); - - /* multiple bookmarks - on or off */ - fprintf(fp,"\ -# If sub_bookmarks are turned on then all bookmark operations\n\ -# will first prompt the user to select an active sub-bookmark file.\n\ -# If the default lynx bookmarks file is defined, it will be used as\n\ -# the default selection. When this option is set to 'advanced', and\n\ -# the user mode is advanced, the 'v'iew bookmark command will invoke\n\ -# a statusline prompt instead of the menu seen in novice and intermediate\n\ -# user modes. When this option is set to 'standard', the menu will be\n\ -# presented regardless of user mode. If this option is set to 'off',\n\ -# sub-bookmark files are disabled.\n"); - fprintf(fp,"sub_bookmarks=%s\n\n", (LYMultiBookmarks ? - (LYMBMAdvanced ? "advanced" : "standard") : "off")); - - /* multiple bookmarks support - list out sub-bookmarks */ - fprintf(fp,"\ -# The following allow you to define sub-bookmark files and definitions.\n\ -# Format is <keyword><letter>=<filename>,<description>\n\ -# Up to MBM_V_MAXFILES (26 MAX) are allowed.\n\ -# We start with 'multi_bookmarkB' since 'A' is reserved!\n"); - for (MBM_c = 1; MBM_c <= MBM_V_MAXFILES; MBM_c++) - fprintf(fp,"multi_bookmark%c=%s%s%s\n", (MBM_c + 'A'), - (MBM_A_subbookmark[MBM_c] ? MBM_A_subbookmark[MBM_c] : ""), - (MBM_A_subbookmark[MBM_c] ? "," : ""), - (MBM_A_subdescript[MBM_c] ? MBM_A_subdescript[MBM_c] : "")); - fprintf(fp,"\n"); - - /* keypad mode */ - fprintf(fp,"\ -# if keypad_mode is set to NUMBERS_AS_ARROWS then the numbers\n\ -# on your keypad when the numlock is on will act as arrow keys.\n\ -# i.e. 4 - Left Arrow, 6 - Right Arrow, 2 - Down Arrow, 8 - Up Arrow, etc.\n\ -# if keypad_mode is set to LINKS_ARE_NUMBERED then numbers will appear\n\ -# next to each link and numbers are used to select links.\n\ -# note: some fixed format documents may look disfigured when\n\ -# LINKS_ARE_NUMBERED is enabled.\n"); - fprintf(fp,"keypad_mode=%s\n\n",(keypad_mode==NUMBERS_AS_ARROWS ? - "NUMBERS_AS_ARROWS" : "LINKS_ARE_NUMBERED")); - - /* lineedit */ - fprintf(fp,"\ -# linedit_mode specifies the key binding used for inputting strings in\n\ -# prompts and forms. if line_editmode is set to DEFAULT_BINDING then the\n\ -# following control characters are used for moving and deleting:\n\ -#\n\ -# left word char char word right Enter = Next line\n\ -# W E remove R T ^G = Cancel input\n\ -# D <- move -> F ^U = Erase line\n\ -#\n\ -# Current lineedit modes are:\n"); - - { char **bindings = LYLineeditNames; - while (*bindings) { - fprintf(fp,"# %s\n",*bindings); - bindings++; - } - } - fprintf(fp,"lineedit_mode=%s\n\n",LYLineeditNames[current_lineedit]); - - /* preferred language */ - fprintf(fp,"\ + /* + * Preferred language. + */ + fprintf(fp, "\ # preferred_language specifies the language in MIME notation (e.g., en,\n\ # fr) which Lynx will indicate you prefer in requests to http servers.\n\ # If a file in that language is available, the server will send it.\n\ # Otherwise, the server will send the file in it's default language.\n"); - fprintf(fp,"preferred_language=%s\n\n", (language ? language : "")); + fprintf(fp, "preferred_language=%s\n\n", (language ? language : "")); - /* preferred charset */ - fprintf(fp,"\ + /* + * Preferred charset. + */ + fprintf(fp, "\ # preferred_charset specifies the character set in MIME notation (e.g.,\n\ # ISO-8859-2, ISO-8859-5) which Lynx will indicate you prefer in requests\n\ # to http servers using an Accept-Charset header. The value should NOT\n\ @@ -634,31 +622,45 @@ PUBLIC int save_rc () # default. If a file in that character set is available, the server will\n\ # send it. Otherwise, the server will send the file in ISO-8859-1 or\n\ # US-ASCII.\n"); - fprintf(fp,"preferred_charset=%s\n\n", (pref_charset ? pref_charset : "")); + fprintf(fp, "preferred_charset=%s\n\n", + (pref_charset ? pref_charset : "")); + + /* + * VI keys. + */ + fprintf(fp, "\ +# If vi_keys is set to \"on\", then the normal VI movement keys:\n\ +# j = down k = up\n\ +# h = left l = right\n\ +# will be enabled. These keys are only lower case.\n\ +# Capital 'H', 'J' and 'K will still activate help, jump shortcuts,\n\ +# and the keymap display, respectively.\n"); + fprintf(fp, "vi_keys=%s\n\n", (vi_keys ? "on" : "off")); + + /* + * EMACS keys. + */ + fprintf(fp, "\ +# If emacs_keys is to \"on\" then the normal EMACS movement keys:\n\ +# ^N = down ^P = up\n\ +# ^B = left ^F = right\n\ +# will be enabled.\n"); + fprintf(fp, "emacs_keys=%s\n\n", (emacs_keys ? "on" : "off")); - /* show dot files */ + /* + * Show dot files. + */ fprintf(fp, "\ # show_dotfiles specifies that the directory listing should include\n\ # \"hidden\" (dot) files/directories. If set \"on\", this will be\n\ # honored only if enabled via userdefs.h and/or lynx.cfg, and not\n\ # restricted via a command line switch. If display of hidden files\n\ # is disabled, creation of such files via Lynx also is disabled.\n"); - fprintf(fp, "show_dotfiles=%s\n\n",(show_dotfiles ? "on" : "off")); + fprintf(fp, "show_dotfiles=%s\n\n", (show_dotfiles ? "on" : "off")); -#ifdef DIRED_SUPPORT - /* list directory style */ - fprintf(fp,"\ -# dir_list_styles specifies the directory list style under DIRED_SUPPORT\n\ -# (if implemented). The default is MIXED_STYLE, which sorts both files and\n\ -# directories together. FILES_FIRST lists files first and DIRECTORIES_FIRST\n\ -# lists directories first.\n"); - fprintf(fp,"dir_list_style=%s\n\n", - (dir_list_style==FILES_FIRST ? "FILES_FIRST" : - (dir_list_style==MIXED_STYLE ? "MIXED_STYLE" : - "DIRECTORIES_FIRST"))); -#endif /* DIRED_SUPPORT */ - - /* select popups */ + /* + * Select popups. + */ fprintf(fp, "\ # select_popups specifies whether the OPTIONs in a SELECT block which\n\ # lacks a MULTIPLE attribute are presented as a vertical list of radio\n\ @@ -667,17 +669,132 @@ PUBLIC int save_rc () # of checkboxes for the OPTIONs. A value of \"on\" will set popup menus\n\ # as the default while a value of \"off\" will set use of radio boxes.\n\ # The default can be overridden via the -popup command line toggle.\n"); - fprintf(fp, "select_popups=%s\n\n",(LYSelectPopups ? "on" : "off")); + fprintf(fp, "select_popups=%s\n\n", (LYSelectPopups ? "on" : "off")); + + /* + * Keypad mode. + */ + fprintf(fp, "\ +# If keypad_mode is set to \"NUMBERS_AS_ARROWS\", then the numbers on\n\ +# your keypad when the numlock is on will act as arrow keys:\n\ +# 8 = Up Arrow\n\ +# 4 = Left Arrow 6 = Right Arrow\n\ +# 2 = Down Arrow\n\ +# If keypad_mode is set to \"LINKS_ARE_NUMBERED\", then numbers will\n\ +# appear next to each link and numbers are used to select links.\n\ +# NOTE: Some fixed format documents may look disfigured when\n\ +# \"LINKS_ARE_NUMBERED\" is enabled.\n"); + fprintf(fp, "keypad_mode=%s\n\n", + (keypad_mode==NUMBERS_AS_ARROWS ? + "NUMBERS_AS_ARROWS" : "LINKS_ARE_NUMBERED")); + + /* + * Lineedit mode. + */ + fprintf(fp, "\ +# linedit_mode specifies the key binding used for inputting strings in\n\ +# prompts and forms. If lineedit_mode is set to \"Default Binding\" then\n\ +# the following control characters are used for moving and deleting:\n\ +#\n\ +# Prev Next Enter = Accept input\n\ +# Move char: <- -> ^G = Cancel input\n\ +# Move word: ^P ^N ^U = Erase line\n\ +# Delete char: ^H ^R ^A = Beginning of line\n\ +# Delete word: ^B ^F ^E = End of line\n\ +#\n\ +# Current lineedit modes are:\n"); + { + char **bindings = LYLineeditNames; + while (*bindings) { + fprintf(fp, "# %s\n", *bindings); + bindings++; + } + } + fprintf(fp, "lineedit_mode=%s\n\n", LYLineeditNames[current_lineedit]); + +#ifdef DIRED_SUPPORT + /* + * List directory style. + */ + fprintf(fp, "\ +# dir_list_styles specifies the directory list style under DIRED_SUPPORT\n\ +# (if implemented). The default is \"MIXED_STYLE\", which sorts both\n\ +# files and directories together. \"FILES_FIRST\" lists files first and\n\ +# \"DIRECTORIES_FIRST\" lists directories first.\n"); + fprintf(fp, "dir_list_style=%s\n\n", + (dir_list_style==FILES_FIRST ? "FILES_FIRST" + : + (dir_list_style==MIXED_STYLE ? "MIXED_STYLE" + : "DIRECTORIES_FIRST"))); +#endif /* DIRED_SUPPORT */ + + /* + * User mode. + */ + fprintf(fp, "\ +# user_mode specifies the users level of knowledge with Lynx. The\n\ +# default is \"NOVICE\" which displays two extra lines of help at the\n\ +# bottom of the screen to aid the user in learning the basic Lynx\n\ +# commands. Set user_mode to \"INTERMEDIATE\" to turn off the extra info.\n\ +# Use \"ADVANCED\" to see the URL of the currently selected link at the\n\ +# bottom of the screen.\n"); + fprintf(fp, "user_mode=%s\n\n", + (user_mode == NOVICE_MODE ? "NOVICE" : + (user_mode == ADVANCED_MODE ? + "ADVANCED" : "INTERMEDIATE"))); + +#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) + /* + * Local execution mode - all links. + */ + fprintf(fp, "\ +# If run_all_execution_links is set \"on\" then all local exection links\n\ +# will be executed when they are selected.\n\ +#\n\ +# WARNING - This is potentially VERY dangerous. Since you may view\n\ +# information that is written by unknown and untrusted sources\n\ +# there exists the possibility that Trojan horse links could be\n\ +# written. Trojan horse links could be written to erase files\n\ +# or compromise security. This should only be set to \"on\" if\n\ +# you are viewing trusted source information.\n"); + fprintf(fp, "run_all_execution_links=%s\n\n", + (local_exec ? "on" : "off")); + + /* + * Local execution mode - only links in local files. + */ + fprintf(fp, "\ +# If run_execution_links_on_local_files is set \"on\" then all local\n\ +# execution links that are found in LOCAL files will be executed when they\n\ +# are selected. This is different from run_all_execution_links in that\n\ +# only files that reside on the local system will have execution link\n\ +# permissions.\n\ +#\n\ +# WARNING - This is potentially dangerous. Since you may view\n\ +# information that is written by unknown and untrusted sources\n\ +# there exists the possibility that Trojan horse links could be\n\ +# written. Trojan horse links could be written to erase files\n\ +# or compromise security. This should only be set to \"on\" if\n\ +# you are viewing trusted source information.\n"); + fprintf(fp, "run_execution_links_on_local_files=%s\n\n", + (local_exec_on_local_files ? "on" : "off")); +#endif /* defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) */ + /* + * Close the RC file. + */ fclose(fp); - /* get rid of any copies of the .lynxrc file that VMS creates */ #ifdef VMS - while (remove("sys$login:.lynxrc;-1") == 0) ; - /* reset version number */ + /* + * Get rid of any copies of the .lynxrc file that VMS creates. + */ + while (remove("sys$login:.lynxrc;-1") == 0) ; + /* + * Reset version number. + */ rename("sys$login:.lynxrc", "sys$login:.lynxrc;1"); #endif /* VMS */ return TRUE; - } diff --git a/src/Makefile b/src/Makefile index 4b8d5741..73e271b9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,7 +5,7 @@ LYOptions.o LYReadCFG.o LYSearch.o LYHistory.o \ LYForms.o LYPrint.o LYrcFile.o LYDownload.o LYNews.o LYKeymap.o \ HTML.o HTFWriter.o HTInit.o DefaultStyle.o LYLocal.o LYUpload.o \ LYLeaks.o LYexit.o LYJump.o LYList.o LYCgi.o LYTraversal.o \ -LYEditmap.o LYCharSets.o LYCharUtils.o LYMap.o +LYEditmap.o LYCharSets.o LYCharUtils.o LYMap.o LYCookie.o CFLAGS= $(MCFLAGS) -I.. $(SLANGINC) @@ -45,3 +45,4 @@ HTInit.o: ../userdefs.h LYTraversal.o: ../userdefs.h LYMail.o: ../userdefs.h LYCharSets.o: ../userdefs.h +LYCookie.o: ../userdefs.h diff --git a/src/descrip.mms b/src/descrip.mms index 6451ee8b..389514f0 100644 --- a/src/descrip.mms +++ b/src/descrip.mms @@ -52,11 +52,11 @@ OBJS = DefaultStyle.obj, GridText.obj, HTAlert.obj, HTFWriter.obj, - HTInit.obj, HTML.obj, LYBookmark.obj, LYCgi.obj, LYCharSets.obj, - - LYCharUtils.obj, LYClean.obj, LYCurses.obj, LYDownload.obj, - - LYEdit.obj, LYEditmap.obj, LYexit.obj, LYForms.obj, LYGetFile.obj, - - LYHistory.obj, LYJump.obj, LYKeymap.obj, LYLeaks.obj, LYList.obj, - - LYMail.obj, LYMain.obj, LYMainLoop.obj, LYMap.obj, LYNews.obj, - - LYOptions.obj, LYPrint.obj, LYrcFile.obj, LYReadCFG.obj, - + LYCharUtils.obj, LYClean.obj, LYCookie.obj, LYCurses.obj, - + LYDownload.obj, LYEdit.obj, LYEditmap.obj, LYexit.obj, LYForms.obj, - + LYGetFile.obj, LYHistory.obj, LYJump.obj, LYKeymap.obj, LYLeaks.obj, - + LYList.obj, LYMail.obj, LYMain.obj, LYMainLoop.obj, LYMap.obj, - + LYNews.obj, LYOptions.obj, LYPrint.obj, LYrcFile.obj, LYReadCFG.obj, - LYSearch.obj, LYShowInfo.obj, LYStrings.obj, LYTraversal.obj, - LYUpload.obj, LYUtils.obj |