about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorThomas E. Dickey <dickey@invisible-island.net>2007-05-04 00:37:14 -0400
committerThomas E. Dickey <dickey@invisible-island.net>2007-05-04 00:37:14 -0400
commit9fa44396215d14644ecd5aa32c04327d4e6243a2 (patch)
tree1c40b5fdc2472ee358d61703ee91aa0bf2070671
parent89168f60aa971ea8290d91e05557c7a21cdb22f1 (diff)
downloadlynx-snapshots-9fa44396215d14644ecd5aa32c04327d4e6243a2.tar.gz
snapshot of project "lynx", label v2-8-7dev_4c
-rw-r--r--CHANGES10
-rw-r--r--WWW/Library/Implementation/HTFTP.c67
-rw-r--r--lynx.cfg18
-rw-r--r--lynx.man3
-rw-r--r--src/LYGlobalDefs.h11
-rw-r--r--src/LYMain.c34
-rw-r--r--src/LYOptions.c12
-rw-r--r--src/LYReadCFG.c31
-rw-r--r--src/LYStructs.h19
-rw-r--r--src/LYUtils.c4
-rw-r--r--src/LYrcFile.h2
11 files changed, 160 insertions, 51 deletions
diff --git a/CHANGES b/CHANGES
index bed26f73..f74a2c10 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,16 @@ Changes since Lynx 2.8 release
 ===============================================================================
 
 2007-0?-?? (2.8.7dev.5)
+* replace BROKEN_PROFTPD and BROKEN_WU_FTPD logic with configurable list of
+  strings in lynx.cfg, i.e., BROKEN_FTP_RETR and BROKEN_FTP_EPSV, and add
+  "spftp/" to the predefined values for the former.  Prompted by report by
+  Fred Kasner for
+	ftp.symantec.com/AVDEFS/norton_antivirus
+  which has a broken RETR command -TD
+* add -passive-ftp option -TD
+* ifdef'd -ftp option in case ftp is disabled, for consistency -TD
+* ifdef'd options menu so that if ftp is disabled, the corresponding options
+  are not shown -TD
 * improve pretty-src in a few places by passing-through whitespace as
   demonstrated by
 	http://www.w3.org/TR/html401/index/elements.html
diff --git a/WWW/Library/Implementation/HTFTP.c b/WWW/Library/Implementation/HTFTP.c
index 978d67c1..3dc2698a 100644
--- a/WWW/Library/Implementation/HTFTP.c
+++ b/WWW/Library/Implementation/HTFTP.c
@@ -179,21 +179,20 @@ static char *user_entered_password = NULL;
 static char *last_username_and_host = NULL;
 
 /*
- * ProFTPD 1.2.5rc1 is known to have a broken implementation of RETR.  If asked
- * to retrieve a directory, it gets confused and fails subsequent commands such
- * as CWD and LIST.  Since this is an unusual bug, we should remove this ifdef
- * at some point - TD 2004/1/1.
+ * Some ftp servers are known to have a broken implementation of RETR.  If
+ * asked to retrieve a directory, they get confused and fail subsequent
+ * commands such as CWD and LIST.
  */
-#define BROKEN_PROFTPD 1
-static int ProFTPD_bugs = FALSE;
+static int Broken_RETR = FALSE;
 
 /*
- * wu-ftpd 2.6.2(12) is known to have a broken implementation of EPSV.  The
+ * Some ftp servers are known to have a broken implementation of EPSV.  The
  * server will hang for a long time when we attempt to connect after issuing
- * this command - TD 2004/12/28
+ * this command.
  */
-#define BROKEN_WUFTPD 1
-static int WU_FTPD_bugs = FALSE;
+#ifdef INET6
+static int Broken_EPSV = FALSE;
+#endif
 
 typedef enum {
     GENERIC_SERVER
@@ -470,6 +469,25 @@ static int write_cmd(const char *cmd)
     return 1;
 }
 
+/*
+ * For each string in the list, check if it is found in the response text.
+ * If so, return TRUE.
+ */
+static BOOL find_response(HTList *list)
+{
+    BOOL result = FALSE;
+    HTList *p = list;
+    char *value;
+
+    while ((value = (char *) HTList_nextObject(p)) != NULL) {
+	if (LYstrstr(response_text, value)) {
+	    result = TRUE;
+	    break;
+	}
+    }
+    return result;
+}
+
 /*	Execute Command and get Response
  *	--------------------------------
  *
@@ -537,16 +555,13 @@ static int response(const char *cmd)
 			continuation == ' ')
 			continuation_response = -1;	/* ended */
 		}
