1 /* $LynxId: LYrcFile.c,v 1.90 2012/11/14 01:06:06 tom Exp $ */
2 #include <HTUtils.h>
3 #include <HTFTP.h>
4 #include <LYUtils.h>
5 #include <LYrcFile.h>
6 #include <LYStrings.h>
7 #include <LYGlobalDefs.h>
8 #include <LYCharSets.h>
9 #include <LYBookmark.h>
10 #include <LYCookie.h>
11 #include <LYKeymap.h>
12 #include <HTMLDTD.h>
13 
14 #include <LYLeaks.h>
15 
16 #define MSG_ENABLE_LYNXRC N_("Normally disabled.  See ENABLE_LYNXRC in lynx.cfg\n")
17 #define putBool(value) ((value) ? "on" : "off")
18 /* *INDENT-OFF* */
19 static Config_Enum tbl_DTD_recovery[] = {
20     { "true",		TRUE },
21     { "false",		FALSE },
22     { "on",		TRUE },
23     { "off",		FALSE },
24     { "sortasgml",	TRUE },
25     { "tagsoup",	FALSE },
26     { NULL,		-1 },
27 };
28 
29 static Config_Enum tbl_bad_html[] = {
30     { "ignore",		BAD_HTML_IGNORE	 },
31     { "trace",		BAD_HTML_TRACE	 },
32     { "message",	BAD_HTML_MESSAGE },
33     { "warn",		BAD_HTML_WARN	 },
34     { NULL,		-1		 }
35 };
36 
37 #ifdef DIRED_SUPPORT
38 static Config_Enum tbl_dir_list_style[] = {
39     { "FILES_FIRST",	FILES_FIRST },
40     { "DIRECTORIES_FIRST", DIRS_FIRST },
41     { "MIXED_STYLE",	MIXED_STYLE },
42     { NULL,		MIXED_STYLE },
43 };
44 #ifdef LONG_LIST
45 static Config_Enum tbl_dir_list_order[] = {
46     { "ORDER_BY_NAME",	ORDER_BY_NAME },
47     { "ORDER_BY_TYPE",	ORDER_BY_TYPE },
48     { "ORDER_BY_SIZE",  ORDER_BY_SIZE },
49     { "ORDER_BY_DATE",	ORDER_BY_DATE },
50     { "ORDER_BY_MODE",	ORDER_BY_MODE },
51 #ifndef NO_GROUPS
52     { "ORDER_BY_USER",	ORDER_BY_USER },
53     { "ORDER_BY_GROUP",	ORDER_BY_GROUP },
54 #endif
55     { NULL,		ORDER_BY_NAME },
56 };
57 #endif /* LONG_LIST */
58 #endif /* DIRED_SUPPORT */
59 
60 static Config_Enum tbl_file_sort[] = {
61     { "BY_FILENAME",	FILE_BY_NAME },
62     { "BY_TYPE",	FILE_BY_TYPE },
63     { "BY_SIZE",	FILE_BY_SIZE },
64     { "BY_DATE",	FILE_BY_DATE },
65     { NULL,		-1 },
66 };
67 
68 Config_Enum tbl_keypad_mode[] = {
69     { "FIELDS_ARE_NUMBERED", FIELDS_ARE_NUMBERED },
70     { "LINKS_AND_FIELDS_ARE_NUMBERED", LINKS_AND_FIELDS_ARE_NUMBERED },
71     { "LINKS_ARE_NUMBERED", LINKS_ARE_NUMBERED },
72     { "LINKS_ARE_NOT_NUMBERED", NUMBERS_AS_ARROWS },
73     /* obsolete variations: */
74     { "LINKS_AND_FORM_FIELDS_ARE_NUMBERED", LINKS_AND_FIELDS_ARE_NUMBERED },
75     { "NUMBERS_AS_ARROWS", NUMBERS_AS_ARROWS },
76     { NULL,		DEFAULT_KEYPAD_MODE }
77 };
78 
79 Config_Enum tbl_multi_bookmarks[] = {
80     { "OFF",		MBM_OFF },
81     { "STANDARD",	MBM_STANDARD },
82     { "ON",		MBM_STANDARD },
83     { "ADVANCED",	MBM_ADVANCED },
84     { NULL,		-1 }
85 };
86 
87 /* the names in this table are used as lowercase in HTTP.c */
88 Config_Enum tbl_preferred_encoding[] = {
89     { "none",		encodingNONE },
90 #if defined(USE_ZLIB) || defined(GZIP_PATH)
91     { "gzip",		encodingGZIP },
92     { "deflate",	encodingDEFLATE },
93 #endif
94 #if defined(USE_ZLIB) || defined(COMPRESS_PATH)
95     { "compress",	encodingCOMPRESS },
96 #endif
97 #if defined(USE_BZLIB) || defined(BZIP2_PATH)
98     { "bzip2",		encodingBZIP2 },
99 #endif
100     { "all",		encodingALL },
101     { NULL,		-1 }
102 };
103 
104 Config_Enum tbl_preferred_media[] = {
105     { "INTERNAL",	mediaOpt1 },
106     { "CONFIGFILE",	mediaOpt2 },
107     { "USER",		mediaOpt3 },
108     { "SYSTEM",		mediaOpt4 },
109     { "ALL",		mediaALL },
110     { NULL,		-1 }
111 };
112 
113 static Config_Enum tbl_show_colors[] = {
114     { "default",	SHOW_COLOR_UNKNOWN },
115     { "default",	SHOW_COLOR_OFF },
116     { "default",	SHOW_COLOR_ON },
117     { "on",		SHOW_COLOR_UNKNOWN },
118     { "off",		SHOW_COLOR_UNKNOWN },
119     { "never",		SHOW_COLOR_NEVER },
120     { "always",		SHOW_COLOR_ALWAYS },
121     { NULL,		SHOW_COLOR_UNKNOWN }
122 };
123 
124 Config_Enum tbl_transfer_rate[] = {
125     { "NONE",		rateOFF },
126     { "KB",		rateKB },
127     { "TRUE",		rateKB },
128     { "BYTES",		rateBYTES },
129     { "FALSE",		rateBYTES },
130 #ifdef USE_READPROGRESS
131     { "KB,ETA",		rateEtaKB },
132     { "BYTES,ETA",	rateEtaBYTES },
133     { "KB2,ETA",	rateEtaKB2 },
134     { "BYTES2,ETA",	rateEtaBYTES2 },
135 #endif
136 #ifdef USE_PROGRESSBAR
137     { "METER",		rateBAR },
138     { "FALSE",		rateBAR },
139 #endif
140     { NULL,		-1 },
141 };
142 
143 Config_Enum tbl_user_mode[] = {
144     { "ADVANCED",	ADVANCED_MODE },
145     { "INTERMEDIATE",	INTERMEDIATE_MODE },
146     { "NOVICE",		NOVICE_MODE },
147     { NULL,		NOVICE_MODE }
148 };
149 
150 static Config_Enum tbl_visited_links[] = {
151     { "FIRST_REVERSED",	VISITED_LINKS_AS_FIRST_V | VISITED_LINKS_REVERSE },
152     { "FIRST",		VISITED_LINKS_AS_FIRST_V },
153     { "TREE",		VISITED_LINKS_AS_TREE    },
154     { "LAST_REVERSED",	VISITED_LINKS_AS_LATEST | VISITED_LINKS_REVERSE },
155     { "LAST",		VISITED_LINKS_AS_LATEST  },
156     { NULL,		DEFAULT_VISITED_LINKS }
157 };
158 
159 Config_Enum tbl_force_prompt[] = {
160     { "prompt",		FORCE_PROMPT_DFT	},
161     { "yes",		FORCE_PROMPT_YES	},
162     { "no",		FORCE_PROMPT_NO		},
163     { NULL,		-1			}
164 };
165 /* *INDENT-ON* */
166 
getBool(char * src)167 static BOOL getBool(char *src)
168 {
169     return (BOOL) (!strncasecomp(src, "on", 2) || !strncasecomp(src, "true", 4));
170 }
171 
LYputEnum(Config_Enum * table,int value)172 const char *LYputEnum(Config_Enum * table, int value)
173 {
174     while (table->name != 0) {
175 	if (table->value == value) {
176 	    return table->name;
177 	}
178 	table++;
179     }
180     return "?";
181 }
182 
LYgetEnum(Config_Enum * table,const char * name,int * result)183 BOOL LYgetEnum(Config_Enum * table, const char *name,
184 	       int *result)
185 {
186     Config_Enum *found = 0;
187     unsigned len = (unsigned) strlen(name);
188     int match = 0;
189 
190     if (len != 0) {
191 	while (table->name != 0) {
192 	    if (!strncasecomp(table->name, name, (int) len)) {
193 		found = table;
194 		if (!strcasecomp(table->name, name)) {
195 		    match = 1;
196 		    break;
197 		}
198 		++match;
199 	    }
200 	    table++;
201 	}
202 	if (match == 1) {	/* if unambiguous */
203 	    *result = found->value;
204 	    return TRUE;
205 	}
206     }
207     return FALSE;		/* no match */
208 }
209 
210 /* these are for data that are normally not read/written from .lynxrc */
211 #define PARSE_SET(n,v,h)   {n,    1, CONF_BOOL,  UNION_SET(v), 0, 0, 0, h}
212 #define PARSE_ARY(n,v,t,h) {n,    1, CONF_ARRAY, UNION_INT(v), t, 0, 0, h}
213 #define PARSE_ENU(n,v,t,h) {n,    1, CONF_ENUM,  UNION_INT(v), 0, t, 0, h}
214 #define PARSE_LIS(n,v,h)   {n,    1, CONF_LIS,   UNION_STR(v), 0, 0, 0, h}
215 #define PARSE_STR(n,v,h)   {n,    1, CONF_STR,   UNION_STR(v), 0, 0, 0, h}
216 #define PARSE_FUN(n,v,w,h) {n,    1, CONF_FUN,   UNION_FUN(v), 0, 0, w, h}
217 #define PARSE_MBM(n,h)     {n,    1, CONF_MBM,   UNION_DEF(0), 0, 0, 0, h}
218 
219 /* these are for data that are optionally read/written from .lynxrc */
220 #define MAYBE_SET(n,v,h)   {n,    0, CONF_BOOL,  UNION_SET(v), 0, 0, 0, h}
221 #define MAYBE_ARY(n,v,t,h) {n,    0, CONF_ARRAY, UNION_INT(v), t, 0, 0, h}
222 #define MAYBE_ENU(n,v,t,h) {n,    0, CONF_ENUM,  UNION_INT(v), 0, t, 0, h}
223 #define MAYBE_LIS(n,v,h)   {n,    0, CONF_LIS,   UNION_STR(v), 0, 0, 0, h}
224 #define MAYBE_STR(n,v,h)   {n,    0, CONF_STR,   UNION_STR(v), 0, 0, 0, h}
225 #define MAYBE_FUN(n,v,w,h) {n,    0, CONF_FUN,   UNION_FUN(v), 0, 0, w, h}
226 #define MAYBE_MBM(n,h)     {n,    0, CONF_MBM,   UNION_DEF(0), 0, 0, 0, h}
227 
228 #define PARSE_NIL          {NULL, 1, CONF_NIL,   UNION_DEF(0), 0, 0, 0, 0}
229 
230 typedef enum {
231     CONF_NIL = 0
232     ,CONF_ARRAY
233     ,CONF_BOOL
234     ,CONF_FUN
235     ,CONF_INT
236     ,CONF_ENUM
237     ,CONF_LIS
238     ,CONF_MBM
239     ,CONF_STR
240 } Conf_Types;
241 
242 typedef struct config_type {
243     const char *name;
244     int enabled;		/* see lynx.cfg ENABLE_LYNXRC "off" lines */
245     Conf_Types type;
246       ParseData;
247     const char **strings;
248     Config_Enum *table;
249     void (*write_it) (FILE *fp, struct config_type *);
250     const char *note;
251 } Config_Type;
252 
get_assume_charset(char * value)253 static int get_assume_charset(char *value)
254 {
255     int i;
256 
257     for (i = 0; i < LYNumCharsets; ++i) {
258 	if (!strcasecomp(value, LYCharSet_UC[i].MIMEname)) {
259 	    UCLYhndl_for_unspec = i;
260 	    break;
261 	}
262     }
263     return 0;
264 }
265 
put_assume_charset(FILE * fp,struct config_type * tbl)266 static void put_assume_charset(FILE *fp, struct config_type *tbl)
267 {
268     int i;
269 
270     for (i = 0; i < LYNumCharsets; ++i)
271 	fprintf(fp, "#    %s\n", LYCharSet_UC[i].MIMEname);
272     fprintf(fp, "%s=%s\n\n", tbl->name, LYCharSet_UC[UCLYhndl_for_unspec].MIMEname);
273 }
274 
get_display_charset(char * value)275 static int get_display_charset(char *value)
276 {
277     int i = 0;
278 
279     i = UCGetLYhndl_byAnyName(value);	/* by MIME or full name */
280     if (i >= 0)
281 	current_char_set = i;
282     return 0;
283 }
284 
put_display_charset(FILE * fp,struct config_type * tbl)285 static void put_display_charset(FILE *fp, struct config_type *tbl)
286 {
287     int i;
288 
289     for (i = 0; LYchar_set_names[i]; i++)
290 	fprintf(fp, "#    %s\n", LYchar_set_names[i]);
291     fprintf(fp, "%s=%s\n\n", tbl->name, LYchar_set_names[current_char_set]);
292 }
293 
get_editor(char * value)294 static int get_editor(char *value)
295 {
296     if (!system_editor)
297 	StrAllocCopy(editor, value);
298     return 0;
299 }
300 
put_editor(FILE * fp,struct config_type * tbl)301 static void put_editor(FILE *fp, struct config_type *tbl)
302 {
303     fprintf(fp, "%s=%s\n\n", tbl->name, NonNull(editor));
304 }
305 
get_tagsoup(char * value)306 int get_tagsoup(char *value)
307 {
308     int found = Old_DTD;
309 
310     if (LYgetEnum(tbl_DTD_recovery, value, &found)
311 	&& Old_DTD != found) {
312 	Old_DTD = found;
313 	HTSwitchDTD(!Old_DTD);
314     }
315     return 0;
316 }
317 
put_tagsoup(FILE * fp,struct config_type * tbl)318 static void put_tagsoup(FILE *fp, struct config_type *tbl)
319 {
320     fprintf(fp, "%s=%s\n\n", tbl->name, LYputEnum(tbl_DTD_recovery, Old_DTD));
321 }
322 
323 /* This table is searched ignoring case */
324 /* *INDENT-OFF* */
325 static Config_Type Config_Table [] =
326 {
327     PARSE_SET(RC_ACCEPT_ALL_COOKIES,    LYAcceptAllCookies, N_("\
328 accept_all_cookies allows the user to tell Lynx to automatically\n\
329 accept all cookies if desired.  The default is \"FALSE\" which will\n\
330 prompt for each cookie.  Set accept_all_cookies to \"TRUE\" to accept\n\
331 all cookies.\n\
332 ")),
333     MAYBE_FUN(RC_ASSUME_CHARSET,        get_assume_charset, put_assume_charset, MSG_ENABLE_LYNXRC),
334 #ifndef DISABLE_FTP
335     PARSE_STR(RC_ANONFTP_PASSWORD,      anonftp_password, N_("\
336 anonftp_password allows the user to tell Lynx to use the personal\n\
337 email address as the password for anonymous ftp.  If no value is given,\n\
338 Lynx will use the personal email address.  Set anonftp_password\n\
339 to a different value if you choose.\n\
340 ")),
341 #endif
342     MAYBE_ENU(RC_BAD_HTML,              cfg_bad_html,      tbl_bad_html,
343 	      MSG_ENABLE_LYNXRC),
344     PARSE_STR(RC_BOOKMARK_FILE,         bookmark_page,     N_("\
345 bookmark_file specifies the name and location of the default bookmark\n\
346 file into which the user can paste links for easy access at a later\n\
347 date.\n\
348 ")),
349     PARSE_SET(RC_CASE_SENSITIVE_SEARCHING, LYcase_sensitive, N_("\
350 If case_sensitive_searching is \"on\" then when the user invokes a search\n\
351 using the 's' or '/' keys, the search performed will be case sensitive\n\
352 instead of case INsensitive.  The default is usually \"off\".\n\
353 ")),
354     PARSE_FUN(RC_CHARACTER_SET,         get_display_charset, put_display_charset, N_("\
355 The character_set definition controls the representation of 8 bit\n\
356 characters for your terminal.  If 8 bit characters do not show up\n\
357 correctly on your screen you may try changing to a different 8 bit\n\
358 set or using the 7 bit character approximations.\n\
359 Current valid characters sets are:\n\
360 ")),
361     PARSE_LIS(RC_COOKIE_ACCEPT_DOMAINS, LYCookieAcceptDomains, N_("\
362 cookie_accept_domains and cookie_reject_domains are comma-delimited\n\
363 lists of domains from which Lynx should automatically accept or reject\n\
364 all cookies.  If a domain is specified in both options, rejection will\n\
365 take precedence.  The accept_all_cookies parameter will override any\n\
366 settings made here.\n\
367 ")),
368 #ifdef USE_PERSISTENT_COOKIES
369     PARSE_STR(RC_COOKIE_FILE,	        LYCookieFile, N_("\
370 cookie_file specifies the file from which to read persistent cookies.\n\
371 The default is ~/" FNAME_LYNX_COOKIES ".\n\
372 ")),
373 #endif
374     PARSE_STR(RC_COOKIE_LOOSE_INVALID_DOMAINS, LYCookieLooseCheckDomains, N_("\
375 cookie_loose_invalid_domains, cookie_strict_invalid_domains, and\n\
376 cookie_query_invalid_domains are comma-delimited lists of which domains\n\
377 should be subjected to varying degrees of validity checking.  If a\n\
378 domain is set to strict checking, strict conformance to RFC2109 will\n\
379 be applied.  A domain with loose checking will be allowed to set cookies\n\
380 with an invalid path or domain attribute.  All domains will default to\n\
381 querying the user for an invalid path or domain.\n\
382 ")),
383     PARSE_STR(RC_COOKIE_QUERY_INVALID_DOMAINS, LYCookieQueryCheckDomains, NULL),
384     PARSE_LIS(RC_COOKIE_REJECT_DOMAINS, LYCookieRejectDomains, NULL),
385     PARSE_STR(RC_COOKIE_STRICT_INVALID_DOMAIN, LYCookieStrictCheckDomains, NULL),
386 #ifdef DIRED_SUPPORT
387 #ifdef LONG_LIST
388     PARSE_ENU(RC_DIR_LIST_ORDER,        dir_list_order,     tbl_dir_list_order, N_("\
389 dir_list_order specifies the directory list order under DIRED_SUPPORT\n\
390 (if implemented).  The default is \"ORDER_BY_NAME\"\n\
391 ")),
392 #endif
393     PARSE_ENU(RC_DIR_LIST_STYLE,        dir_list_style,     tbl_dir_list_style, N_("\
394 dir_list_styles specifies the directory list style under DIRED_SUPPORT\n\
395 (if implemented).  The default is \"MIXED_STYLE\", which sorts both\n\
396 files and directories together.  \"FILES_FIRST\" lists files first and\n\
397 \"DIRECTORIES_FIRST\" lists directories first.\n\
398 ")),
399 #endif
400     MAYBE_STR(RC_DISPLAY,               x_display,          MSG_ENABLE_LYNXRC),
401     PARSE_SET(RC_EMACS_KEYS,            emacs_keys, N_("\
402 If emacs_keys is to \"on\" then the normal EMACS movement keys:\n\
403   ^N = down    ^P = up\n\
404   ^B = left    ^F = right\n\
405 will be enabled.\n\
406 ")),
407     PARSE_FUN(RC_FILE_EDITOR,           get_editor,         put_editor, N_("\
408 file_editor specifies the editor to be invoked when editing local files\n\
409 or sending mail.  If no editor is specified, then file editing is disabled\n\
410 unless it is activated from the command line, and the built-in line editor\n\
411 will be used for sending mail.\n\
412 ")),
413 #ifndef DISABLE_FTP
414     PARSE_ENU(RC_FILE_SORTING_METHOD,   HTfileSortMethod,   tbl_file_sort, N_("\
415 The file_sorting_method specifies which value to sort on when viewing\n\
416 file lists such as FTP directories.  The options are:\n\
417    BY_FILENAME -- sorts on the name of the file\n\
418    BY_TYPE     -- sorts on the type of the file\n\
419    BY_SIZE     -- sorts on the size of the file\n\
420    BY_DATE     -- sorts on the date of the file\n\
421 ")),
422 #endif
423     MAYBE_ENU(RC_FORCE_COOKIE_PROMPT,   cookie_noprompt,    tbl_force_prompt,
424 	      MSG_ENABLE_LYNXRC),
425 #ifdef USE_SSL
426     MAYBE_ENU(RC_FORCE_SSL_PROMPT,      ssl_noprompt,       tbl_force_prompt,
427 	      MSG_ENABLE_LYNXRC),
428 #endif
429 #ifndef DISABLE_FTP
430     MAYBE_SET(RC_FTP_PASSIVE,           ftp_passive,        MSG_ENABLE_LYNXRC),
431 #endif
432     MAYBE_SET(RC_HTML5_CHARSETS,        html5_charsets,     MSG_ENABLE_LYNXRC),
433 #ifdef EXP_KEYBOARD_LAYOUT
434     PARSE_ARY(RC_KBLAYOUT,              current_layout,     LYKbLayoutNames, NULL),
435 #endif
436     PARSE_ENU(RC_KEYPAD_MODE,           keypad_mode,        tbl_keypad_mode, NULL),
437     PARSE_ARY(RC_LINEEDIT_MODE,         current_lineedit,   LYLineeditNames, N_("\
438 lineedit_mode specifies the key binding used for inputting strings in\n\
439 prompts and forms.  If lineedit_mode is set to \"Default Binding\" then\n\
440 the following control characters are used for moving and deleting:\n\
441 \n\
442              Prev  Next       Enter = Accept input\n\
443    Move char: <-    ->        ^G    = Cancel input\n\
444    Move word: ^P    ^N        ^U    = Erase line\n\
445  Delete char: ^H    ^R        ^A    = Beginning of line\n\
446  Delete word: ^B    ^F        ^E    = End of line\n\
447 \n\
448 Current lineedit modes are:\n\
449 ")),
450 #ifdef USE_LOCALE_CHARSET
451     MAYBE_SET(RC_LOCALE_CHARSET,      LYLocaleCharset,        MSG_ENABLE_LYNXRC),
452 #endif
453     MAYBE_SET(RC_MAKE_PSEUDO_ALTS_FOR_INLINES, pseudo_inline_alts, MSG_ENABLE_LYNXRC),
454     MAYBE_SET(RC_MAKE_LINKS_FOR_ALL_IMAGES, clickable_images, MSG_ENABLE_LYNXRC),
455     PARSE_MBM(RC_MULTI_BOOKMARK, N_("\
456 The following allow you to define sub-bookmark files and descriptions.\n\
457 The format is multi_bookmark<capital_letter>=<filename>,<description>\n\
458 Up to 26 bookmark files (for the English capital letters) are allowed.\n\
459 We start with \"multi_bookmarkB\" since 'A' is the default (see above).\n\
460 ")),
461     PARSE_STR(RC_PERSONAL_MAIL_ADDRESS, personal_mail_address, N_("\
462 personal_mail_address specifies your personal mail address.  The\n\
463 address will be sent during HTTP file transfers for authorization and\n\
464 logging purposes, and for mailed comments.\n\
465 If you do not want this information given out, set the NO_FROM_HEADER\n\
466 to TRUE in lynx.cfg, or use the -nofrom command line switch.  You also\n\
467 could leave this field blank, but then you won't have it included in\n\
468 your mailed comments.\n\
469 ")),
470     PARSE_STR(RC_PERSONAL_MAIL_NAME,    personal_mail_name, N_("\
471 personal_mail_name specifies your personal name, for mail.  The\n\
472 name is sent for mailed comments.  Lynx will prompt for this,\n\
473 showing the configured value as a default when sending mail.\n\
474 This is not necessarily the same as a name provided as part of the\n\
475 personal_mail_address.\n\
476 Lynx does not save your changes to that default value as a side-effect\n\
477 of sending email.  To update the default value, you must use the options\n\
478 menu, or modify this file directly.\n\
479 ")),
480     PARSE_STR(RC_PREFERRED_CHARSET,     pref_charset, N_("\
481 preferred_charset specifies the character set in MIME notation (e.g.,\n\
482 ISO-8859-2, ISO-8859-5) which Lynx will indicate you prefer in requests\n\
483 to http servers using an Accept-Charset header.  The value should NOT\n\
484 include ISO-8859-1 or US-ASCII, since those values are always assumed\n\
485 by default.  May be a comma-separated list.\n\
486 If a file in that character set is available, the server will send it.\n\
487 If no Accept-Charset header is present, the default is that any\n\
488 character set is acceptable.  If an Accept-Charset header is present,\n\
489 and if the server cannot send a response which is acceptable\n\
490 according to the Accept-Charset header, then the server SHOULD send\n\
491 an error response, though the sending of an unacceptable response\n\
492 is also allowed.\n\
493 ")),
494     MAYBE_ENU(RC_PREFERRED_ENCODING,    LYAcceptEncoding,   tbl_preferred_encoding,
495 	      MSG_ENABLE_LYNXRC),
496     PARSE_STR(RC_PREFERRED_LANGUAGE,    language, N_("\
497 preferred_language specifies the language in MIME notation (e.g., en,\n\
498 fr, may be a comma-separated list in decreasing preference)\n\
499 which Lynx will indicate you prefer in requests to http servers.\n\
500 If a file in that language is available, the server will send it.\n\
501 Otherwise, the server will send the file in its default language.\n\
502 ")),
503     MAYBE_ENU(RC_PREFERRED_MEDIA_TYPES, LYAcceptMedia,      tbl_preferred_media,
504 	      MSG_ENABLE_LYNXRC),
505     MAYBE_SET(RC_RAW_MODE,              LYRawMode,          MSG_ENABLE_LYNXRC),
506 #if defined(ENABLE_OPTS_CHANGE_EXEC) && (defined(EXEC_LINKS) || defined(EXEC_SCRIPTS))
507     PARSE_SET(RC_RUN_ALL_EXECUTION_LINKS, local_exec, N_("\
508 If run_all_execution_links is set \"on\" then all local execution links\n\
509 will be executed when they are selected.\n\
510 \n\
511 WARNING - This is potentially VERY dangerous.  Since you may view\n\
512           information that is written by unknown and untrusted sources\n\
513           there exists the possibility that Trojan horse links could be\n\
514           written.  Trojan horse links could be written to erase files\n\
515           or compromise security.  This should only be set to \"on\" if\n\
516           you are viewing trusted source information.\n\
517 ")),
518     PARSE_SET(RC_RUN_EXECUTION_LINKS_LOCAL, local_exec_on_local_files, N_("\
519 If run_execution_links_on_local_files is set \"on\" then all local\n\
520 execution links that are found in LOCAL files will be executed when they\n\
521 are selected.  This is different from run_all_execution_links in that\n\
522 only files that reside on the local system will have execution link\n\
523 permissions.\n\
524 \n\
525 WARNING - This is potentially dangerous.  Since you may view\n\
526           information that is written by unknown and untrusted sources\n\
527           there exists the possibility that Trojan horse links could be\n\
528           written.  Trojan horse links could be written to erase files\n\
529           or compromise security.  This should only be set to \"on\" if\n\
530           you are viewing trusted source information.\n\
531 ")),
532 #endif
533 #ifdef USE_SCROLLBAR
534     MAYBE_SET(RC_SCROLLBAR,             LYShowScrollbar, MSG_ENABLE_LYNXRC),
535 #endif
536     PARSE_SET(RC_SELECT_POPUPS,         LYSelectPopups, N_("\
537 select_popups specifies whether the OPTIONs in a SELECT block which\n\
538 lacks a MULTIPLE attribute are presented as a vertical list of radio\n\
539 buttons or via a popup menu.  Note that if the MULTIPLE attribute is\n\
540 present in the SELECT start tag, Lynx always will create a vertical list\n\
541 of checkboxes for the OPTIONs.  A value of \"on\" will set popup menus\n\
542 as the default while a value of \"off\" will set use of radio boxes.\n\
543 The default can be overridden via the -popup command line toggle.\n\
544 ")),
545     MAYBE_SET(RC_SEND_USERAGENT,        LYSendUserAgent,   MSG_ENABLE_LYNXRC),
546     MAYBE_SET(RC_SET_COOKIES,           LYSetCookies,      MSG_ENABLE_LYNXRC),
547     PARSE_ENU(RC_SHOW_COLOR,            LYrcShowColor,     tbl_show_colors, N_("\
548 show_color specifies how to set the color mode at startup.  A value of\n\
549 \"never\" will force color mode off (treat the terminal as monochrome)\n\
550 at startup even if the terminal appears to be color capable.  A value of\n\
551 \"always\" will force color mode on even if the terminal appears to be\n\
552 monochrome, if this is supported by the library used to build lynx.\n\
553 A value of \"default\" will yield the behavior of assuming\n\
554 a monochrome terminal unless color capability is inferred at startup\n\
555 based on the terminal type, or the -color command line switch is used, or\n\
556 the COLORTERM environment variable is set.  The default behavior always is\n\
557 used in anonymous accounts or if the \"option_save\" restriction is set.\n\
558 The effect of the saved value can be overridden via\n\
559 the -color and -nocolor command line switches.\n\
560 The mode set at startup can be changed via the \"show color\" option in\n\
561 the 'o'ptions menu.  If the option settings are saved, the \"on\" and\n\
562 \"off\" \"show color\" settings will be treated as \"default\".\n\
563 ")),
564     PARSE_SET(RC_SHOW_CURSOR,           LYShowCursor, N_("\
565 show_cursor specifies whether to 'hide' the cursor to the right (and\n\
566 bottom, if possible) of the screen, or to place it to the left of the\n\
567 current link in documents, or current option in select popup windows.\n\
568 Positioning the cursor to the left of the current link or option is\n\
569 helpful for speech or braille interfaces, and when the terminal is\n\
570 one which does not distinguish the current link based on highlighting\n\
571 or color.  A value of \"on\" will set positioning to the left as the\n\
572 default while a value of \"off\" will set 'hiding' of the cursor.\n\
573 The default can be overridden via the -show_cursor command line toggle.\n\
574 ")),
575     PARSE_SET(RC_SHOW_DOTFILES,         show_dotfiles, N_("\
576 show_dotfiles specifies that the directory listing should include\n\
577 \"hidden\" (dot) files/directories.  If set \"on\", this will be\n\
578 honored only if enabled via userdefs.h and/or lynx.cfg, and not\n\
579 restricted via a command line switch.  If display of hidden files\n\
580 is disabled, creation of such files via Lynx also is disabled.\n\
581 ")),
582 #ifdef USE_READPROGRESS
583     MAYBE_ENU(RC_SHOW_KB_RATE,          LYTransferRate,    tbl_transfer_rate,
584 	      MSG_ENABLE_LYNXRC),
585 #endif
586     PARSE_ENU(RC_SUB_BOOKMARKS,         LYMultiBookmarks,  tbl_multi_bookmarks, N_("\
587 If sub_bookmarks is not turned \"off\", and multiple bookmarks have\n\
588 been defined (see below), then all bookmark operations will first\n\
589 prompt the user to select an active sub-bookmark file.  If the default\n\
590 Lynx bookmark_file is defined (see above), it will be used as the\n\
591 default selection.  When this option is set to \"advanced\", and the\n\
592 user mode is advanced, the 'v'iew bookmark command will invoke a\n\
593 statusline prompt instead of the menu seen in novice and intermediate\n\
594 user modes.  When this option is set to \"standard\", the menu will be\n\
595 presented regardless of user mode.\n\
596 ")),
597     MAYBE_FUN(RC_TAGSOUP,               get_tagsoup,        put_tagsoup,
598               MSG_ENABLE_LYNXRC),
599     MAYBE_SET(RC_UNDERLINE_LINKS,       LYUnderlineLinks,   MSG_ENABLE_LYNXRC),
600     PARSE_ENU(RC_USER_MODE,             user_mode,          tbl_user_mode, N_("\
601 user_mode specifies the users level of knowledge with Lynx.  The\n\
602 default is \"NOVICE\" which displays two extra lines of help at the\n\
603 bottom of the screen to aid the user in learning the basic Lynx\n\
604 commands.  Set user_mode to \"INTERMEDIATE\" to turn off the extra info.\n\
605 Use \"ADVANCED\" to see the URL of the currently selected link at the\n\
606 bottom of the screen.\n\
607 ")),
608     MAYBE_STR(RC_USERAGENT,             LYUserAgent,        MSG_ENABLE_LYNXRC),
609     PARSE_SET(RC_VERBOSE_IMAGES,        verbose_img, N_("\
610 If verbose_images is \"on\", lynx will print the name of the image\n\
611 source file in place of [INLINE], [LINK] or [IMAGE]\n\
612 See also VERBOSE_IMAGES in lynx.cfg\n\
613 ")),
614     PARSE_SET(RC_VI_KEYS,               vi_keys, N_("\
615 If vi_keys is set to \"on\", then the normal VI movement keys:\n\
616   j = down    k = up\n\
617   h = left    l = right\n\
618 will be enabled.  These keys are only lower case.\n\
619 Capital 'H', 'J' and 'K will still activate help, jump shortcuts,\n\
620 and the keymap display, respectively.\n\
621 ")),
622     PARSE_ENU(RC_VISITED_LINKS,         Visited_Links_As,   tbl_visited_links, N_("\
623 The visited_links setting controls how Lynx organizes the information\n\
624 in the Visited Links Page.\n\
625 ")),
626 #ifdef USE_SESSIONS
627     MAYBE_SET(RC_AUTO_SESSION,		LYAutoSession,	MSG_ENABLE_LYNXRC),
628     MAYBE_STR(RC_SESSION_FILE,		LYSessionFile,	MSG_ENABLE_LYNXRC),
629 #endif
630     MAYBE_SET(RC_NO_PAUSE,		no_pause,	MSG_ENABLE_LYNXRC),
631 
632     PARSE_NIL
633 };
634 /* *INDENT-ON* */
635 
lookup_config(const char * name)636 static Config_Type *lookup_config(const char *name)
637 {
638     Config_Type *tbl = Config_Table;
639     char ch = (char) TOUPPER(*name);
640 
641     while (tbl->name != 0) {
642 	if (tbl->enabled) {
643 	    char ch1 = tbl->name[0];
644 
645 	    if ((ch == TOUPPER(ch1))
646 		&& (0 == strcasecomp(name, tbl->name)))
647 		break;
648 	}
649 
650 	tbl++;
651     }
652     return tbl;
653 }
654 
LYsetRcValue(const char * name,const char * param)655 BOOL LYsetRcValue(const char *name, const char *param)
656 {
657     char MBM_line[256];
658     char *notes;
659     int n;
660     Config_Type *tbl;
661     ParseUnionPtr q;
662     BOOL changed = TRUE;
663     char *value = NULL;
664 
665     StrAllocCopy(value, param);
666     value = LYSkipBlanks(value);
667     CTRACE2(TRACE_CFG, (tfp, "LYrcFile %s:%s\n", name, value));
668 
669     tbl = lookup_config(name);
670     if (tbl->name == 0) {
671 	const char *special = RC_MULTI_BOOKMARK;
672 
673 	if (!strncasecomp(name, special, (int) strlen(special))) {
674 	    tbl = lookup_config(special);
675 	}
676 	/*
677 	 * lynx ignores unknown keywords.
678 	 * This includes known keywords where there is no ENABLE_LYNXRC.
679 	 */
680 	if (tbl->name == 0) {
681 	    CTRACE((tfp, "LYrcFile: ignored %s=%s\n", name, value));
682 	    return FALSE;
683 	}
684     }
685 
686     q = ParseUnionOf(tbl);
687     switch (tbl->type) {
688     case CONF_BOOL:
689 	if (q->set_value != 0)
690 	    *(q->set_value) = getBool(value);
691 	break;
692 
693     case CONF_FUN:
694 	if (q->fun_value != 0)
695 	    (*(q->fun_value)) (value);
696 	break;
697 
698     case CONF_ARRAY:
699 	for (n = 0; tbl->strings[n] != 0; ++n) {
700 	    if (!strcasecomp(value, tbl->strings[n])) {
701 		*(q->int_value) = n;
702 		break;
703 	    }
704 	}
705 	break;
706 
707     case CONF_ENUM:
708 	if (tbl->table != 0)
709 	    LYgetEnum(tbl->table, value, q->int_value);
710 	break;
711 
712     case CONF_INT:
713 	if (q->int_value != 0) {
714 	    int ival;
715 
716 	    if (1 == sscanf(value, "%d", &ival))
717 		*(q->int_value) = ival;
718 	}
719 	break;
720 
721     case CONF_LIS:
722 	if (q->str_value != 0) {
723 	    if (*(q->str_value) != NULL)
724 		StrAllocCat(*(q->str_value), ",");
725 	    StrAllocCat(*(q->str_value), value);
726 	}
727 	break;
728 
729     case CONF_MBM:
730 	for (n = 1; n <= MBM_V_MAXFILES; n++) {
731 	    sprintf(MBM_line, "multi_bookmark%c", LYindex2MBM(n));
732 
733 	    if (!strcasecomp(name, MBM_line)) {
734 		if ((notes = strchr(value, ',')) != 0) {
735 		    *notes++ = '\0';
736 		    LYTrimTrailing(value);
737 		    notes = LYSkipBlanks(notes);
738 		} else {
739 		    notes = value + strlen(value);
740 		}
741 		StrAllocCopy(MBM_A_subbookmark[n], value);
742 		StrAllocCopy(MBM_A_subdescript[n], notes);
743 		break;
744 	    }
745 	}
746 	break;
747 
748     case CONF_STR:
749 	if (q->str_value != 0)
750 	    StrAllocCopy(*(q->str_value), value);
751 	break;
752 
753     default:
754 	changed = FALSE;
755 	break;
756     }
757     FREE(value);
758 
759     return changed;
760 }
761 
762 /* Read and process user options.  If the passed-in fp is NULL, open the
763  * regular user defaults file for reading, otherwise use fp which has to be a
764  * file open for reading.  - kw
765  */
read_rc(FILE * fp)766 void read_rc(FILE *fp)
767 {
768     char *buffer = NULL;
769     char rcfile[LY_MAXPATH];
770 
771     if (!fp) {
772 	/*
773 	 * Make an RC file name, open it for reading.
774 	 */
775 	LYAddPathToHome(rcfile, sizeof(rcfile), FNAME_LYNXRC);
776 	if ((fp = fopen(rcfile, TXT_R)) == NULL) {
777 	    return;
778 	}
779 	CTRACE((tfp, "read_rc opened %s\n", rcfile));
780     } else {
781 	CTRACE((tfp, "read_rc used passed-in stream\n"));
782     }
783 
784     /*
785      * Process the entries.
786      */
787     while (LYSafeGets(&buffer, fp) != NULL) {
788 	char *name, *value;
789 
790 	/* Most lines in the config file are comment lines.  Weed them out
791 	 * now.  Also, leading whitespace is ok, so trim it.
792 	 */
793 	LYTrimTrailing(buffer);
794 	name = LYSkipBlanks(buffer);
795 	if (ispunct(UCH(*name)) || *name == '\0')
796 	    continue;
797 
798 	/*
799 	 * Parse the "name=value" strings.
800 	 */
801 	if ((value = strchr(name, '=')) == 0) {
802 	    CTRACE((tfp, "LYrcFile: missing '=' %s\n", name));
803 	    continue;
804 	}
805 	*value++ = '\0';
806 	LYTrimTrailing(name);
807 	LYsetRcValue(name, value);
808     }
809 
810     LYCloseInput(fp);
811     LYConfigCookies();		/* update cookie settings, if any */
812 
813 #if defined(USE_SLANG) || defined(COLOR_CURSES)
814     /*
815      * We may override the commandline "-color" option with the .lynxrc file
816      */
817     switch (LYrcShowColor) {
818     case SHOW_COLOR_ALWAYS:
819 	if (LYShowColor != SHOW_COLOR_NEVER)
820 	    LYShowColor = SHOW_COLOR_ALWAYS;
821 	break;
822     case SHOW_COLOR_NEVER:
823 	if (LYShowColor == SHOW_COLOR_ON)
824 	    LYShowColor = SHOW_COLOR_OFF;
825 	break;
826     default:
827 	/* don't override */
828 	break;
829     }
830 #endif
831     set_default_bookmark_page(bookmark_page);
832 }
833 
834 /*
835  * Write a set of comments.  Doing it this way avoids preprocessor problems
836  * with the leading '#', makes it simpler to use gettext.
837  */
write_list(FILE * fp,const char * list)838 static void write_list(FILE *fp, const char *list)
839 {
840     int first = TRUE;
841 
842     while (*list != 0) {
843 	int ch = *list++;
844 
845 	if (first) {
846 	    fputs("# ", fp);
847 	    first = FALSE;
848 	}
849 	if (ch == '\n') {
850 	    first = TRUE;
851 	}
852 	fputc(ch, fp);
853     }
854 }
855 
856 /*
857  * This is too long for some compilers.
858  */
explain_keypad_mode(FILE * fp)859 static void explain_keypad_mode(FILE *fp)
860 {
861     write_list(fp, gettext("\
862 If keypad_mode is set to \"NUMBERS_AS_ARROWS\", then the numbers on\n\
863 your keypad when the numlock is on will act as arrow keys:\n\
864             8 = Up Arrow\n\
865   4 = Left Arrow    6 = Right Arrow\n\
866             2 = Down Arrow\n\
867 and the corresponding keyboard numbers will act as arrow keys,\n\
868 regardless of whether numlock is on.\n\
869 "));
870     write_list(fp, gettext("\
871 If keypad_mode is set to \"LINKS_ARE_NUMBERED\", then numbers will\n\
872 appear next to each link and numbers are used to select links.\n\
873 "));
874     write_list(fp, gettext("\
875 If keypad_mode is set to \"LINKS_AND_FORM_FIELDS_ARE_NUMBERED\", then\n\
876 numbers will appear next to each link and visible form input field.\n\
877 Numbers are used to select links, or to move the \"current link\" to a\n\
878 form input field or button.  In addition, options in popup menus are\n\
879 indexed so that the user may type an option number to select an option in\n\
880 a popup menu, even if the option isn't visible on the screen.  Reference\n\
881 lists and output from the list command also enumerate form inputs.\n\
882 "));
883     write_list(fp, gettext("\
884 NOTE: Some fixed format documents may look disfigured when\n\
885 \"LINKS_ARE_NUMBERED\" or \"LINKS_AND_FORM_FIELDS_ARE_NUMBERED\" are\n\
886 enabled.\n\
887 "));
888 }
889 
890 /* Save user options.  If the passed-in fp is NULL, open the regular user
891  * defaults file for writing, otherwise use fp which has to be a temp file open
892  * for writing.  - kw
893  */
save_rc(FILE * fp)894 int save_rc(FILE *fp)
895 {
896     Config_Type *tbl = Config_Table;
897     char rcfile[LY_MAXPATH];
898     BOOLEAN is_tempfile = (BOOL) (fp != NULL);
899     int n;
900 
901     if (!fp) {
902 	/*
903 	 * Make a name.
904 	 */
905 	LYAddPathToHome(rcfile, sizeof(rcfile), FNAME_LYNXRC);
906 
907 	/*
908 	 * Open the file for write.
909 	 */
910 	if ((fp = LYNewTxtFile(rcfile)) == NULL) {
911 	    return FALSE;
912 	}
913     }
914 
915     write_list(fp, gettext("\
916 Lynx User Defaults File\n\
917 \n\
918 "));
919 
920     /*
921      * We have either the HTML options form, or the older menu, or both.
922      */
923 #ifndef NO_OPTION_FORMS
924     write_list(fp, gettext("\
925 This file contains options saved from the Lynx Options Screen (normally\n\
926 with the 'o' key).  To save options with that screen, you must select the\n\
927 checkbox:\n\
928 "));
929     fprintf(fp, "#\t%s\n", SAVE_OPTIONS);
930     fprintf(fp, "#\n");
931     write_list(fp, gettext("\
932 You must then save the settings using the link on the line above the\n\
933 checkbox:\n\
934 "));
935     fprintf(fp, "#\t%s\n", ACCEPT_CHANGES);
936     fprintf(fp, "#\n");
937 #ifndef NO_OPTION_MENU
938     write_list(fp, gettext("\
939 You may also use the command-line option \"-forms_options\", which displays\n\
940 the simpler Options Menu instead.  Save options with that using the '>' key.\n\
941 \n\
942 "));
943 #endif
944 #else /* we only have old options-menu */
945     write_list(fp, gettext("\
946 This file contains options saved from the Lynx Options Screen (normally\n\
947 with the '>' key).\n\
948 \n\
949 "));
950 #endif
951 
952     write_list(fp, gettext("\
953 There is normally no need to edit this file manually, since the defaults\n\
954 here can be controlled from the Options Screen, and the next time options\n\
955 are saved from the Options Screen this file will be completely rewritten.\n\
956 You have been warned...\n\
957 \n\
958 If you are looking for the general configuration file - it is normally\n\
959 called \"lynx.cfg\".  It has different content and a different format.\n\
960 It is not this file.\n\
961 "));
962     fprintf(fp, "\n");
963 
964     while (tbl->name != 0) {
965 	ParseUnionPtr q = ParseUnionOf(tbl);
966 
967 	if (!tbl->enabled) {
968 	    tbl++;
969 	    continue;
970 	}
971 	if (tbl->note != NULL) {
972 	    write_list(fp, gettext(tbl->note));
973 	} else if (tbl->table == tbl_keypad_mode) {
974 	    explain_keypad_mode(fp);
975 	}
976 
977 	switch (tbl->type) {
978 	case CONF_BOOL:
979 	    fprintf(fp, "%s=%s\n\n", tbl->name, putBool(*(q->set_value)));
980 	    break;
981 
982 	case CONF_FUN:
983 	    if (tbl->write_it != 0)
984 		tbl->write_it(fp, tbl);
985 	    break;
986 
987 	case CONF_ARRAY:
988 	    for (n = 0; tbl->strings[n] != 0; ++n)
989 		fprintf(fp, "#    %s\n", tbl->strings[n]);
990 	    fprintf(fp, "%s=%s\n\n", tbl->name,
991 		    tbl->strings[*(q->int_value)]);
992 	    break;
993 
994 	case CONF_ENUM:
995 	    fprintf(fp, "%s=%s\n\n", tbl->name,
996 		    LYputEnum(tbl->table, *(q->int_value)));
997 	    break;
998 
999 	case CONF_INT:
1000 	    fprintf(fp, "%s=%d\n\n", tbl->name, *(q->int_value));
1001 	    break;
1002 
1003 	case CONF_MBM:
1004 	    for (n = 1; n <= MBM_V_MAXFILES; n++) {
1005 		fprintf(fp, "multi_bookmark%c=", LYindex2MBM(n));
1006 
1007 		fprintf(fp, "%s", NonNull(MBM_A_subbookmark[n]));
1008 		if (MBM_A_subdescript[n] != 0
1009 		    && *MBM_A_subdescript[n] != 0)
1010 		    fprintf(fp, ",%s", MBM_A_subdescript[n]);
1011 		fprintf(fp, "\n");
1012 	    }
1013 	    fprintf(fp, "\n");
1014 	    break;
1015 
1016 	case CONF_LIS:
1017 	    /* FALLTHRU */
1018 	case CONF_STR:
1019 	    fprintf(fp, "%s=%s\n\n", tbl->name,
1020 		    (q->str_value != 0 && *(q->str_value) != 0)
1021 		    ? *(q->str_value)
1022 		    : "");
1023 	    break;
1024 
1025 	case CONF_NIL:
1026 	    break;
1027 	}
1028 	tbl++;
1029     }
1030 
1031     /*
1032      * Close the RC file.
1033      */
1034     if (is_tempfile) {
1035 	LYCloseTempFP(fp);
1036     } else {
1037 	LYCloseOutput(fp);
1038 	HTSYS_purge(rcfile);
1039     }
1040 
1041     return TRUE;
1042 }
1043 
1044 /*
1045  * Returns true if the given name would be saved in .lynxrc
1046  */
will_save_rc(const char * name)1047 BOOL will_save_rc(const char *name)
1048 {
1049     Config_Type *tbl = lookup_config(name);
1050 
1051     return (BOOL) (tbl->name != 0);
1052 }
1053 
enable_lynxrc(char * value)1054 int enable_lynxrc(char *value)
1055 {
1056     Config_Type *tbl;
1057     char *colon = strchr(value, ':');
1058 
1059     if (colon != 0) {
1060 	*colon++ = 0;
1061 	LYTrimLeading(value);
1062 	LYTrimTrailing(value);
1063 
1064 	for (tbl = Config_Table; tbl->name != 0; tbl++) {
1065 	    if (!strcasecomp(value, tbl->name)) {
1066 		tbl->enabled = getBool(colon);
1067 		break;
1068 	    }
1069 	}
1070     }
1071     return 0;
1072 }
1073