diff options
author | Thomas E. Dickey <dickey@invisible-island.net> | 1999-06-29 13:01:29 -0400 |
---|---|---|
committer | Thomas E. Dickey <dickey@invisible-island.net> | 1999-06-29 13:01:29 -0400 |
commit | 83824f14360f92f8a3a47ac5f136bb077b141065 (patch) | |
tree | 9b21f7145d93e54ad67f57e8807f20493dfcbc3d /src | |
parent | 5be99e2ee1a17028574fcbd90b9ba2c09555585e (diff) | |
download | lynx-snapshots-83824f14360f92f8a3a47ac5f136bb077b141065.tar.gz |
snapshot of project "lynx", label v2-8-3_3
Diffstat (limited to 'src')
-rw-r--r-- | src/HTAlert.c | 39 | ||||
-rw-r--r-- | src/HTInit.c | 4 | ||||
-rw-r--r-- | src/HTML.c | 278 | ||||
-rw-r--r-- | src/LYCharSets.c | 2 | ||||
-rw-r--r-- | src/LYCharUtils.c | 24 | ||||
-rw-r--r-- | src/LYCharUtils.h | 3 | ||||
-rw-r--r-- | src/LYCookie.c | 301 | ||||
-rw-r--r-- | src/LYCookie.h | 15 | ||||
-rw-r--r-- | src/LYCurses.h | 4 | ||||
-rw-r--r-- | src/LYDownload.c | 18 | ||||
-rw-r--r-- | src/LYGetFile.c | 2 | ||||
-rw-r--r-- | src/LYGlobalDefs.h | 1 | ||||
-rw-r--r-- | src/LYHistory.c | 52 | ||||
-rw-r--r-- | src/LYKeymap.c | 2 | ||||
-rw-r--r-- | src/LYLeaks.c | 3 | ||||
-rw-r--r-- | src/LYLocal.c | 408 | ||||
-rw-r--r-- | src/LYLocal.h | 5 | ||||
-rw-r--r-- | src/LYMail.c | 2 | ||||
-rw-r--r-- | src/LYMain.c | 2 | ||||
-rw-r--r-- | src/LYMainLoop.c | 14 | ||||
-rw-r--r-- | src/LYOptions.c | 36 | ||||
-rw-r--r-- | src/LYPrint.c | 13 | ||||
-rw-r--r-- | src/LYReadCFG.c | 1 | ||||
-rw-r--r-- | src/LYShowInfo.c | 11 | ||||
-rw-r--r-- | src/LYStrings.c | 5 | ||||
-rw-r--r-- | src/LYUtils.c | 165 | ||||
-rw-r--r-- | src/LYUtils.h | 3 |
27 files changed, 999 insertions, 414 deletions
diff --git a/src/HTAlert.c b/src/HTAlert.c index 4889f719..29abf7c1 100644 --- a/src/HTAlert.c +++ b/src/HTAlert.c @@ -48,12 +48,14 @@ PUBLIC void HTAlwaysAlert ARGS2( "%s %s!\n", extra_prefix, Msg); fflush(stdout); + LYstore_message2(ALERT_FORMAT, Msg); sleep(AlertSecs); } else { fprintf(((TRACE) ? stdout : stderr), ALERT_FORMAT, (Msg == 0) ? "" : Msg); fflush(stdout); + LYstore_message2(ALERT_FORMAT, Msg); sleep(AlertSecs); fprintf(((TRACE) ? stdout : stderr), "\n"); } @@ -211,6 +213,12 @@ PUBLIC BOOL HTConfirmDefault ARGS2(CONST char *, Msg, int, Dft) conf_cancelled = NO; if (dump_output_immediately) { /* Non-interactive, can't respond */ + if (Dft == DFT_CONFIRM) { + CTRACE(tfp, "Confirm: %s (%c/%c) ", Msg, *msg_yes, *msg_no); + } else { + CTRACE(tfp, "Confirm: %s (%c) ", Msg, (Dft == YES) ? *msg_yes : *msg_no); + } + CTRACE(tfp, "- NO, not interactive.\n"); result = NO; } else { char *msg = NULL; @@ -219,6 +227,9 @@ PUBLIC BOOL HTConfirmDefault ARGS2(CONST char *, Msg, int, Dft) HTSprintf0(&msg, "%s (%c/%c) ", Msg, *msg_yes, *msg_no); else HTSprintf0(&msg, "%s (%c) ", Msg, (Dft == YES) ? *msg_yes : *msg_no); + if (LYTraceLogFP) { + CTRACE(tfp, "Confirm: %s", msg); + } _statusline(msg); FREE(msg); @@ -236,11 +247,15 @@ PUBLIC BOOL HTConfirmDefault ARGS2(CONST char *, Msg, int, Dft) } else if (TOUPPER(c) == TOUPPER(*msg_yes)) { result = YES; } else if (TOUPPER(c) == TOUPPER(*msg_no)) { - return(NO); + result = NO; } else if (Dft != DFT_CONFIRM) { - return(Dft); + result = Dft; + break; } } + CTRACE(tfp, "- %s%s.\n", + (result != NO) ? "YES" : "NO", + conf_cancelled ? ", cancelled" : ""); } return (result); } @@ -478,17 +493,16 @@ PUBLIC BOOL HTConfirmCookie ARGS4( if ((de = (domain_entry *)dp) == NULL) return FALSE; -#ifdef ENHANCED_COOKIES /* If the user has specified a list of domains to allow or deny ** from the config file, then they'll already have de->bv set to ** ACCEPT_ALWAYS or REJECT_ALWAYS so we can relax and let the - ** default cookie handling code cope with this fine. I hope. + ** default cookie handling code cope with this fine. */ -#endif + /* ** If the user has specified a constant action, don't prompt at all. */ - if (de->bv == ACCEPT_ALWAYS || de->bv == FROM_FILE) + if (de->bv == ACCEPT_ALWAYS) return TRUE; if (de->bv == REJECT_ALWAYS) return FALSE; @@ -505,19 +519,14 @@ PUBLIC BOOL HTConfirmCookie ARGS4( /* ** Estimate how much of the cookie we can show. */ - if (de != NULL) { - if (de->bv == ACCEPT_ALWAYS) - return TRUE; - if (de->bv == REJECT_ALWAYS) - return FALSE; - } if(!LYAcceptAllCookies) { int namelen, valuelen, space_free, percentage; char *message = 0; - space_free = (((LYcols - 1) - - strlen(ADVANCED_COOKIE_CONFIRMATION)) - - strlen(server)); + space_free = ((LYcols - 1) + - (strlen(ADVANCED_COOKIE_CONFIRMATION) + - 10) /* %s and %.*s and %.*s chars */ + - strlen(server)); if (space_free < 0) space_free = 0; namelen = strlen(name); diff --git a/src/HTInit.c b/src/HTInit.c index d65298d7..b5f39fb7 100644 --- a/src/HTInit.c +++ b/src/HTInit.c @@ -530,7 +530,9 @@ PRIVATE int PassesTest ARGS1( /* * Save overhead of system() calls by faking these. - FM */ - if (0 == strcasecomp(mc->testcommand, "test -n \"$DISPLAY\"")) { + if (0 == strcmp(mc->testcommand, "test \"$DISPLAY\"") || + 0 == strcmp(mc->testcommand, "test \"$DISPLAY\" != \"\"") || + 0 == strcasecomp(mc->testcommand, "test -n \"$DISPLAY\"")) { FREE(mc->testcommand); CTRACE(tfp, "PassesTest: Testing for XWINDOWS environment.\n"); if (LYgetXDisplay() != NULL) { diff --git a/src/HTML.c b/src/HTML.c index 36143414..4849b24b 100644 --- a/src/HTML.c +++ b/src/HTML.c @@ -1720,11 +1720,33 @@ PRIVATE void HTML_start_element ARGS6( "HTML: ****** Maximum nesting of %d divisions exceeded!\n", MAX_NESTING); } + if (me->inP) + LYEnsureSingleSpace(me); /* always at least break line - kw */ if (ElementNumber == HTML_CENTER) { me->DivisionAlignments[me->Division_Level] = HT_CENTER; change_paragraph_style(me, styles[HTML_DCENTER]); UPDATE_STYLE; me->current_default_alignment = styles[HTML_DCENTER]->alignment; + } else if (me->List_Nesting_Level >= 0 && + !(present && present[HTML_DIV_ALIGN] && + value[HTML_DIV_ALIGN] && + (!strcasecomp(value[HTML_DIV_ALIGN], "center") || + !strcasecomp(value[HTML_DIV_ALIGN], "right")))) { + if (present && present[HTML_DIV_ALIGN]) + me->current_default_alignment = HT_LEFT; + else if (me->Division_Level == 0) + me->current_default_alignment = HT_LEFT; + else if (me->sp[0].tag_number == HTML_UL || + me->sp[0].tag_number == HTML_OL || + me->sp[0].tag_number == HTML_MENU || + me->sp[0].tag_number == HTML_DIR || + me->sp[0].tag_number == HTML_LI || + me->sp[0].tag_number == HTML_LH || + me->sp[0].tag_number == HTML_DD) + me->current_default_alignment = HT_LEFT; + LYHandlePlike(me, present, value, include, HTML_DIV_ALIGN, TRUE); + me->DivisionAlignments[me->Division_Level] = + me->current_default_alignment; } else if (present && present[HTML_DIV_ALIGN] && value[HTML_DIV_ALIGN] && *value[HTML_DIV_ALIGN]) { if (!strcasecomp(value[HTML_DIV_ALIGN], "center")) { @@ -1779,7 +1801,8 @@ PRIVATE void HTML_start_element ARGS6( (me->sp[0].tag_number == HTML_UL || me->sp[0].tag_number == HTML_OL || me->sp[0].tag_number == HTML_MENU || - me->sp[0].tag_number == HTML_DIR)) { + me->sp[0].tag_number == HTML_DIR || + me->sp[0].tag_number == HTML_LI)) { if (HTML_dtd.tags[HTML_LH].contents == SGML_EMPTY) { ElementNumber = HTML_LH; } else { @@ -1844,7 +1867,8 @@ PRIVATE void HTML_start_element ARGS6( break; case HTML_P: - LYHandleP(me, present, value, include, TRUE); + LYHandlePlike(me, present, value, include, HTML_P_ALIGN, TRUE); + CHECK_ID(HTML_P_ID); break; case HTML_BR: @@ -2525,97 +2549,107 @@ PRIVATE void HTML_start_element ARGS6( HText_appendParagraph(me->text); me->sp->style->alignment = HT_LEFT; CHECK_ID(HTML_LI_ID); - if (me->sp[0].tag_number == HTML_OL) { - char number_string[20]; - int counter, seqnum; - char seqtype; - - counter = me->List_Nesting_Level < 11 ? - me->List_Nesting_Level : 11; - if (present && present[HTML_LI_TYPE] && value[HTML_LI_TYPE]) { - if (*value[HTML_LI_TYPE] == '1') { - me->OL_Type[counter] = '1'; - } else if (*value[HTML_LI_TYPE] == 'A') { - me->OL_Type[counter] = 'A'; - } else if (*value[HTML_LI_TYPE] == 'a') { - me->OL_Type[counter] = 'a'; - } else if (*value[HTML_LI_TYPE] == 'I') { - me->OL_Type[counter] = 'I'; - } else if (*value[HTML_LI_TYPE] == 'i') { - me->OL_Type[counter] = 'i'; + { + int surrounding_tag_number = me->sp[0].tag_number; + /* + * No, a LI should never occur directly within another LI, + * but this may result from incomplete error recovery. + * So check one more surrounding level in this case. - kw + */ + if (surrounding_tag_number == HTML_LI && + me->sp < (me->stack + MAX_NESTING - 1)) + surrounding_tag_number = me->sp[1].tag_number; + if (surrounding_tag_number == HTML_OL) { + char number_string[20]; + int counter, seqnum; + char seqtype; + + counter = me->List_Nesting_Level < 11 ? + me->List_Nesting_Level : 11; + if (present && present[HTML_LI_TYPE] && value[HTML_LI_TYPE]) { + if (*value[HTML_LI_TYPE] == '1') { + me->OL_Type[counter] = '1'; + } else if (*value[HTML_LI_TYPE] == 'A') { + me->OL_Type[counter] = 'A'; + } else if (*value[HTML_LI_TYPE] == 'a') { + me->OL_Type[counter] = 'a'; + } else if (*value[HTML_LI_TYPE] == 'I') { + me->OL_Type[counter] = 'I'; + } else if (*value[HTML_LI_TYPE] == 'i') { + me->OL_Type[counter] = 'i'; + } } - } - if (present && present[HTML_LI_VALUE] && - ((value[HTML_LI_VALUE] != NULL) && - (*value[HTML_LI_VALUE] != '\0')) && - ((isdigit(*value[HTML_LI_VALUE])) || - (*value[HTML_LI_VALUE] == '-' && - isdigit(*(value[HTML_LI_VALUE] + 1))))) { - seqnum = atoi(value[HTML_LI_VALUE]); - if (seqnum <= OL_VOID) - seqnum = OL_VOID + 1; - seqtype = me->OL_Type[counter]; - if (seqtype != '1' && seqnum < 1) - seqnum = 1; - 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; + if (present && present[HTML_LI_VALUE] && + ((value[HTML_LI_VALUE] != NULL) && + (*value[HTML_LI_VALUE] != '\0')) && + ((isdigit(*value[HTML_LI_VALUE])) || + (*value[HTML_LI_VALUE] == '-' && + isdigit(*(value[HTML_LI_VALUE] + 1))))) { + seqnum = atoi(value[HTML_LI_VALUE]); + if (seqnum <= OL_VOID) + seqnum = OL_VOID + 1; + seqtype = me->OL_Type[counter]; + if (seqtype != '1' && seqnum < 1) + seqnum = 1; me->OL_Counter[counter] = seqnum + 1; - } - } else { - seqnum = me->Last_OL_Count + 1; - seqtype = me->Last_OL_Type; - for (i = (counter - 1); i >= 0; i--) { - if (me->OL_Counter[i] > OL_VOID) { - seqnum = me->OL_Counter[i]++; - seqtype = me->OL_Type[i]; - i = 0; + } 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; + me->OL_Counter[counter] = seqnum + 1; + } + } else { + seqnum = me->Last_OL_Count + 1; + seqtype = me->Last_OL_Type; + for (i = (counter - 1); i >= 0; i--) { + if (me->OL_Counter[i] > OL_VOID) { + seqnum = me->OL_Counter[i]++; + seqtype = me->OL_Type[i]; + i = 0; + } } } - } - if (seqtype == 'A') { - sprintf(number_string, LYUppercaseA_OL_String(seqnum)); - } else if (seqtype == 'a') { - sprintf(number_string, LYLowercaseA_OL_String(seqnum)); - } else if (seqtype == 'I') { - sprintf(number_string, LYUppercaseI_OL_String(seqnum)); - } else if (seqtype == 'i') { - sprintf(number_string, LYLowercaseI_OL_String(seqnum)); - } else { - sprintf(number_string, "%2d.", seqnum); - } - 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] == ' ') - HTML_put_character(me, HT_NON_BREAK_SPACE); - else - HTML_put_character(me, number_string[i]); + if (seqtype == 'A') { + sprintf(number_string, LYUppercaseA_OL_String(seqnum)); + } else if (seqtype == 'a') { + sprintf(number_string, LYLowercaseA_OL_String(seqnum)); + } else if (seqtype == 'I') { + sprintf(number_string, LYUppercaseI_OL_String(seqnum)); + } else if (seqtype == 'i') { + sprintf(number_string, LYLowercaseI_OL_String(seqnum)); + } else { + sprintf(number_string, "%2d.", seqnum); + } + 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] == ' ') + HTML_put_character(me, HT_NON_BREAK_SPACE); + else + HTML_put_character(me, number_string[i]); - /* - * Use HTML_put_character so that any other spaces - * coming through will be collapsed. We'll use - * nbsp, so it won't break at the spacing character - * if there are no spaces in the subsequent text up - * to the right margin, but will declare it as a - * normal space to ensure collapsing if a normal - * space does immediately follow it. - FM - */ - HTML_put_character(me, HT_NON_BREAK_SPACE); - HText_setLastChar(me->text, ' '); - } else if (me->sp[0].tag_number == HTML_UL) { - /* - * Hack, because there is no append string! - */ - HTML_put_character(me, HT_NON_BREAK_SPACE); - HTML_put_character(me, HT_NON_BREAK_SPACE); - switch(me->List_Nesting_Level % 7) { + /* + * Use HTML_put_character so that any other spaces + * coming through will be collapsed. We'll use + * nbsp, so it won't break at the spacing character + * if there are no spaces in the subsequent text up + * to the right margin, but will declare it as a + * normal space to ensure collapsing if a normal + * space does immediately follow it. - FM + */ + HTML_put_character(me, HT_NON_BREAK_SPACE); + HText_setLastChar(me->text, ' '); + } else if (surrounding_tag_number == HTML_UL) { + /* + * Hack, because there is no append string! + */ + HTML_put_character(me, HT_NON_BREAK_SPACE); + HTML_put_character(me, HT_NON_BREAK_SPACE); + switch(me->List_Nesting_Level % 7) { case 0: HTML_put_character(me, '*'); break; @@ -2638,25 +2672,26 @@ PRIVATE void HTML_start_element ARGS6( HTML_put_character(me, '='); break; + } + /* + * Keep using HTML_put_character so that any other + * spaces coming through will be collapsed. We use + * nbsp, so we won't wrap at the spacing character + * if there are no spaces in the subsequent text up + * to the right margin, but will declare it as a + * normal space to ensure collapsing if a normal + * space does immediately follow it. - FM + */ + HTML_put_character(me, HT_NON_BREAK_SPACE); + HText_setLastChar(me->text, ' '); + } else { + /* + * Hack, because there is no append string! + */ + HTML_put_character(me, HT_NON_BREAK_SPACE); + HTML_put_character(me, HT_NON_BREAK_SPACE); + HText_setLastChar(me->text, ' '); } - /* - * Keep using HTML_put_character so that any other - * spaces coming through will be collapsed. We use - * nbsp, so we won't wrap at the spacing character - * if there are no spaces in the subsequent text up - * to the right margin, but will declare it as a - * normal space to ensure collapsing if a normal - * space does immediately follow it. - FM - */ - HTML_put_character(me, HT_NON_BREAK_SPACE); - HText_setLastChar(me->text, ' '); - } else { - /* - * Hack, because there is no append string! - */ - HTML_put_character(me, HT_NON_BREAK_SPACE); - HTML_put_character(me, HT_NON_BREAK_SPACE); - HText_setLastChar(me->text, ' '); } me->in_word = NO; me->inP = FALSE; @@ -4628,7 +4663,7 @@ PRIVATE void HTML_start_element ARGS6( HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR); } -#else +#else CTRACE(tfp, "Attempting to fake as: %s\n", I.type); #endif /* EXP_FILE_UPLOAD */ #ifdef NOTDEFINED @@ -5696,7 +5731,8 @@ PRIVATE void HTML_end_element ARGS3( (me->sp[0].tag_number == HTML_UL || me->sp[0].tag_number == HTML_OL || me->sp[0].tag_number == HTML_MENU || - me->sp[0].tag_number == HTML_DIR) && + me->sp[0].tag_number == HTML_DIR || + me->sp[0].tag_number == HTML_LI) && (element_number == HTML_H1 || element_number == HTML_H2 || element_number == HTML_H3 || @@ -5742,7 +5778,8 @@ PRIVATE void HTML_end_element ARGS3( (me->sp[0].tag_number == HTML_UL || me->sp[0].tag_number == HTML_OL || me->sp[0].tag_number == HTML_MENU || - me->sp[0].tag_number == HTML_DIR) && + me->sp[0].tag_number == HTML_DIR || + me->sp[0].tag_number == HTML_LI) && (element_number == HTML_H1 || element_number == HTML_H2 || element_number == HTML_H3 || @@ -5944,14 +5981,23 @@ PRIVATE void HTML_end_element ARGS3( case HTML_DIV: if (me->Division_Level >= 0) me->Division_Level--; - if (me->Division_Level >= 0) - me->sp->style->alignment = + if (me->Division_Level >= 0) { + if (me->sp->style->alignment != + me->DivisionAlignments[me->Division_Level]) { + if (me->inP) + LYEnsureSingleSpace(me); + me->sp->style->alignment = me->DivisionAlignments[me->Division_Level]; + } + } change_paragraph_style(me, me->sp->style); - UPDATE_STYLE; + if (me->style_change) { + actually_set_style(me); + if (me->List_Nesting_Level >= 0) + HText_NegateLineOne(me->text); + } else if (me->inP) + LYEnsureSingleSpace(me); me->current_default_alignment = me->sp->style->alignment; - if (me->List_Nesting_Level >= 0) - HText_NegateLineOne(me->text); break; case HTML_H1: /* header styles */ @@ -5988,9 +6034,9 @@ PRIVATE void HTML_end_element ARGS3( break; case HTML_P: - LYHandleP(me, + LYHandlePlike(me, (CONST BOOL*)0, (CONST char **)0, - include, + include, 0, FALSE); break; diff --git a/src/LYCharSets.c b/src/LYCharSets.c index e58cc37e..8890f9df 100644 --- a/src/LYCharSets.c +++ b/src/LYCharSets.c @@ -21,7 +21,7 @@ extern HTCJKlang HTCJK; PUBLIC HTkcode kanji_code = NOKANJI; PUBLIC BOOLEAN LYHaveCJKCharacterSet = FALSE; PUBLIC BOOLEAN DisplayCharsetMatchLocale = TRUE; -PUBLIC BOOL force_old_UCLYhndl_on_reload; +PUBLIC BOOL force_old_UCLYhndl_on_reload = FALSE; PUBLIC int forced_UCLYhdnl; extern void UCInit NOARGS; extern int UCInitialized; diff --git a/src/LYCharUtils.c b/src/LYCharUtils.c index 717409ce..5e15c2a2 100644 --- a/src/LYCharUtils.c +++ b/src/LYCharUtils.c @@ -133,8 +133,8 @@ PUBLIC void LYEntify ARGS2( *q++ = *p; } } - StrAllocCopy(*str, cp); - FREE(cp); + FREE(*str); + *str = cp; } /* @@ -367,7 +367,8 @@ PUBLIC void LYFillLocalFileURL ARGS2( char curdir[LY_MAXPATH]; temp2 = wwwName(Current_Dir(curdir)); #endif /* VMS */ - LYAddHtmlSep(href); + if (!LYIsHtmlSep(*temp2)) + LYAddHtmlSep(href); /* * Check for pathological cases - current dir has chars which * MUST BE URL-escaped - kw @@ -3084,11 +3085,12 @@ free_META_copies: ** current paragraph and subsequent text when a P ** end tag is present or not in the markup. - FM */ -PUBLIC void LYHandleP ARGS5( +PUBLIC void LYHandlePlike ARGS6( HTStructured *, me, CONST BOOL*, present, CONST char **, value, char **, include GCC_UNUSED, + int, align_idx, BOOL, start) { if (TRUE) { @@ -3151,7 +3153,8 @@ PUBLIC void LYHandleP ARGS5( if (LYoverride_default_alignment(me)) { me->sp->style->alignment = LYstyles(me->sp[0].tag_number)->alignment; - } else if (me->List_Nesting_Level >= 0 || + } else if ((me->List_Nesting_Level >= 0 && + strncmp(me->sp->style->name, "Div", 3)) || ((me->Division_Level < 0) && (!strcmp(me->sp->style->name, "Normal") || !strcmp(me->sp->style->name, "Preformatted")))) { @@ -3161,19 +3164,18 @@ PUBLIC void LYHandleP ARGS5( } if (start) { - if (present && present[HTML_P_ALIGN] && value[HTML_P_ALIGN]) { - if (!strcasecomp(value[HTML_P_ALIGN], "center") && + if (present && present[align_idx] && value[align_idx]) { + if (!strcasecomp(value[align_idx], "center") && !(me->List_Nesting_Level >= 0 && !me->inP)) me->sp->style->alignment = HT_CENTER; - else if (!strcasecomp(value[HTML_P_ALIGN], "right") && + else if (!strcasecomp(value[align_idx], "right") && !(me->List_Nesting_Level >= 0 && !me->inP)) me->sp->style->alignment = HT_RIGHT; - else if (!strcasecomp(value[HTML_P_ALIGN], "left") || - !strcasecomp(value[HTML_P_ALIGN], "justify")) + else if (!strcasecomp(value[align_idx], "left") || + !strcasecomp(value[align_idx], "justify")) me->sp->style->alignment = HT_LEFT; } - CHECK_ID(HTML_P_ID); } /* diff --git a/src/LYCharUtils.h b/src/LYCharUtils.h index dc5a6c7f..d518d3ae 100644 --- a/src/LYCharUtils.h +++ b/src/LYCharUtils.h @@ -63,11 +63,12 @@ extern void LYHandleMETA PARAMS(( CONST BOOL* present, CONST char ** value, char ** include)); -extern void LYHandleP PARAMS(( +extern void LYHandlePlike PARAMS(( HTStructured * me, CONST BOOL* present, CONST char ** value, char ** include, + int align_idx, BOOL start)); extern void LYHandleSELECT PARAMS(( HTStructured * me, diff --git a/src/LYCookie.c b/src/LYCookie.c index bd0bab72..e93b27f2 100644 --- a/src/LYCookie.c +++ b/src/LYCookie.c @@ -74,6 +74,9 @@ #define max_cookies_global 500 #define max_cookies_buffer 4096 +/* default for new domains, one of the invcheck_behaviour_t values: */ +#define DEFAULT_INVCHECK_BV INVCHECK_QUERY + /* ** 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 @@ -271,6 +274,9 @@ PRIVATE void store_cookie ARGS3( CONST char *ptr; domain_entry *de = NULL; BOOL Replacement = FALSE; + int invprompt_reasons = 0; /* what is wrong with this cookie - kw */ +#define FAILS_COND1 0x01 +#define FAILS_COND4 0x02 if (co == NULL) return; @@ -294,7 +300,7 @@ PRIVATE void store_cookie ARGS3( 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)) { + !strcasecomp(co->domain, de->domain)) { cookie_list = de->cookie_list; break; } @@ -316,32 +322,21 @@ PRIVATE void store_cookie ARGS3( * if set to INVCHECK_QUERY. */ if (strncmp(co->path, path, co->pathlen) != 0) { - if((de != NULL && de->invcheck_bv != INVCHECK_LOOSE) - || de == NULL) { - if(de != NULL && de->invcheck_bv == INVCHECK_STRICT) { - CTRACE(tfp, "store_cookie: Rejecting because '%s' is not a prefix of '%s'.\n", - co->path, path); - freeCookie(co); - co = NULL; - return; - } else if ((de != NULL - && de->invcheck_bv == INVCHECK_QUERY) - || de == NULL) { - char *msg = 0; - HTSprintf0(&msg, - INVALID_COOKIE_PATH_CONFIRMATION, - co->path, path); - if (!HTConfirm(msg)) { - CTRACE(tfp, "store_cookie: Rejecting because '%s' is not a prefix of '%s'.\n", - co->path, path); - freeCookie(co); - co = NULL; - FREE(msg); - return; - } else { - FREE(msg); - } - } + invcheck_behaviour_t invcheck_bv = (de ? de->invcheck_bv + : DEFAULT_INVCHECK_BV); + switch (invcheck_bv) { + case INVCHECK_LOOSE: + break; /* continue as if nothing were wrong */ + + case INVCHECK_QUERY: + invprompt_reasons |= FAILS_COND1; + break; /* will prompt later if we get that far */ + + case INVCHECK_STRICT: + CTRACE(tfp, "store_cookie: Rejecting because '%s' is not a prefix of '%s'.\n", + co->path, path); + freeCookie(co); + return; } } /* @@ -356,7 +351,6 @@ PRIVATE void store_cookie ARGS3( CTRACE(tfp, "store_cookie: Rejecting because '%s' has no dot.\n", hostname); freeCookie(co); - co = NULL; return; } @@ -371,7 +365,6 @@ PRIVATE void store_cookie ARGS3( CTRACE(tfp, "store_cookie: Rejecting domain '%s'.\n", co->domain); freeCookie(co); - co = NULL; return; } ptr = strchr((co->domain + 1), '.'); @@ -379,7 +372,6 @@ PRIVATE void store_cookie ARGS3( CTRACE(tfp, "store_cookie: Rejecting domain '%s'.\n", co->domain); freeCookie(co); - co = NULL; return; } @@ -391,7 +383,6 @@ PRIVATE void store_cookie ARGS3( CTRACE(tfp, "store_cookie: Rejecting domain '%s' for host '%s'.\n", co->domain, hostname); freeCookie(co); - co = NULL; return; } @@ -406,36 +397,61 @@ PRIVATE void store_cookie ARGS3( */ ptr = ((hostname + strlen(hostname)) - strlen(co->domain)); if (strchr(hostname, '.') < ptr) { - if((de != NULL && de->invcheck_bv != INVCHECK_LOOSE) - || de == NULL) { - if(de != NULL && de->invcheck_bv == INVCHECK_STRICT) { - CTRACE(tfp, "store_cookie: Rejecting domain '%s' for host '%s'.\n", - co->domain, - hostname); - freeCookie(co); - co = NULL; - return; - } else if ((de != NULL - && de->invcheck_bv == INVCHECK_QUERY) - || de == NULL) { - char *msg = 0; - HTSprintf0(&msg, - INVALID_COOKIE_DOMAIN_CONFIRMATION, - co->domain, - hostname); - if (!HTConfirm(msg)) { - CTRACE(tfp, "store_cookie: Rejecting domain '%s' for host '%s'.\n", + invcheck_behaviour_t invcheck_bv = (de ? de->invcheck_bv + : DEFAULT_INVCHECK_BV); + switch (invcheck_bv) { + case INVCHECK_LOOSE: + break; /* continue as if nothing were wrong */ + + case INVCHECK_QUERY: + invprompt_reasons |= FAILS_COND4; + break; /* will prompt later if we get that far */ + + case INVCHECK_STRICT: + CTRACE(tfp, "store_cookie: Rejecting because '%s' is not a prefix of '%s'.\n", + co->path, path); + freeCookie(co); + return; + } + } + } + + /* + * If we found reasons for issuing an invalid cookie confirmation + * prompt, do that now. Rejection by the user here is the last + * chance to completely ignore this cookie; after it passes this + * hurdle, it may at least supersede a previous cookie (even if + * it finally gets rejected). - kw + */ + if (invprompt_reasons) { + char *msg = 0; + if (invprompt_reasons & FAILS_COND4) { + HTSprintf0(&msg, + INVALID_COOKIE_DOMAIN_CONFIRMATION, + co->domain, + hostname); + if (!HTConfirmDefault(msg, NO)) { + CTRACE(tfp, "store_cookie: Rejecting domain '%s' for host '%s'.\n", co->domain, hostname); - freeCookie(co); - co = NULL; - FREE(msg); - return; - } - FREE(msg); - } - } + freeCookie(co); + FREE(msg); + return; + } + } + if (invprompt_reasons & FAILS_COND1) { + HTSprintf0(&msg, + INVALID_COOKIE_PATH_CONFIRMATION, + co->path, path); + if (!HTConfirmDefault(msg, NO)) { + CTRACE(tfp, "store_cookie: Rejecting because '%s' is not a prefix of '%s'.\n", + co->path, path); + freeCookie(co); + FREE(msg); + return; + } } + FREE(msg); } if (hl == NULL) { @@ -447,21 +463,20 @@ PRIVATE void store_cookie ARGS3( outofmem(__FILE__, "store_cookie"); #if 0 /* was: ifdef EXP_PERSISTENT_COOKIES */ /* - * Ok, this is a problem. The first cookie for a domain - * effectively sets the policy for that whole domain - for - * something like Netlink, where there are lots of websites - * under www.netlink.co.uk, this isn't sensible. However, - * taking this sort of decision down to cookie level also - * isn't sensible. Perhaps something based on the domain - * and the path in conjunction makes more sense? - RP + * The default behavior for this new domain could be set + * differently if the cookie comes from a file, as the + * code had it originally, but there doesn't seem to be + * a good reason for it any more; setting more permissive + * behavior for individual domains is now possible via + * configuration options. - kw */ if (persistent_cookies && (co->flags & COOKIE_FLAG_FROM_FILE)) - de->bv = FROM_FILE; + de->bv = ACCEPT_ALWAYS; /* ?? */ else #endif de->bv = QUERY_USER; - de->invcheck_bv = INVCHECK_QUERY; /* should this go here? */ + de->invcheck_bv = DEFAULT_INVCHECK_BV; /* should this go here? */ cookie_list = de->cookie_list = HTList_new(); StrAllocCopy(de->domain, co->domain); HTList_appendObject(domain_list, de); @@ -490,7 +505,7 @@ PRIVATE void store_cookie ARGS3( * Check if this cookie matches the one we're inserting. */ } else if ((c2) && - !strcmp(co->domain, c2->domain) && + !strcasecomp(co->domain, c2->domain) && !strcmp(co->path, c2->path) && !strcmp(co->name, c2->name)) { HTList_removeObject(cookie_list, c2); @@ -547,7 +562,12 @@ PRIVATE void store_cookie ARGS3( /* * Don't add the cookie if the value is NULL. - BJP */ - } else if (co->value[0] == '\0') { + /* + * Presence of value is now needed (indicated normally by '='), + * but it can now be an empty string. + * - kw 1999-06-24 + */ + } else if (co->value == NULL) { /* should not happen - kw */ CTRACE(tfp, "store_cookie: Value is NULL! Not storing cookie.\n"); freeCookie(co); co = NULL; @@ -940,16 +960,27 @@ PRIVATE void LYProcessSetCookies ARGS6( break; } } else if (*p == '"') { + BOOLEAN escaped = FALSE; /* - * It's a quoted string. + * It looks like quoted string. */ p++; value_start = p; - while (*p != '\0' && *p != '"') + while (*p != '\0' && (*p != '"' || escaped)) { + escaped = (!escaped && *p == '\\'); p++; - value_end = p; - if (*p == '"') + } + if (p != value_start && *p == '"' && !escaped) { + value_end = p; p++; + Quoted = TRUE; + } else { + value_start--; + value_end = p; + if (*p) + p++; + Quoted = FALSE; + } } else { /* * Otherwise, it's an unquoted string. @@ -987,7 +1018,12 @@ PRIVATE void LYProcessSetCookies ARGS6( BOOLEAN known_attr = NO; char *value = NULL; - if (value_end > value_start) { + if (value_start && value_end >= value_start) { + /* + * Presence of value is now needed (indicated normally by '=') + * to start a cookie, but it can now be an empty string. + * - kw 1999-06-24 + */ int value_len = (value_end - value_start); if (value_len > max_cookies_buffer) { @@ -1218,8 +1254,11 @@ PRIVATE void LYProcessSetCookies ARGS6( * no value? This seems to be needed for sites that reset a * cookie by nulling out the value. If this causes problems, * we can go back to the original behavior above. - BJP + * + * Presence of value is now needed (indicated normally by '='), + * but it can now be an empty string. - kw 1999-06-24 */ - if (!known_attr) { + if (!known_attr && value && value_end >= value_start) { /* * If we've started a cookie, and it's not too big, * save it in the CombinedCookies list. - FM @@ -1441,17 +1480,27 @@ PRIVATE void LYProcessSetCookies ARGS6( break; } } else if (*p == '"') { + BOOLEAN escaped = FALSE; /* - * It's a quoted string. + * It looks like quoted string. */ p++; value_start = p; - while (*p != '\0' && *p != '"') + while (*p != '\0' && (*p != '"' || escaped)) { + escaped = (!escaped && *p == '\\'); p++; - value_end = p; - if (*p == '"') + } + if (p != value_start && *p == '"' && !escaped) { + value_end = p; p++; - Quoted = TRUE; + Quoted = TRUE; + } else { + value_start--; + value_end = p; + if (*p) + p++; + Quoted = FALSE; + } } else { /* * Otherwise, it's an unquoted string. @@ -1489,7 +1538,12 @@ PRIVATE void LYProcessSetCookies ARGS6( BOOLEAN known_attr = NO; char *value = NULL; - if (value_end > value_start) { + if (value_start && value_end >= value_start) { + /* + * Presence of value is now needed (indicated normally by '=') + * to start a cookie, but it can now be an empty string. + * - kw 1999-06-24 + */ int value_len = (value_end - value_start); if (value_len > max_cookies_buffer) { @@ -1497,7 +1551,7 @@ PRIVATE void LYProcessSetCookies ARGS6( } value = (char *)calloc(1, value_len + 1); if (value == NULL) - outofmem(__FILE__, "LYProcessSetCookie"); + outofmem(__FILE__, "LYProcessSetCookies"); LYstrncpy(value, value_start, value_len); } if (len == 6 && !strncasecomp(attr_start, "secure", 6)) { @@ -1705,8 +1759,11 @@ PRIVATE void LYProcessSetCookies ARGS6( * no value? This seems to be needed for sites that reset a * cookie by nulling out the value. If this causes problems, * we can go back to the original behavior above. - BJP + * + * Presence of value is now needed (indicated normally by '='), + * but it can now be an empty string. - kw 1999-06-24 */ - if (!known_attr) { + if (!known_attr && value && value_end >= value_start) { /* * If we've started a cookie, and it's not too big, * save it in the CombinedCookies list. - FM @@ -1924,7 +1981,7 @@ PUBLIC char * LYCookie ARGS4( */ header = scan_cookie_sublist(hostname, path, port, de->cookie_list, header, secure); - } else if (de->bv == QUERY_USER && de->invcheck_bv == INVCHECK_QUERY) { + } else if (de->bv == QUERY_USER && de->invcheck_bv == DEFAULT_INVCHECK_BV) { /* * No cookies in this domain, and no default * accept/reject choice was set by the user, @@ -1998,7 +2055,10 @@ PUBLIC void LYLoadCookies ARGS1 ( while(buf[i] != '\n' && buf[i] != 0) { i++; } - buf[i] = '\0'; + if (buf[i] == '\n') { + buf[i++] = '\t'; /* add sep after line if enough space - kw */ + buf[i] = '\0'; + } /* * Tokenise the cookie line into its component parts - @@ -2010,6 +2070,12 @@ PUBLIC void LYLoadCookies ARGS1 ( * 'fixed' by using strsep instead of strtok. No idea * what kind of platform problems this might introduce. - RP */ + /* + * This fails when the path is blank + * + * sscanf(buf, "%s\t%s\t%s\t%s\t%d\t%s\t%[ -~]", + * domain, what, path, secure, &expires, name, value); + */ CTRACE(tfp, "LYLoadCookies: tokenising %s\n", buf); tok_ptr = buf; tok_out = LYstrsep(&tok_ptr, "\t"); @@ -2025,15 +2091,14 @@ PUBLIC void LYLoadCookies ARGS1 ( */ tok_out = LYstrsep(&tok_ptr, "\t"); } - expires = atol(expires_a); - /* - * This fails when the path is blank - * - * sscanf(buf, "%s\t%s\t%s\t%s\t%d\t%s\t%[ -~]", - * domain, what, path, secure, &expires, name, value); - */ + if (tok_values[tok_loop].s) { + /* tok_out in above loop must have been NULL prematurely - kw */ + CTRACE(tfp, "*** wrong format: not enough tokens, ignoring line!\n"); + continue; + } + expires = atol(expires_a); CTRACE(tfp, "expires:\t%s\n", ctime(&expires)); /* CTRACE(tfp, "%s\t%s\t%s\t%s\t%ld\t%s\t%s\tREADCOOKIE\n", */ /* domain, what, path, secure, (long) expires, name, value); */ @@ -2041,7 +2106,15 @@ PUBLIC void LYLoadCookies ARGS1 ( StrAllocCopy(moo->domain, domain); StrAllocCopy(moo->path, path); StrAllocCopy(moo->name, name); - StrAllocCopy(moo->value, value); + if (value && value[0] == '"' && + value[1] && value[strlen(value)-1] == '"' && + value[strlen(value)-2] != '\\') { + value[strlen(value)-1] = '\0'; + StrAllocCopy(moo->value, value+1); + moo->quoted = TRUE; + } else { + StrAllocCopy(moo->value, value); + } moo->pathlen = strlen(moo->path); /* * Justification for following flags: @@ -2171,11 +2244,15 @@ PUBLIC void LYStoreCookies ARGS1 ( continue; } - fprintf(cookie_handle, "%s\t%s\t%s\t%s\t%ld\t%s\t%s\n", + fprintf(cookie_handle, "%s\t%s\t%s\t%s\t%ld\t%s\t%s%s%s\n", de->domain, - "FALSE", co->path, + (de->domain[0] == '.') ? "TRUE" : "FALSE", + co->path, co->flags & COOKIE_FLAG_SECURE ? "TRUE" : "FALSE", - (long) co->expires, co->name, co->value); + (long) co->expires, co->name, + (co->quoted ? "\"" : ""), + co->value, + (co->quoted ? "\"" : "")); CTRACE(tfp, "STORED\n"); } @@ -2264,7 +2341,7 @@ PRIVATE int LYHandleCookies ARGS4 ( * First object in the list always is empty. - FM */ continue; - if (!strcmp(domain, de->domain)) { + if (!strcasecomp(domain, de->domain)) { FREE(domain); /* * We found the domain. Check @@ -2527,11 +2604,6 @@ Delete_all_cookies_in_domain: case (QUERY_USER): HTSprintf0(&buf, COOKIES_ALLOWED_VIA_PROMPT); break; - case (FROM_FILE): -#if 0 /* not used any more - kw */ - HTSprintf0(&buf, COOKIES_READ_FROM_FILE); -#endif - break; } PUTS(buf); HTSprintf0(&buf, "\n"); @@ -2673,8 +2745,11 @@ PUBLIC void cookie_domain_flag_set ARGS2( char *strsmall = NULL; int isexisting = FALSE; - if (str == NULL) - outofmem(__FILE__, "cookie_set_invcheck"); + if (str == NULL) { + HTAlwaysAlert(gettext("Internal"), + gettext("cookie_domain_flag_set error, aborting program")); + exit_immediately(-1); + } /* * Is this the first domain we're handling? If so, initialize @@ -2695,6 +2770,11 @@ PUBLIC void cookie_domain_flag_set ARGS2( while ((strsmall = LYstrsep(str, ",")) != 0) { + if (*strsmall == '\0') + /* Never add a domain for empty string. It would actually + * make more sense to use strtok here. - kw */ + continue; + /* * Check the list of existing domains to see if this is a * re-setting of an already existing domains -- if so, just @@ -2704,7 +2784,7 @@ PUBLIC void cookie_domain_flag_set ARGS2( for (hl = domain_list; hl != NULL; hl = hl->next) { de2 = (domain_entry *)hl->object; if ((de2 != NULL && de2->domain != NULL) && - !strcmp(strsmall, de2->domain)) { + !strcasecomp(strsmall, de2->domain)) { isexisting = TRUE; break; } else { @@ -2720,16 +2800,13 @@ PUBLIC void cookie_domain_flag_set ARGS2( switch(flag) { case (FLAG_ACCEPT_ALWAYS): de->bv = ACCEPT_ALWAYS; - de->invcheck_bv = INVCHECK_QUERY; + de->invcheck_bv = DEFAULT_INVCHECK_BV; break; case (FLAG_REJECT_ALWAYS): de->bv = REJECT_ALWAYS; - de->invcheck_bv = INVCHECK_QUERY; + de->invcheck_bv = DEFAULT_INVCHECK_BV; break; case (FLAG_QUERY_USER): de->bv = QUERY_USER; - de->invcheck_bv = INVCHECK_QUERY; - break; - case (FLAG_FROM_FILE): de->bv = FROM_FILE; - de->invcheck_bv = INVCHECK_QUERY; + de->invcheck_bv = DEFAULT_INVCHECK_BV; break; case (FLAG_INVCHECK_QUERY): de->invcheck_bv = INVCHECK_QUERY; de->bv = QUERY_USER; @@ -2753,8 +2830,6 @@ PUBLIC void cookie_domain_flag_set ARGS2( break; case (FLAG_QUERY_USER): de2->bv = QUERY_USER; break; - case (FLAG_FROM_FILE): de2->bv = FROM_FILE; - break; case (FLAG_INVCHECK_QUERY): de2->invcheck_bv = INVCHECK_QUERY; break; case (FLAG_INVCHECK_STRICT): de2->invcheck_bv = INVCHECK_STRICT; diff --git a/src/LYCookie.h b/src/LYCookie.h index b811e371..5e599191 100644 --- a/src/LYCookie.h +++ b/src/LYCookie.h @@ -7,10 +7,10 @@ #include <HTList.h> -typedef enum {ACCEPT_ALWAYS, REJECT_ALWAYS, QUERY_USER, FROM_FILE} behaviour; +typedef enum {ACCEPT_ALWAYS, REJECT_ALWAYS, QUERY_USER} behaviour_t; typedef enum {INVCHECK_QUERY, INVCHECK_STRICT, - INVCHECK_LOOSE} invcheck_behaviour; + INVCHECK_LOOSE} invcheck_behaviour_t; typedef enum {FLAG_ACCEPT_ALWAYS, FLAG_REJECT_ALWAYS, FLAG_QUERY_USER, @@ -21,8 +21,8 @@ typedef enum {FLAG_ACCEPT_ALWAYS, struct _domain_entry { char * domain; /* Domain for which these cookies are valid */ - behaviour bv; - invcheck_behaviour invcheck_bv; + behaviour_t bv; + invcheck_behaviour_t invcheck_bv; HTList * cookie_list; }; typedef struct _domain_entry domain_entry; @@ -40,13 +40,6 @@ extern void LYStoreCookies PARAMS(( char * cookie_file)); extern void LYLoadCookies PARAMS(( char * cookie_file)); -extern void cookie_add_acceptlist PARAMS(( - char * acceptdomains)); -extern void cookie_add_rejectlist PARAMS(( - char * rejectdomains)); -extern void cookie_set_invcheck PARAMS(( - char * domains, - invcheck_behaviour setting)); extern void cookie_domain_flag_set PARAMS(( char * domainstr, int flag)); diff --git a/src/LYCurses.h b/src/LYCurses.h index 5505e9ca..51c116e1 100644 --- a/src/LYCurses.h +++ b/src/LYCurses.h @@ -306,8 +306,8 @@ extern int lynx_chg_color PARAMS((int, int, int)); #undef standend #define standend() lynx_standout(FALSE) #else -#define LYaddAttr attrset -#define LYaddWAttr wattrset +#define LYaddAttr attron +#define LYaddWAttr wattron #define LYsubAttr attroff #define LYsubWAttr wattroff #endif diff --git a/src/LYDownload.c b/src/LYDownload.c index eaf1690b..5b079b32 100644 --- a/src/LYDownload.c +++ b/src/LYDownload.c @@ -91,7 +91,14 @@ PUBLIC void LYDownload ARGS1( #ifdef DIRED_SUPPORT /* FIXME: use HTLocalName */ if (!strncmp(file, "file://localhost", 16)) +#ifdef __DJGPP__ + { + file += 17; + file = HTDOS_name(file); + } +#else file += 16; +#endif /* __DJGPP__ */ else if (!strncmp(file, "file:", 5)) file += 5; HTUnEscape(file); @@ -469,7 +476,7 @@ PUBLIC int LYdownload_options ARGS2( char **, newfile, char *, data_file) { - static char tempfile[LY_MAXPATH]; + static char tempfile[LY_MAXPATH] = "\0"; char *downloaded_url = NULL; char *sug_filename = NULL; FILE *fp0; @@ -482,8 +489,13 @@ PUBLIC int LYdownload_options ARGS2( StrAllocCopy(sug_filename, *newfile); change_sug_filename(sug_filename); - LYRemoveTemp(tempfile); - if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) { + if (LYReuseTempfiles) { + fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w"); + } else { + LYRemoveTemp(tempfile); + fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w"); + } + if (fp0 == NULL) { HTAlert(CANNOT_OPEN_TEMP); return(-1); } diff --git a/src/LYGetFile.c b/src/LYGetFile.c index 2bb09ea3..aa95cd9e 100644 --- a/src/LYGetFile.c +++ b/src/LYGetFile.c @@ -54,7 +54,7 @@ PUBLIC int HTNoDataOK = 0; /* * getfile is the main mechanism to load a new document (or a previously - * laoded one whose rendering is cached in a HText structure) from + * loaded one whose rendering is cached in a HText structure) from * mainloop, nearly everything goes through it. * It should return one of the values * NORMAL - requested document loaded successfully, usually [always?] diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h index 91923705..9148285e 100644 --- a/src/LYGlobalDefs.h +++ b/src/LYGlobalDefs.h @@ -383,6 +383,7 @@ extern BOOLEAN LYPrependBaseToSource; extern BOOLEAN LYPrependCharsetToSource; extern BOOLEAN LYQuitDefaultYes; extern BOOLEAN LYNonRestartingSIGWINCH; +extern BOOLEAN LYReuseTempfiles; #ifndef VMS extern BOOLEAN LYNoCore; diff --git a/src/LYHistory.c b/src/LYHistory.c index eef57082..6edc58c0 100644 --- a/src/LYHistory.c +++ b/src/LYHistory.c @@ -395,13 +395,18 @@ PUBLIC void LYpop_num ARGS2( PUBLIC int showhistory ARGS1( char **, newfile) { - static char tempfile[LY_MAXPATH]; + static char tempfile[LY_MAXPATH] = "\0"; char *Title = NULL; int x = 0; FILE *fp0; - LYRemoveTemp(tempfile); - if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) { + if (LYReuseTempfiles) { + fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w"); + } else { + LYRemoveTemp(tempfile); + fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w"); + } + if (fp0 == NULL) { HTAlert(CANNOT_OPEN_TEMP); return(-1); } @@ -413,7 +418,7 @@ PUBLIC int showhistory ARGS1( BeginInternalPage(fp0, HISTORY_PAGE_TITLE, HISTORY_PAGE_HELP); - fprintf(fp0, "<tr align=right> <a href=\"LYNXMESSAGES:\">[%s]</a> </tr>\n", + fprintf(fp0, "<p align=right> <a href=\"LYNXMESSAGES:\">[%s]</a>\n", STATUSLINES_TITLE); fprintf(fp0, "<pre>\n"); @@ -557,7 +562,7 @@ PUBLIC BOOLEAN historytarget ARGS1( PUBLIC int LYShowVisitedLinks ARGS1( char **, newfile) { - static char tempfile[LY_MAXPATH]; + static char tempfile[LY_MAXPATH] = "\0"; char *Title = NULL; char *Address = NULL; int x; @@ -568,8 +573,13 @@ PUBLIC int LYShowVisitedLinks ARGS1( if (!cur) return(-1); - LYRemoveTemp(tempfile); - if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) { + if (LYReuseTempfiles) { + fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w"); + } else { + LYRemoveTemp(tempfile); + fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w"); + } + if (fp0 == NULL) { HTAlert(CANNOT_OPEN_TEMP); return(-1); } @@ -683,13 +693,19 @@ PRIVATE void to_stack ARGS1(char *, str) PUBLIC int LYshow_statusline_messages ARGS1( document *, newdoc) { - static char tempfile[LY_MAXPATH]; + static char tempfile[LY_MAXPATH] = "\0"; static char *info_url; FILE *fp0; int i; + char *temp = NULL; - LYRemoveTemp(tempfile); - if ((fp0 = LYOpenTemp (tempfile, HTML_SUFFIX, "w")) == 0) { + if (LYReuseTempfiles) { + fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w"); + } else { + LYRemoveTemp(tempfile); + fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w"); + } + if (fp0 == NULL) { HTAlert(CANNOT_OPEN_TEMP); return(NOT_FOUND); } @@ -704,13 +720,19 @@ PUBLIC int LYshow_statusline_messages ARGS1( /* print messages in reverse order: */ i = topOfStack; while (--i >= 0) { - if (buffstack[i] != NULL) - fprintf(fp0, "<li> <em>%s</em>\n", buffstack[i]); + if (buffstack[i] != NULL) { + StrAllocCopy(temp, buffstack[i]); + LYEntify(&temp, TRUE); + fprintf(fp0, "<li> <em>%s</em>\n", temp); + } } i = STATUSBUFSIZE; while (--i >= topOfStack) { - if (buffstack[i] != NULL) - fprintf(fp0, "<li> <em>%s</em>\n", buffstack[i]); + if (buffstack[i] != NULL) { + StrAllocCopy(temp, buffstack[i]); + LYEntify(&temp, TRUE); + fprintf(fp0, "<li> <em>%s</em>\n", temp); + } } fprintf(fp0, "</ol>\n"); @@ -772,6 +794,7 @@ PUBLIC void LYstore_message2 ARGS2( if (message != NULL) { char *temp = NULL; HTSprintf(&temp, message, (argument == 0) ? "" : argument); + LYEntify(&temp, TRUE); to_stack(temp); } } @@ -782,6 +805,7 @@ PUBLIC void LYstore_message ARGS1( if (message != NULL) { char *temp = NULL; StrAllocCopy(temp, message); + LYEntify(&temp, TRUE); to_stack(temp); } } diff --git a/src/LYKeymap.c b/src/LYKeymap.c index 3999898c..be169559 100644 --- a/src/LYKeymap.c +++ b/src/LYKeymap.c @@ -893,7 +893,7 @@ PUBLIC int lkcstring_to_lkc ARGS1( #ifndef USE_SLANG if (c >= 0) { if ((c&LKC_MASK) > 255 && !(c & LKC_ISLKC)) - return (-1); /* Don't accept untranslatable curses KEY_* */ + return (-1); /* Don't accept untranslated curses KEY_* */ else c &= ~LKC_ISLKC; } diff --git a/src/LYLeaks.c b/src/LYLeaks.c index 70c8d8a1..0d8ff2bf 100644 --- a/src/LYLeaks.c +++ b/src/LYLeaks.c @@ -129,7 +129,6 @@ PUBLIC void LYLeaks NOARGS } } fprintf(Fp_leakagesink, "\n"); - FREE(ALp_head->vp_Alloced); fprintf(Fp_leakagesink, "%s\t%d\n", gettext("ByteSize:"), (int)(ALp_head->st_Bytes)); @@ -151,6 +150,8 @@ PUBLIC void LYLeaks NOARGS gettext("LineCount:"), ALp_head->SL_realloc.ssi_LineNumber); } + fflush(Fp_leakagesink); + FREE(ALp_head->vp_Alloced); } /* diff --git a/src/LYLocal.c b/src/LYLocal.c index df254292..7409535a 100644 --- a/src/LYLocal.c +++ b/src/LYLocal.c @@ -82,6 +82,10 @@ #define EXT_Z ".Z" #endif +#ifndef DIRED_MAXBUF +#define DIRED_MAXBUF 512 +#endif + PRIVATE int LYExecv PARAMS(( char * path, char ** argv, @@ -91,6 +95,15 @@ PRIVATE int LYExecv PARAMS(( PUBLIC char LYPermitFileURL[LY_MAXPATH] = "\0"; PUBLIC char LYDiredFileURL[LY_MAXPATH] = "\0"; +#ifdef OK_INSTALL +PUBLIC char LYInstallFileURL[LY_MAXPATH] = "\0"; +#ifdef FNAMES_8_3 +#define INSTALLDIRS_FILE "instdirs.htm" +#else +#define INSTALLDIRS_FILE ".installdirs.html" +#endif /* FNAMES_8_3 */ +#endif /* OK_INSTALL */ + PRIVATE char *get_filename PARAMS(( char * prompt, char * buf, @@ -105,8 +118,8 @@ PRIVATE BOOLEAN permit_location PARAMS(( PRIVATE char *render_item PARAMS(( CONST char * s, - char * path, - char * dir, + CONST char * path, + CONST char * dir, char * buf, int bufsize, BOOLEAN url_syntax)); @@ -136,10 +149,17 @@ struct dired_menu { { 0, "", "New Directory", "(in current directory)", "LYNXDIRED://NEW_FOLDER%d", NULL }, +#ifdef OK_INSTALL { DE_FILE, "", "Install", -"(of current selection)", "LYNXDIRED://INSTALL_SRC%p", NULL }, +"selected file to new location", "LYNXDIRED://INSTALL_SRC%p", NULL }, +/* The following (installing a directory) doesn't work for me, at least + with the "install" from GNU fileutils 4.0. I leave it in anyway, in + case one compiles with INSTALL_PATH / INSTALL_ARGS defined to some + other command for which it works (like a script, or maybe "cp -a"). - kw +*/ { DE_DIR, "", "Install", -"(of current selection)", "LYNXDIRED://INSTALL_SRC%p", NULL }, +"selected directory to new location", "LYNXDIRED://INSTALL_SRC%p", NULL }, +#endif /* OK_INSTALL */ { DE_FILE, "", "Modify File Name", "(of current selection)", "LYNXDIRED://MODIFY_NAME%p", NULL }, @@ -249,6 +269,11 @@ struct dired_menu { { DE_TAG, "", "Move all tagged items to another location.", "", "LYNXDIRED://MOVE_TAGGED%d", NULL }, +#ifdef OK_INSTALL +{ DE_TAG, "", "Install tagged files into another directory.", + "", "LYNXDIRED://INSTALL_SRC%00", NULL }, +#endif + { DE_TAG, "", "Remove all tagged files and directories.", "", "LYNXDIRED://REMOVE_TAGGED", NULL }, @@ -259,7 +284,7 @@ struct dired_menu { NULL, NULL, NULL } }; -PRIVATE BOOLEAN cannot_stat ARGS1(char *, name) +PRIVATE BOOLEAN cannot_stat ARGS1(CONST char *, name) { char *tmpbuf = 0; HTSprintf(&tmpbuf, gettext("Unable to get status of '%s'."), name); @@ -268,10 +293,12 @@ PRIVATE BOOLEAN cannot_stat ARGS1(char *, name) return FALSE; } -PRIVATE BOOLEAN ok_stat ARGS2(char *, name, struct stat*, sb) +#define OK_STAT(name, sb) (stat(name, sb) == 0) + +PRIVATE BOOLEAN ok_stat ARGS2(CONST char *, name, struct stat*, sb) { CTRACE(tfp, "testing ok_stat(%s)\n", name); - if (stat(name, sb) < 0) { + if (!OK_STAT(name, sb)) { return cannot_stat(name); } return TRUE; @@ -300,20 +327,23 @@ PRIVATE BOOLEAN ok_file_or_dir ARGS1(struct stat*, sb) return TRUE; } -PRIVATE BOOLEAN ok_localname ARGS2(char*, dst, char*, src) +#ifdef OK_INSTALL /* currently only used in local_install */ +PRIVATE BOOLEAN ok_localname ARGS2(char*, dst, CONST char*, src) { - char *s = HTfullURL_toFile(strip_trailing_slash(src)); struct stat dir_info; - if (!ok_stat(s, &dir_info) + if (!ok_stat(src, &dir_info) || !ok_file_or_dir(&dir_info)) { - FREE(s); return FALSE; } - strcpy(dst, s); - FREE(s); + if (strlen(src) >= DIRED_MAXBUF) { + CTRACE(tfp, "filename too long in ok_localname!\n"); + return FALSE; + } + strcpy(dst, src); return TRUE; } +#endif /* OK_INSTALL */ PRIVATE int move_file ARGS2(char *, source, char *, target) { @@ -335,7 +365,7 @@ PRIVATE BOOLEAN not_already_exists ARGS1(char *, name) { struct stat dir_info; - if (stat(name, &dir_info) == -1) { + if (!OK_STAT(name, &dir_info)) { if (errno != ENOENT) { cannot_stat(name); } else { @@ -437,7 +467,7 @@ PRIVATE BOOLEAN modify_tagged ARGS1( ino_t inode; uid_t owner; char tmpbuf[1024]; - char *savepath = NULL; + char *savepath; char *srcpath = NULL; struct stat dir_info; int count = 0; @@ -471,21 +501,28 @@ PRIVATE BOOLEAN modify_tagged ARGS1( cp = HTList_lastObject(tagged); testpath = NULL; /* Won't be needed any more in this function, set to NULL as a flag. */ - if (!cp) /* Last resort, should never happen. */ - cp = "/"; } if (testpath == NULL) { /* * Get the directory containing the file or subdir. */ - cp = HTfullURL_toFile(strip_trailing_slash(cp)); - savepath = HTParse(".", cp, PARSE_PATH+PARSE_PUNCTUATION); + if (cp) { + cp = strip_trailing_slash(cp); + cp = HTParse(".", cp, PARSE_PATH+PARSE_PUNCTUATION); + savepath = HTURLPath_toFile(cp, TRUE); + FREE(cp); + } else { /* Last resort, should never happen. */ + savepath = HTURLPath_toFile(".", TRUE); + } } else { - cp = HTfullURL_toFile(cp); - StrAllocCopy(savepath, cp); + if (!strncmp(cp, "file://localhost", 16)) { + cp += 16; + } else if (!strncmp(cp, "file:", 5)) { + cp += 5; + } + savepath = HTURLPath_toFile(cp, TRUE); } - FREE(cp); if (!ok_stat(savepath, &dir_info)) { FREE(savepath); @@ -556,8 +593,7 @@ PRIVATE BOOLEAN modify_tagged ARGS1( * Move all tagged items to the target location. */ while ((cp = (char *)HTList_nextObject(tag)) != NULL) { - cp = HTfullURL_toFile(cp); - StrAllocCopy(srcpath, cp); + srcpath = HTfullURL_toFile(cp); if (move_file(srcpath, savepath) < 0) { FREE(cp); @@ -565,7 +601,7 @@ PRIVATE BOOLEAN modify_tagged ARGS1( count = -1; break; } - FREE(cp); + FREE(srcpath); ++count; } clear_tags(); @@ -584,9 +620,9 @@ PRIVATE BOOLEAN modify_name ARGS1( char *, testpath) { char *cp; - char tmpbuf[512]; - char newpath[512]; - char savepath[512]; + char tmpbuf[DIRED_MAXBUF]; + char newpath[DIRED_MAXBUF]; + char savepath[DIRED_MAXBUF]; struct stat dir_info; /* @@ -642,8 +678,8 @@ PRIVATE BOOLEAN modify_location ARGS1( ino_t inode; uid_t owner; char tmpbuf[1024]; - char newpath[512]; - char savepath[512]; + char newpath[DIRED_MAXBUF]; + char savepath[DIRED_MAXBUF]; struct stat dir_info; /* @@ -725,15 +761,14 @@ PUBLIC BOOLEAN local_modify ARGS2( { int c, ans; char *cp; - char testpath[512]; /* a bit ridiculous */ + char testpath[DIRED_MAXBUF]; /* a bit ridiculous */ int count; if (!HTList_isEmpty(tagged)) { cp = HTpartURL_toFile(doc->address); - strcpy(testpath, cp); - FREE(cp); - count = modify_tagged(testpath); + count = modify_tagged(cp); + FREE(cp); if (doc->link > (nlinks-count - 1)) doc->link = (nlinks-count - 1); @@ -762,6 +797,10 @@ PUBLIC BOOLEAN local_modify ARGS2( if (strchr("NLP", ans) != NULL) { cp = HTfullURL_toFile(links[doc->link].lname); + if (strlen(cp) >= DIRED_MAXBUF) { + FREE(cp); + return 0; + } strcpy(testpath, cp); FREE(cp); @@ -794,8 +833,8 @@ PRIVATE BOOLEAN create_file ARGS1( char *, current_location) { int code = FALSE; - char tmpbuf[512]; - char testpath[512]; + char tmpbuf[DIRED_MAXBUF]; + char testpath[DIRED_MAXBUF]; char *args[5]; char *bad_chars = ".~/"; @@ -842,8 +881,8 @@ PRIVATE BOOLEAN create_directory ARGS1( char *, current_location) { int code = FALSE; - char tmpbuf[512]; - char testpath[512]; + char tmpbuf[DIRED_MAXBUF]; + char testpath[DIRED_MAXBUF]; char *args[5]; char *bad_chars = ".~/"; @@ -888,16 +927,20 @@ PUBLIC BOOLEAN local_create ARGS1( { int c, ans; char *cp; - char testpath[512]; - - _statusline(gettext("Create file or directory (f or d): ")); - c = LYgetch(); - ans = TOUPPER(c); + char testpath[DIRED_MAXBUF]; cp = HTfullURL_toFile(doc->address); + if (strlen(cp) >= DIRED_MAXBUF) { + FREE(cp); + return 0; + } strcpy(testpath,cp); FREE(cp); + _statusline(gettext("Create file or directory (f or d): ")); + c = LYgetch(); + ans = TOUPPER(c); + if (ans == 'F') { return(create_file(testpath)); } else if (ans == 'D') { @@ -980,7 +1023,7 @@ PUBLIC BOOLEAN local_remove ARGS1( document *, doc) { char *cp, *tp; - char testpath[512]; + char testpath[DIRED_MAXBUF]; int count, i; if (!HTList_isEmpty(tagged)) { @@ -996,6 +1039,10 @@ PUBLIC BOOLEAN local_remove ARGS1( cp = links[doc->link].lname; if (is_url(cp) == FILE_URL_TYPE) { tp = HTfullURL_toFile(cp); + if (strlen(tp) >= DIRED_MAXBUF) { + FREE(tp); + return 0; + } strcpy(testpath, tp); FREE(tp); @@ -1058,22 +1105,19 @@ PRIVATE BOOLEAN permit_location ARGS3( * Create form. */ FILE *fp0; - char local_src[LY_MAXPATH]; char * user_filename; char * group_name; - cp = HTfullURL_toFile(strip_trailing_slash(srcpath)); - strcpy(local_src, cp); - FREE(cp); + srcpath = strip_trailing_slash(srcpath); /* * A couple of sanity tests. */ - if (!ok_lstat(local_src, &dir_info) + if (!ok_lstat(srcpath, &dir_info) || !ok_file_or_dir(&dir_info)) return 0; - user_filename = LYPathLeaf(local_src); + user_filename = LYPathLeaf(srcpath); LYRemoveTemp(tempfile); if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) { @@ -1089,7 +1133,7 @@ PRIVATE BOOLEAN permit_location ARGS3( group_name = HTAA_GidToName (dir_info.st_gid); LYstrncpy(LYValidPermitFile, - local_src, + srcpath, (sizeof(LYValidPermitFile) - 1)); fprintf(fp0, "<Html><Head>\n<Title>%s</Title>\n</Head>\n<Body>\n", @@ -1194,10 +1238,14 @@ PRIVATE BOOLEAN permit_location ARGS3( *cp++ = '\0'; /* Null terminate file name and start working on the masks. */ - if ((destpath = HTfullURL_toFile(destpath)) == 0) + /* Will now operate only on filename part. */ + if ((destpath = HTURLPath_toFile(destpath, TRUE)) == 0) return(0); - - strcpy(tmpdst, destpath); /* operate only on filename */ + if (strlen(destpath) >= LY_MAXPATH) { + FREE(destpath); + return(0); + } + strcpy(tmpdst, destpath); FREE(destpath); destpath = tmpdst; @@ -1358,15 +1406,20 @@ PRIVATE char * DirectoryOf ARGS1( } #ifdef __DJGPP__ -/* Convert filenames to acceptable 8+3 names when necessary -*/ +/* + * Convert filenames to acceptable 8+3 names when necessary. Make a copy of + * the parameter if we must modify it. + */ PRIVATE char * LYonedot ARGS1( char *, line) { char *dot; + static char line1[LY_MAXPATH]; + if (pathconf (line, _PC_NAME_MAX) <= 12) { + strcpy(line1, line); for (;;) { - if ((dot = strrchr(line, '.')) == 0 + if ((dot = strrchr(line1, '.')) == 0 || LYLastPathSep(dot) != 0) { break; } else if (strlen(dot) == 1) { @@ -1375,6 +1428,7 @@ PRIVATE char * LYonedot ARGS1( *dot = '_'; } } + return(line1); } return(line); } @@ -1428,15 +1482,19 @@ PUBLIC int local_dired ARGS1( } else if (!strncmp(line, "LYNXDIRED://NEW_FOLDER", 22)) { if (create_directory(&line[22]) > 0) LYforce_no_cache = TRUE; +#ifdef OK_INSTALL } else if (!strncmp(line, "LYNXDIRED://INSTALL_SRC", 23)) { local_install(NULL, &line[23], &tp); - StrAllocCopy(doc->address, tp); - FREE(tp); + if (tp) { + FREE(doc->address); + doc->address = tp; + } FREE(line); return 0; } else if (!strncmp(line, "LYNXDIRED://INSTALL_DEST", 24)) { local_install(&line[24], NULL, &tp); LYpop(doc); +#endif /* OK_INSTALL */ } else if (!strncmp(line, "LYNXDIRED://MODIFY_NAME", 23)) { if (modify_name(&line[23]) > 0) LYforce_no_cache = TRUE; @@ -1449,13 +1507,14 @@ PUBLIC int local_dired ARGS1( #ifdef OK_PERMIT } else if (!strncmp(line, "LYNXDIRED://PERMIT_SRC", 22)) { permit_location(NULL, &line[22], &tp); - if (tp) + if (tp) { /* * One of the checks may have failed. */ - StrAllocCopy(doc->address, tp); + FREE(doc->address); + doc->address = tp; + } FREE(line); - FREE(tp); return 0; } else if (!strncmp(line, "LYNXDIRED://PERMIT_LOCATION", 27)) { permit_location(&line_url[27], NULL, &tp); @@ -1619,7 +1678,7 @@ PUBLIC int local_dired ARGS1( } _statusline(tmpbuf); stop_curses(); - printf("%s\n", tmpbuf); + printf("%s\r\n", tmpbuf); LYSystem(buffer); #ifdef VMS HadVMSInterrupt = FALSE; @@ -1646,11 +1705,11 @@ PUBLIC int dired_options ARGS2( char **, newfile) { static char tempfile[LY_MAXPATH]; - char path[512], dir[512]; /* much too large */ + char *path; + char *dir; lynx_html_item_type *nxt; struct stat dir_info; FILE *fp0; - char *cp = NULL; char *dir_url; char *path_url; BOOLEAN nothing_tagged; @@ -1670,26 +1729,23 @@ PUBLIC int dired_options ARGS2( LYLocalFileToURL(newfile, tempfile); strcpy(LYDiredFileURL, *newfile); - cp = HTpartURL_toFile(doc->address); - strcpy(dir, cp); - LYTrimPathSep(dir); - FREE(cp); - if (doc->link > -1 && doc->link < (nlinks+1)) { - cp = HTfullURL_toFile(links[doc->link].lname); - strcpy(path, cp); + path = HTfullURL_toFile(links[doc->link].lname); LYTrimPathSep(path); - FREE(cp); if (!ok_lstat(path, &dir_info)) { LYCloseTempFP(fp0); + FREE(path); return 0; } } else { - path[0] = '\0'; + StrAllocCopy(path, ""); } + dir = HTfullURL_toFile(doc->address); + LYTrimPathSep(dir); + nothing_tagged = (HTList_isEmpty(tagged)); BeginInternalPage(fp0, DIRED_MENU_TITLE, DIRED_MENU_HELP); @@ -1778,6 +1834,7 @@ PUBLIC int dired_options ARGS2( FREE(dir_url); FREE(path_url); } + FREE(path); if (uploaders != NULL) { fprintf(fp0, "<p>Upload to current directory:<p>\n"); @@ -1789,6 +1846,7 @@ PUBLIC int dired_options ARGS2( count, dir, nxt->name); } } + FREE(dir); EndInternalPage(fp0); LYCloseTempFP(fp0); @@ -1831,6 +1889,72 @@ PRIVATE char *get_filename ARGS3( return buf; } +#ifdef OK_INSTALL + +#define LYEXECV_MAX_ARGC 15 +/* these are quasi-constant once they have been allocated: */ +static char ** install_argp = NULL; /* args for execv install */ +static char * install_path = NULL; /* auxiliary */ +#ifdef LY_FIND_LEAKS +PRIVATE void clear_install_path NOARGS +{ + FREE(install_argp); + FREE(install_path); +} +#endif /* LY_FIND_LEAKS */ +/* + * Fill in args array for execv (or execvp etc.) call, after first + * allocating it if necessary. No fancy parsing, cmd_args is just + * split at spaces. Leave room for reserve additional args to be + * added by caller. + * On success *argvp points to new args vector, *pathp is auxiliary. + * On success returns index of next argument, else -1. + * This is generic enough that it could be used for other calls than + * install, except the atexit call. Go through this trouble for install + * because INSTALL_ARGS may be significant, and someone may configure it + * with more than one significant flags. - kw + */ +PRIVATE int fill_argv_for_execv ARGS5( + char ***, argvp, + char **, pathp, + char *, cmd_path, + CONST char *, cmd_args, + int, reserve) +{ + int n = 0; + + char **args; + char *cp; + if (*argvp == NULL) { + *argvp = (char **)calloc(LYEXECV_MAX_ARGC+1, sizeof(char *)); + if (!*argvp) + return(-1); +#ifdef LY_FIND_LEAKS + atexit(clear_install_path); +#endif + } + args = *argvp; + args[n++] = cmd_path; + if (cmd_args) { + StrAllocCopy(*pathp, cmd_args); + cp = strtok(*pathp, " "); + if (cp) { + while (cp && (n < LYEXECV_MAX_ARGC - reserve)) { + args[n++] = cp; + cp = strtok(NULL, " "); + } + if (cp && (n >= LYEXECV_MAX_ARGC - reserve)) { + CTRACE(tfp, "Too many args for '%s' in '%s'!\n", + cmd_path ? cmd_path : "<null>" , cmd_args); + return(-1); + } + } else { + args[n++] = *pathp; + } + } + args[n] = (char *)0; + return(n); +} /* * Install the specified file or directory. */ @@ -1840,71 +1964,173 @@ PUBLIC BOOLEAN local_install ARGS3( char **, newpath) { char *tmpbuf = NULL; - char savepath[512]; /* This will be the link that is to be installed. */ + static char savepath[DIRED_MAXBUF]; /* This will be the link that + is to be installed. */ struct stat dir_info; - char *args[6]; + char **args; HTList *tag; + char *cp = NULL; + char *tmpdest = NULL; int count = 0; - int n = 0, src; /* indices into 'args[]' */ + int n = 0; /* indices into 'args[]' */ + static int src = -1; /* * Determine the status of the selected item. */ if (srcpath) { - if (!ok_localname(savepath, srcpath)) + srcpath = strip_trailing_slash(srcpath); + if (is_url(srcpath)) { + char *local_src = HTfullURL_toFile(srcpath); + if (!ok_localname(savepath, local_src)) { + FREE(local_src); + return 0; + } + FREE(local_src); + } else if (!HTList_isEmpty(tagged) && + srcpath[0] == '\0') { + savepath[0] = '\0'; /* will always use tagged list - kw */ + } else if (!ok_localname(savepath, srcpath)) { return 0; - + } LYforce_no_cache = TRUE; LYLocalFileToURL(newpath, Home_Dir()); - StrAllocCat(*newpath, "/.installdirs.html"); + LYAddHtmlSep(newpath); + StrAllocCat(*newpath, INSTALLDIRS_FILE); + LYstrncpy(LYInstallFileURL, + *newpath, + (sizeof(LYInstallFileURL) - 1)); return 0; } + /* deal with ~/ or /~/ at the beginning - kw */ + if (destpath[0] == '~' && + (destpath[1] == '/' || destpath[1] == '\0')) { + cp = &destpath[1]; + } else if (destpath[0] == '/' && destpath[1] == '~' && + (destpath[2] == '/' || destpath[2] == '\0')) { + cp = &destpath[2]; + } + if (cp) { + /* If found, allocate new string, make destpath point to it - kw */ + StrAllocCopy(tmpdest, Home_Dir()); + if (cp[0] && cp[1]) { + LYAddPathSep(&tmpdest); + StrAllocCat(tmpdest, cp + 1); + } + destpath = tmpdest; + } + destpath = strip_trailing_slash(destpath); if (!ok_stat(destpath, &dir_info)) { + FREE(tmpdest); return 0; } else if (!S_ISDIR(dir_info.st_mode)) { HTAlert(gettext("The selected item is not a directory! Request ignored.")); + FREE(tmpdest); return 0; } else if (0 /*directory not writable*/) { HTAlert(gettext("Install in the selected directory not permitted.")); + FREE(tmpdest); return 0; } statusline(gettext("Just a moment, ...")); - args[n++] = "install"; + + /* fill in the fixed args, if not already done - kw */ + if (src > 0 && install_argp) { + n = src; + n++; + } else { + n = fill_argv_for_execv(&install_argp, &install_path, + "install", #ifdef INSTALL_ARGS - args[n++] = INSTALL_ARGS; + INSTALL_ARGS, +#else + NULL, #endif /* INSTALL_ARGS */ - src = n++; + 2); + if (n <= 0) { + src = 0; + HTAlert(gettext("Error buiding install args")); + FREE(tmpdest); + return 0; + } + src = n++; + } + args = install_argp; + args[n++] = destpath; args[n] = (char *)0; - HTSprintf(&tmpbuf, "install %s", destpath); tag = tagged; if (HTList_isEmpty(tagged)) { + /* simplistic detection of identical src and dest - kw */ + if (!strcmp(savepath, destpath)) { + HTUserMsg2(gettext("Source and target are the same: %s"), + savepath); + FREE(tmpdest); + return(-1); /* don't do it */ + } else if (!strncmp(savepath, destpath, strlen(destpath)) && + LYIsPathSep(savepath[strlen(destpath)]) && +#ifdef DOSPATH + !strchr(savepath + strlen(destpath) + 1, '\\') && +#endif + !strchr(savepath + strlen(destpath) + 1, '/')) { + HTUserMsg2(gettext("Already in target directory: %s"), + savepath); + FREE(tmpdest); + return 0; /* don't do it */ + } args[src] = savepath; - if (LYExecv(INSTALL_PATH, args, tmpbuf) <= 0) + HTSprintf(&tmpbuf, "install %s in %s", savepath, destpath); + if (LYExecv(INSTALL_PATH, args, tmpbuf) <= 0) { + FREE(tmpbuf); + FREE(tmpdest); return (-1); + } count++; } else { char *name; + HTSprintf(&tmpbuf, "install in %s", destpath); while ((name = (char *)HTList_nextObject(tag))) { int err; args[src] = HTfullURL_toFile(name); + + /* simplistic detection of identical src and dest - kw */ + if (!strcmp(args[src], destpath)) { + HTUserMsg2(gettext("Source and target are the same: %s"), + args[src]); + FREE(args[src]); + continue; /* skip this source file */ + } else if (!strncmp(args[src], destpath, strlen(destpath)) && + LYIsPathSep(args[src][strlen(destpath)]) && +#ifdef DOSPATH + !strchr(args[src] + strlen(destpath) + 1, '\\') && +#endif + !strchr(args[src] + strlen(destpath) + 1, '/')) { + HTUserMsg2(gettext("Already in target directory: %s"), + args[src]); + FREE(args[src]); + continue; /* skip this source file */ + } err = (LYExecv(INSTALL_PATH, args, tmpbuf) <= 0); FREE(args[src]); - if (err) + if (err) { + FREE(tmpdest); return ((count == 0) ? -1 : count); + } count++; } clear_tags(); } FREE(tmpbuf); + FREE(tmpdest); HTInfoMsg(gettext("Installation complete")); return count; } +#endif /* OK_INSTALL */ /* * Clear DIRED tags. @@ -1990,13 +2216,13 @@ PUBLIC void add_menu_item ARGS1( */ PRIVATE char * render_item ARGS6( CONST char *, s, - char *, path, - char *, dir, + CONST char *, path, + CONST char *, dir, char *, buf, int, bufsize, BOOLEAN, url_syntax) { - char *cp; + CONST char *cp; char *bp; char overrun = '\0'; char *taglist = NULL; @@ -2081,6 +2307,7 @@ PRIVATE char * render_item ARGS6( *bp = '\0'; return buf; } + #endif /* DIRED_SUPPORT */ /* @@ -2169,7 +2396,8 @@ PRIVATE int LYExecv ARGS3( } start_curses(); if (tmpbuf != 0) { - HTAlert(tmpbuf); + if (rc == 0) + HTAlert(tmpbuf); FREE(tmpbuf); } diff --git a/src/LYLocal.h b/src/LYLocal.h index 029718d1..143e3914 100644 --- a/src/LYLocal.h +++ b/src/LYLocal.h @@ -35,11 +35,16 @@ extern char LYPermitFileURL[]; extern char LYDiredFileURL[]; extern char LYUploadFileURL[]; +#ifdef OK_INSTALL +extern char LYInstallFileURL[]; +#endif extern BOOLEAN local_create PARAMS((document *doc)); extern BOOLEAN local_modify PARAMS((document *doc, char **newpath)); extern BOOLEAN local_remove PARAMS((document *doc)); +#ifdef OK_INSTALL extern BOOLEAN local_install PARAMS((char *destpath, char *srcpath, char **newpath)); +#endif /* MainLoop needs to know about this one for atexit cleanup */ extern void clear_tags NOPARAMS; diff --git a/src/LYMail.c b/src/LYMail.c index 340f14c9..37764eab 100644 --- a/src/LYMail.c +++ b/src/LYMail.c @@ -1852,7 +1852,7 @@ PUBLIC void reply_by_mail ARGS4( sleep(AlertSecs); start_curses(); goto cleandown; -#else /* Unix: */ +#else /* not VMS: */ /* * Send the tmpfile into sendmail. */ diff --git a/src/LYMain.c b/src/LYMain.c index e422853b..1c7f6c87 100644 --- a/src/LYMain.c +++ b/src/LYMain.c @@ -409,6 +409,7 @@ PUBLIC int partial_threshold = -1; /* # of lines to be d/l'ed until we repaint #endif PUBLIC BOOLEAN LYNonRestartingSIGWINCH = FALSE; +PUBLIC BOOLEAN LYReuseTempfiles = FALSE; /* These are declared in cutil.h for current freeWAIS libraries. - FM */ #ifdef DECLARE_WAIS_LOGFILES @@ -2561,6 +2562,7 @@ static int restrictions_fun ARGS1( #ifndef NO_CONFIG_INFO ," lynxcfg_xinfo disable extended lynx.cfg viewing and reloading" #endif +," mail disallow mail" ," multibook disallow multiple bookmark files" ," news_post disallow USENET News posting." ," option_save disallow saving options in .lynxrc" diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c index 51cfb467..47ac1d67 100644 --- a/src/LYMainLoop.c +++ b/src/LYMainLoop.c @@ -743,6 +743,7 @@ try_again: LYCancelledFetch = FALSE; ForcePush = FALSE; LYforce_HTML_mode = FALSE; + force_old_UCLYhndl_on_reload = FALSE; if (traversal) { crawl_ok = FALSE; if (traversal_link_to_add) { @@ -1121,6 +1122,7 @@ try_again: LYPermitURL = FALSE; /* only for LYValidate or check_realm */ ForcePush = FALSE; /* only set for some PRINT requests. */ LYforce_HTML_mode = FALSE; + force_old_UCLYhndl_on_reload = FALSE; popped_doc = FALSE; } /* end if (LYforce_no_cache || force_load || are_different(...)) */ @@ -1761,6 +1763,7 @@ new_cmd: /* * back through the getch() loop. */ + force_old_UCLYhndl_on_reload = FALSE; CTRACE_FLUSH(tfp); switch(cmd) { @@ -3329,6 +3332,9 @@ new_cmd: /* (strcmp(curdoc.address, LYPermitFileURL) || strcmp((curdoc.title ? curdoc.title : ""), PERMIT_OPTIONS_TITLE)) && +#ifdef OK_INSTALL + strcmp(curdoc.address, LYInstallFileURL) && +#endif /* OK_INSTALL */ (strcmp(curdoc.address, LYUploadFileURL) || strcmp((curdoc.title ? curdoc.title : ""), UPLOAD_OPTIONS_TITLE))) || @@ -3509,7 +3515,9 @@ new_cmd: /* * unescaping of other chars. - KW */ HTUnEscapeSome(newdoc.address,"/"); - strip_trailing_slash(newdoc.address); + /* avoid stripping final slash for root dir - kw */ + if (strcasecomp(newdoc.address, "file://localhost/")) + strip_trailing_slash(newdoc.address); } #endif /* DIRED_SUPPORT && !__DJGPP__ */ if (!strncmp(curdoc.address, "LYNXCOOKIE:", 11)) { @@ -4738,12 +4746,12 @@ if (!LYUseFormsOptions) { } break; -#ifdef DIRED_SUPPORT +#if defined(DIRED_SUPPORT) && defined(OK_INSTALL) 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; -#endif /* DIRED_SUPPORT */ +#endif /* DIRED_SUPPORT && OK_INSTALL */ case LYK_INFO: /* show document info */ /* diff --git a/src/LYOptions.c b/src/LYOptions.c index 560b29e8..7bc6e1d0 100644 --- a/src/LYOptions.c +++ b/src/LYOptions.c @@ -3553,17 +3553,22 @@ PUBLIC int postoptions ARGS1( return(NULLFILE); } + data = break_data(newdoc->post_data); - /*------------------------------------------------- - * kludge gen_options() call: - *--------------------------------------------------*/ - - if (strstr(newdoc->address, "LYNXOPTIONS:/") && !newdoc->post_data) { - int status = gen_options(&newdoc->address); - if (status == NOT_FOUND) - return(NOT_FOUND); + if (!data) { + int status; + + /*------------------------------------------------- + * kludge gen_options() call: + *--------------------------------------------------*/ + status = gen_options(&newdoc->address); + if (status != NORMAL) { + HTAlwaysAlert("Unexpected way of accessing", newdoc->address); + FREE(newdoc->address); + return(status); + } - /* exit to getfile() cyrcle */ + /* exit to getfile() cycle */ WWWDoc.address = newdoc->address; WWWDoc.post_data = newdoc->post_data; WWWDoc.post_content_type = newdoc->post_content_type; @@ -3576,9 +3581,6 @@ PUBLIC int postoptions ARGS1( return(NORMAL); } - - data = break_data(newdoc->post_data); - for (i = 0; data[i].tag != NULL; i++) { /* * Paranoid security. @@ -4085,13 +4087,17 @@ PRIVATE int gen_options ARGS1( #if defined(USE_SLANG) || defined(COLOR_CURSES) BOOLEAN can_do_colors; #endif - static char tempfile[LY_MAXPATH]; + static char tempfile[LY_MAXPATH] = "\0"; FILE *fp0; size_t cset_len = 0; size_t text_len = COLS - 38; /* cf: PutLabel */ - LYRemoveTemp(tempfile); - fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w"); + if (LYReuseTempfiles) { + fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w"); + } else { + LYRemoveTemp(tempfile); + fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w"); + } if (fp0 == NULL) { HTAlert(UNABLE_TO_OPEN_TEMPFILE); return(NOT_FOUND); diff --git a/src/LYPrint.c b/src/LYPrint.c index 810a1ab7..489e88ae 100644 --- a/src/LYPrint.c +++ b/src/LYPrint.c @@ -986,6 +986,7 @@ PRIVATE void send_file_to_screen ARGS3( if (Lpansi) { printf("\n\014"); /* Form feed */ printf("\033[4i"); + fflush(stdout); /* refresh to screen */ Lpansi = FALSE; } else { fprintf(stdout,"\n\n%s", PRESS_RETURN_TO_FINISH); @@ -995,7 +996,6 @@ PRIVATE void send_file_to_screen ARGS3( HadVMSInterrupt = FALSE; #endif /* VMS */ } - fflush(stdout); /* refresh to screen */ start_curses(); done: @@ -1237,15 +1237,20 @@ PUBLIC int print_options ARGS3( char **, printed_url, int, lines_in_file) { - static char my_temp[LY_MAXPATH]; + static char my_temp[LY_MAXPATH] = "\0"; char *buffer = 0; int count; int pages; FILE *fp0; lynx_printer_item_type *cur_printer; - LYRemoveTemp(my_temp); - if ((fp0 = LYOpenTemp(my_temp, HTML_SUFFIX, "w")) == NULL) { + if (LYReuseTempfiles) { + fp0 = LYOpenTempRewrite(my_temp, HTML_SUFFIX, "w"); + } else { + LYRemoveTemp(my_temp); + fp0 = LYOpenTemp(my_temp, HTML_SUFFIX, "w"); + } + if (fp0 == NULL) { HTAlert(UNABLE_TO_OPEN_PRINTOP_FILE); return(-1); } diff --git a/src/LYReadCFG.c b/src/LYReadCFG.c index a8cc016b..5a535ffc 100644 --- a/src/LYReadCFG.c +++ b/src/LYReadCFG.c @@ -1181,6 +1181,7 @@ static Config_Type Config_Table [] = PARSE_SET("prepend_charset_to_source", CONF_BOOL, &LYPrependCharsetToSource), PARSE_FUN("printer", CONF_FUN, printer_fun), PARSE_SET("quit_default_yes", CONF_BOOL, &LYQuitDefaultYes), + PARSE_SET("reuse_tempfiles", CONF_BOOL, &LYReuseTempfiles), #ifndef NO_RULES PARSE_FUN("rule", CONF_FUN, HTSetConfiguration), PARSE_FUN("rulesfile", CONF_FUN, cern_rulesfile_fun), diff --git a/src/LYShowInfo.c b/src/LYShowInfo.c index 56340c16..d7389761 100644 --- a/src/LYShowInfo.c +++ b/src/LYShowInfo.c @@ -33,7 +33,7 @@ PUBLIC int showinfo ARGS4( document *, newdoc, char *, owner_address) { - static char tempfile[LY_MAXPATH]; + static char tempfile[LY_MAXPATH] = "\0"; int url_type; FILE *fp0; char *Address = NULL, *Title = NULL; @@ -48,8 +48,13 @@ PUBLIC int showinfo ARGS4( struct stat dir_info; #endif /* DIRED_SUPPORT */ - LYRemoveTemp(tempfile); - if ((fp0 = LYOpenTemp (tempfile, HTML_SUFFIX, "w")) == 0) { + if (LYReuseTempfiles) { + fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w"); + } else { + LYRemoveTemp(tempfile); + fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w"); + } + if (fp0 == NULL) { HTAlert(CANNOT_OPEN_TEMP); return(-1); } diff --git a/src/LYStrings.c b/src/LYStrings.c index 5fa74a85..01981de5 100644 --- a/src/LYStrings.c +++ b/src/LYStrings.c @@ -2737,11 +2737,6 @@ PUBLIC char *LYstrsep ARGS2( if (!stringp || !*stringp) /* nothing to do? */ return 0; /* then don't fall on our faces */ - if (!**stringp) { /* empty string: */ - *stringp = 0; /* let caller see he's done; */ - return 0; /* no tokens in an empty string */ - } - out = *stringp; /* save the start of the string */ tmp = strpbrk(*stringp, delim); if (tmp) { diff --git a/src/LYUtils.c b/src/LYUtils.c index 157cef47..73ff1bf3 100644 --- a/src/LYUtils.c +++ b/src/LYUtils.c @@ -17,6 +17,10 @@ #include <LYMainLoop.h> #include <LYKeymap.h> +#ifndef NO_GROUPS +#include <HTFile.h> +#endif + #ifdef DJGPP_KEYHANDLER #include <bios.h> #endif /* DJGPP_KEYHANDLER */ @@ -6114,6 +6118,165 @@ PUBLIC FILE *LYReopenTemp ARGS1( } /* + * Open a temp-file for writing, possibly re-using a previously used + * name and file. + * If a non-empty fname is given, it is reused if it indicates a file + * previously registered as a temp file and, in case the file still + * exists, if it looks like we can write to it safely. Otherwise a + * new temp file (with new name) will be generated and returned in fname. + * + * File permissions are set so that the file is not readable by unprivileged + * other users. + * + * Suffix is only used if fname is not being reused. + * The mode should be "w", others are possible (they may be passed on) + * but probably don't make sense. - kw + */ +PUBLIC FILE *LYOpenTempRewrite ARGS3( + char *, fname, + CONST char *, suffix, + CONST char *, mode) +{ + FILE *fp = 0; + BOOL txt = TRUE; + char wrt = 'r'; + BOOL registered = NO; + BOOL writable_exists = NO; + BOOL is_ours = NO; + BOOL still_open = NO; + LY_TEMP *p; + struct stat stat_buf; + + CTRACE(tfp, "LYOpenTempRewrite(%s,%s,%s)\n", fname, suffix, mode); + if (*fname == '\0') /* first time, no filename yet */ + return (LYOpenTemp(fname, suffix, mode)); + + for (p = ly_temp; p != 0; p = p->next) { + if (!strcmp(fname, p->name)) { + registered = YES; + if (p->file != 0) + still_open = YES; + CTRACE(tfp, "...used before%s\n", + still_open ? ", still open!" : "."); + break; + } + } + + if (registered) { +#ifndef NO_GROUPS + writable_exists = HTEditable(fname); /* existing, can write */ +#else + writable_exists = (stat(fname, &stat_buf) == 0); /* existing, assume can write */ +#endif + + if (writable_exists) { +#ifdef UNIX + is_ours = IsOurFile(fname); +#else + is_ours = TRUE; /* assume ok, if we get to here */ +#endif + } + CTRACE(tfp, "...%s%s\n", + writable_exists ? +#ifndef NO_GROUPS + "exists and is writable, " +#else + "exists, " +#endif + : "", + is_ours ? "is our file." : "is NOT our file."); + } + + /* + * Note that in cases where LYOpenTemp is called as fallback below, + * we don't call LYRemoveTemp first. That may be appropriate in some + * cases, but not trying to remove a weird existing file seems safer + * and could help diagnose an unusual situation. (They may be removed + * anyway later.) + */ + if (still_open) { + /* + * This should probably not happen. Make a new one. + */ + return (LYOpenTemp(fname, suffix, mode)); + } else if (is_ours) { + /* + * Yes, it exists, is writable if we checked, and everything + * looks ok so far. This should be the most regular case. + * We truncate and then append, this avoids having a small + * window in which the file doesn't exist. - kw + */ + if (truncate(fname, 0) != 0) { + CTRACE(tfp, "... truncate(%s,0) failed: %s\n", + fname, LYStrerror(errno)); + return (LYOpenTemp(fname, suffix, mode)); + } else { + return (LYReopenTemp(fname)); + } + } else if (writable_exists) { + /* + * File exists, writable if we checked, but something is wrong + * with it. + */ + return (LYOpenTemp(fname, suffix, mode)); +#ifndef NO_GROUPS + } else if (registered && (lstat(fname, &stat_buf) == 0)) { + /* + * Exists but not writable, and something is wrong with it. + */ + return (LYOpenTemp(fname, suffix, mode)); +#endif + } else if (!registered) { + /* + * Not registered. It should have been registered at one point + * though, otherwise we wouldn't be called like this. + */ + return (LYOpenTemp(fname, suffix, mode)); + } else { + /* + * File does not exist, but is registered as a temp file. + * It must have been removed by some means other than + * LYRemoveTemp. Reuse the name! + */ + } + + while (*mode != '\0') { + switch (*mode++) { + case 'w': wrt = 'w'; break; + case 'a': wrt = 'a'; break; + case 'b': txt = FALSE; break; + default: + CTRACE(tfp, "%s @%d: BUG\n", __FILE__, __LINE__); + return fp; + } + } + + if (txt) { + switch (wrt) { + case 'w': + fp = LYNewTxtFile (fname); + break; + case 'a': + fp = LYAppendToTxtFile (fname); + break; + } + } else { + fp = LYNewBinFile (fname); + } + p->file = fp; + + CTRACE(tfp, "... LYOpenTempRewrite(%s), %s\n", fname, + (fp) ? "ok" : "failed"); + /* + * We could fall back to trying LYOpenTemp() here in case of failure. + * After all the checks already done above a filure here should be + * pretty unusual though, so maybe it's better to let the user notice + * that something went wrong, and not try to fix it up. - kw + */ + return fp; +} + +/* * Special case of LYOpenTemp, used for manipulating bookmark file, i.e., with * renaming. */ @@ -6536,7 +6699,7 @@ PUBLIC void LYAddPathSep0 ARGS1( * Check if a given string contains a path separator */ PUBLIC char * LYLastPathSep ARGS1( - char *, path) + CONST char *, path) { char *result; #ifdef DOSPATH diff --git a/src/LYUtils.h b/src/LYUtils.h index 8a8608f3..10cf755b 100644 --- a/src/LYUtils.h +++ b/src/LYUtils.h @@ -71,9 +71,10 @@ extern FILE *LYNewBinFile PARAMS((char * name)); extern FILE *LYNewTxtFile PARAMS((char * name)); extern FILE *LYOpenScratch PARAMS((char *result, CONST char *prefix)); extern FILE *LYOpenTemp PARAMS((char *result, CONST char *suffix, CONST char *mode)); +extern FILE *LYOpenTempRewrite PARAMS((char *result, CONST char *suffix, CONST char *mode)); extern FILE *LYReopenTemp PARAMS((char *name)); extern char *Current_Dir PARAMS((char * pathname)); -extern char *LYLastPathSep PARAMS((char *path)); +extern char *LYLastPathSep PARAMS((CONST char *path)); extern char *LYPathLeaf PARAMS((char * pathname)); extern char *LYSysShell NOPARAMS; extern char *LYgetXDisplay NOPARAMS; |