diff options
author | Thomas E. Dickey <dickey@invisible-island.net> | 1997-11-07 12:30:00 -0500 |
---|---|---|
committer | Thomas E. Dickey <dickey@invisible-island.net> | 1997-11-07 12:30:00 -0500 |
commit | b63d287c6f3e67f8574ca2155c661288bc7dcd05 (patch) | |
tree | 6a3b376424faf4d50058e91988c2d6eaa49cfbdc /src | |
parent | 8f8c57cc7c0e876cd291e2b4de23a52e060b30ba (diff) | |
download | lynx-snapshots-b63d287c6f3e67f8574ca2155c661288bc7dcd05.tar.gz |
snapshot of project "lynx", label v2-7-1ac_0-93
Diffstat (limited to 'src')
-rw-r--r-- | src/GridText.c | 95 | ||||
-rw-r--r-- | src/HTAlert.c | 15 | ||||
-rw-r--r-- | src/HTAlert.h | 5 | ||||
-rw-r--r-- | src/HTML.c | 279 | ||||
-rw-r--r-- | src/LYCgi.c | 58 | ||||
-rw-r--r-- | src/LYCurses.c | 18 | ||||
-rw-r--r-- | src/LYCurses.h | 5 | ||||
-rw-r--r-- | src/LYDownload.c | 7 | ||||
-rw-r--r-- | src/LYForms.c | 19 | ||||
-rw-r--r-- | src/LYGetFile.c | 24 | ||||
-rw-r--r-- | src/LYGlobalDefs.h | 3 | ||||
-rw-r--r-- | src/LYHistory.c | 5 | ||||
-rw-r--r-- | src/LYList.c | 73 | ||||
-rw-r--r-- | src/LYList.h | 2 | ||||
-rw-r--r-- | src/LYMain.c | 7 | ||||
-rw-r--r-- | src/LYMainLoop.c | 509 | ||||
-rw-r--r-- | src/LYMap.c | 238 | ||||
-rw-r--r-- | src/LYMap.h | 8 | ||||
-rw-r--r-- | src/LYOptions.c | 10 | ||||
-rw-r--r-- | src/LYPrint.c | 58 | ||||
-rw-r--r-- | src/LYStyle.c | 4 | ||||
-rw-r--r-- | src/LYUtils.c | 82 | ||||
-rw-r--r-- | src/LYUtils.h | 5 | ||||
-rw-r--r-- | src/LYexit.c | 1 | ||||
-rw-r--r-- | src/chrtrans/README.format | 5 | ||||
-rw-r--r-- | src/chrtrans/cp437_uni.tbl | 6 | ||||
-rw-r--r-- | src/chrtrans/iso01_uni.tbl | 4 | ||||
-rw-r--r-- | src/chrtrans/iso01_uni.tbl.orig | 78 | ||||
-rw-r--r-- | src/chrtrans/iso08_uni.tbl | 12 | ||||
-rw-r--r-- | src/chrtrans/makeuctb.c | 53 | ||||
-rw-r--r-- | src/chrtrans/viscii_uni.tbl | 2 |
31 files changed, 1485 insertions, 205 deletions
diff --git a/src/GridText.c b/src/GridText.c index 3eb1cf0a..25ebf20b 100644 --- a/src/GridText.c +++ b/src/GridText.c @@ -175,7 +175,8 @@ struct _HText { BOOL source; /* Is the text source? */ BOOL toolbar; /* Toolbar set? */ HTList * tabs; /* TAB IDs */ - HTList * hidden_links; /* Content-less links */ + HTList * hidden_links; /* Content-less links ... */ + int hiddenlinkflag; /* ... and how to treat them */ BOOL no_cache; /* Always refresh? */ char LastChar; /* For aborbing white space */ BOOL IgnoreExcess; /* Ignore chars at wrap point */ @@ -472,6 +473,15 @@ PUBLIC HText * HText_new ARGS1( self->stale = YES; self->toolbar = NO; self->tabs = NULL; + /* + * If we are going to render the List Page, always merge in hidden + * links to get the numbering consistent if form fields are numbered + * and show up as hidden links in the list of links. - kw + */ + if (anchor->address && !strcmp(anchor->address, LYlist_temp_url())) + self->hiddenlinkflag = HIDDENLINKS_MERGE; + else + self->hiddenlinkflag = LYHiddenLinks; self->hidden_links = NULL; self->no_cache = ((anchor->no_cache || anchor->post_data) ? YES : NO); @@ -588,9 +598,14 @@ PUBLIC void HText_free ARGS1( /* * Free form fields. */ - if (l->input_field->type == F_OPTION_LIST_TYPE) { + if (l->input_field->type == F_OPTION_LIST_TYPE && + l->input_field->select_list != NULL) { /* - * Free off option lists. + * Free off option lists if present. + * It should always be present for F_OPTION_LIST_TYPE + * unless we had invalid markup which prevented + * HText_setLastOptionValue from finishing its job + * and left the input field in an insane state. - kw */ OptionType *optptr = l->input_field->select_list; OptionType *tmp; @@ -603,7 +618,7 @@ PUBLIC void HText_free ARGS1( } l->input_field->select_list = NULL; /* - * Don't free the value field on option + * Don't free the value field on sane option * lists since it points to a option value * same for orig value. */ @@ -1561,6 +1576,54 @@ PRIVATE void display_page ARGS3( } +#ifdef NOT_USED +/* + * Refresh a form link on the current page after it may have changed. + * Could be used after change_form_link after a popup was opened, IF + * refresh of the rest of the screen is not necessary, instead of a + * full display_page - probably only for VMS curses. - kw + */ +PUBLIC void refresh_form_link ARGS2( + int, linkno, + char *, target) +{ + FormInfo *FormInfo_ptr; + /* + * Update links[] for one input link, and call refresh. + * basically redo some things display_page did. + */ + if (linkno >= 0 && linkno < nlinks && + links[linkno].type == WWW_FORM_LINK_TYPE) { + FormInfo_ptr = links[linkno].form; + + if (FormInfo_ptr->type == F_RADIO_TYPE) { + if (FormInfo_ptr->num_value) + links[linkno].hightext = checked_radio; + else + links[linkno].hightext = unchecked_radio; + + } else if (FormInfo_ptr->type == F_CHECKBOX_TYPE) { + if (FormInfo_ptr->num_value) + links[linkno].hightext = checked_box; + else + links[linkno].hightext = unchecked_box; + + } else if (FormInfo_ptr->type == F_PASSWORD_TYPE) { + links[linkno].hightext = STARS(strlen(FormInfo_ptr->value)); + + } else if (FormInfo_ptr->type == F_HIDDEN_TYPE) { + ; /* should never happen. */ + } else { /* TEXT type */ + links[linkno].hightext = FormInfo_ptr->value; + } + /* + * Bold the link, then update the screen + */ + highlight(OFF, linkno, target); + refresh(); + } +} +#endif /* NOT_USED */ /* Object Building methods ** ----------------------- @@ -2724,7 +2787,7 @@ PUBLIC void HText_endAnchor ARGS2( BOOL remove_numbers_on_empty = ((keypad_mode == LINKS_ARE_NUMBERED || keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) && - (LYHiddenLinks != HIDDENLINKS_MERGE || + (text->hiddenlinkflag != HIDDENLINKS_MERGE || (LYNoISMAPifUSEMAP && HTAnchor_isISMAPScript( HTAnchor_followMainLink((HTAnchor *)a->anchor))))); @@ -3072,7 +3135,7 @@ PUBLIC void HText_endAnchor ARGS2( * to the hidden links list. - FM */ a->extent = 0; - if (LYHiddenLinks != HIDDENLINKS_MERGE) { + if (text->hiddenlinkflag != HIDDENLINKS_MERGE) { a->number = 0; HText_AddHiddenLink(text, a); text->last_anchor_number--; @@ -5665,7 +5728,7 @@ PRIVATE void HText_AddHiddenLink ARGS2( * retrievals. - FM */ if ((dest = HTAnchor_followMainLink((HTAnchor *)textanchor->anchor)) && - (LYHiddenLinks != HIDDENLINKS_IGNORE || + (text->hiddenlinkflag != HIDDENLINKS_IGNORE || HTList_isEmpty(text->hidden_links))) HTList_appendObject(text->hidden_links, HTAnchor_address(dest)); @@ -6111,6 +6174,15 @@ PUBLIC char * HText_setLastOptionValue ARGS7( /* * No option items yet. */ + if (text->last_anchor->input_field->type != F_OPTION_LIST_TYPE) { + if (TRACE) + fprintf(stderr, + "HText_setLastOptionValue: last input_field not OPTION_LIST_TYPE but %d, ignoring!\n", + text->last_anchor->input_field->type); + return NULL; + } + + new_ptr = text->last_anchor->input_field->select_list = (OptionType *) calloc(1, sizeof(OptionType)); if (new_ptr == NULL) @@ -6173,6 +6245,15 @@ PUBLIC char * HText_setLastOptionValue ARGS7( if (first_option) { StrAllocCopy(HTCurSelectedOptionValue, new_ptr->name); text->last_anchor->input_field->num_value = 0; + /* + * If this is the first option in a popup select list, + * HText_beginInput may have allocated the value and + * cp_submit_value fields, so free them now to avoid + * a memory leak. - kw + */ + FREE(text->last_anchor->input_field->value); + FREE(text->last_anchor->input_field->cp_submit_value); + text->last_anchor->input_field->value = text->last_anchor->input_field->select_list->name; text->last_anchor->input_field->orig_value = diff --git a/src/HTAlert.c b/src/HTAlert.c index a83014db..0886d81e 100644 --- a/src/HTAlert.c +++ b/src/HTAlert.c @@ -55,11 +55,24 @@ PUBLIC void HTProgress ARGS1( statusline(Msg); } +PRIVATE BOOL conf_cancelled = NO; /* used by HTConfirm only - kw */ + +PUBLIC BOOL HTLastConfirmCancelled NOARGS +{ + if (conf_cancelled) { + conf_cancelled = NO; /* reset */ + return(YES); + } else { + return(NO); + } +} + /* Seek confirmation. HTConfirm() ** ------------------ */ PUBLIC BOOL HTConfirm ARGS1(CONST char *, Msg) { + conf_cancelled = NO; if (dump_output_immediately) { /* Non-interactive, can't respond */ return(NO); } else { @@ -80,6 +93,8 @@ PUBLIC BOOL HTConfirm ARGS1(CONST char *, Msg) #endif /* VMS */ if (TOUPPER(c) == 'Y') return(YES); + if (c == 7 || c == 3) /* remember we had ^G or ^C */ + conf_cancelled = YES; if (TOUPPER(c) == 'N' || c == 7 || c == 3) /* ^G or ^C cancels */ return(NO); } diff --git a/src/HTAlert.h b/src/HTAlert.h index bb07b2a1..ce40afb5 100644 --- a/src/HTAlert.h +++ b/src/HTAlert.h @@ -40,6 +40,11 @@ extern void HTProgress PARAMS((CONST char * Msg)); extern BOOLEAN mustshow; #define _HTProgress(msg) mustshow = TRUE, HTProgress(msg) +/* + * Indicates whether last HTConfirm was cancelled (^G or ^C) and + * resets flag. (so only call once!) - kw + */ +extern BOOL HTLastConfirmCancelled NOPARAMS; /* Display a message, then wait for 'yes' or 'no'. ** diff --git a/src/HTML.c b/src/HTML.c index 15ed71c6..a020ba56 100644 --- a/src/HTML.c +++ b/src/HTML.c @@ -243,7 +243,24 @@ PUBLIC void HTML_put_character ARGS2(HTStructured *, me, char, c) return; default: - break; + if (me->inSELECT) { + /* + * If we are within a SELECT not caught by the cases + * above - HTML_SELECT or HTML_OPTION may not be the + * last element pushed on the style stack if there were + * invalid markup tags within a SELECT element. For error + * recovery, treat text as part of the OPTION text, it is + * probably meant to show up as user-visible text. + * Having A as an open element while in SELECT is really sick, + * don't make anchor text part of the option text in that case + * since the option text will probably just be discarded. - kw + */ + if (me->sp[0].tag_number == HTML_A) + break; + HTChunkPutc(&me->option, c); + return; + } + break; } /* end first switch */ /* @@ -498,13 +515,57 @@ PUBLIC void HTML_write ARGS3(HTStructured *, me, CONST char*, s, int, l) HTML_put_character(me, *p); } -#ifndef DONT_TRACK_INTERNAL_LINKS +/* + * "Internal links" are hyperlinks whose source and destination are + * within the same document, and for which the destination is given + * as a URL Reference with an empty URL, but possibly with a non-empty + * #fragment. (This terminology re URL-Reference vs. URL follows the + * Fielding URL syntax and semantics drafts). + * Differences: + * (1) The document's base (in whatever way it is given) is not used for + * resolving internal link references. + * (2) Activating an internal link should not result in a new retrieval + * of a copy of the document. + * (3) Internal links are the only way to refer with a hyperlink to a document + * (or a location in it) which is only known as the result of a POST + * request (doesn't have a URL from which the document can be retrieved + * with GET), and can only be used from within that document. + * + * *If DONT_TRACK_INTERNAL_LINKS is not defined, we keep track of whether a + * link destination was given as an internal link. This information is + * recorded in the type of the link between anchor objects, and is available + * to the HText object and the mainloop from there. URL References to + * internal destinations are still resolved into an absolute form before + * being passed on, but using the current stream's retrieval address instead + * of the base URL. + * Examples: (replace [...] to have a valid absolute URL) + * In document retrieved from [...]/mypath/mydoc.htm w/ base [...]/otherpath/ + * a. HREF="[...]/mypath/mydoc.htm" -> [...]/mypath/mydoc.htm + * b. HREF="[...]/mypath/mydoc.htm#frag" -> [...]/mypath/mydoc.htm#frag + * c. HREF="mydoc.htm" -> [...]/otherpath/mydoc.htm + * d. HREF="mydoc.htm#frag" -> [...]/otherpath/mydoc.htm#frag + * e. HREF="" -> [...]/mypath/mydoc.htm (marked internal) + * f. HREF="#frag" -> [...]/mypath/mydoc.htm#frag (marked internal) + * + * *If DONT_TRACK_INTERNAL_LINKS is defined, URL-less URL-References are + * resolved differently from URL-References with a non-empty URL (using the + * current stream's retrieval address instead of the base), but we make no + * further distinction. Resolution is then as in the examples above, execept + * that there is no "(marked internal)". + * + * *Note that this doesn't apply to form ACTIONs (always resolved using base, + * never marked internal). Also other references encountered or generated + * are not marked internal, whether they have a URL or not, if in a given + * context an internal link makes no sense (e.g. IMG SRC=). + */ +#ifndef DONT_TRACK_INTERNAL_LINKS /* A flag is used to keep track of whether an "URL reference" encountered - had a real "URL" or not. (This is the terminology of the Fielding - Internet Draft.) In the latter case, it will be marked as an "internal" - link. The flag is set before we start messing around with the string - (resolution of relative URLs etc.). - kw */ + had a real "URL" or not. In the latter case, it will be marked as + "internal". The flag is set before we start messing around with the + string (resolution of relative URLs etc.). This variable only used + locally here, don't confuse with LYinternal_flag which is for + for overriding non-caching similar to LYoverride_no_cache. - kw */ #define CHECK_FOR_INTERN(s) intern_flag = (s && (*s=='#' || *s=='\0')) ? TRUE : FALSE; /* Last argument to pass to HTAnchor_findChildAndLink() calls, @@ -741,6 +802,25 @@ PRIVATE void HTML_start_element ARGS6( me->inBadBASE = TRUE; } + if (url_type == LYNXIMGMAP_URL_TYPE) { + /* + * These have a are non-standard form, basically + * strip the prefix or the code below would insert + * a nonsense host into the pseudo URL. These + * should never occur where they would used for + * resolution of relative URLs anyway. We can + * also strip the #map part. - kw + */ + temp = HTParse(base + 11, "", + PARSE_ACCESS+PARSE_HOST+PARSE_PATH + +PARSE_PUNCTUATION); + if (temp) { + FREE(base); + base = temp; + temp = NULL; + } + } + /* * Get parent's address for defaulted fields. */ @@ -754,6 +834,7 @@ PRIVATE void HTML_start_element ARGS6( *temp != '\0') { StrAllocCopy(me->base_href, temp); } else { + FREE(temp); StrAllocCopy(me->base_href, (temp = HTParse(related, "", PARSE_ACCESS+PARSE_PUNCTUATION))); } @@ -773,6 +854,7 @@ PRIVATE void HTML_start_element ARGS6( if (!strcmp(me->base_href, "file:")) { StrAllocCat(me->base_href, "//localhost"); } else if (strcmp(me->base_href, "news:")) { + FREE(temp); StrAllocCat(me->base_href, (temp = HTParse(related, "", PARSE_HOST+PARSE_PUNCTUATION))); } @@ -787,7 +869,6 @@ PRIVATE void HTML_start_element ARGS6( PARSE_PATH+PARSE_PUNCTUATION)) && *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) || @@ -797,6 +878,7 @@ PRIVATE void HTML_start_element ARGS6( } else { StrAllocCat(me->base_href, "/"); } + FREE(temp); FREE(base); me->inBASE = TRUE; @@ -3307,7 +3389,7 @@ PRIVATE void HTML_start_element ARGS6( FREE(title); } } - LYAddImageMap(me->map_address, title); + LYAddImageMap(me->map_address, title, me->node_anchor); FREE(title); } break; @@ -3401,7 +3483,8 @@ PRIVATE void HTML_start_element ARGS6( StrAllocCopy(alt_string, href); } - LYAddMapElement(me->map_address, href, alt_string, intern_flag); + LYAddMapElement(me->map_address, href, alt_string, + me->node_anchor, intern_flag); FREE(href); FREE(alt_string); } @@ -4622,6 +4705,19 @@ PRIVATE void HTML_start_element ARGS6( } /* + * Check for an unclosed SELECT, try to close it if found. + */ + if (me->inSELECT) { + if (TRACE) { + fprintf(stderr, "HTML: Missing SELECT end tag, faking it...\n"); + } + if (me->sp->tag_number != HTML_SELECT) { + SET_SKIP_STACK(HTML_SELECT); + } + HTML_end_element(me, HTML_SELECT, (char **)&include); + } + + /* * Handle the INPUT as for a FORM. - FM */ if (!(present && present[HTML_INPUT_NAME] && @@ -5059,7 +5155,9 @@ PRIVATE void HTML_start_element ARGS6( me->inBadHTML = TRUE; sleep(MessageSecs); } - SET_SKIP_STACK(HTML_SELECT); + if (me->sp->tag_number != HTML_SELECT) { + SET_SKIP_STACK(HTML_SELECT); + } HTML_end_element(me, HTML_SELECT, (char **)&include); } { @@ -5086,9 +5184,14 @@ PRIVATE void HTML_start_element ARGS6( } /* - * Too likely to cause a crash, so we'll ignore it. - FM - */ + * We should have covered all crash possibilities with the + * current TagSoup parser, so we'll allow it because some + * people with other browsers use SELECT for "information" + * popups, outside of FORM blocks, though no Lynx user + * would do anything that awful, right? - FM + *//*** break; + ***/ } /* @@ -5815,6 +5918,17 @@ PRIVATE void HTML_end_element ARGS3( case HTML_HEAD: if (!me->text) UPDATE_STYLE; + if (me->inBASE && + !strcmp(me->node_anchor->address, LYlist_temp_url())) { + /* If we are parsing the List Page, and have a BASE after + * we are done with the HEAD element, propagate it back + * to the node_anchor object. The base should have been + * inserted by showlist() to record what document the List + * Page is about, and other functions may later look for it + * in the anchor. - kw + */ + StrAllocCopy(me->node_anchor->content_base, me->base_href); + } if (HText_hasToolbar(me->text)) HText_appendParagraph(me->text); break; @@ -6670,7 +6784,9 @@ End_Object: me->inBadHTML = TRUE; sleep(MessageSecs); } - SET_SKIP_STACK(HTML_SELECT); + if (me->sp->tag_number != HTML_SELECT) { + SET_SKIP_STACK(HTML_SELECT); + } HTML_end_element(me, HTML_SELECT, (char **)&include); } @@ -6907,12 +7023,9 @@ End_Object: me->inBadHTML = TRUE; sleep(MessageSecs); } - /* - * Too likely to cause a crash, so we'll ignore it. - kw + * Hopefully won't crash, so we'll ignore it. - kw */ - HTChunkClear(&me->option); - break; } /* @@ -6971,9 +7084,11 @@ End_Object: /* * Add end option character. */ - HText_appendCharacter(me->text, ']'); - HText_setLastChar(me->text, ']'); - me->in_word = YES; + if (!me->first_option) { + HText_appendCharacter(me->text, ']'); + HText_setLastChar(me->text, ']'); + me->in_word = YES; + } HText_setIgnoreExcess(me->text, FALSE); } HTChunkClear(&me->option); @@ -7211,7 +7326,56 @@ PRIVATE void HTML_free ARGS1(HTStructured *, me) HTML_end_element(me, HTML_FORM, (char **)&include); me->inFORM = FALSE; } - + if (me->option.size > 0) { + /* + * If we still have data in the me->option chunk after + * forcing a close of a still-open form, something must + * have gone very wrong. - kw + */ + if (TRACE) { + fprintf(stderr, + "HTML_free: ***** SELECT or OPTION not ended properly *****\n"); + } else if (!me->inBadHTML) { + _statusline(BAD_HTML_USE_TRACE); + me->inBadHTML = TRUE; + sleep(MessageSecs); + } + HTChunkTerminate(&me->option); + /* + * Output the left-over data as text, maybe it was invalid + * markup meant to be shown somewhere. - kw + */ + if (TRACE) + fprintf(stderr, " ***** leftover option data: %s\n", + me->option.data); + HTML_put_string(me, me->option.data); + HTChunkClear(&me->option); + } + if (me->textarea.size > 0) { + /* + * If we still have data in the me->textarea chunk after + * forcing a close of a still-open form, something must + * have gone very wrong. - kw + */ + if (TRACE) { + fprintf(stderr, + "HTML_free: ***** TEXTAREA not used properly *****\n"); + } else if (!me->inBadHTML) { + _statusline(BAD_HTML_USE_TRACE); + me->inBadHTML = TRUE; + sleep(MessageSecs); + } + HTChunkTerminate(&me->textarea); + /* + * Output the left-over data as text, maybe it was invalid + * markup meant to be shown somewhere. - kw + */ + if (TRACE) + fprintf(stderr, " ***** leftover textarea data: %s\n", + me->textarea.data); + HTML_put_string(me, me->textarea.data); + HTChunkClear(&me->textarea); + } /* * If we're interactive and have hidden links but no visible * links, add a message informing the user about this and @@ -7235,6 +7399,48 @@ PRIVATE void HTML_free ARGS1(HTStructured *, me) */ HText_endAppend(me->text); } + if (me->option.size > 0) { + /* + * If we still have data in the me->option chunk after + * forcing a close of a still-open form, something must + * have gone very wrong. - kw + */ + if (TRACE) { + fprintf(stderr, + "HTML_free: ***** SELECT or OPTION not ended properly *****\n"); + } else if (!me->inBadHTML) { + _statusline(BAD_HTML_USE_TRACE); + me->inBadHTML = TRUE; + sleep(MessageSecs); + } + if (TRACE) { + HTChunkTerminate(&me->option); + fprintf(stderr, " ***** leftover option data: %s\n", + me->option.data); + } + HTChunkClear(&me->option); + } + if (me->textarea.size > 0) { + /* + * If we still have data in the me->textarea chunk after + * forcing a close of a still-open form, something must + * have gone very wrong. - kw + */ + if (TRACE) { + fprintf(stderr, + "HTML_free: ***** TEXTAREA not used properly *****\n"); + } else if (!me->inBadHTML) { + _statusline(BAD_HTML_USE_TRACE); + me->inBadHTML = TRUE; + sleep(MessageSecs); + } + if (TRACE) { + HTChunkTerminate(&me->textarea); + fprintf(stderr, " ***** leftover textarea data: %s\n", + me->textarea.data); + } + HTChunkClear(&me->textarea); + } if (me->target) { (*me->targetClass._free)(me->target); @@ -7291,6 +7497,37 @@ PRIVATE void HTML_abort ARGS2(HTStructured *, me, HTError, e) HText_endAppend(me->text); } + if (me->option.size > 0) { + /* + * If we still have data in the me->option chunk after + * forcing a close of a still-open form, something must + * have gone very wrong. - kw + */ + if (TRACE) { + fprintf(stderr, + "HTML_abort: ***** SELECT or OPTION not ended properly *****\n"); + HTChunkTerminate(&me->option); + fprintf(stderr, " ***** leftover option data: %s\n", + me->option.data); + } + HTChunkClear(&me->option); + } + if (me->textarea.size > 0) { + /* + * If we still have data in the me->textarea chunk after + * forcing a close of a still-open form, something must + * have gone very wrong. - kw + */ + if (TRACE) { + fprintf(stderr, + "HTML_abort: ***** TEXTAREA not used properly *****\n"); + HTChunkTerminate(&me->textarea); + fprintf(stderr, " ***** leftover textarea data: %s\n", + me->textarea.data); + } + HTChunkClear(&me->textarea); + } + if (me->target) { (*me->targetClass._abort)(me->target, e); } diff --git a/src/LYCgi.c b/src/LYCgi.c index 4f6d0171..6bb32a34 100644 --- a/src/LYCgi.c +++ b/src/LYCgi.c @@ -307,8 +307,15 @@ PRIVATE int LYLoadCGI ARGS4( int wstatus; #endif - /* Decode full HTTP response */ - format_in = HTAtom_for("www/mime"); + if (anAnchor->isHEAD || keep_mime_headers) { + + /* Show output as plain text */ + format_in = WWW_PLAINTEXT; + } else { + + /* Decode full HTTP response */ + format_in = HTAtom_for("www/mime"); + } target = HTStreamStack(format_in, format_out, @@ -361,6 +368,7 @@ PRIVATE int LYLoadCGI ARGS4( close(fd2[1]); if (anAnchor->post_data) { + int written, remaining, total_written = 0; close(fd1[0]); /* We have form data to push across the pipe */ @@ -371,8 +379,41 @@ PRIVATE int LYLoadCGI ARGS4( "LYNXCGI: Writing:\n%s----------------------------------\n", anAnchor->post_data); } - write(fd1[1], anAnchor->post_data, - strlen(anAnchor->post_data)); + remaining = strlen(anAnchor->post_data); + while ((written = write(fd1[1], + anAnchor->post_data + total_written, + remaining)) != 0) { + if (written < 0) { +#ifdef EINTR + if (errno == EINTR) + continue; +#endif /* EINTR */ +#ifdef ERESTARTSYS + if (errno == ERESTARTSYS) + continue; +#endif /* ERESTARTSYS */ + if (TRACE) { + perror("LYNXCGI: write() of POST data failed"); + } + break; + } + if (TRACE) { + fprintf(stderr, + "LYNXCGI: Wrote %d bytes of POST data.\n", + written); + } + total_written += written; + remaining -= written; + if (remaining == 0) + break; + } + if (remaining != 0) { + if (TRACE) + fprintf(stderr, + "LYNXCGI: %d bytes remain unwritten!\n", + remaining); + } + close(fd1[1]); } total_chars = 0; @@ -404,9 +445,6 @@ PRIVATE int LYLoadCGI ARGS4( break; } #endif /* !HAVE_WAITPID */ - if (anAnchor->post_data) { - close(fd1[1]); - } close(fd2[0]); status = HT_LOADED; @@ -449,6 +487,10 @@ PRIVATE int LYLoadCGI ARGS4( add_environment_value(post_len); } else { close(fileno(stdin)); + + if (anAnchor->isHEAD) { + add_environment_value("REQUEST_METHOD=HEAD"); + } } /* @@ -473,7 +515,7 @@ PRIVATE int LYLoadCGI ARGS4( /* Data for a get/search form */ if (is_www_index) { add_environment_value("REQUEST_METHOD=SEARCH"); - } else { + } else if (!anAnchor->isHEAD) { add_environment_value("REQUEST_METHOD=GET"); } diff --git a/src/LYCurses.c b/src/LYCurses.c index 35bfc6eb..b4738a0f 100644 --- a/src/LYCurses.c +++ b/src/LYCurses.c @@ -75,7 +75,11 @@ PUBLIC void LY_SLrefresh NOARGS return; } -PUBLIC void LY_SLclear NOARGS +/* the following renamed from LY_SLclear since it is more like erase() + described in curses man pages than like clear(); but for USE_SLANG + clear() is still a macro calling this, and will do the same thing as + erase(). - kw */ +PUBLIC void LY_SLerase NOARGS { SLsmg_gotorc (0, 0); SLsmg_erase_eos (); @@ -409,7 +413,7 @@ PRIVATE void LYsetWAttr ARGS1(WINDOW *, win) #endif /* DOSPATH */ } -#ifndef __DJGPP__ +#if ( !defined(__DJGPP__) && !defined(_WINDOWS) ) if (no_color_video < 0) { no_color_video = tigetnum("ncv"); } @@ -1554,9 +1558,17 @@ PUBLIC void VMSbox ARGS3( PUBLIC void lynx_force_repaint NOARGS { #if defined(COLOR_CURSES) - chtype a = (LYShowColor >= SHOW_COLOR_ON) ? COLOR_PAIR(9) : A_NORMAL; + chtype a; +#ifndef USE_COLOR_STYLE + if (LYShowColor >= SHOW_COLOR_ON) + a = COLOR_PAIR(9); + else +#endif + a = A_NORMAL; bkgdset(a | ' '); +#ifndef USE_COLOR_STYLE bkgd(a | ' '); +#endif attrset(a); #endif clearok(curscr, TRUE); diff --git a/src/LYCurses.h b/src/LYCurses.h index 1478cade..89d64c5e 100644 --- a/src/LYCurses.h +++ b/src/LYCurses.h @@ -177,8 +177,9 @@ extern int PHYSICAL_SLtt_Screen_Cols; #define LINES SLtt_Screen_Rows #define move SLsmg_gotorc #define addstr SLsmg_write_string -extern void LY_SLclear NOPARAMS; -#define clear LY_SLclear +extern void LY_SLerase NOPARAMS; +#define erase LY_SLerase +#define clear LY_SLerase #define standout SLsmg_reverse_video #define standend SLsmg_normal_video #define clrtoeol SLsmg_erase_eol diff --git a/src/LYDownload.c b/src/LYDownload.c index 644ade45..0934266f 100644 --- a/src/LYDownload.c +++ b/src/LYDownload.c @@ -366,6 +366,7 @@ check_recall: */ LYDidRename = TRUE; } + chmod(buffer, HIDE_CHMOD); #else /* Unix: */ /* * Prevent spoofing of the shell. @@ -384,10 +385,10 @@ check_recall: fflush(stdout); fflush(stderr); start_curses(); +#if defined(UNIX) + LYRelaxFilePermissions(buffer); +#endif /* defined(UNIX) */ #endif /* VMS */ -#if defined(VMS) || defined(UNIX) - chmod(buffer, HIDE_CHMOD); -#endif /* defined(VMS) || defined(UNIX) */ } else { /* diff --git a/src/LYForms.c b/src/LYForms.c index 12e6f032..d9dee701 100644 --- a/src/LYForms.c +++ b/src/LYForms.c @@ -88,7 +88,7 @@ PUBLIC int change_form_link ARGS6( #if defined(VMS) && !defined(USE_SLANG) c = DO_NOTHING; #else - c = 23; /* CTRL-W for repaint */ + c = 23; /* CTRL-W refresh without clearok */ #endif /* VMS && !USE_SLANG */ else #endif /* FANCY_CURSES || USE_SLANG */ @@ -119,16 +119,17 @@ PUBLIC int change_form_link ARGS6( form->value_cs = opt_ptr->value_cs; } #if defined(FANCY_CURSES) || defined(USE_SLANG) - if (!enable_scrollback && form->num_value == OrigNumValue) + if (!enable_scrollback) #if defined(VMS) && !defined(USE_SLANG) - c = DO_NOTHING; -#else - c = 23; /* CTRL-W for repaint */ -#endif /* VMS && !USE_SLANG */ - else + if (form->num_value == OrigNumValue) + c = DO_NOTHING; + else +#endif /* VMS && !USE_SLANG*/ + c = 23; /* CTRL-W refresh without clearok */ + else #endif /* FANCY_CURSES || USE_SLANG */ - c = 12; /* CTRL-L for repaint */ - break; + c = 12; /* CTRL-L for repaint */ + break; case F_RADIO_TYPE: if (form->disabled == YES) diff --git a/src/LYGetFile.c b/src/LYGetFile.c index 08551035..863c905a 100644 --- a/src/LYGetFile.c +++ b/src/LYGetFile.c @@ -24,6 +24,7 @@ #include "LYKeymap.h" #include "LYBookmark.h" #include "LYMap.h" +#include "LYList.h" #ifdef VMS #include "HTVMSUtils.h" #endif /* VMS */ @@ -251,6 +252,27 @@ Try_Redirected_URL: return(NULLFILE); } } + if (WWWDoc.post_data && + url_type != HTTP_URL_TYPE && + url_type != HTTPS_URL_TYPE && + url_type != LYNXCGI_URL_TYPE && + url_type != LYNXIMGMAP_URL_TYPE && + url_type != GOPHER_URL_TYPE && + url_type != CSO_URL_TYPE && + url_type != PROXY_URL_TYPE && + !(url_type == FILE_URL_TYPE && + *(LYlist_temp_url()) && + !strncmp(WWWDoc.address, LYlist_temp_url(), + strlen(LYlist_temp_url())))) { + if (TRACE) + fprintf(stderr, + "getfile: dropping post_data!\n"); + HTAlert("POST not supported for this URL - ignoring POST data!"); + FREE(doc->post_data); + FREE(doc->post_content_type); + WWWDoc.post_data = NULL; + WWWDoc.post_content_type = NULL; + } #ifndef VMS #ifdef SYSLOG_REQUESTED_URLS syslog(LOG_INFO|LOG_LOCAL5, "%s", doc->address); @@ -350,7 +372,7 @@ Try_Redirected_URL: WWWDoc.safe = doc->safe; #ifndef DONT_TRACK_INTERNAL_LINKS if (doc->internal_link && !reloading) { - LYoverride_no_cache = TRUE; + LYinternal_flag = TRUE; } #endif diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h index bff8c881..ee2939b6 100644 --- a/src/LYGlobalDefs.h +++ b/src/LYGlobalDefs.h @@ -146,7 +146,8 @@ extern char *lynx_temp_space; extern char *lynx_save_space; extern BOOLEAN LYforce_HTML_mode; extern BOOLEAN LYforce_no_cache; -extern BOOLEAN LYoverride_no_cache; +extern BOOLEAN LYoverride_no_cache; /* don't need fresh copy, from history */ +extern BOOLEAN LYinternal_flag; /* don't need fresh copy, was internal link */ extern BOOLEAN LYresubmit_posts; extern BOOLEAN user_mode; /* novice or advanced */ extern BOOLEAN is_www_index; diff --git a/src/LYHistory.c b/src/LYHistory.c index 1a3a3990..cb6751e3 100644 --- a/src/LYHistory.c +++ b/src/LYHistory.c @@ -507,7 +507,7 @@ PUBLIC BOOLEAN historytarget ARGS1( && !(LYforce_no_cache == TRUE && LYoverride_no_cache == FALSE)) { #ifndef DONT_TRACK_INTERNAL_LINKS LYforce_no_cache = FALSE; - LYoverride_no_cache = TRUE; + LYinternal_flag = TRUE; newdoc->internal_link = TRUE; treat_as_intern = TRUE; #endif @@ -533,7 +533,8 @@ PUBLIC BOOLEAN historytarget ARGS1( LYoverride_no_cache == FALSE)) && !(treat_as_intern && !reloading)) || text == NULL) && - HTConfirm(CONFIRM_POST_RESUBMISSION) == TRUE) { + (!strncmp(newdoc->address, "LYNXIMGMAP:", 11) || + HTConfirm(CONFIRM_POST_RESUBMISSION) == TRUE)) { LYforce_no_cache = TRUE; LYoverride_no_cache = FALSE; } else if (text != NULL) { diff --git a/src/LYList.c b/src/LYList.c index 804da051..f5225c7b 100644 --- a/src/LYList.c +++ b/src/LYList.c @@ -8,8 +8,8 @@ #include "HTUtils.h" #include "tcp.h" #include "LYUtils.h" -#include "LYList.h" #include "GridText.h" +#include "LYList.h" #include "LYSignal.h" #include "LYGlobalDefs.h" #include "LYCharUtils.h" @@ -36,13 +36,18 @@ static char list_filename[256] = "\0"; +/* + * Returns the name of the file used for the List Page, if one has + * been created, as a full URL; otherwise, returns an empty string. + * - kw + */ PUBLIC char * LYlist_temp_url NOARGS { return list_filename; } PUBLIC int showlist ARGS2( - char **, newfile, + document *, newdoc, BOOLEAN, titles) { int cnt; @@ -51,6 +56,7 @@ PUBLIC int showlist ARGS2( static BOOLEAN first = TRUE; FILE *fp0; char *Address = NULL, *Title = NULL, *cp = NULL; + BOOLEAN intern_w_post = FALSE; char *desc = "unknown field or link"; refs = HText_sourceAnchors(HTMainText); @@ -90,13 +96,24 @@ PUBLIC int showlist ARGS2( return(-1); } - StrAllocCopy(*newfile, list_filename); + StrAllocCopy(newdoc->address, list_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"); LYAddMETAcharsetToFD(fp0, -1); + if (strchr(HTLoadedDocumentURL(), '"') == NULL) { + /* + * Insert a BASE tag so there is some way to relate the List Page + * file to its underlying document after we are done. It won't + * be actually used for resolving relative URLs. - kw + */ + StrAllocCopy(Address, HTLoadedDocumentURL()); + LYEntify(&Address, FALSE); + fprintf(fp0, "<base href=\"%s\">\n", Address); + FREE(Address); + } fprintf(fp0, "<title>%s</title>\n</head>\n<body>\n", LIST_PAGE_TITLE); fprintf(fp0, "<h1>You have reached the List Page</h1>\n"); @@ -130,10 +147,16 @@ PUBLIC int showlist ARGS2( * ensure that the link numbers on the list page match the * numbering in the original document, but won't create a * forward link to the form. - FM && LE + * + * Changed to create a fake hidden link, to get the numbering + * right in connection with always treating this file as + * HIDDENLINKS_MERGE in GridText.c - kw */ if (keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) { HText_FormDescNumber(cnt, (char **)&desc); - fprintf(fp0, "<li>[%d](<em>%s</em>)</a>\n", cnt, desc); + /* fprintf(fp0, "<li>[%d](<em>%s</em>)\n", cnt, desc); */ + fprintf(fp0, "<li><a id=%d href='#%d'></a>(<em>%s</em>)\n", + cnt, cnt, desc); } continue; } @@ -144,6 +167,19 @@ PUBLIC int showlist ARGS2( dest = dest_intl ? dest_intl : HTAnchor_followMainLink((HTAnchor *)child); parent = HTAnchor_parent(dest); + if (!intern_w_post && dest_intl && + HTMainAnchor && HTMainAnchor->post_data && + parent->post_data && + !strcmp(HTMainAnchor->post_data, parent->post_data)) { + /* + * Set flag to note that we had at least one internal link, + * if the document from which we are generating the list + * has assosiated POST data; after an extra check that the + * link destination really has hthe same POST data so that + * we can believe it is an internal link. + */ + intern_w_post = TRUE; + } address = HTAnchor_address(dest); title = titles ? HTAnchor_title(parent) : NULL; StrAllocCopy(Address, address); @@ -196,6 +232,26 @@ PUBLIC int showlist ARGS2( fprintf(fp0,"\n</%s>\n</body>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ? "ol" : "ul")); + /* + * Make necessary changes to newdoc before returning to caller. + * If the intern_w_post flag is set, we keep the POST data in + * newdoc that have been passed in. They should be the same as + * in the loaded locument for which we generated the list. + * In that case the file we have written will be associated with + * the same POST data when it is loaded after we are done here, + * so that following one of the links we have marked as "internal + * link" can lead back to the underlying document with the right + * address+post_data combination. - kw + */ + if (intern_w_post) { + newdoc->internal_link = TRUE; + } else { + FREE(newdoc->post_data); + FREE(newdoc->post_content_type); + newdoc->internal_link = FALSE; + } + newdoc->isHEAD = FALSE; + newdoc->safe = FALSE; fclose(fp0); return(0); } @@ -256,6 +312,15 @@ PUBLIC void printlist ARGS2( continue; } dest = HTAnchor_followMainLink((HTAnchor *)child); + /* + * Ignore if child anchor points to itself, i.e. we had + * something like <A NAME=xyz HREF="#xyz"> and it is not + * treated as a hidden link. Useful if someone 'P'rints + * the List Page (which isn't a very useful action to do, + * but anyway...) - kw + */ + if (dest == (HTAnchor *)child) + continue; parent = HTAnchor_parent(dest); title = titles ? HTAnchor_title(parent) : NULL; address = HTAnchor_address(dest); diff --git a/src/LYList.h b/src/LYList.h index e1e0b8de..4a717284 100644 --- a/src/LYList.h +++ b/src/LYList.h @@ -3,7 +3,7 @@ #define LYLIST_H extern char * LYlist_temp_url NOPARAMS; -extern int showlist PARAMS((char **newfile, BOOLEAN titles)); +extern int showlist PARAMS((document *newdoc, BOOLEAN titles)); extern void printlist PARAMS((FILE *fp, BOOLEAN titles)); #define LIST_PAGE_TITLE "Lynx List Page" diff --git a/src/LYMain.c b/src/LYMain.c index b5749c9e..5a6875e3 100644 --- a/src/LYMain.c +++ b/src/LYMain.c @@ -164,7 +164,8 @@ PUBLIC int LYrcShowColor = SHOW_COLOR_UNKNOWN; /* ... as last read or written * PUBLIC BOOLEAN LYShowCursor = SHOW_CURSOR; /* to show or not to show */ PUBLIC BOOLEAN LYUseDefShoCur = TRUE; /* Command line -show_cursor toggle */ PUBLIC BOOLEAN LYforce_no_cache = FALSE; -PUBLIC BOOLEAN LYoverride_no_cache = FALSE; +PUBLIC BOOLEAN LYoverride_no_cache = FALSE;/*override no-cache b/c history etc*/ +PUBLIC BOOLEAN LYinternal_flag = FALSE; /* override no-cache b/c internal link*/ PUBLIC BOOLEAN LYresubmit_posts = ALWAYS_RESUBMIT_POSTS; PUBLIC BOOLEAN LYUserSpecifiedURL = TRUE;/* always TRUE the first time */ PUBLIC BOOLEAN LYJumpFileURL = FALSE; /* always FALSE the first time */ @@ -1563,7 +1564,7 @@ PUBLIC int main ARGS2( /* * Check for a valid HEAD request. - FM */ - if (HEAD_request && strncmp(startfile, "http", 4)) { + if (HEAD_request && LYCanDoHEAD(startfile) != TRUE) { fprintf(stderr, "The '-head' switch is for http HEAD requests and cannot be used for\n'%s'.\n", startfile); @@ -1584,7 +1585,7 @@ PUBLIC int main ARGS2( /* * Check for a valid MIME headers request. - FM */ - if (keep_mime_headers && strncmp(startfile, "http", 4)) { + if (keep_mime_headers && LYCanDoHEAD(startfile) != TRUE) { fprintf(stderr, "The '-mime_header' switch is for http URLs and cannot be used for\n'%s'.\n", startfile); diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c index 12e43f5b..11020387 100644 --- a/src/LYMainLoop.c +++ b/src/LYMainLoop.c @@ -56,6 +56,11 @@ #include "LYexit.h" #include "LYLeaks.h" +PRIVATE BOOL confirm_post_resub PARAMS(( + CONST char* address, + CONST char* title, + int if_imgmap, + int if_file)); PRIVATE int are_different PARAMS((document *doc1, document *doc2)); PRIVATE int are_phys_different PARAMS((document *doc1, document *doc2)); PUBLIC void HTGotoURLs_free NOPARAMS; @@ -129,7 +134,8 @@ PRIVATE void free_mainloop_variables NOARGS int mainloop NOARGS { - int c = 0, real_c = 0, old_c = 0, cmd, real_cmd = LYK_DO_NOTHING; + int c = 0, real_c = 0, old_c = 0; + int cmd = LYK_DO_NOTHING, real_cmd = LYK_DO_NOTHING; int getresult; int arrowup = FALSE, show_help = FALSE; int lines_in_file = -1; @@ -336,11 +342,11 @@ try_again: #ifndef DONT_TRACK_INTERNAL_LINKS -#define NONINTERNAL_OR_DIFFERENT(c,n) TRUE +#define NO_INTERNAL_OR_DIFFERENT(c,n) TRUE #define NONINTERNAL_OR_PHYS_DIFFERENT(p,n) (!curdoc.internal_link || \ are_phys_different(p,n)) #else /* TRACK_INTERNAL_LINKS */ -#define NONINTERNAL_OR_DIFFERENT(c,n) are_different(c,n) +#define NO_INTERNAL_OR_DIFFERENT(c,n) are_different(c,n) #define NONINTERNAL_OR_PHYS_DIFFERENT(p,n) are_different(p,n) #endif /* TRACK_INTERNAL_LINKS */ @@ -354,6 +360,7 @@ try_again: */ if (curdoc.internal_link && !are_phys_different(&curdoc, &newdoc)) { + LYinternal_flag = TRUE; LYoverride_no_cache = TRUE; LYforce_no_cache = FALSE; try_internal = TRUE; @@ -362,7 +369,7 @@ try_again: if ((newdoc.bookmark != NULL) || (newdoc.post_data != NULL && !newdoc.safe && LYresubmit_posts && - NONINTERNAL_OR_DIFFERENT(&curdoc, &newdoc))) { + NO_INTERNAL_OR_DIFFERENT(&curdoc, &newdoc))) { LYoverride_no_cache = FALSE; } else { LYoverride_no_cache = TRUE; @@ -374,10 +381,10 @@ try_again: * Make SURE this is an appropriate request. - FM */ if (newdoc.address) { - if (!strncmp(newdoc.address, "http", 4)) { + if (LYCanDoHEAD(newdoc.address) == TRUE) { newdoc.isHEAD = TRUE; } else if (!strncmp(newdoc.address, "LYNXIMGMAP:", 11)) { - if (!strncmp(newdoc.address + 11, "http", 4)) { + if (LYCanDoHEAD(newdoc.address + 11) == TRUE) { StrAllocCopy(temp, newdoc.address + 11); FREE(newdoc.address); newdoc.address = temp; @@ -505,6 +512,7 @@ try_again: */ LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */ popped_doc = FALSE; /* Was TRUE if popped. - FM */ + LYinternal_flag = FALSE; /* Reset to default. - kw */ if (trace_mode_flag == TRUE) { WWW_TraceFlag = TRUE; trace_mode_flag = FALSE; @@ -595,6 +603,7 @@ try_again: */ LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */ popped_doc = FALSE; /* Was TRUE if popped. - FM */ + LYinternal_flag = FALSE; /* Reset to default. - kw */ if (trace_mode_flag == TRUE) { WWW_TraceFlag = TRUE; trace_mode_flag = FALSE; @@ -632,11 +641,11 @@ try_again: */ if (first_file && homepage && #ifdef VMS - strcasecomp(homepage, startfile) != 0) + strcasecomp(homepage, startfile) != 0 #else - strcmp(homepage, startfile) != 0) + strcmp(homepage, startfile) != 0 #endif /* VMS */ - { + ) { /* * Couldn't return to the first file but there is a * homepage we can use instead. Useful for when the @@ -655,6 +664,7 @@ try_again: newdoc.isHEAD = FALSE; newdoc.safe = FALSE; newdoc.internal_link = FALSE; + goto try_again; } else { if (!dump_output_immediately) cleanup(); @@ -688,6 +698,48 @@ try_again: } } + /* + * Retrieval of a newdoc just failed, and just + * going to try_again would pop the next doc + * from history and try to get it without further + * questions. This may not be the right thing to do if + * we have POST data, so fake a PREV_DOC key if it seems + * that some prompting should be done. Dunno about the + * traversal logic, so I leave that case alone. + */ + if (history[nhist - 1].post_data && + !history[nhist - 1].safe) { + /* Set newdoc fields, just in case the PREV_DOC + * gets cancelled. - kw */ + if (!curdoc.address) { + StrAllocCopy(newdoc.address, HTLoadedDocumentURL()); + StrAllocCopy(newdoc.title, HTLoadedDocumentTitle()); + if (HTMainAnchor && HTMainAnchor->post_data) { + StrAllocCopy(newdoc.post_data, + HTMainAnchor->post_data); + StrAllocCopy(newdoc.post_content_type, + HTMainAnchor->post_content_type); + } else { + FREE(newdoc.post_data); + } + newdoc.isHEAD = HTLoadedDocumentIsHEAD(); + newdoc.safe = HTLoadedDocumentIsSafe(); + newdoc.internal_link = FALSE; + } else { + 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); + newdoc.isHEAD = curdoc.isHEAD; + newdoc.safe = curdoc.safe; + newdoc.internal_link = curdoc.internal_link; + newdoc.line = curdoc.line; + newdoc.link = curdoc.link; + } + cmd = LYK_PREV_DOC; + goto new_cmd; + } goto try_again; break; @@ -696,6 +748,7 @@ try_again: * Marvelously, we got the document! */ LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */ + LYinternal_flag = FALSE; /* Reset to default. - kw */ if (trace_mode_flag == TRUE) { WWW_TraceFlag = TRUE; trace_mode_flag = FALSE; @@ -728,10 +781,12 @@ try_again: len = strlen(cp); #ifdef VMS if (!strncasecomp(temp, cp, len) && + strlen(temp) > len) #else if (!strncmp(temp, cp, len) && + strlen(temp) > len) #endif /* VMS */ - strlen(temp) > len) { + { /* * We're interactive and this might be a * bookmark file entered as a startfile @@ -755,11 +810,11 @@ try_again: for (i = 0; i <= MBM_V_MAXFILES; i++) { if (MBM_A_subbookmark[i] && #ifdef VMS - !strcasecomp(cp, MBM_A_subbookmark[i])) + !strcasecomp(cp, MBM_A_subbookmark[i]) #else - !strcmp(cp, MBM_A_subbookmark[i])) + !strcmp(cp, MBM_A_subbookmark[i]) #endif /* VMS */ - { + ) { StrAllocCopy(BookmarkPage, MBM_A_subbookmark[i]); break; @@ -943,7 +998,7 @@ try_again: LYforce_HTML_mode = FALSE; popped_doc = FALSE; - } /* end if (STREQ(newdoc.address, curdoc.address) */ + } /* end if (LYforce_no_cache || force_load || are_different(...)) */ if (dump_output_immediately) { if (crawl) { @@ -1165,7 +1220,10 @@ try_again: * Refresh the screen if neccessary. */ if (refresh_screen) { - clear(); + if (enable_scrollback) + clear(); + else + erase(); HText_pageDisplay(Newline, prev_target); #ifdef DIRED_SUPPORT @@ -1629,22 +1687,112 @@ new_cmd: /* */ StrAllocCopy(newdoc.address, links[lindx].lname); StrAllocCopy(newdoc.title, links[lindx].hightext); +#ifndef DONT_TRACK_INTERNAL_LINKS /* - * Might be an anchor in the same doc from a POST - * form. If so, don't free the content. -- FM + * For internal links, retain POST content if present. + * If we are on the List Page, prevent pushing it on + * the history stack. Otherwise set try_internal to + * signal that the top of the loop should attempt to + * reposition directly, without calling getfile. - kw */ if (links[lindx].type == WWW_INTERN_LINK_TYPE) { - LYoverride_no_cache = TRUE; + LYinternal_flag = TRUE; newdoc.internal_link = TRUE; - if (0==strcmp(curdoc.address, LYlist_temp_url()) && - 0==strcmp((curdoc.title ? curdoc.title : ""), - LIST_PAGE_TITLE)) { + if (0==strcmp((curdoc.title ? curdoc.title : ""), + LIST_PAGE_TITLE) && + 0==strcmp(HTLoadedDocumentURL(), LYlist_temp_url())) { + if (!curdoc.post_data || + /* + * Normal case - List Page is not associated + * with post data. - kw + */ + (!LYresubmit_posts && curdoc.post_data && + history[nhist - 1].post_data && + !strcmp(curdoc.post_data, + history[nhist - 1].post_data) && + HText_getContentBase() && + !strncmp(HText_getContentBase(), + strncmp(history[nhist - 1].address, + "LYNXIMGMAP:", 11) ? + history[nhist - 1].address : + history[nhist - 1].address + 11, + strlen(HText_getContentBase())))) { + /* + * Normal case - as best as we can check, the + * document at the top of the history stack + * seems to be the document the List Page is + * about (or a LYNXIMGMAP derived from it), + * and LYresubmit_posts is not set, so don't + * prompt here. If we actually have to repeat + * a POST because, against expectations, the + * underlying document isn't cached any more, + * HTAccess will prompt for confirmation, + * unless we had LYK_NOCACHE. - kw + */ + LYinternal_flag = TRUE; + } else { + HTLastConfirmCancelled(); /* reset flag */ + if (!confirm_post_resub(newdoc.address, + newdoc.title, + (LYresubmit_posts && + HText_POSTReplyLoaded(&newdoc)) ? 1 : 2, + 2)) { + if (HTLastConfirmCancelled() || + (LYresubmit_posts && + !HText_POSTReplyLoaded(&newdoc))) { + /* cancel the whole thing */ + LYforce_no_cache = FALSE; + reloading = FALSE; + StrAllocCopy(newdoc.address, curdoc.address); + StrAllocCopy(newdoc.title, curdoc.title); + newdoc.internal_link = curdoc.internal_link; + _statusline(CANCELLED); + sleep(InfoSecs); + if (nlinks > 0) + HText_pageDisplay(curdoc.line, prev_target); + break; + } else if (LYresubmit_posts) { + /* If LYresubmit_posts is set, and the + answer was No, and we have a cached + copy, then use it. - kw */ + LYforce_no_cache = FALSE; + } else { + /* if No, but not ^C or ^G, drop + * the post data. Maybe the link + * wasn't meant to be internal after + * all, here we can recover from that + * assumption. - kw */ + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); + newdoc.internal_link = FALSE; + _statusline(DISCARDING_POST_DATA); + sleep(AlertSecs); + } + } + } + /* + * Don't push the List Page if we follow an + * internal link given by it. - kw + */ FREE(curdoc.address); } else try_internal = TRUE; + if (!(LYresubmit_posts && newdoc.post_data)) + LYinternal_flag = TRUE; force_load = TRUE; break; + } else { + /* + * Free POST content if not an internal link. - kw + */ + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); } +#endif /* DONT_TRACK_INTERNAL_LINKS */ + /* + * 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); @@ -1742,7 +1890,8 @@ new_cmd: /* */ if ((curdoc.post_data != NULL && curdoc.safe != TRUE) && - HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + confirm_post_resub(curdoc.address, curdoc.title, + 1, 1) == FALSE) { _statusline(CANCELLED); sleep(InfoSecs); break; @@ -1832,7 +1981,8 @@ new_cmd: /* */ if ((curdoc.post_data != NULL && curdoc.safe != TRUE) && - HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + confirm_post_resub(curdoc.address, NULL, + 0, 0) == FALSE) { _statusline(WILL_NOT_RELOAD_DOC); sleep(InfoSecs); } else { @@ -1863,7 +2013,8 @@ new_cmd: /* */ if ((curdoc.post_data != NULL && curdoc.safe != TRUE) && - HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + confirm_post_resub(curdoc.address, NULL, + 0, 0) == FALSE) { _statusline(WILL_NOT_RELOAD_DOC); sleep(InfoSecs); } else { @@ -1894,7 +2045,8 @@ new_cmd: /* */ if ((curdoc.post_data != NULL && curdoc.safe != TRUE) && - HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + confirm_post_resub(curdoc.address, NULL, + 1, 1) == FALSE) { _statusline(WILL_NOT_RELOAD_DOC); sleep(InfoSecs); } else { @@ -1919,7 +2071,8 @@ new_cmd: /* */ if ((curdoc.post_data != NULL && curdoc.safe != TRUE) && - HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + confirm_post_resub(curdoc.address, NULL, + 1, 1) == FALSE) { _statusline(WILL_NOT_RELOAD_DOC); sleep(InfoSecs); } else { @@ -2080,9 +2233,7 @@ new_cmd: /* case LYK_REFRESH: refresh_screen = TRUE; -#if defined(VMS) || defined(USE_SLANG) lynx_force_repaint(); -#endif /* VMS || USE_SLANG */ break; case LYK_HOME: @@ -2398,8 +2549,12 @@ new_cmd: /* */ DocAddress WWWDoc; HTParentAnchor *tmpanchor; + HText *text; + BOOLEAN conf = FALSE, first = TRUE; + HTLastConfirmCancelled(); /* reset flag */ while (nhist > 0) { + conf = FALSE; if (history[(nhist - 1)].post_data == NULL) { break; } @@ -2414,12 +2569,29 @@ new_cmd: /* if (HTAnchor_safe(tmpanchor)) { break; } - if (((HText *)HTAnchor_document(tmpanchor) == NULL || - (LYresubmit_posts && - NONINTERNAL_OR_PHYS_DIFFERENT( + if (((text = + (HText *)HTAnchor_document(tmpanchor)) == NULL && + (!strncmp(WWWDoc.address, "LYNXIMGMAP:", 11) || + (conf = confirm_post_resub(WWWDoc.address, + history[(nhist - 1)].title, + 0, 0)) + == FALSE)) || + ((LYresubmit_posts && !conf && + (NONINTERNAL_OR_PHYS_DIFFERENT( (document *)&history[(nhist - 1)], - &curdoc))) && - HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + &curdoc) || + NONINTERNAL_OR_PHYS_DIFFERENT( + (document *)&history[(nhist - 1)], + &newdoc))) && + !confirm_post_resub(WWWDoc.address, + history[(nhist - 1)].title, + 2, 2))) { + if (HTLastConfirmCancelled()) { + if (!first && curdoc.internal_link) + FREE(curdoc.address); + cmd = LYK_DO_NOTHING; + goto new_cmd; + } if (nhist == 1) { _statusline(CANCELLED); sleep(InfoSecs); @@ -2429,13 +2601,29 @@ new_cmd: /* } else { _user_message(WWW_SKIP_MESSAGE, WWWDoc.address); sleep(MessageSecs); - LYpop(&curdoc); + do { + LYpop(&curdoc); + } while (nhist > 1 && !are_different( + (document *)&history[(nhist - 1)], + &curdoc)); + first = FALSE; /* have popped at least one */ continue; } } else { + /* + * Break from loop; if user just confirmed to + * load again because document wasn't in cache, + * set LYforce_no_cache to avoid unnecessary + * repeat question down the road. - kw + */ + if (conf) + LYforce_no_cache = TRUE; break; } } + + if (!first) + curdoc.internal_link = FALSE; /* * Set newdoc.address to empty to pop a file. @@ -2494,6 +2682,7 @@ new_cmd: /* if (links[curdoc.link].form->disabled == YES) { HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; + reloading = FALSE; break; } /* @@ -2506,6 +2695,7 @@ new_cmd: /* sleep(MessageSecs); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; + reloading = FALSE; break; } /* @@ -2517,6 +2707,7 @@ new_cmd: /* HTAlert(FORM_MAILTO_DISALLOWED); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; + reloading = FALSE; break; } /* @@ -2530,6 +2721,7 @@ new_cmd: /* HTAlert(FILE_ACTIONS_DISALLOWED); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; + reloading = FALSE; break; } /* @@ -2586,6 +2778,7 @@ new_cmd: /* } HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; + reloading = FALSE; break; } #ifdef NOTDEFINED /* We're disabling form inputs instead of using this. - FM */ @@ -2601,6 +2794,7 @@ new_cmd: /* "Enctype multipart/form-data not yet supported! Cannot submit."); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; + reloading = FALSE; break; } } @@ -2656,9 +2850,11 @@ new_cmd: /* !strncmp(links[curdoc.link].lname, "file:", 5)) { if (strncmp(curdoc.address, "file:", 5)) { HTAlert(FILE_SERVED_LINKS_DISALLOWED); + reloading = FALSE; break; } else if (curdoc.bookmark != NULL) { HTAlert(FILE_BOOKMARKS_DISALLOWED); + reloading = FALSE; break; } } @@ -2691,7 +2887,8 @@ new_cmd: /* (!strncmp(links[curdoc.link].lname, "LYNXHIST:", 9) && strcmp((curdoc.title ? curdoc.title : ""), - HISTORY_PAGE_TITLE)) || + HISTORY_PAGE_TITLE) && + strcmp(curdoc.address, LYlist_temp_url())) || (!strncmp(links[curdoc.link].lname, "LYNXPRINT:", 10) && strcmp((curdoc.title ? curdoc.title : ""), @@ -2699,6 +2896,7 @@ new_cmd: /* HTAlert(SPECIAL_VIA_EXTERNAL_DISALLOWED); HTOutputFormat = WWW_PRESENT; LYforce_no_cache = FALSE; + reloading = FALSE; break; } /* @@ -2707,6 +2905,13 @@ new_cmd: /* StrAllocCopy(newdoc.address, links[curdoc.link].lname); StrAllocCopy(newdoc.title, links[curdoc.link].hightext); #ifndef DONT_TRACK_INTERNAL_LINKS + /* + * For internal links, retain POST content if present. + * If we are on the List Page, prevent pushing it on + * the history stack. Otherwise set try_internal to + * signal that the top of the loop should attempt to + * reposition directly, without calling getfile. - kw + */ /* * Might be an internal link anchor in the same doc. * If so, take the try_internal shortcut if we didn't @@ -2715,19 +2920,105 @@ new_cmd: /* newdoc.internal_link = (links[curdoc.link].type == WWW_INTERN_LINK_TYPE); if (newdoc.internal_link) { + /* + * Special case of List Page document with an + * internal link indication, which may really stand + * for an internal link within the document the + * List Page is about. - kw + */ if (0==strcmp(curdoc.address, LYlist_temp_url()) && 0==strcmp((curdoc.title ? curdoc.title : ""), LIST_PAGE_TITLE)) { + if (!curdoc.post_data || + /* + * Normal case - List Page is not associated + * with post data. - kw + */ + (!LYresubmit_posts && curdoc.post_data && + history[nhist - 1].post_data && + !strcmp(curdoc.post_data, + history[nhist - 1].post_data) && + HText_getContentBase() && + !strncmp(HText_getContentBase(), + strncmp(history[nhist - 1].address, + "LYNXIMGMAP:", 11) ? + history[nhist - 1].address : + history[nhist - 1].address + 11, + strlen(HText_getContentBase())))) { + /* + * Normal case - as best as we can check, the + * document at the top of the history stack + * seems to be the document the List Page is + * about (or a LYNXIMGMAP derived from it), + * and LYresubmit_posts is not set, so don't + * prompt here. If we actually have to repeat + * a POST because, against expectations, the + * underlying document isn't cached any more, + * HTAccess will prompt for confirmation, + * unless we had LYK_NOCACHE. - kw + */ + LYinternal_flag = TRUE; + } else { + HTLastConfirmCancelled(); /* reset flag */ + if (!confirm_post_resub(newdoc.address, + newdoc.title, + (LYresubmit_posts && + HText_POSTReplyLoaded(&newdoc)) ? 1 : 2, + 2)) { + if (HTLastConfirmCancelled() || + (LYresubmit_posts && + cmd != LYK_NOCACHE && + !HText_POSTReplyLoaded(&newdoc))) { + /* cancel the whole thing */ + LYforce_no_cache = FALSE; + reloading = FALSE; + StrAllocCopy(newdoc.address, curdoc.address); + StrAllocCopy(newdoc.title, curdoc.title); + newdoc.internal_link = curdoc.internal_link; + _statusline(CANCELLED); + sleep(InfoSecs); + break; + } else if (LYresubmit_posts && + cmd != LYK_NOCACHE) { + /* If LYresubmit_posts is set, and the + answer was No, and the key wasn't + NOCACHE, and we have a cached copy, + then use it. - kw */ + LYforce_no_cache = FALSE; + } else { + /* if No, but not ^C or ^G, drop + * the post data. Maybe the link + * wasn't meant to be internal after + * all, here we can recover from that + * assumption. - kw */ + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); + newdoc.internal_link = FALSE; + _statusline(DISCARDING_POST_DATA); + sleep(AlertSecs); + } + } + } + /* + * Don't push the List Page if we follow an + * internal link given by it. - kw + */ FREE(curdoc.address); } else if (cmd != LYK_NOCACHE) { try_internal = TRUE; } - LYoverride_no_cache = TRUE; /* ??? */ + if (!(LYresubmit_posts && newdoc.post_data)) + LYinternal_flag = TRUE; /* We still set force_load so that history pushing ** etc. will be done. - kw */ force_load = TRUE; break; } else { + /* + * Free POST content if not an internal link. - kw + */ + FREE(newdoc.post_data); + FREE(newdoc.post_content_type); } #endif /* TRACK_INTERNAL_LINKS */ /* @@ -3309,7 +3600,8 @@ check_goto_URL: */ if ((curdoc.post_data != NULL && curdoc.safe != TRUE) && - HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) { + confirm_post_resub(curdoc.address, curdoc.title, + 2, 1) == FALSE) { _statusline(WILL_NOT_RELOAD_DOC); sleep(InfoSecs); @@ -3814,6 +4106,10 @@ check_goto_URL: curdoc.bookmark); } else { /* behave like REFRESH for backward compatability */ refresh_screen = TRUE; + if (old_c != real_c) { + old_c = real_c; + lynx_force_repaint(); + } break; } if (TOUPPER(c) == 'Y') { @@ -3914,15 +4210,16 @@ check_goto_URL: /* * Print list page to file. */ - if (showlist(&newdoc.address, TRUE) < 0) + if (showlist(&newdoc, TRUE) < 0) break; StrAllocCopy(newdoc.title, LIST_PAGE_TITLE); - FREE(newdoc.post_data); - FREE(newdoc.post_content_type); - FREE(newdoc.bookmark); - newdoc.isHEAD = FALSE; - newdoc.safe = FALSE; - newdoc.internal_link = FALSE; + /* + * showlist will sett newdoc's other fields. It may leave + * post_data intact so the list can be used to follow + * internal links in the current document even if it is + * a POST response. - kw + */ + refresh_screen = TRUE; /* redisplay */ if (LYValidate || check_realm) { LYPermitURL = TRUE; @@ -4207,6 +4504,14 @@ check_goto_URL: * exists in this bookmark file. - FM */ _statusline(MULTIBOOKMARKS_SELF); + } else if (curdoc.post_data != NULL && + links[curdoc.link].type == WWW_INTERN_LINK_TYPE) { + /* + * Internal link, and document has POST content. + */ + _statusline(NOBOOK_POST_FORM); + sleep(MessageSecs); + break; } else { /* * Only offer the link in a document with @@ -4219,6 +4524,15 @@ check_goto_URL: c = LYgetch(); } if (TOUPPER(c) == 'L') { + if (curdoc.post_data != NULL && + links[curdoc.link].type == WWW_INTERN_LINK_TYPE) { + /* + * Internal link, and document has POST content. + */ + _statusline(NOBOOK_POST_FORM); + sleep(MessageSecs); + break; + } /* * User does want to save the link. - FM */ @@ -4468,7 +4782,8 @@ check_add_bookmark_to_self: #endif /* DIRED_SUPPORT */ } else if (!strcmp((curdoc.title ? curdoc.title : ""), - HISTORY_PAGE_TITLE)) { + HISTORY_PAGE_TITLE) && + !strncmp(links[curdoc.link].lname, "LYNXHIST:", 9)) { int number = atoi(links[curdoc.link].lname+9); if ((history[number].post_data != NULL && history[number].safe != TRUE) && @@ -4528,18 +4843,27 @@ check_add_bookmark_to_self: */ StrAllocCopy(newdoc.address, links[curdoc.link].lname); StrAllocCopy(newdoc.title, links[curdoc.link].hightext); - newdoc.internal_link = FALSE; +#ifndef DONT_TRACK_INTERNAL_LINKS + /* + * Might be an internal link in the same doc from a + * POST form. If so, don't free the content. - kw + */ + if (links[curdoc.link].type != WWW_INTERN_LINK_TYPE) +#else /* * 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)) { + if (are_different(&curdoc, &newdoc)) +#endif /* TRACK_INTERNAL_LINKS */ + { FREE(newdoc.post_data); FREE(newdoc.post_content_type); FREE(newdoc.bookmark); newdoc.isHEAD = FALSE; newdoc.safe = FALSE; } + newdoc.internal_link = FALSE; newdoc.link = 0; HTOutputFormat = HTAtom_for("www/download"); /* @@ -4744,7 +5068,7 @@ check_add_bookmark_to_self: if (TOUPPER(c) == 'D') { char *scheme = strncmp(curdoc.address, "LYNXIMGMAP:", 11) ? curdoc.address : curdoc.address + 11; - if (strncmp(scheme, "http", 4)) { + if (LYCanDoHEAD(scheme) != TRUE) { _statusline(DOC_NOT_HTTP_URL); sleep(MessageSecs); } else { @@ -4776,6 +5100,7 @@ check_add_bookmark_to_self: strncmp(links[curdoc.link].lname, "http", 4) && strncmp(links[curdoc.link].lname, "LYNXIMGMAP:http", 15) && + LYCanDoHEAD(links[curdoc.link].lname) != TRUE && (links[curdoc.link].type != WWW_INTERN_LINK_TYPE || !curdoc.address || strncmp(curdoc.address, "http", 4))) { @@ -4787,6 +5112,8 @@ check_add_bookmark_to_self: sleep(MessageSecs); } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE && strncmp(links[curdoc.link].form->submit_action, + "lynxcgi:", 8) && + strncmp(links[curdoc.link].form->submit_action, "http", 4)) { _statusline(FORM_ACTION_NOT_HTTP_URL); sleep(MessageSecs); @@ -4799,8 +5126,6 @@ check_add_bookmark_to_self: } else { HEAD_request = TRUE; LYforce_no_cache = TRUE; - StrAllocCopy(newdoc.title, links[curdoc.link].hightext); - StrAllocCat(newdoc.title, " - (HEAD)"); cmd = LYK_ACTIVATE; goto new_cmd; } @@ -4844,7 +5169,7 @@ check_add_bookmark_to_self: * a HEAD request is appropriate for the * current document. - FM */ - if (strncmp(scheme, "http", 4)) { + if (LYCanDoHEAD(scheme) != TRUE) { _statusline(DOC_NOT_HTTP_URL); sleep(MessageSecs); } else { @@ -4998,6 +5323,88 @@ check_add_bookmark_to_self: } } +/* + * Ask a post resubmission prompt with some indication of what would + * be resubmitted, useful especially for going backward in history. + * Try to use parts of the address or, if given, the title, depending + * on how much fits on the statusline. + * if_imgmap and if_file indicate how to handle an address that is + * a "LYNXIMGMAP:", or a "file:" URL (presumably the List Page file), + * respectively: 0: auto-deny, 1: auto-confirm, 2: prompt. + * - kw + */ + +PRIVATE BOOL confirm_post_resub ARGS4( + CONST char*, address, + CONST char*, title, + int, if_imgmap, + int, if_file) +{ + size_t len1; + CONST char *msg = CONFIRM_POST_RESUBMISSION_TO; + char buf[240]; + char *temp = NULL; + BOOL res; + size_t maxlen = LYcols - 6; + if (!address) { + return(NO); + } else if (!strncmp(address, "LYNXIMGMAP:", 11)) { + if (if_imgmap <= 0) + return(NO); + else if (if_imgmap == 1) + return(YES); + else + msg = CONFIRM_POST_LIST_RELOAD; + } else if (!strncmp(address, "file:", 5)) { + if (if_file <= 0) + return(NO); + else if (if_file == 1) + return(YES); + else + msg = CONFIRM_POST_LIST_RELOAD; + } else if (dump_output_immediately) { + return(NO); + } + if (maxlen >= sizeof(buf)) + maxlen = sizeof(buf) - 1; + if ((len1 = strlen(msg)) + + strlen(address) <= maxlen) { + sprintf(buf, msg, address); + return HTConfirm(buf); + } + if (len1 + strlen(temp = HTParse(address, "", + PARSE_ACCESS+PARSE_HOST+PARSE_PATH + +PARSE_PUNCTUATION)) <= maxlen) { + sprintf(buf, msg, temp); + res = HTConfirm(buf); + FREE(temp); + return(res); + } + FREE(temp); + if (title && (len1 + strlen(title) <= maxlen)) { + sprintf(buf, msg, title); + return HTConfirm(buf); + } + if (len1 + strlen(temp = HTParse(address, "", + PARSE_ACCESS+PARSE_HOST + +PARSE_PUNCTUATION)) <= maxlen) { + sprintf(buf, msg, temp); + res = HTConfirm(buf); + FREE(temp); + return(res); + } + FREE(temp); + if ((temp = HTParse(address, "", PARSE_HOST)) && *temp && + len1 + strlen(temp) <= maxlen) { + sprintf(buf, msg, temp); + res = HTConfirm(buf); + FREE(temp); + return(res); + } + FREE(temp); + return HTConfirm(CONFIRM_POST_RESUBMISSION); +} + PRIVATE int are_different ARGS2( document *, doc1, document *, doc2) diff --git a/src/LYMap.c b/src/LYMap.c index 103a41eb..1c2a194e 100644 --- a/src/LYMap.c +++ b/src/LYMap.c @@ -53,13 +53,14 @@ PRIVATE HTList * LynxMaps = NULL; PUBLIC BOOL LYMapsOnly = FALSE; /* - * Utility for freeing the list of MAPs. - FM + * Utility for freeing a list of MAPs. */ -PRIVATE void LYLynxMaps_free NOARGS +PUBLIC void ImageMapList_free ARGS1( + HTList *, theList) { LYImageMap *map; LYMapElement *element; - HTList *cur = LynxMaps; + HTList *cur = theList; HTList *current; if (!cur) @@ -81,36 +82,92 @@ PRIVATE void LYLynxMaps_free NOARGS } FREE(map); } - HTList_delete(LynxMaps); + HTList_delete(theList); + return; +} + +/* + * Utility for freeing the global list of MAPs. - kw + */ +PRIVATE void LYLynxMaps_free NOARGS +{ + ImageMapList_free(LynxMaps); LynxMaps = NULL; return; } +/* + * We keep two kinds of lists: + * - A global list (LynxMaps) shared by MAPs from all documents that + * do not have POST data. + * - For each response to a POST which contains MAPs, a list specific + * to this combination of URL and post_data. It is kept in the + * HTParentAnchor structure and is freed when the document is removed + * from memory, in the course of normal removal of anchors. + * MAPs from POST responses can only be accessed via internal links, + * i.e. from within the same document (with the same post_data). + * The notion of "same document" is extended, so that LYNXIMGMAP: + * and List Page screens are logically part of the document on which + * they are based. - kw + * + * If DONT_TRACK_INTERNAL_LINKS is defined, only the global list will + * be used for all MAPs. + * + */ + /* - * Utility for creating an LYImageMap list (LynxMaps), if it doesn't + * Utility for creating an LYImageMap list, if it doesn't * exist already, adding LYImageMap entry structures if needed, and * removing any LYMapElements in a pre-existing LYImageMap entry so that * it will have only those from AREA tags for the current analysis of * MAP element content. - FM */ -PUBLIC BOOL LYAddImageMap ARGS2( +PUBLIC BOOL LYAddImageMap ARGS3( char *, address, - char *, title) + char *, title, + HTParentAnchor *, node_anchor) { LYImageMap *new = NULL; LYImageMap *old = NULL; HTList *cur = NULL; + HTList *theList = NULL; HTList *curele = NULL; LYMapElement *ele = NULL; if (!(address && *address)) return FALSE; + if (!(node_anchor && node_anchor->address)) + return FALSE; - if (!LynxMaps) { - LynxMaps = HTList_new(); - atexit(LYLynxMaps_free); - } else { - cur = LynxMaps; + /* + * Set theList to either the global LynxMaps list or, if we + * are associated with post data, the specific list. The + * list is created if it doesn't already exist. - kw + */ +#ifndef DONT_TRACK_INTERNAL_LINKS + if (node_anchor->post_data) { + /* + * We are handling a MAP element found while parsing + * node_anchor's stream of data, and node_anchor has + * post_data associated and should therefore represent + * a POST response, so use the specific list. - kw + */ + theList = node_anchor->imaps; + if (!theList) { + theList = node_anchor->imaps = HTList_new(); + } + } else +#endif + { + if (!LynxMaps) { + LynxMaps = HTList_new(); + atexit(LYLynxMaps_free); + } + theList = LynxMaps; + } + + if (theList) { + cur = theList; while (NULL != (old = (LYImageMap *)HTList_nextObject(cur))) { if (!strcmp(old->address, address)) { FREE(old->address); @@ -141,31 +198,59 @@ PUBLIC BOOL LYAddImageMap ARGS2( if (title && *title) StrAllocCopy(new->title, title); if (new != old) - HTList_addObject(LynxMaps, new); + HTList_addObject(theList, new); return TRUE; } /* * Utility for adding LYMapElements to LYImageMaps - * in the LynxMaps list. - FM + * in the appropriate list. - FM */ -PUBLIC BOOL LYAddMapElement ARGS4( +PUBLIC BOOL LYAddMapElement ARGS5( char *, map, char *, address, char *, title, + HTParentAnchor *, node_anchor, BOOL, intern_flag) { LYMapElement *new = NULL; LYImageMap *theMap = NULL; + HTList *theList = NULL; HTList *cur = NULL; if (!(map && *map && address && *address)) return FALSE; + if (!(node_anchor && node_anchor->address)) + return FALSE; - if (!LynxMaps) - LYAddImageMap(map, NULL); + /* + * Set theList to either the global LynxMaps list or, if we + * are associated with post data, the specific list. The + * list should already exist, since this function is only called + * if the AREA tag we are handling was within a MAP element + * in node_anchor's stream of data, so that LYAddImageMap has + * been called. - kw + */ +#ifndef DONT_TRACK_INTERNAL_LINKS + if (node_anchor->post_data) { + /* + * We are handling an AREA tag found while parsing + * node_anchor's stream of data, and node_anchor has + * post_data associated and should therefore represent + * a POST response, so use the specific list. - kw + */ + theList = node_anchor->imaps; + if (!theList) + return FALSE; + } else +#endif + { + if (!LynxMaps) + LYAddImageMap(map, NULL, node_anchor); + theList = LynxMaps; + } - cur = LynxMaps; + cur = theList; while (NULL != (theMap = (LYImageMap *)HTList_nextObject(cur))) { if (!strcmp(theMap->address, map)) { break; @@ -224,6 +309,82 @@ PUBLIC BOOL LYHaveImageMap ARGS1( return FALSE; } +/* + * Fills in a Doccaddress structure for getting the HTParentAnchor of + * the underlying resource. ALso returns a pointer to that anchor in + * *punderlying if we are dealing with POST data. - kw + * + * address is the address of the underlying resource, i.e. the one + * containing the MAP element, the MAP's name appended as + * fragment is ignored. + * anAnchor is the LYNXIMGMAP: anchor; if it is associated with POST + * data, we want the specific list, otherwise the global list. + */ +PRIVATE void fill_DocAddress ARGS4( + DocAddress *, wwwdoc, + char *, address, + HTParentAnchor *, anAnchor, + HTParentAnchor **, punderlying) +{ + HTParentAnchor * underlying; + if (anAnchor && anAnchor->post_data) { + wwwdoc->address = address; + wwwdoc->post_data = anAnchor->post_data; + wwwdoc->post_content_type = anAnchor->post_content_type; + wwwdoc->bookmark = NULL; + wwwdoc->isHEAD = FALSE; + wwwdoc->safe = FALSE; + underlying = HTAnchor_parent(HTAnchor_findAddress(wwwdoc)); + if (underlying->safe) + wwwdoc->safe = TRUE; + if (punderlying) + *punderlying = underlying; + } else { + wwwdoc->address = address; + wwwdoc->post_data = NULL; + wwwdoc->post_content_type = NULL; + wwwdoc->bookmark = NULL; + wwwdoc->isHEAD = FALSE; + wwwdoc->safe = FALSE; + if (punderlying) + *punderlying = NULL; + } +} + +/* + * Get the appropriate list for creating a LYNXIMGMAP: pseudo- + * document: either the global list (LynxMaps), or the specific + * list if a List Page for a POST response is requested. Also + * fill in the DocAddress structure etc. by calling fill_DocAddress(). + * + * address is the address of the underlying resource, i.e. the one + * containing the MAP element, the MAP's name appended as + * fragment is ignored. + * anchor is the LYNXIMGMAP: anchor for which LYLoadIMGmap() is + * requested; if it is associated with POST data, we want the + * specific list for this combination of address+post_data. + * + * if DONT_TRACK_INTERNAL_LINKS is defined, the Anchor passed to + * LYLoadIMGmap() will never have post_data, so that the global list + * will be used. - kw + */ +PRIVATE HTList * get_the_list ARGS4( + DocAddress *, wwwdoc, + char *, address, + HTParentAnchor *, anchor, + HTParentAnchor **, punderlying) +{ + if (anchor && anchor->post_data) { + fill_DocAddress(wwwdoc, address, anchor, punderlying); + if (punderlying && *punderlying) + return (*punderlying)->imaps; + return anchor->imaps; + } else { + fill_DocAddress(wwwdoc, address, NULL, punderlying); + return LynxMaps; + } +} + /* LYLoadIMGmap - F.Macrides (macrides@sci.wfeb.edu) ** ------------ ** Create a text/html stream with a list of links @@ -243,10 +404,12 @@ PRIVATE int LYLoadIMGmap ARGS4 ( LYImageMap *theMap = NULL; char *MapTitle = NULL; char *MapAddress = NULL; + HTList *theList; HTList *cur = NULL; char *address = NULL; char *cp = NULL; DocAddress WWWDoc; + HTParentAnchor * underlying; BOOL old_cache_setting = LYforce_no_cache; BOOL old_reloading = reloading; HTFormat old_format_out = HTOutputFormat; @@ -259,13 +422,17 @@ PRIVATE int LYLoadIMGmap ARGS4 ( return(HT_NOT_LOADED); } - if (!LynxMaps) { - WWWDoc.address = address; - WWWDoc.post_data = NULL; - WWWDoc.post_content_type = NULL; - WWWDoc.bookmark = NULL; - WWWDoc.isHEAD = FALSE; - WWWDoc.safe = FALSE; + theList = get_the_list(&WWWDoc, address, anAnchor, &underlying); + if (WWWDoc.safe) + anAnchor->safe = TRUE; + + if (!theList) { + if (anAnchor->post_data && !WWWDoc.safe && + ((underlying && underlying->document && !LYforce_no_cache) || + HTConfirm("LYNXIMGMAP: " CONFIRM_POST_RESUBMISSION) != TRUE)) { + HTAlert("Image map from POST response not available!"); + return(HT_NOT_LOADED); + } LYforce_no_cache = TRUE; reloading = TRUE; HTOutputFormat = WWW_PRESENT; @@ -282,26 +449,27 @@ PRIVATE int LYLoadIMGmap ARGS4 ( reloading = old_reloading; HTOutputFormat = old_format_out; LYMapsOnly = FALSE; + theList = get_the_list(&WWWDoc, address, anAnchor, &underlying); } - if (!LynxMaps) { + if (!theList) { HTAlert(MAPS_NOT_AVAILABLE); return(HT_NOT_LOADED); } - cur = LynxMaps; + cur = theList; while (NULL != (theMap = (LYImageMap *)HTList_nextObject(cur))) { if (!strcmp(theMap->address, address)) { break; } } if (!(theMap && theMap->elements)) { - WWWDoc.address = address; - WWWDoc.post_data = NULL; - WWWDoc.post_content_type = NULL; - WWWDoc.bookmark = NULL; - WWWDoc.isHEAD = FALSE; - WWWDoc.safe = FALSE; + if (anAnchor->post_data && !WWWDoc.safe && + ((underlying && underlying->document && !LYforce_no_cache) || + HTConfirm("LYNXIMGMAP: " CONFIRM_POST_RESUBMISSION) != TRUE)) { + HTAlert("Image map from POST response not available!"); + return(HT_NOT_LOADED); + } LYforce_no_cache = TRUE; reloading = TRUE; HTOutputFormat = WWW_PRESENT; @@ -318,7 +486,7 @@ PRIVATE int LYLoadIMGmap ARGS4 ( reloading = old_reloading; HTOutputFormat = old_format_out; LYMapsOnly = FALSE; - cur = LynxMaps; + cur = get_the_list(&WWWDoc, address, anAnchor, &underlying); while (NULL != (theMap = (LYImageMap *)HTList_nextObject(cur))) { if (!strcmp(theMap->address, address)) { break; @@ -330,7 +498,9 @@ PRIVATE int LYLoadIMGmap ARGS4 ( } } +#ifdef DONT_TRACK_INTERNAL_LINKS anAnchor->no_cache = TRUE; +#endif target = HTStreamStack(format_in, format_out, diff --git a/src/LYMap.h b/src/LYMap.h index 48829eb7..a0ef6337 100644 --- a/src/LYMap.h +++ b/src/LYMap.h @@ -4,7 +4,11 @@ extern BOOL LYMapsOnly; -extern BOOL LYAddImageMap PARAMS((char *address, char *title)); -extern BOOL LYAddMapElement PARAMS((char *map, char *address, char *title, BOOL intern_flag)); +extern void ImageMapList_free PARAMS((HTList * list)); +extern BOOL LYAddImageMap PARAMS((char *address, char *title, + HTParentAnchor *node_anchor)); +extern BOOL LYAddMapElement PARAMS((char *map, char *address, char *title, + HTParentAnchor *node_anchor, + BOOL intern_flag)); #endif /* LYMAP_H */ diff --git a/src/LYOptions.c b/src/LYOptions.c index 61f9e187..8eaa64a0 100644 --- a/src/LYOptions.c +++ b/src/LYOptions.c @@ -205,7 +205,10 @@ draw_options: * might have non-ASCII or multibyte/CJK characters. - FM */ response = 0; - clear(); + if (enable_scrollback) + clear(); + else + erase(); move(0, 5); lynx_start_h1_color (); @@ -1792,7 +1795,10 @@ draw_bookmark_list: * to increase the chances that any non-ASCII or multibyte/CJK * characters will be handled properly. - FM */ - clear(); + if (enable_scrollback) + clear(); + else + erase(); move(0, 5); lynx_start_h1_color (); diff --git a/src/LYPrint.c b/src/LYPrint.c index 5ded8fc1..b466ff74 100644 --- a/src/LYPrint.c +++ b/src/LYPrint.c @@ -16,16 +16,14 @@ #include "LYHistory.h" #include "LYSystem.h" #include "LYList.h" +#include "LYCharSets.h" /* To get current charset for mail header. */ #ifdef VMS #include "HTVMSUtils.h" #endif /* VMS */ #ifdef DOSPATH #include "HTDOS.h" #endif -#ifdef EXP_CHARTRANS -#include "LYCharSets.h" /* to get current charset for mail header */ extern BOOLEAN LYHaveCJKCharacterSet; -#endif #include "LYLeaks.h" @@ -104,19 +102,23 @@ PUBLIC int printfile ARGS1( WWWDoc.safe = newdoc->safe; if (!HTLoadAbsolute(&WWWDoc)) return(NOT_FOUND); - + + /* + * If we have an explicit content-base, we may use it even + * if not in source mode. - kw + */ + if (HText_getContentBase()) { + StrAllocCopy(content_base, HText_getContentBase()); + collapse_spaces(content_base); + if (!(content_base && *content_base)) { + FREE(content_base); + } + } /* * 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); @@ -433,13 +435,16 @@ PUBLIC int printfile ARGS1( } } - if ((outfile_fp = LYNewTxtFile(buffer)) == NULL) { + if ((outfile_fp = fopen(buffer,"w")) == NULL) { HTAlert(CANNOT_WRITE_TO_FILE); _statusline(NEW_FILENAME_PROMPT); FirstRecall = TRUE; FnameNum = FnameTotal; goto retry; } +#ifdef VMS + chmod(buffer, 0600); +#endif if (HTisDocumentSource()) { /* @@ -611,7 +616,6 @@ PUBLIC int printfile ARGS1( * if the document has 8-bit characters and we we seem * to have a valid charset. - kw */ -#ifdef EXP_CHARTRANS use_cte = HTLoadedDocumentEightbit(); disp_charset = LYCharSet_UC[current_char_set].MIMEname; /* @@ -623,10 +627,12 @@ PUBLIC int printfile ARGS1( strncasecomp(disp_charset, "x-", 2) == 0) { disp_charset = NULL; } -#else - use_cte = NO; - disp_charset = NULL; -#endif /* EXP_CHARTRANS */ +#ifdef NOTDEFINED + /* Enable this if indicating an 8-bit transfer without + * also indicating the charset causes problems. - kw */ + if (use_cte && !disp_charse) + use_cte = FALSE; +#endif /* NOTDEFINED */ use_type = (disp_charset || HTisDocumentSource()); use_mime = (use_cte || use_type); @@ -648,10 +654,6 @@ PUBLIC int printfile ARGS1( } else { fprintf(outfile_fp, "\n"); } - fprintf(outfile_fp, "Content-Base: %s\n", - content_base); - fprintf(outfile_fp, "Content-Location: %s\n", - content_location); } else { /* * Add Content-Type: text/plain if we have 8-bit @@ -665,6 +667,20 @@ PUBLIC int printfile ARGS1( } } /* + * If we are using MIME headers, add content-base and + * content-location if we have them. This will always + * be the case if the document is source. - kw + */ + if (use_mime) { + if (content_base) + fprintf(outfile_fp, "Content-Base: %s\n", + content_base); + if (content_location) + fprintf(outfile_fp, "Content-Location: %s\n", + content_location); + } + + /* * Add the To, Subject, and X-URL headers. - FM */ fprintf(outfile_fp, "To: %s\nSubject: %s\n", diff --git a/src/LYStyle.c b/src/LYStyle.c index 160eff5f..a596214e 100644 --- a/src/LYStyle.c +++ b/src/LYStyle.c @@ -237,6 +237,10 @@ where OBJECT is one of EM,STRONG,B,I,U,BLINK etc.\n\n", buffer); { parse_attributes(mono,fg,bg,DSTYLE_HIGH,"high"); } + else if (!strcmp(element, "normal")) /* added - kw */ + { + parse_attributes(mono,fg,bg,DSTYLE_NORMAL,"html"); + } /* this may vanish */ else if (!strncasecmp(element, "candy", 5)) /* [INLINE]'s */ { diff --git a/src/LYUtils.c b/src/LYUtils.c index a39042f3..47a2fca1 100644 --- a/src/LYUtils.c +++ b/src/LYUtils.c @@ -1897,11 +1897,18 @@ PUBLIC void statusline ARGS1( int a=(strncmp(buffer, "Alert", 5) || !hashStyles[s_alert].name ? s_status : s_alert); LynxChangeStyle (a, ABS_ON, 1); addstr(buffer); - wbkgdset(stdscr, (lynx_has_color - ? hashStyles[a].color - : hashStyles[a].mono) | ' '); + wbkgdset(stdscr, + ((lynx_has_color && LYShowColor >= SHOW_COLOR_ON) + ? hashStyles[a].color + :A_NORMAL) | ' '); clrtoeol(); - wbkgdset(stdscr, hashStyles[s_normal].color | ' '); + if (s_normal != NOSTYLE) + wbkgdset(stdscr, hashStyles[s_normal].color | ' '); + else + wbkgdset(stdscr, + ((lynx_has_color && LYShowColor >= SHOW_COLOR_ON) + ? displayStyles[DSTYLE_NORMAL].color + : A_NORMAL) | ' '); LynxChangeStyle (a, ABS_OFF, 0); } #endif @@ -2697,6 +2704,47 @@ PUBLIC int is_url ARGS1( } /* + * Determine whether we allow HEAD and related flags for a URL. - kw + */ +PUBLIC BOOLEAN LYCanDoHEAD ARGS1( + CONST char *, address + ) +{ + char *temp0 = NULL; + int isurl; + if (!(address && *address)) + return FALSE; + if (!strncmp(address, "http", 4)) + return TRUE; + /* Make copy for is_url() since caller may not care for case changes */ + StrAllocCopy(temp0, address); + isurl = is_url(temp0); + FREE(temp0); + if (!isurl) + return FALSE; + if (isurl == LYNXCGI_URL_TYPE) { +#if defined(LYNXCGI_LINKS) && !defined(VMS) + return TRUE; +#else + return FALSE; +#endif + } + if (isurl == NEWS_URL_TYPE || isurl == NNTP_URL_TYPE) { + char *temp = HTParse(address, "", PARSE_PATH); + char *cp = strrchr(temp, '/'); + if (strchr((cp ? cp : temp), '@') != NULL) { + FREE(temp); + return TRUE; + } + if (cp && isdigit(cp[1]) && strchr(cp, '-') == NULL) { + FREE(temp); + return TRUE; + } + FREE(temp); + } + return FALSE; +} +/* * Remove backslashes from any string. */ PUBLIC void remove_backslashes ARGS1( @@ -5530,3 +5578,29 @@ PUBLIC FILE *LYAppendToTxtFile ARGS1(char *, name) #endif return fp; } + +#ifdef UNIX +/* + * Restore normal permisions to a copy of a file that we have created + * with temp file restricted permissions. The normal umask should + * apply for user files. - kw + */ +PUBLIC void LYRelaxFilePermissions ARGS1(CONST char *, name) +{ + int mode; + struct stat stat_buf; + if (stat(name, &stat_buf) == 0 && + S_ISREG(stat_buf.st_mode) && + (mode = (stat_buf.st_mode & 0777)) == HIDE_CHMOD) { + /* + * It looks plausible that this is a file we created with + * temp file paranoid permissions (and the umask wasn't even + * more restrictive when it was copied). - kw + */ + int save = umask(HIDE_UMASK); + mode = ((mode & 0700) | 0066) & ~save; + umask(save); + chmod(name, mode); + } +} +#endif diff --git a/src/LYUtils.h b/src/LYUtils.h index 7af31349..9b8a8b35 100644 --- a/src/LYUtils.h +++ b/src/LYUtils.h @@ -25,6 +25,7 @@ extern void LYAddLocalhostAlias PARAMS((char *alias)); extern BOOLEAN LYisLocalAlias PARAMS((char *filename)); extern int LYCheckForProxyURL PARAMS((char *filename)); extern int is_url PARAMS((char *filename)); +extern BOOLEAN LYCanDoHEAD PARAMS((CONST char *address)); extern void remove_backslashes PARAMS((char *buf)); extern char *quote_pathname PARAMS((char *pathname)); extern BOOLEAN inlocaldomain NOPARAMS; @@ -61,7 +62,9 @@ extern int putenv PARAMS((CONST char *string)); FILE *LYNewBinFile PARAMS((char * name)); FILE *LYNewTxtFile PARAMS((char * name)); FILE *LYAppendToTxtFile PARAMS((char * name)); - +#ifdef UNIX +extern void LYRelaxFilePermissions PARAMS((CONST char * name)); +#endif /* * Whether or not the status line must be shown. */ diff --git a/src/LYexit.c b/src/LYexit.c index 625c05e3..74ce16c3 100644 --- a/src/LYexit.c +++ b/src/LYexit.c @@ -107,6 +107,7 @@ PUBLIC void LYexit ARGS1( #endif /* exit */ #ifndef VMS /* On VMS, the VMSexit() handler does these. - FM */ + fflush(stderr); if (LYOutOfMemory == TRUE) { LYOutOfMemory = FALSE; printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT); diff --git a/src/chrtrans/README.format b/src/chrtrans/README.format index 58f0b1cc..0ec556a2 100644 --- a/src/chrtrans/README.format +++ b/src/chrtrans/README.format @@ -96,11 +96,14 @@ d) string replacement definitions: * Syntax accepted: * <unicode> :<replace> * <unicode range> :<replace> + * <unicode> "<C replace>" + * <unicode range> "<C replace>" * * where <unicode range> ::= <unicode>-<unicode> * and <unicode> ::= U+<h><h><h><h> * and <h> ::= <hexadecimal digit> - * and <replace> any string not containing '\n' or '\0' + * and <replace> any string not containing '\n' or '\0', taken verbatim + * and <C replace> any string, with backslash having the usual C meaning Motivation: diff --git a/src/chrtrans/cp437_uni.tbl b/src/chrtrans/cp437_uni.tbl index ed97a69c..6bfbab22 100644 --- a/src/chrtrans/cp437_uni.tbl +++ b/src/chrtrans/cp437_uni.tbl @@ -1,7 +1,5 @@ #Shall this become the "default" translation? -#Meaning of that is currently unclear... It's different -#from the default input or defualt output charset... -#but there has to be exactly one table marked as "default". +#There has to be exactly one table marked as "default". D0 # #The MIME name of this charset. @@ -287,7 +285,7 @@ OIBM PC character set 0xff U+00a0 #NO-BREAK SPACE U+03ac:a' -U+03ad:î' +U+03ad "\356'" #:î' U+03ae:h' U+03af:i' U+03cc:o' diff --git a/src/chrtrans/iso01_uni.tbl b/src/chrtrans/iso01_uni.tbl index 14f71ff3..d2147771 100644 --- a/src/chrtrans/iso01_uni.tbl +++ b/src/chrtrans/iso01_uni.tbl @@ -21,7 +21,7 @@ OISO Latin 1 0x63 U+0063 U+0107 U+0109 U+010B U+010D 0x64-0x7e idem 0xa0-0xff idem -#0x00 U+fffd # don't let failed char lookups return '\0' +#0x00 U+fffd # don't let failed char lookups return 0 # Mappings of C0 control chars from original, disabled #0x01 U+263A #0x02 U+263B @@ -75,4 +75,4 @@ U+2122:(TM) 0x27 U+2019-U+201b # various single quotation marks 0x22 U+201c-U+201f # various double quotation marks -U+2297:(×) \ No newline at end of file +U+2297 "(\327)" \ No newline at end of file diff --git a/src/chrtrans/iso01_uni.tbl.orig b/src/chrtrans/iso01_uni.tbl.orig new file mode 100644 index 00000000..14f71ff3 --- /dev/null +++ b/src/chrtrans/iso01_uni.tbl.orig @@ -0,0 +1,78 @@ +# +# Unicode mapping table for ISO 8859-1 fonts iso01.* +# [use: unicode_start iso01.f16 iso01] +# +#Shall this become the "default" translation? +#Meaning of that is currently not well defined. It is different +#from the default input or default output charset... +#but there has to be exactly one table marked as "default". +D0 +# +#The MIME name of this charset. +Miso-8859-1 + +#Name as a Display Charset (used on Options screen) +OISO Latin 1 + +0x20 U+0020 U+1360 +0x21-0x62 idem +# The following line is an example for mapping several accented versions +# of small letter 'c' to 'c': +0x63 U+0063 U+0107 U+0109 U+010B U+010D +0x64-0x7e idem +0xa0-0xff idem +#0x00 U+fffd # don't let failed char lookups return '\0' +# Mappings of C0 control chars from original, disabled +#0x01 U+263A +#0x02 U+263B +#0x03 U+2665 +#0x04 U+2666 +#0x05 U+2663 +#0x06 U+2660 +#0x07 U+2022 +#0x08 U+25D8 +#0x09 U+25CB +#0x0A U+25D9 +#0x0B U+2642 +#0x0C U+2640 +#0x0D U+266A +#0x0E U+266B +#0x0E U+266C +#0x0F U+263C +#0x10 U+25B6 +#0x10 U+25BA +#0x11 U+25C0 +#0x11 U+25C4 +#0x12 U+2195 +#0x13 U+203C +#0x14 U+00B6 +#0x15 U+00A7 +#0x16 U+25AC +#0x17 U+21A8 +#0x18 U+2191 +#0x19 U+2193 +#0x1A U+2192 +#0x1B U+2190 +#0x1C U+221F +#0x1C U+2319 +#0x1D U+2194 +#0x1E U+25B2 +#0x1F U+25BC +#0x7f U+2302 + +0xd0 U+0110 # Dstrok and ETH are nearly the same... + +# Dont wanna see these: +# POP DIRECTIONAL FORMATTING 202C +U+202c: +# LEFT-TO-RIGHT OVERRIDE 202D +U+202d: + +# TRADE MARK SIGN: +U+2122:(TM) + +0x60 U+2018 # left single quotation mark +0x27 U+2019-U+201b # various single quotation marks +0x22 U+201c-U+201f # various double quotation marks + +U+2297:(×) \ No newline at end of file diff --git a/src/chrtrans/iso08_uni.tbl b/src/chrtrans/iso08_uni.tbl index f11dff4a..d1c33b1d 100644 --- a/src/chrtrans/iso08_uni.tbl +++ b/src/chrtrans/iso08_uni.tbl @@ -89,12 +89,12 @@ OISO 8859-8 Hebrew #Hebrew points - map to empty string U+05B0-U+05C2: -#HEBREW LETTER DOUBLE VAV -U+05F0:åå -#HEBREW LETTER VAV YOD -U+05F1:éå -#HEBREW LETTER DOUBLE YOD -U+05F2:éé +#HEBREW LETTER DOUBLE VAV #U+05F0:åå +U+05F0 "\345\345" +#HEBREW LETTER VAV YOD #U+05F1:éå +U+05F1 "\351\345" +#HEBREW LETTER DOUBLE YOD #U+05F2:éé +U+05F2 "\351\351" # TRADE MARK SIGN: diff --git a/src/chrtrans/makeuctb.c b/src/chrtrans/makeuctb.c index e0630cc3..ad95c534 100644 --- a/src/chrtrans/makeuctb.c +++ b/src/chrtrans/makeuctb.c @@ -256,7 +256,8 @@ PUBLIC int main ARGS2( if ((p = strchr(buffer, '\n')) != NULL) { *p = '\0'; } else { - fprintf(stderr, "%s: Warning: line too long\n", tblname); + fprintf(stderr, "%s: Warning: line too long or incomplete\n", + tblname); } /* @@ -268,11 +269,14 @@ PUBLIC int main ARGS2( * <range> <unicode range> * <unicode> :<replace> * <unicode range> :<replace> + * <unicode> "<C replace>" + * <unicode range> "<C replace>" * * where <range> ::= <fontpos>-<fontpos> * and <unicode> ::= U+<h><h><h><h> * and <h> ::= <hexadecimal digit> * and <replace> any string not containing '\n' or '\0' + * and <C replace> any string with C backslash escapes */ p = buffer; while (*p == ' ' || *p == '\t') { @@ -405,24 +409,51 @@ PUBLIC int main ARGS2( p++; } } - if (*p != ':') { - fprintf(stderr, "No ':' where expected: %s\n", buffer); + + if (*p != ':' && *p != '"') { + fprintf(stderr, "No ':' or '\"' where expected: %s\n", + buffer); continue; } - tbuf = (char *) malloc (4*strlen(++p) + 1); + tbuf = (char *) malloc (4*strlen(p)); if (!(p1 = tbuf)) { fprintf(stderr, "%s: Out of memory\n", tblname); exit(EX_DATAERR); } - for (ch = *p; (ch = *p) != '\0'; p++, p1++) { - if ((unsigned char)ch < 32 || ch == '\\' || ch == '\"' || - (unsigned char)ch >= 127) { - sprintf(p1, "\\%.3o", (unsigned char)ch); + if (*p == '"') { + /* + * handle "<C replace>" + * Copy chars verbatim until first '"' not \-escaped or + * end of buffer + */ + int escaped = 0; + for (ch = *++p; (ch = *p) != '\0'; p++) { + if (escaped) { + escaped = 0; + } else if (ch == '"') { + break; + } else if (ch == '\\') { + escaped = 1; + } + *p1++ = ch; + } + if (escaped || ch != '"') { + fprintf(stderr, "Warning: String not terminated: %s\n", + buffer); + if (escaped) + *p1++ = '\n'; + } + } else { /* we had ':' */ + for (ch = *++p; (ch = *p) != '\0'; p++, p1++) { + if ((unsigned char)ch < 32 || ch == '\\' || ch == '\"' || + (unsigned char)ch >= 127) { + sprintf(p1, "\\%.3o", (unsigned char)ch); /* fprintf(stderr, "%s\n", tbuf); */ - p1 += 3; - } else { - *p1 = ch; + p1 += 3; + } else { + *p1 = ch; + } } } *p1 = '\0'; diff --git a/src/chrtrans/viscii_uni.tbl b/src/chrtrans/viscii_uni.tbl index 006fa0ea..33677163 100644 --- a/src/chrtrans/viscii_uni.tbl +++ b/src/chrtrans/viscii_uni.tbl @@ -210,7 +210,7 @@ U+001a:^Z 0x86 U+1ea8 0xa6 U+1ea9 0x06 U+1eaa -U+1eaa:Â~ +U+1eaa "\302~" # A with circumflex (same code as in iso-8859-1) and tilde 0xe7 U+1eab 0x87 U+1eac 0xa7 U+1ead |