-#ifdef BROKEN_PROFTPD
-		if (result == 220 && LYstrstr(response_text, "ProFTPD 1.2.5")) {
-		    ProFTPD_bugs = TRUE;
+		if (result == 220 && find_response(broken_ftp_retr)) {
+		    Broken_RETR = TRUE;
 		    CTRACE((tfp, "This server is broken (RETR)\n"));
 		}
-#endif
-#ifdef BROKEN_WUFTPD
-		if (result == 220 && LYstrstr(response_text,
-					      "(Version wu-2.6.2-12)")) {
-		    WU_FTPD_bugs = TRUE;
+#ifdef INET6
+		if (result == 220 && find_response(broken_ftp_epsv)) {
+		    Broken_EPSV = TRUE;
 		    CTRACE((tfp, "This server is broken (EPSV)\n"));
 		}
 #endif
@@ -2984,8 +2999,11 @@ static int setup_connection(const char *name,
      */
     use_list = FALSE;
     server_type = GENERIC_SERVER;
-    ProFTPD_bugs = FALSE;
-    WU_FTPD_bugs = FALSE;
+    Broken_RETR = FALSE;
+
+#ifdef INET6
+    Broken_EPSV = FALSE;
+#endif
 
     for (retry = 0; retry < 2; retry++) {	/* For timed out/broken connections */
 	status = get_connection(name, anchor);
@@ -3042,7 +3060,7 @@ static int setup_connection(const char *name,
 
 #ifdef INET6
 	    /* see RFC 2428 */
-	    if (WU_FTPD_bugs)
+	    if (Broken_EPSV)
 		status = 1;
 	    else
 		status = send_cmd_1(p = "EPSV");
@@ -3658,14 +3676,10 @@ int HTFTPLoad(const char *name,
 	 */
 	if (!(type) || (type && *type != 'D')) {
 	    status = send_cmd_2("RETR", filename);
-#ifdef BROKEN_PROFTPD
-	    /*
-	     * ProFTPD 1.2.5rc1 gets confused when asked to RETR a directory.
-	     */
 	    if (status >= 5) {
 		int check;
 
-		if (ProFTPD_bugs) {
+		if (Broken_RETR) {
 		    CTRACE((tfp, "{{reconnecting...\n"));
 		    close_connection(control);
 		    check = setup_connection(name, anchor);
@@ -3674,7 +3688,6 @@ int HTFTPLoad(const char *name,
 			return check;
 		}
 	    }
-#endif
 	} else {
 	    status = 5;		/* Failed status set as flag. - FM */
 	}
diff --git a/lynx.cfg b/lynx.cfg
index ab8e6692..d65801bc 100644
--- a/lynx.cfg
+++ b/lynx.cfg
@@ -3440,3 +3440,21 @@ COLOR:6:brightred:black
 # Add the given text to calls made to syslog, to distinguish Lynx from other
 # applications which use that interface.
 #SYSLOG_TEXT:
+
+.h1 Internal Behavior
+.h2 BROKEN_FTP_RETR
+# Some ftp servers are known to have a broken implementation of RETR.  If asked
+# to retrieve a directory, they get confused and fails subsequent commands such
+# as CWD and LIST.  Workaround: reconnect after a failed RETR, which is slow.
+#
+# Each BROKEN_FTP_RETR gives a string match for the reported FTP server version
+#BROKEN_FTP_RETR:ProFTPD 1.2.5
+#BROKEN_FTP_RETR:spftp/
+
+.h2 BROKEN_FTP_EPSV
+# Some ftp servers are known to have a broken implementation of EPSV.  The
+# server will hang for a long time when we attempt to connect after issuing
+# this command.   Workaround: do not use EPSV, just use PASV.
+#
+# Each BROKEN_FTP_EPSV gives a string match for the reported FTP server version
+#BROKEN_FTP_EPSV:(Version wu-2.6.2-12)
diff --git a/lynx.man b/lynx.man
index 991fda89..37874fb3 100644
--- a/lynx.man
+++ b/lynx.man
@@ -464,6 +464,9 @@ toggles display partial pages while loading.
 number of lines to render before repainting display
 with partial-display logic
 .TP
+.B \-passive-ftp
+toggles passive ftp connections.
+.TP
 .B \-pauth\fR=\fIID\fR:\fIPASSWD
 set authorization ID and password for a protected proxy
 server at startup.  Be sure to protect any script files
diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h
index a3ec2edf..9372d7fd 100644
--- a/src/LYGlobalDefs.h
+++ b/src/LYGlobalDefs.h
@@ -214,9 +214,7 @@ extern "C" {
     extern BOOLEAN dump_to_stderr;
     extern BOOLEAN emacs_keys;	/* TRUE to turn on emacs-like key movement */
     extern BOOLEAN error_logging;	/* TRUE to mail error messages */
-    extern BOOLEAN ftp_local_passive;
     extern BOOLEAN ftp_ok;
-    extern BOOLEAN ftp_passive;	/* TRUE if we want to use passive mode ftp */
     extern BOOLEAN goto_buffer;	/* TRUE if offering default goto URL */
     extern BOOLEAN is_www_index;
     extern BOOLEAN jump_buffer;	/* TRUE if offering default shortcut */
@@ -241,7 +239,6 @@ extern "C" {
     extern char *LYTransferName;	/* abbreviation for Kilobytes */
     extern char *LynxHome;
     extern char *LynxSigFile;	/* Signature file, in or off home */
-    extern char *ftp_lasthost;
     extern char *helpfile;
     extern char *helpfilepath;
     extern char *jumpprompt;	/* The default jump statusline prompt */
@@ -472,6 +469,14 @@ extern "C" {
     extern BOOLEAN BibP_bibhost_available;	/* bibhost is responding         */
 #endif
 
+#ifndef DISABLE_FTP
+    extern BOOLEAN ftp_local_passive;
+    extern BOOLEAN ftp_passive;	/* TRUE if we want to use passive mode ftp */
+    extern HTList *broken_ftp_epsv;
+    extern HTList *broken_ftp_retr;
+    extern char *ftp_lasthost;
+#endif
+
 #ifdef USE_PERSISTENT_COOKIES
     extern BOOLEAN persistent_cookies;
     extern char *LYCookieFile;	/* cookie read file              */
diff --git a/src/LYMain.c b/src/LYMain.c
index 878b64ab..af108097 100644
--- a/src/LYMain.c
+++ b/src/LYMain.c
@@ -204,9 +204,6 @@ BOOLEAN dump_output_immediately = FALSE;
 BOOLEAN dump_to_stderr = FALSE;
 BOOLEAN emacs_keys = EMACS_KEYS_ALWAYS_ON;
 BOOLEAN error_logging = MAIL_SYSTEM_ERROR_LOGGING;
-BOOLEAN ftp_passive = FTP_PASSIVE;	/* TRUE if doing ftp in passive mode */
-BOOLEAN ftp_local_passive;
-char *ftp_lasthost;
 BOOLEAN goto_buffer = GOTOBUFFER;	/* TRUE if offering default goto URL */
 BOOLEAN historical_comments = FALSE;
 BOOLEAN is_www_index = FALSE;
@@ -281,6 +278,14 @@ BOOLEAN no_suspend = FALSE;
 BOOLEAN no_telnet_port = FALSE;
 BOOLEAN no_useragent = FALSE;
 
+#ifndef DISABLE_FTP
+BOOLEAN ftp_passive = FTP_PASSIVE;	/* TRUE if doing ftp in passive mode */
+BOOLEAN ftp_local_passive;
+HTList *broken_ftp_epsv = NULL;
+HTList *broken_ftp_retr = NULL;
+char *ftp_lasthost = NULL;
+#endif
+
 #ifndef DISABLE_NEWS
 BOOLEAN no_goto_news = FALSE;
 BOOLEAN no_goto_nntp = FALSE;
@@ -753,7 +758,11 @@ static void free_lynx_globals(void)
     FREE(proxyauth_info[0]);
     FREE(proxyauth_info[1]);
     FREE(lynxjumpfile);
+#ifndef DISABLE_FTP
     FREE(ftp_lasthost);
+    LYFreeStringList(broken_ftp_epsv);
+    LYFreeStringList(broken_ftp_retr);
+#endif
     FREE(startrealm);
     FREE(personal_mail_address);
     FREE(anonftp_password);
@@ -2048,6 +2057,17 @@ int main(int argc,
 	ftp_ok = (BOOL) (!no_outside_ftp && ftp_ok);
 	rlogin_ok = (BOOL) (!no_outside_rlogin && rlogin_ok);
     }
+#ifdef DISABLE_FTP
+    ftp_ok = FALSE;
+#else
+    /* predefine some known broken ftp servers */
+    LYSetConfigValue(RC_BROKEN_FTP_RETR, "ProFTPD 1.2.5");
+    LYSetConfigValue(RC_BROKEN_FTP_RETR, "spftp/");
+    LYSetConfigValue(RC_BROKEN_FTP_EPSV, "(Version wu-2.6.2-12)");
+#ifdef LY_FIND_LEAKS
+    atexit(broken_ftp_free);
+#endif
+#endif
 
     /*
      * Make sure our bookmark default strings are all allocated and
@@ -3444,10 +3464,12 @@ keys (may be incompatible with some curses packages)"
       "from",		4|TOGGLE_ARG,		LYNoFromHeader,
       "toggle transmission of From headers"
    ),
+#ifndef DISABLE_FTP
    PARSE_SET(
       "ftp",		4|UNSET_ARG,		ftp_ok,
       "disable ftp access"
    ),
+#endif
    PARSE_FUN(
       "get_data",	2|FUNCTION_ARG,		get_data_fun,
       "user data for get forms, read from stdin,\nterminated by '---' on a line"
@@ -3655,6 +3677,12 @@ keys (may be incompatible with some curses packages)"
 with partial-display logic"
    ),
 #endif
+#ifndef DISABLE_FTP
+   PARSE_SET(
+      "passive-ftp",	4|TOGGLE_ARG,		ftp_passive,
+      "toggles passive ftp connection"
+   ),
+#endif
    PARSE_FUN(
       "pauth",		4|NEED_FUNCTION_ARG,	pauth_fun,
       "=id:pw\nauthentication information for protected proxy server"
diff --git a/src/LYOptions.c b/src/LYOptions.c
index c5776a42..61f3e49a 100644
--- a/src/LYOptions.c
+++ b/src/LYOptions.c
@@ -2187,8 +2187,12 @@ static OptValues keypad_mode_values[] =
 };
 static const char *lineedit_mode_string = RC_LINEEDIT_MODE;
 static const char *mail_address_string = RC_PERSONAL_MAIL_ADDRESS;
-static const char *anonftp_password_string = RC_ANONFTP_PASSWORD;
 static const char *search_type_string = RC_CASE_SENSITIVE_SEARCHING;
+
+#ifndef DISABLE_FTP
+static const char *anonftp_password_string = RC_ANONFTP_PASSWORD;
+#endif
+
 static OptValues search_type_values[] =
 {
     {FALSE, N_("Case insensitive"), "case_insensitive"},
@@ -2796,10 +2800,12 @@ int postoptions(DocInfo *newdoc)
 	}
 
 	/* Anonymous FTP Password: INPUT */
+#ifndef DISABLE_FTP
 	if (!strcmp(data[i].tag, anonftp_password_string)) {
 	    FREE(anonftp_password);
 	    StrAllocCopy(anonftp_password, data[i].value);
 	}
+#endif
 
 	/* Search Type: SELECT */
 	if (!strcmp(data[i].tag, search_type_string)
@@ -3719,9 +3725,11 @@ static int gen_options(char **newfile)
 		 NonNull(personal_mail_address), text_len, "");
 
     /* Mail Address: INPUT */
+#ifndef DISABLE_FTP
     PutLabel(fp0, gettext("Password for anonymous ftp"), mail_address_string);
     PutTextInput(fp0, anonftp_password_string,
 		 NonNull(anonftp_password), text_len, "");
+#endif
 
     /* Preferred media type: SELECT */
     PutLabel(fp0, gettext("Preferred media type"), preferred_media_string);
@@ -3758,6 +3766,7 @@ static int gen_options(char **newfile)
     PutHeader(fp0, gettext("Listing and Accessing Files"));
     /*****************************************************************/
 
+#ifndef DISABLE_FTP
     /* FTP sort: SELECT */
     PutLabel(fp0, gettext("FTP sort criteria"), ftp_sort_string);
     BeginSelect(fp0, ftp_sort_string);
@@ -3786,6 +3795,7 @@ static int gen_options(char **newfile)
 	PutOptValues(fp0, show_dotfiles, bool_values);
 	EndSelect(fp0);
     }
+#endif /* DISABLE_FTP */
 
     /* Execution links: SELECT */
 #if defined(ENABLE_OPTS_CHANGE_EXEC) && (defined(EXEC_LINKS) || defined(EXEC_SCRIPTS))
diff --git a/src/LYReadCFG.c b/src/LYReadCFG.c
index 3ed09d89..bcdfff19 100644
--- a/src/LYReadCFG.c
+++ b/src/LYReadCFG.c
@@ -425,6 +425,7 @@ static Config_Enum tbl_abort_source_cache[] = {
 #define PARSE_ENV(n,v)   {n, CONF_ENV2,        UNION_ENV(v), 0}
 #define PARSE_FUN(n,v)   {n, CONF_FUN,         UNION_FUN(v), 0}
 #define PARSE_REQ(n,v)   {n, CONF_INCLUDE,     UNION_FUN(v), 0}
+#define PARSE_LST(n,v)   {n, CONF_ADD_STRING,  UNION_LST(v), 0}
 #define PARSE_DEF(n,v)   {n, CONF_ADD_TRUSTED, UNION_DEF(v), 0}
 #define PARSE_NIL        {NULL, CONF_NIL,      UNION_DEF(0), 0}
 
@@ -441,6 +442,7 @@ typedef enum {
     ,CONF_ENV2			/* from environment VARIABLE */
     ,CONF_INCLUDE		/* include file-- handle special */
     ,CONF_ADD_ITEM
+    ,CONF_ADD_STRING
     ,CONF_ADD_TRUSTED
 } Conf_Types;
 
@@ -819,12 +821,6 @@ static int cern_rulesfile_fun(char *value)
 }
 #endif /* NO_RULES */
 
-static int printer_fun(char *value)
-{
-    add_item_to_list(value, &printers, TRUE);
-    return 0;
-}
-
 static int referer_with_query_fun(char *value)
 {
     if (!strncasecomp(value, "SEND", 4))
@@ -1268,6 +1264,10 @@ static Config_Type Config_Table [] =
      PARSE_SET(RC_BOLD_H1,              bold_H1),
      PARSE_SET(RC_BOLD_HEADERS,         bold_headers),
      PARSE_SET(RC_BOLD_NAME_ANCHORS,    bold_name_anchors),
+#ifndef DISABLE_FTP
+     PARSE_LST(RC_BROKEN_FTP_EPSV,      broken_ftp_epsv),
+     PARSE_LST(RC_BROKEN_FTP_RETR,      broken_ftp_retr),
+#endif
      PARSE_PRG(RC_BZIP2_PATH,           ppBZIP2),
      PARSE_SET(RC_CASE_SENSITIVE_ALWAYS_ON, case_sensitive),
      PARSE_FUN(RC_CHARACTER_SET,        character_set_fun),
@@ -1343,7 +1343,9 @@ static Config_Type Config_Table [] =
 #if !defined(NO_OPTION_FORMS) && !defined(NO_OPTION_MENU)
      PARSE_SET(RC_FORMS_OPTIONS,        LYUseFormsOptions),
 #endif
+#ifndef DISABLE_FTP
      PARSE_SET(RC_FTP_PASSIVE,          ftp_passive),
+#endif
      PARSE_Env(RC_FTP_PROXY,            0),
      PARSE_STR(RC_GLOBAL_EXTENSION_MAP, global_extension_map),
      PARSE_STR(RC_GLOBAL_MAILCAP,       global_type_map),
@@ -1465,7 +1467,7 @@ static Config_Type Config_Table [] =
      PARSE_FUN(RC_PRETTYSRC_SPEC,       psrcspec_fun),
      PARSE_SET(RC_PRETTYSRC_VIEW_NO_ANCHOR_NUM, psrcview_no_anchor_numbering),
 #endif
-     PARSE_FUN(RC_PRINTER,              printer_fun),
+     PARSE_ADD(RC_PRINTER,              printers),
      PARSE_SET(RC_QUIT_DEFAULT_YES,     LYQuitDefaultYes),
      PARSE_FUN(RC_REFERER_WITH_QUERY,   referer_with_query_fun),
 #ifdef EXP_CMD_LOGGING
@@ -1770,7 +1772,19 @@ void LYSetConfigValue(char *name,
 	break;
     case CONF_ADD_ITEM:
 	if (q->add_value != 0)
-	    add_item_to_list(value, q->add_value, FALSE);
+	    add_item_to_list(value, q->add_value, (q->add_value == &printers));
+	break;
+
+    case CONF_ADD_STRING:
+	if (*(q->lst_value) == NULL) {
+	    *(q->lst_value) = HTList_new();
+	}
+	if (q->lst_value != 0) {
+	    char *my_value = NULL;
+
+	    StrAllocCopy(my_value, value);
+	    HTList_appendObject(*(q->lst_value), my_value);
+	}
 	break;
 
 #if defined(EXEC_LINKS) || defined(LYNXCGI_LINKS)
@@ -1924,6 +1938,7 @@ static void do_read_cfg(const char *cfg_filename,
 	case CONF_ENV2:
 	case CONF_PRG:
 	case CONF_ADD_ITEM:
+	case CONF_ADD_STRING:
 	case CONF_ADD_TRUSTED:
 	    LYSetConfigValue(name, value);
 	    break;
diff --git a/src/LYStructs.h b/src/LYStructs.h
index 4a030ab7..bfc446a7 100644
--- a/src/LYStructs.h
+++ b/src/LYStructs.h
@@ -140,7 +140,8 @@ extern "C" {
 	int *     int_value; \
 	char **   str_value; \
 	ParseFunc fun_value; \
-	long	  def_value
+	long	  def_value; \
+	HTList**  lst_value
 
     typedef union {
 	ParseUnionMembers;
@@ -150,13 +151,14 @@ extern "C" {
 #define ParseUnionPtr Config_Type *
 #define ParseUnionOf(tbl) tbl
 #define ParseData ParseUnionMembers
-#define UNION_ADD(v) &v,  0,  0,  0,  0,  0
-#define UNION_SET(v)  0, &v,  0,  0,  0,  0
-#define UNION_INT(v)  0,  0, &v,  0,  0,  0
-#define UNION_STR(v)  0,  0,  0, &v,  0,  0
-#define UNION_ENV(v)  0,  0,  0,  v,  0,  0
-#define UNION_FUN(v)  0,  0,  0,  0,  v,  0
-#define UNION_DEF(v)  0,  0,  0,  0,  0,  v
+#define UNION_ADD(v) &v,  0,  0,  0,  0,  0,  0
+#define UNION_SET(v)  0, &v,  0,  0,  0,  0,  0
+#define UNION_INT(v)  0,  0, &v,  0,  0,  0,  0
+#define UNION_STR(v)  0,  0,  0, &v,  0,  0,  0
+#define UNION_ENV(v)  0,  0,  0,  v,  0,  0,  0
+#define UNION_FUN(v)  0,  0,  0,  0,  v,  0,  0
+#define UNION_DEF(v)  0,  0,  0,  0,  0,  v,  0
+#define UNION_LST(v)  0,  0,  0,  0,  0,  0, &v
 #else
 #define ParseUnionPtr ParseUnion *
 #define ParseUnionOf(tbl) (ParseUnionPtr)(&(tbl->value))
@@ -168,6 +170,7 @@ extern "C" {
 #define UNION_ENV(v) (long) (v)
 #define UNION_FUN(v) (long) (v)
 #define UNION_DEF(v) (long) (v)
+#define UNION_LST(v) (long)&(v)
 #endif
 
 #ifdef __cplusplus
diff --git a/src/LYUtils.c b/src/LYUtils.c
index 8d5cca02..190f1a7f 100644
--- a/src/LYUtils.c
+++ b/src/LYUtils.c
@@ -5876,14 +5876,16 @@ static BOOL IsOurSymlink(const char *name)
 {
     BOOL result = FALSE;
     int size = LY_MAXPATH;
+    int used;
     char *buffer = malloc(size);
 
     if (buffer != 0) {
-	while (readlink(name, buffer, size) == -1) {
+	while ((used = readlink(name, buffer, size)) == -1) {
 	    buffer = realloc(buffer, size *= 2);
 	    if (buffer == 0)
 		break;
 	}
+	buffer[used] = '\0';
     }
     if (buffer != 0) {
 	CTRACE2(TRACE_CFG, (tfp, "IsOurSymlink(%s -> %s)\n", name, buffer));
diff --git a/src/LYrcFile.h b/src/LYrcFile.h
index 5da0e1bb..7de4cd78 100644
--- a/src/LYrcFile.h
+++ b/src/LYrcFile.h
@@ -24,6 +24,8 @@
 #define RC_BOLD_HEADERS                 "bold_headers"
 #define RC_BOLD_NAME_ANCHORS            "bold_name_anchors"
 #define RC_BOOKMARK_FILE                "bookmark_file"
+#define RC_BROKEN_FTP_EPSV              "broken_ftp_epsv"
+#define RC_BROKEN_FTP_RETR              "broken_ftp_retr"
 #define RC_BZIP2_PATH                   "bzip2_path"
 #define RC_CASE_SENSITIVE_ALWAYS_ON     "case_sensitive_always_on"
 #define RC_CASE_SENSITIVE_SEARCHING     "case_sensitive_searching"