1 /*
2  *  Project   : tin - a Usenet reader
3  *  Module    : attrib.c
4  *  Author    : I. Lea
5  *  Created   : 1993-12-01
6  *  Updated   : 2020-04-23
7  *  Notes     : Group attribute routines
8  *
9  * Copyright (c) 1993-2021 Iain Lea <iain@bricbrac.de>
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright notice,
17  *    this list of conditions and the following disclaimer.
18  *
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * 3. Neither the name of the copyright holder nor the names of its
24  *    contributors may be used to endorse or promote products derived from
25  *    this software without specific prior written permission.
26  *
27  * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 
41 #ifndef TIN_H
42 #	include "tin.h"
43 #endif /* !TIN_H */
44 #ifndef VERSION_H
45 #	include "version.h"
46 #endif /* !VERSION_H */
47 #ifndef TCURSES_H
48 #	include "tcurses.h"
49 #endif /* !TCURSES_H */
50 
51 
52 /*
53  * Global file offset for local_attributes_file
54  */
55 int attrib_file_offset;
56 
57 
58 /*
59  * Local prototypes
60  */
61 static void set_attrib(int type, const char *scope, const char *line, void *data);
62 static void set_default_attributes(struct t_attribute *attributes, struct t_attribute *scope, t_bool global);
63 static void set_default_state(struct t_attribute_state *state);
64 #ifdef DEBUG
65 	static void dump_attributes(void);
66 	static void dump_scopes(const char *fname);
67 #	if 0 /* unused */
68 		static void debug_print_filter_attributes(void);
69 #	endif /* 0 */
70 #endif /* DEBUG */
71 
72 
73 /*
74  * Per group attributes. This fills out a basic template of defaults
75  * before the attributes in the current scope are applied.
76  */
77 static void
set_default_attributes(struct t_attribute * attributes,struct t_attribute * scope,t_bool global)78 set_default_attributes(
79 	struct t_attribute *attributes,
80 	struct t_attribute *scope,
81 	t_bool global)
82 {
83 	attributes->global = (global ? TRUE : FALSE);	/* global/group specific */
84 	attributes->maildir = (scope ? scope->maildir : (global ? tinrc.maildir : NULL));
85 	attributes->savedir = (scope ? scope->savedir : (global ? tinrc.savedir : NULL));
86 	attributes->savefile = NULL;
87 	attributes->sigfile = (scope ? scope->sigfile : (global ? tinrc.sigfile : NULL));
88 	attributes->group_format = (scope ? scope->group_format : (global ? tinrc.group_format : NULL));
89 	attributes->thread_format = (scope ? scope->thread_format : (global ? tinrc.thread_format : NULL));
90 	attributes->date_format = (scope ? scope->date_format : (global ? tinrc.date_format : NULL));
91 	attributes->editor_format = (scope ? scope->editor_format : (global ? tinrc.editor_format : NULL));
92 	attributes->organization = (scope ? scope->organization : (global ? (*default_organization ? default_organization : NULL) : NULL));
93 	attributes->followup_to = NULL;
94 	attributes->mailing_list = NULL;
95 	attributes->x_headers = NULL;
96 	attributes->x_body = NULL;
97 	attributes->from = (scope ? scope->from : (global ? tinrc.mail_address : NULL));
98 	attributes->news_quote_format = (scope ? scope->news_quote_format : (global ? tinrc.news_quote_format : NULL));
99 	attributes->quote_chars = (scope ? scope->quote_chars : (global ? tinrc.quote_chars : NULL));
100 	attributes->mime_types_to_save = (scope ? scope->mime_types_to_save : (global ? my_strdup("*/*") : NULL));
101 #ifdef HAVE_ISPELL
102 	attributes->ispell = NULL;
103 #endif /* HAVE_ISPELL */
104 	attributes->quick_kill_scope = (scope ? scope->quick_kill_scope : (global ? (tinrc.default_filter_kill_global ? my_strdup("*") : NULL) : NULL));
105 	attributes->quick_kill_header = tinrc.default_filter_kill_header;
106 	attributes->quick_kill_case = tinrc.default_filter_kill_case;
107 	attributes->quick_kill_expire = tinrc.default_filter_kill_expire;
108 	attributes->quick_select_scope = (scope ? scope->quick_select_scope : (global ? (tinrc.default_filter_select_global ? my_strdup("*") : NULL) : NULL));
109 	attributes->quick_select_header = tinrc.default_filter_select_header;
110 	attributes->quick_select_case = tinrc.default_filter_select_case;
111 	attributes->quick_select_expire = tinrc.default_filter_select_expire;
112 	attributes->show_only_unread_arts = tinrc.show_only_unread_arts;
113 	attributes->thread_articles = tinrc.thread_articles;
114 	attributes->thread_catchup_on_exit = tinrc.thread_catchup_on_exit;
115 	attributes->thread_perc = tinrc.thread_perc;
116 	attributes->sort_article_type = tinrc.sort_article_type;
117 	attributes->sort_threads_type = tinrc.sort_threads_type;
118 	attributes->show_author = tinrc.show_author;
119 	attributes->show_signatures = tinrc.show_signatures;
120 	attributes->trim_article_body = tinrc.trim_article_body;
121 	attributes->verbatim_handling = tinrc.verbatim_handling;
122 #ifdef HAVE_COLOR
123 	attributes->extquote_handling = tinrc.extquote_handling;
124 #endif /* HAVE_COLOR */
125 	attributes->wrap_on_next_unread = tinrc.wrap_on_next_unread;
126 	attributes->add_posted_to_filter = tinrc.add_posted_to_filter;
127 	attributes->advertising = tinrc.advertising;
128 	attributes->alternative_handling = tinrc.alternative_handling;
129 	attributes->ask_for_metamail = tinrc.ask_for_metamail;
130 	attributes->auto_cc_bcc = tinrc.auto_cc_bcc;
131 	attributes->auto_list_thread = tinrc.auto_list_thread;
132 	attributes->auto_save = tinrc.auto_save;
133 	attributes->auto_select = FALSE;
134 	attributes->batch_save = tinrc.batch_save;
135 	attributes->delete_tmp_files = FALSE;
136 	attributes->group_catchup_on_exit = tinrc.group_catchup_on_exit;
137 	attributes->mail_8bit_header = tinrc.mail_8bit_header;
138 	attributes->mail_mime_encoding = tinrc.mail_mime_encoding;
139 	attributes->mark_ignore_tags = tinrc.mark_ignore_tags;
140 	attributes->mark_saved_read = tinrc.mark_saved_read;
141 	attributes->news_headers_to_display = (global ? tinrc.news_headers_to_display : NULL);
142 	attributes->headers_to_display = (scope ? (scope->headers_to_display ? scope->headers_to_display : NULL) : NULL);
143 	attributes->news_headers_to_not_display = (global ? tinrc.news_headers_to_not_display : NULL);
144 	attributes->headers_to_not_display = (scope ? (scope->headers_to_not_display ? scope->headers_to_not_display : NULL) : NULL);
145 	attributes->pos_first_unread = tinrc.pos_first_unread;
146 	attributes->post_8bit_header = tinrc.post_8bit_header;
147 	attributes->post_mime_encoding = tinrc.post_mime_encoding;
148 	attributes->post_process_view = tinrc.post_process_view;
149 	attributes->post_process_type = tinrc.post_process_type;
150 #ifndef DISABLE_PRINTING
151 	attributes->print_header = tinrc.print_header;
152 #endif /* !DISABLE_PRINTING */
153 	attributes->process_only_unread = tinrc.process_only_unread;
154 	attributes->prompt_followupto = tinrc.prompt_followupto;
155 	attributes->sigdashes = tinrc.sigdashes;
156 	attributes->signature_repost = tinrc.signature_repost;
157 	attributes->start_editor_offset = tinrc.start_editor_offset;
158 	attributes->x_comment_to = FALSE;
159 	attributes->tex2iso_conv = tinrc.tex2iso_conv;
160 	attributes->mime_forward = FALSE;
161 	attributes->fcc = NULL;
162 #ifdef CHARSET_CONVERSION
163 	attributes->mm_network_charset = tinrc.mm_network_charset;
164 	attributes->undeclared_charset = NULL;
165 #endif /* CHARSET_CONVERSION */
166 }
167 
168 
169 static void
set_default_state(struct t_attribute_state * state)170 set_default_state(
171 	struct t_attribute_state *state)
172 {
173 	state->add_posted_to_filter = FALSE;
174 	state->advertising = FALSE;
175 	state->alternative_handling = FALSE;
176 	state->ask_for_metamail = FALSE;
177 	state->auto_cc_bcc = FALSE;
178 	state->auto_list_thread = FALSE;
179 	state->auto_save = FALSE;
180 	state->auto_select = FALSE;
181 	state->batch_save = FALSE;
182 	state->date_format = FALSE;
183 	state->delete_tmp_files = FALSE;
184 	state->editor_format = FALSE;
185 	state->fcc = FALSE;
186 	state->followup_to = FALSE;
187 	state->from = FALSE;
188 	state->group_catchup_on_exit = FALSE;
189 	state->group_format = FALSE;
190 #ifdef HAVE_ISPELL
191 	state->ispell = FALSE;
192 #endif /* HAVE_ISPELL */
193 	state->mail_8bit_header = FALSE;
194 	state->mail_mime_encoding = FALSE;
195 	state->maildir = FALSE;
196 	state->mailing_list = FALSE;
197 	state->mark_ignore_tags = FALSE;
198 	state->mark_saved_read = FALSE;
199 	state->mime_forward = FALSE;
200 	state->mime_types_to_save = FALSE;
201 	state->news_headers_to_display = FALSE;
202 	state->news_headers_to_not_display = FALSE;
203 	state->news_quote_format = FALSE;
204 	state->organization = FALSE;
205 	state->pos_first_unread = FALSE;
206 	state->post_8bit_header = FALSE;
207 	state->post_mime_encoding = FALSE;
208 	state->post_process_type = FALSE;
209 	state->post_process_view = FALSE;
210 #ifndef DISABLE_PRINTING
211 	state->print_header = FALSE;
212 #endif /* !DISABLE_PRINTING */
213 	state->process_only_unread = FALSE;
214 	state->prompt_followupto = FALSE;
215 	state->quick_kill_case = FALSE;
216 	state->quick_kill_expire = FALSE;
217 	state->quick_kill_header = FALSE;
218 	state->quick_kill_scope = FALSE;
219 	state->quick_select_case = FALSE;
220 	state->quick_select_expire = FALSE;
221 	state->quick_select_header = FALSE;
222 	state->quick_select_scope = FALSE;
223 	state->quote_chars = FALSE;
224 	state->savedir = FALSE;
225 	state->savefile = FALSE;
226 	state->show_author = FALSE;
227 	state->show_only_unread_arts = FALSE;
228 	state->show_signatures = FALSE;
229 	state->sigdashes = FALSE;
230 	state->sigfile = FALSE;
231 	state->signature_repost = FALSE;
232 	state->sort_article_type = FALSE;
233 	state->sort_threads_type = FALSE;
234 	state->start_editor_offset = FALSE;
235 	state->tex2iso_conv = FALSE;
236 	state->thread_articles = FALSE;
237 	state->thread_catchup_on_exit = FALSE;
238 	state->thread_format = FALSE;
239 	state->thread_perc = FALSE;
240 	state->trim_article_body = FALSE;
241 #ifdef CHARSET_CONVERSION
242 	state->undeclared_charset = FALSE;
243 	state->mm_network_charset = FALSE;
244 #endif /* CHARSET_CONVERSION */
245 	state->verbatim_handling = FALSE;
246 #ifdef HAVE_COLOR
247 	state->extquote_handling = FALSE;
248 #endif /* HAVE_COLOR */
249 	state->wrap_on_next_unread = FALSE;
250 	state->x_body = FALSE;
251 	state->x_comment_to = FALSE;
252 	state->x_headers = FALSE;
253 }
254 
255 
256 #define MATCH_BOOLEAN(pattern, type) \
257 	if (match_boolean(line, pattern, &flag)) { \
258 		num = (flag != FALSE); \
259 		set_attrib(type, scope, line, &num); \
260 		found = TRUE; \
261 		break; \
262 	}
263 #define MATCH_INTEGER(pattern, type, maxval) \
264 	if (match_integer(line, pattern, &num, maxval)) { \
265 		set_attrib(type, scope, line, &num); \
266 		found = TRUE; \
267 		break; \
268 	}
269 #define MATCH_STRING(pattern, type) \
270 	if (match_string(line, pattern, buf, sizeof(buf) - strlen(pattern))) { \
271 		set_attrib(type, scope, line, buf); \
272 		found = TRUE; \
273 		break; \
274 	}
275 #define MATCH_LIST(pattern, type, table) \
276 	if (match_list(line, pattern, table, &num)) { \
277 		set_attrib(type, scope, line, &num); \
278 		found = TRUE; \
279 		break; \
280 	}
281 #if !defined(CHARSET_CONVERSION) || !defined(HAVE_ISPELL) || defined(DISABLE_PRINTING)
282 #	define SKIP_ITEM(pattern) \
283 		if (!strncmp(line, pattern, strlen(pattern))) { \
284 			found = TRUE; \
285 			break; \
286 		}
287 #endif /* !CHARSET_CONVERSION || !HAVE_ISPELL || DISABLE_PRINTING */
288 
289 
290 /*
291  * read global/local attributes file
292  */
293 void
read_attributes_file(t_bool global_file)294 read_attributes_file(
295 	t_bool global_file)
296 {
297 	FILE *fp;
298 	char *file;
299 	char buf[LEN];
300 	char line[LEN];
301 	char scope[LEN];
302 	int i, num;
303 	struct t_version *upgrade = NULL;
304 	static t_bool startup = TRUE;
305 	t_bool flag, found = FALSE;
306 
307 	if (!batch_mode || verbose)
308 		wait_message(0, _(txt_reading_attributes_file), (global_file ? _(txt_global) : ""));
309 	/*
310 	 * Initialize global attributes even if there is no global file
311 	 * These setting are used as the default for all groups unless overridden
312 	 */
313 	if (global_file) {
314 		i = add_scope("_default_");
315 		scopes[i].global = TRUE;
316 		set_default_attributes(scopes[i].attribute, NULL, TRUE);
317 		build_news_headers_array(scopes[i].attribute, TRUE);
318 		build_news_headers_array(scopes[i].attribute, FALSE);
319 		file = global_attributes_file;
320 	} else {
321 		attrib_file_offset = 1;
322 		file = local_attributes_file;
323 	}
324 
325 	if ((fp = fopen(file, "r")) != NULL) {
326 		scope[0] = '\0';
327 		/*
328 		 * TODO: use tin_fgets() instead to handle long lines
329 		 * (e.g. buggy translation)
330 		 */
331 		while (fgets(line, (int) sizeof(line), fp) != NULL) {
332 			if (line[0] == '\n')
333 				continue;
334 			if (line[0] == '#') {
335 				if (!global_file) {
336 					if (scope[0] == '\0')
337 						attrib_file_offset++;
338 					if (startup && upgrade == NULL && match_string(line, "# Group attributes file V", NULL, 0)) {
339 						upgrade = check_upgrade(line, "# Group attributes file V", ATTRIBUTES_VERSION);
340 						if (upgrade->state != RC_IGNORE)
341 							upgrade_prompt_quit(upgrade, file); /* TODO: do something (more) useful here */
342 					}
343 				}
344 				continue;
345 			}
346 
347 			switch (my_tolower((unsigned char) line[0])) {
348 				case 'a':
349 					MATCH_BOOLEAN("add_posted_to_filter=", OPT_ATTRIB_ADD_POSTED_TO_FILTER);
350 					MATCH_BOOLEAN("advertising=", OPT_ATTRIB_ADVERTISING);
351 					MATCH_BOOLEAN("alternative_handling=", OPT_ATTRIB_ALTERNATIVE_HANDLING);
352 					MATCH_BOOLEAN("ask_for_metamail=", OPT_ATTRIB_ASK_FOR_METAMAIL);
353 					MATCH_INTEGER("auto_cc_bcc=", OPT_ATTRIB_AUTO_CC_BCC, AUTO_CC_BCC);
354 					MATCH_BOOLEAN("auto_list_thread=", OPT_ATTRIB_AUTO_LIST_THREAD);
355 					MATCH_BOOLEAN("auto_save=", OPT_ATTRIB_AUTO_SAVE);
356 					MATCH_BOOLEAN("auto_select=", OPT_ATTRIB_AUTO_SELECT);
357 					break;
358 
359 				case 'b':
360 					MATCH_BOOLEAN("batch_save=", OPT_ATTRIB_BATCH_SAVE);
361 					break;
362 
363 				case 'd':
364 					MATCH_STRING("date_format=", OPT_ATTRIB_DATE_FORMAT);
365 					MATCH_BOOLEAN("delete_tmp_files=", OPT_ATTRIB_DELETE_TMP_FILES);
366 					break;
367 
368 				case 'e':
369 					MATCH_STRING("editor_format=", OPT_ATTRIB_EDITOR_FORMAT);
370 #ifdef HAVE_COLOR
371 					MATCH_BOOLEAN("extquote_handling=", OPT_ATTRIB_EXTQUOTE_HANDLING);
372 #endif /* HAVE_COLOR */
373 
374 					break;
375 
376 				case 'f':
377 					MATCH_STRING("fcc=", OPT_ATTRIB_FCC);
378 					MATCH_STRING("followup_to=", OPT_ATTRIB_FOLLOWUP_TO);
379 					MATCH_STRING("from=", OPT_ATTRIB_FROM);
380 					break;
381 
382 				case 'g':
383 					MATCH_BOOLEAN("group_catchup_on_exit=", OPT_ATTRIB_GROUP_CATCHUP_ON_EXIT);
384 					MATCH_STRING("group_format=", OPT_ATTRIB_GROUP_FORMAT);
385 					break;
386 
387 				case 'i':
388 #ifdef HAVE_ISPELL
389 					MATCH_STRING("ispell=", OPT_ATTRIB_ISPELL);
390 #else
391 					SKIP_ITEM("ispell=");
392 #endif /* HAVE_ISPELL */
393 					break;
394 
395 				case 'm':
396 					MATCH_BOOLEAN("mail_8bit_header=", OPT_ATTRIB_MAIL_8BIT_HEADER);
397 					MATCH_LIST("mail_mime_encoding=", OPT_ATTRIB_MAIL_MIME_ENCODING, txt_mime_encodings);
398 					MATCH_STRING("maildir=", OPT_ATTRIB_MAILDIR);
399 					MATCH_STRING("mailing_list=", OPT_ATTRIB_MAILING_LIST);
400 					MATCH_BOOLEAN("mark_ignore_tags=", OPT_ATTRIB_MARK_IGNORE_TAGS);
401 					MATCH_BOOLEAN("mark_saved_read=", OPT_ATTRIB_MARK_SAVED_READ);
402 					MATCH_BOOLEAN("mime_forward=", OPT_ATTRIB_MIME_FORWARD);
403 					MATCH_STRING("mime_types_to_save=", OPT_ATTRIB_MIME_TYPES_TO_SAVE);
404 #ifdef CHARSET_CONVERSION
405 					MATCH_LIST("mm_network_charset=", OPT_ATTRIB_MM_NETWORK_CHARSET, txt_mime_charsets);
406 #else
407 					SKIP_ITEM("mm_network_charset=");
408 #endif /* CHARSET_CONVERSION */
409 					break;
410 
411 				case 'n':
412 					MATCH_STRING("news_headers_to_display=", OPT_ATTRIB_NEWS_HEADERS_TO_DISPLAY);
413 					MATCH_STRING("news_headers_to_not_display=", OPT_ATTRIB_NEWS_HEADERS_TO_NOT_DISPLAY);
414 					MATCH_STRING("news_quote_format=", OPT_ATTRIB_NEWS_QUOTE_FORMAT);
415 					break;
416 
417 				case 'o':
418 					MATCH_STRING("organization=", OPT_ATTRIB_ORGANIZATION);
419 					break;
420 
421 				case 'p':
422 					MATCH_BOOLEAN("pos_first_unread=", OPT_ATTRIB_POS_FIRST_UNREAD);
423 					MATCH_BOOLEAN("post_8bit_header=", OPT_ATTRIB_POST_8BIT_HEADER);
424 					MATCH_LIST("post_mime_encoding=", OPT_ATTRIB_POST_MIME_ENCODING, txt_mime_encodings);
425 					MATCH_BOOLEAN("post_process_view=", OPT_ATTRIB_POST_PROCESS_VIEW);
426 					MATCH_INTEGER("post_process_type=", OPT_ATTRIB_POST_PROCESS_TYPE, POST_PROC_YES);
427 #ifndef DISABLE_PRINTING
428 					MATCH_BOOLEAN("print_header=", OPT_ATTRIB_PRINT_HEADER);
429 #else
430 					SKIP_ITEM("print_header=");
431 #endif /* !DISABLE_PRINTING */
432 					MATCH_BOOLEAN("process_only_unread=", OPT_ATTRIB_PROCESS_ONLY_UNREAD);
433 					MATCH_BOOLEAN("prompt_followupto=", OPT_ATTRIB_PROMPT_FOLLOWUPTO);
434 					break;
435 
436 				case 'q':
437 					MATCH_BOOLEAN("quick_kill_case=", OPT_ATTRIB_QUICK_KILL_CASE);
438 					MATCH_BOOLEAN("quick_kill_expire=", OPT_ATTRIB_QUICK_KILL_EXPIRE);
439 					MATCH_INTEGER("quick_kill_header=", OPT_ATTRIB_QUICK_KILL_HEADER, FILTER_LINES);
440 					MATCH_STRING("quick_kill_scope=", OPT_ATTRIB_QUICK_KILL_SCOPE);
441 					MATCH_BOOLEAN("quick_select_case=", OPT_ATTRIB_QUICK_SELECT_CASE);
442 					MATCH_BOOLEAN("quick_select_expire=", OPT_ATTRIB_QUICK_SELECT_EXPIRE);
443 					MATCH_INTEGER("quick_select_header=", OPT_ATTRIB_QUICK_SELECT_HEADER, FILTER_LINES);
444 					MATCH_STRING("quick_select_scope=", OPT_ATTRIB_QUICK_SELECT_SCOPE);
445 					if (match_string(line, "quote_chars=", buf, sizeof(buf))) {
446 						if (upgrade && upgrade->file_version < 10010) { /* %s/%S changed to %I */
447 							char *q = buf;
448 
449 							while (*q) {
450 								if (*q == '%' && (*(q + 1) == 's' || *(q + 1) == 'S'))
451 									*(++q) = 'I';
452 
453 								q++;
454 							}
455 						}
456 						quote_dash_to_space(buf);
457 						set_attrib(OPT_ATTRIB_QUOTE_CHARS, scope, line, buf);
458 						found = TRUE;
459 						break;
460 					}
461 					break;
462 
463 				case 's':
464 					MATCH_STRING("savedir=", OPT_ATTRIB_SAVEDIR);
465 					MATCH_STRING("savefile=", OPT_ATTRIB_SAVEFILE);
466 					if (match_string(line, "scope=", scope, sizeof(scope))) {
467 						i = add_scope(scope);
468 						scopes[i].global = global_file ? TRUE : FALSE;
469 						found = TRUE;
470 						break;
471 					}
472 					MATCH_INTEGER("show_author=", OPT_ATTRIB_SHOW_AUTHOR, SHOW_FROM_BOTH);
473 					MATCH_BOOLEAN("show_only_unread_arts=", OPT_ATTRIB_SHOW_ONLY_UNREAD_ARTS);
474 					MATCH_BOOLEAN("show_signatures=", OPT_ATTRIB_SHOW_SIGNATURES);
475 					MATCH_BOOLEAN("sigdashes=", OPT_ATTRIB_SIGDASHES);
476 					MATCH_BOOLEAN("signature_repost=", OPT_ATTRIB_SIGNATURE_REPOST);
477 					MATCH_BOOLEAN("start_editor_offset=", OPT_ATTRIB_START_EDITOR_OFFSET);
478 					MATCH_STRING("sigfile=", OPT_ATTRIB_SIGFILE);
479 					MATCH_INTEGER("sort_article_type=", OPT_ATTRIB_SORT_ARTICLE_TYPE, SORT_ARTICLES_BY_LINES_ASCEND);
480 					MATCH_INTEGER("sort_threads_type=", OPT_ATTRIB_SORT_THREADS_TYPE, SORT_THREADS_BY_LAST_POSTING_DATE_ASCEND);
481 					break;
482 
483 				case 't':
484 					MATCH_BOOLEAN("tex2iso_conv=", OPT_ATTRIB_TEX2ISO_CONV);
485 					MATCH_INTEGER("thread_articles=", OPT_ATTRIB_THREAD_ARTICLES, THREAD_MAX);
486 					MATCH_BOOLEAN("thread_catchup_on_exit=", OPT_ATTRIB_THREAD_CATCHUP_ON_EXIT);
487 					MATCH_STRING("thread_format=", OPT_ATTRIB_THREAD_FORMAT);
488 					MATCH_INTEGER("thread_perc=", OPT_ATTRIB_THREAD_PERC, 100);
489 					MATCH_INTEGER("trim_article_body=", OPT_ATTRIB_TRIM_ARTICLE_BODY, 7);
490 					break;
491 
492 				case 'u':
493 #ifdef CHARSET_CONVERSION
494 					MATCH_STRING("undeclared_charset=", OPT_ATTRIB_UNDECLARED_CHARSET);
495 #else
496 					SKIP_ITEM("undeclared_charset=");
497 #endif /* CHARSET_CONVERSION */
498 					break;
499 
500 				case 'v':
501 					MATCH_BOOLEAN("verbatim_handling=", OPT_ATTRIB_VERBATIM_HANDLING);
502 					break;
503 
504 				case 'w':
505 					MATCH_BOOLEAN("wrap_on_next_unread=", OPT_ATTRIB_WRAP_ON_NEXT_UNREAD);
506 					break;
507 
508 				case 'x':
509 					MATCH_STRING("x_body=", OPT_ATTRIB_X_BODY);
510 					MATCH_BOOLEAN("x_comment_to=", OPT_ATTRIB_X_COMMENT_TO);
511 					MATCH_STRING("x_headers=", OPT_ATTRIB_X_HEADERS);
512 					break;
513 
514 				default:
515 					break;
516 			}
517 
518 			if (!global_file && upgrade && upgrade->state == RC_UPGRADE) {
519 				int auto_cc_bcc;
520 				int show_info;
521 				t_bool auto_bcc = FALSE;
522 				t_bool auto_cc = FALSE;
523 
524 				switch (my_tolower((unsigned char) line[0])) {
525 					case 'a':
526 						if (match_boolean(line, "auto_bcc=", &auto_bcc)) {
527 							if (scopes[num_scope - 1].attribute->auto_cc_bcc & AUTO_CC)
528 								auto_cc_bcc = (auto_bcc ? AUTO_CC_BCC : AUTO_CC);
529 							else
530 								auto_cc_bcc = (auto_bcc ? AUTO_BCC : 0);
531 							set_attrib(OPT_ATTRIB_AUTO_CC_BCC, scope, line, &auto_cc_bcc);
532 							found = TRUE;
533 							break;
534 						}
535 						if (match_boolean(line, "auto_cc=", &auto_cc)) {
536 							if (scopes[num_scope - 1].attribute->auto_cc_bcc & AUTO_BCC)
537 								auto_cc_bcc = (auto_cc ? AUTO_CC_BCC : AUTO_BCC);
538 							else
539 								auto_cc_bcc = (auto_cc ? AUTO_CC : 0);
540 							set_attrib(OPT_ATTRIB_AUTO_CC_BCC, scope, line, &auto_cc_bcc);
541 							found = TRUE;
542 							break;
543 						}
544 						break;
545 
546 					case 'p':
547 						MATCH_INTEGER("post_proc_type=", OPT_ATTRIB_POST_PROCESS_TYPE, POST_PROC_YES);
548 						break;
549 
550 					case 's':
551 						if (match_integer(line, "show_info=", &show_info, 3)) {
552 							char *gbuf = my_malloc(23);
553 							char *tbuf = my_malloc(23);
554 
555 							switch (show_info) {
556 								case 0:
557 									strcpy(gbuf, "%n %m %R  %s  %F");
558 									strcpy(tbuf, "%n %m  %T  %F");
559 									break;
560 
561 								case 2:
562 									strcpy(gbuf, "%n %m %R %S  %s  %F");
563 									strcpy(tbuf, "%n %m  [%S]  %T  %F");
564 									break;
565 
566 								case 3:
567 									strcpy(gbuf, "%n %m %R %L %S  %s  %F");
568 									strcpy(tbuf, "%n %m  [%L,%S]  %T  %F");
569 									break;
570 
571 								default:
572 									strcpy(gbuf, DEFAULT_GROUP_FORMAT);
573 									strcpy(tbuf, DEFAULT_THREAD_FORMAT);
574 									break;
575 							}
576 							set_attrib(OPT_ATTRIB_GROUP_FORMAT, scope, line, gbuf);
577 							set_attrib(OPT_ATTRIB_THREAD_FORMAT, scope, line, tbuf);
578 							free(gbuf);
579 							free(tbuf);
580 							found = TRUE;
581 							break;
582 						}
583 						/*
584 						 * previous versions has always passed groupname to external
585 						 * commands, now we look for %G
586 						 *
587 						 * 8 == sizeof("sigfile=")
588 						 */
589 						if (match_string(line, "sigfile=", buf, sizeof(buf) - 8) && buf[0] == '!') {
590 							/* just append %G if ATTRIBUTES_VERSION <= 1.0.8 */
591 							if (upgrade && upgrade->file_version < 10009) {
592 								char *newbuf = my_malloc(sizeof(buf) - 8 + 4);
593 
594 								sprintf(newbuf, "%s %s", buf, "%G");
595 								set_attrib(OPT_ATTRIB_SIGFILE, scope, line, newbuf);
596 								free(newbuf);
597 							}
598 							break;
599 						}
600 						MATCH_BOOLEAN("show_only_unread=", OPT_ATTRIB_SHOW_ONLY_UNREAD_ARTS);
601 						MATCH_INTEGER("sort_art_type=", OPT_ATTRIB_SORT_ARTICLE_TYPE, SORT_ARTICLES_BY_LINES_ASCEND);
602 						break;
603 
604 					case 't':
605 						MATCH_INTEGER("thread_arts=", OPT_ATTRIB_THREAD_ARTICLES, THREAD_MAX);
606 						break;
607 
608 					default:
609 						break;
610 				}
611 			}
612 
613 			if (found)
614 				found = FALSE;
615 			else {
616 				/* TODO: even without DEBUG? */
617 				error_message(1, _(txt_bad_attrib), line);
618 #ifdef DEBUG
619 				if (debug & (DEBUG_ATTRIB))
620 					debug_print_file("ATTRIBUTES", txt_bad_attrib, line);
621 #endif /* DEBUG */
622 			}
623 		}
624 		fclose(fp);
625 
626 		/*
627 		 * TODO: do something useful for the other cases
628 		 */
629 		if (!global_file && upgrade && upgrade->state == RC_UPGRADE)
630 			write_attributes_file(file);
631 
632 		FreeAndNull(upgrade);
633 
634 	} else if (!global_file && startup) {
635 		/* no local attributes file, add some useful defaults and write file */
636 
637 		add_scope("*");
638 		snprintf(buf, sizeof(buf), "%s", "~/.tin/headers");
639 		set_attrib(OPT_ATTRIB_X_HEADERS, "*", "", buf);
640 
641 		add_scope("*sources*");
642 		num = POST_PROC_SHAR;
643 		set_attrib(OPT_ATTRIB_POST_PROCESS_TYPE, "*sources*", "", &num);
644 
645 		add_scope("*binaries*");
646 		num = POST_PROC_YES;
647 		set_attrib(OPT_ATTRIB_POST_PROCESS_TYPE, "*binaries*", "", &num);
648 		num = FALSE;
649 		set_attrib(OPT_ATTRIB_TEX2ISO_CONV, "*binaries*", "", &num);
650 		num = TRUE;
651 		set_attrib(OPT_ATTRIB_DELETE_TMP_FILES, "*binaries*", "", &num);
652 		snprintf(buf, sizeof(buf), "%s", "poster");
653 		set_attrib(OPT_ATTRIB_FOLLOWUP_TO, "*binaries*", "", buf);
654 
655 		write_attributes_file(file);
656 	}
657 	if (!global_file && startup)
658 		startup = FALSE;
659 #ifdef DEBUG
660 	if (!global_file)
661 		dump_scopes("SCOPES-R");
662 #endif /* DEBUG */
663 }
664 
665 
666 #define SET_STRING(string) \
667 	FreeIfNeeded(curr_scope->attribute->string); \
668 	curr_scope->attribute->string = my_strdup((char *) data); \
669 	curr_scope->state->string = TRUE; \
670 	break
671 #define SET_INTEGER(integer) \
672 	curr_scope->attribute->integer = *((int *) data); \
673 	curr_scope->state->integer = TRUE; \
674 	break
675 
676 
677 static void
set_attrib(int type,const char * scope,const char * line,void * data)678 set_attrib(
679 	int type,
680 	const char *scope,
681 	const char *line,
682 	void *data)
683 {
684 	struct t_scope *curr_scope;
685 
686 	if (scope == NULL || *scope == '\0') {	/* No active scope set yet */
687 		error_message(2, _(txt_attrib_no_scope), line);
688 #ifdef DEBUG
689 		if (debug & DEBUG_ATTRIB)
690 			debug_print_file("ATTRIBUTES", txt_attrib_no_scope, line);
691 #endif /* DEBUG */
692 		return;
693 	}
694 
695 	if (num_scope > 1) {
696 		curr_scope = &scopes[num_scope - 1];
697 		/*
698 		 * Now set the required attribute
699 		 */
700 		switch (type) {
701 			case OPT_ATTRIB_MAILDIR:
702 				SET_STRING(maildir);
703 
704 			case OPT_ATTRIB_SAVEDIR:
705 				SET_STRING(savedir);
706 
707 			case OPT_ATTRIB_SAVEFILE:
708 				SET_STRING(savefile);
709 
710 			case OPT_ATTRIB_ORGANIZATION:
711 				SET_STRING(organization);
712 
713 			case OPT_ATTRIB_FROM:
714 				SET_STRING(from);
715 
716 			case OPT_ATTRIB_SIGFILE:
717 				SET_STRING(sigfile);
718 
719 			case OPT_ATTRIB_FOLLOWUP_TO:
720 				SET_STRING(followup_to);
721 
722 			case OPT_ATTRIB_ADD_POSTED_TO_FILTER:
723 				SET_INTEGER(add_posted_to_filter);
724 
725 			case OPT_ATTRIB_ADVERTISING:
726 				SET_INTEGER(advertising);
727 
728 			case OPT_ATTRIB_ALTERNATIVE_HANDLING:
729 				SET_INTEGER(alternative_handling);
730 
731 			case OPT_ATTRIB_ASK_FOR_METAMAIL:
732 				SET_INTEGER(ask_for_metamail);
733 
734 			case OPT_ATTRIB_AUTO_CC_BCC:
735 				SET_INTEGER(auto_cc_bcc);
736 
737 			case OPT_ATTRIB_AUTO_LIST_THREAD:
738 				SET_INTEGER(auto_list_thread);
739 
740 			case OPT_ATTRIB_AUTO_SELECT:
741 				SET_INTEGER(auto_select);
742 
743 			case OPT_ATTRIB_AUTO_SAVE:
744 				SET_INTEGER(auto_save);
745 
746 			case OPT_ATTRIB_BATCH_SAVE:
747 				SET_INTEGER(batch_save);
748 
749 			case OPT_ATTRIB_DATE_FORMAT:
750 				SET_STRING(date_format);
751 
752 			case OPT_ATTRIB_DELETE_TMP_FILES:
753 				SET_INTEGER(delete_tmp_files);
754 
755 			case OPT_ATTRIB_EDITOR_FORMAT:
756 				SET_STRING(editor_format);
757 
758 			case OPT_ATTRIB_GROUP_CATCHUP_ON_EXIT:
759 				SET_INTEGER(group_catchup_on_exit);
760 
761 			case OPT_ATTRIB_GROUP_FORMAT:
762 				SET_STRING(group_format);
763 
764 			case OPT_ATTRIB_MAIL_8BIT_HEADER:
765 				SET_INTEGER(mail_8bit_header);
766 
767 			case OPT_ATTRIB_MAIL_MIME_ENCODING:
768 				SET_INTEGER(mail_mime_encoding);
769 
770 			case OPT_ATTRIB_MARK_IGNORE_TAGS:
771 				SET_INTEGER(mark_ignore_tags);
772 
773 			case OPT_ATTRIB_MARK_SAVED_READ:
774 				SET_INTEGER(mark_saved_read);
775 
776 			case OPT_ATTRIB_NEWS_HEADERS_TO_DISPLAY:
777 				FreeIfNeeded(curr_scope->attribute->news_headers_to_display);
778 				curr_scope->attribute->news_headers_to_display = my_strdup((char *) data);
779 				build_news_headers_array(curr_scope->attribute, TRUE);
780 				curr_scope->state->news_headers_to_display = TRUE;
781 				break;
782 
783 			case OPT_ATTRIB_NEWS_HEADERS_TO_NOT_DISPLAY:
784 				FreeIfNeeded(curr_scope->attribute->news_headers_to_not_display);
785 				curr_scope->attribute->news_headers_to_not_display = my_strdup((char *) data);
786 				build_news_headers_array(curr_scope->attribute, FALSE);
787 				curr_scope->state->news_headers_to_not_display = TRUE;
788 				break;
789 
790 			case OPT_ATTRIB_POS_FIRST_UNREAD:
791 				SET_INTEGER(pos_first_unread);
792 
793 			case OPT_ATTRIB_POST_8BIT_HEADER:
794 				SET_INTEGER(post_8bit_header);
795 
796 			case OPT_ATTRIB_POST_MIME_ENCODING:
797 				SET_INTEGER(post_mime_encoding);
798 
799 			case OPT_ATTRIB_POST_PROCESS_VIEW:
800 				SET_INTEGER(post_process_view);
801 
802 #ifndef DISABLE_PRINTING
803 			case OPT_ATTRIB_PRINT_HEADER:
804 				SET_INTEGER(print_header);
805 #endif /* !DISABLE_PRINTING */
806 
807 			case OPT_ATTRIB_PROCESS_ONLY_UNREAD:
808 				SET_INTEGER(process_only_unread);
809 
810 			case OPT_ATTRIB_PROMPT_FOLLOWUPTO:
811 				SET_INTEGER(prompt_followupto);
812 
813 #ifdef HAVE_COLOR
814 			case OPT_ATTRIB_EXTQUOTE_HANDLING:
815 				SET_INTEGER(extquote_handling);
816 #endif /* HAVE_COLOR */
817 
818 			case OPT_ATTRIB_SHOW_ONLY_UNREAD_ARTS:
819 				SET_INTEGER(show_only_unread_arts);
820 
821 			case OPT_ATTRIB_SIGDASHES:
822 				SET_INTEGER(sigdashes);
823 
824 			case OPT_ATTRIB_SIGNATURE_REPOST:
825 				SET_INTEGER(signature_repost);
826 
827 			case OPT_ATTRIB_START_EDITOR_OFFSET:
828 				SET_INTEGER(start_editor_offset);
829 
830 			case OPT_ATTRIB_THREAD_ARTICLES:
831 				SET_INTEGER(thread_articles);
832 
833 			case OPT_ATTRIB_THREAD_CATCHUP_ON_EXIT:
834 				SET_INTEGER(thread_catchup_on_exit);
835 
836 			case OPT_ATTRIB_THREAD_FORMAT:
837 				SET_STRING(thread_format);
838 
839 			case OPT_ATTRIB_THREAD_PERC:
840 				SET_INTEGER(thread_perc);
841 
842 			case OPT_ATTRIB_SHOW_AUTHOR:
843 				SET_INTEGER(show_author);
844 
845 			case OPT_ATTRIB_SHOW_SIGNATURES:
846 				SET_INTEGER(show_signatures);
847 
848 			case OPT_ATTRIB_TRIM_ARTICLE_BODY:
849 				SET_INTEGER(trim_article_body);
850 
851 			case OPT_ATTRIB_VERBATIM_HANDLING:
852 				SET_INTEGER(verbatim_handling);
853 
854 			case OPT_ATTRIB_WRAP_ON_NEXT_UNREAD:
855 				SET_INTEGER(wrap_on_next_unread);
856 
857 			case OPT_ATTRIB_SORT_ARTICLE_TYPE:
858 				SET_INTEGER(sort_article_type);
859 
860 			case OPT_ATTRIB_SORT_THREADS_TYPE:
861 				SET_INTEGER(sort_threads_type);
862 
863 			case OPT_ATTRIB_POST_PROCESS_TYPE:
864 				SET_INTEGER(post_process_type);
865 
866 			case OPT_ATTRIB_QUICK_KILL_HEADER:
867 				SET_INTEGER(quick_kill_header);
868 
869 			case OPT_ATTRIB_QUICK_KILL_SCOPE:
870 				SET_STRING(quick_kill_scope);
871 
872 			case OPT_ATTRIB_QUICK_KILL_EXPIRE:
873 				SET_INTEGER(quick_kill_expire);
874 
875 			case OPT_ATTRIB_QUICK_KILL_CASE:
876 				SET_INTEGER(quick_kill_case);
877 
878 			case OPT_ATTRIB_QUICK_SELECT_HEADER:
879 				SET_INTEGER(quick_select_header);
880 
881 			case OPT_ATTRIB_QUICK_SELECT_SCOPE:
882 				SET_STRING(quick_select_scope);
883 
884 			case OPT_ATTRIB_QUICK_SELECT_EXPIRE:
885 				SET_INTEGER(quick_select_expire);
886 
887 			case OPT_ATTRIB_QUICK_SELECT_CASE:
888 				SET_INTEGER(quick_select_case);
889 
890 			case OPT_ATTRIB_MAILING_LIST:
891 				SET_STRING(mailing_list);
892 
893 #ifdef CHARSET_CONVERSION
894 			case OPT_ATTRIB_MM_NETWORK_CHARSET:
895 				SET_INTEGER(mm_network_charset);
896 
897 			case OPT_ATTRIB_UNDECLARED_CHARSET:
898 				SET_STRING(undeclared_charset);
899 #endif /* CHARSET_CONVERSION */
900 
901 			case OPT_ATTRIB_X_HEADERS:
902 				SET_STRING(x_headers);
903 
904 			case OPT_ATTRIB_X_BODY:
905 				SET_STRING(x_body);
906 
907 			case OPT_ATTRIB_X_COMMENT_TO:
908 				SET_INTEGER(x_comment_to);
909 
910 			case OPT_ATTRIB_FCC:
911 				SET_STRING(fcc);
912 
913 			case OPT_ATTRIB_NEWS_QUOTE_FORMAT:
914 				SET_STRING(news_quote_format);
915 
916 			case OPT_ATTRIB_QUOTE_CHARS:
917 				SET_STRING(quote_chars);
918 
919 			case OPT_ATTRIB_MIME_TYPES_TO_SAVE:
920 				SET_STRING(mime_types_to_save);
921 
922 			case OPT_ATTRIB_MIME_FORWARD:
923 				SET_INTEGER(mime_forward);
924 
925 #ifdef HAVE_ISPELL
926 			case OPT_ATTRIB_ISPELL:
927 				SET_STRING(ispell);
928 #endif /* HAVE_ISPELL */
929 
930 			case OPT_ATTRIB_TEX2ISO_CONV:
931 				SET_INTEGER(tex2iso_conv);
932 
933 			default:
934 				break;
935 		}
936 	}
937 }
938 
939 
940 /*
941  * Insert a new scope entry into scopes[] and return the index.
942  */
943 int
add_scope(const char * scope)944 add_scope(
945 	const char *scope)
946 {
947 	if (!scope || !*scope)
948 		return 0;
949 
950 	if ((num_scope >= max_scope) || (num_scope < 0) || (scopes == NULL))
951 		expand_scope();
952 
953 	scopes[num_scope].scope = my_strdup(scope);
954 	scopes[num_scope].attribute = my_malloc(sizeof(struct t_attribute));
955 	set_default_attributes(scopes[num_scope].attribute, NULL, FALSE);
956 	scopes[num_scope].state = my_malloc(sizeof(struct t_attribute_state));
957 	set_default_state(scopes[num_scope].state);
958 	scopes[num_scope].global = FALSE;
959 	return num_scope++;
960 }
961 
962 
963 #define SET_ATTRIB(attr) do { \
964 		if (curr_scope->state->attr) \
965 			group->attribute->attr = curr_scope->attribute->attr; \
966 	} while (0)
967 
968 
969 /*
970  * Set the attributes of all groups
971  */
972 void
assign_attributes_to_groups(void)973 assign_attributes_to_groups(
974 	void)
975 {
976 	struct t_group *group;
977 	struct t_scope *default_scope, *curr_scope;
978 	t_bool found;
979 	int i, j;
980 	long processed = 0L;
981 #ifdef CHARSET_CONVERSION
982 	t_bool is_7bit;
983 #endif /* CHARSET_CONVERSION */
984 
985 	if (!batch_mode || verbose)
986 		wait_message(0, _("Processing attributes... ")); /* TODO: -> lang.c */
987 
988 	default_scope = &scopes[0];
989 	for_each_group(i) {
990 		if (++processed % (MODULO_COUNT_NUM) == 0)
991 			spin_cursor();
992 		group = &active[i];
993 		found = FALSE;
994 		for (j = 1; j < num_scope; j++) {
995 			curr_scope = &scopes[j];
996 			if (match_group_list(group->name, curr_scope->scope)) {
997 				if (group->attribute == NULL || group->attribute == default_scope->attribute) {
998 					group->attribute = my_malloc(sizeof(struct t_attribute));
999 					set_default_attributes(group->attribute, default_scope->attribute, FALSE);
1000 					found = TRUE;
1001 				}
1002 				if (!found) {
1003 					set_default_attributes(group->attribute, default_scope->attribute, FALSE);
1004 					found = TRUE;
1005 				}
1006 				SET_ATTRIB(maildir);
1007 				SET_ATTRIB(savedir);
1008 				SET_ATTRIB(savefile);
1009 				SET_ATTRIB(sigfile);
1010 				SET_ATTRIB(group_format);
1011 				SET_ATTRIB(thread_format);
1012 				SET_ATTRIB(date_format);
1013 				SET_ATTRIB(editor_format);
1014 				SET_ATTRIB(organization);
1015 				SET_ATTRIB(fcc);
1016 				SET_ATTRIB(followup_to);
1017 				SET_ATTRIB(mailing_list);
1018 				SET_ATTRIB(x_headers);
1019 				SET_ATTRIB(x_body);
1020 				SET_ATTRIB(from);
1021 				SET_ATTRIB(news_quote_format);
1022 				SET_ATTRIB(quote_chars);
1023 				SET_ATTRIB(mime_types_to_save);
1024 #ifdef HAVE_ISPELL
1025 				SET_ATTRIB(ispell);
1026 #endif /* HAVE_ISPELL */
1027 #ifdef CHARSET_CONVERSION
1028 				SET_ATTRIB(mm_network_charset);
1029 				SET_ATTRIB(undeclared_charset);
1030 #endif /* CHARSET_CONVERSION */
1031 				SET_ATTRIB(quick_kill_scope);
1032 				SET_ATTRIB(quick_kill_header);
1033 				SET_ATTRIB(quick_kill_case);
1034 				SET_ATTRIB(quick_kill_expire);
1035 				SET_ATTRIB(quick_select_scope);
1036 				SET_ATTRIB(quick_select_header);
1037 				SET_ATTRIB(quick_select_case);
1038 				SET_ATTRIB(quick_select_expire);
1039 				SET_ATTRIB(show_only_unread_arts);
1040 				SET_ATTRIB(thread_articles);
1041 				SET_ATTRIB(thread_catchup_on_exit);
1042 				SET_ATTRIB(thread_perc);
1043 				SET_ATTRIB(sort_article_type);
1044 				SET_ATTRIB(sort_threads_type);
1045 				SET_ATTRIB(show_author);
1046 				SET_ATTRIB(show_signatures);
1047 				SET_ATTRIB(trim_article_body);
1048 				SET_ATTRIB(verbatim_handling);
1049 #ifdef HAVE_COLOR
1050 				SET_ATTRIB(extquote_handling);
1051 #endif /* HAVE_COLOR */
1052 				SET_ATTRIB(wrap_on_next_unread);
1053 				SET_ATTRIB(add_posted_to_filter);
1054 				SET_ATTRIB(advertising);
1055 				SET_ATTRIB(alternative_handling);
1056 				SET_ATTRIB(ask_for_metamail);
1057 				SET_ATTRIB(auto_cc_bcc);
1058 				SET_ATTRIB(auto_list_thread);
1059 				SET_ATTRIB(auto_save);
1060 				SET_ATTRIB(auto_select);
1061 				SET_ATTRIB(batch_save);
1062 				SET_ATTRIB(delete_tmp_files);
1063 				SET_ATTRIB(group_catchup_on_exit);
1064 				SET_ATTRIB(mail_8bit_header);
1065 				SET_ATTRIB(mail_mime_encoding);
1066 				SET_ATTRIB(mark_ignore_tags);
1067 				SET_ATTRIB(mark_saved_read);
1068 				if (curr_scope->state->news_headers_to_display)
1069 					group->attribute->headers_to_display = curr_scope->attribute->headers_to_display;
1070 				if (curr_scope->state->news_headers_to_not_display)
1071 					group->attribute->headers_to_not_display = curr_scope->attribute->headers_to_not_display;
1072 				SET_ATTRIB(pos_first_unread);
1073 				SET_ATTRIB(post_8bit_header);
1074 				SET_ATTRIB(post_mime_encoding);
1075 				SET_ATTRIB(post_process_view);
1076 				SET_ATTRIB(post_process_type);
1077 #ifndef DISABLE_PRINTING
1078 				SET_ATTRIB(print_header);
1079 #endif /* !DISABLE_PRINTING */
1080 				SET_ATTRIB(process_only_unread);
1081 				SET_ATTRIB(prompt_followupto);
1082 				SET_ATTRIB(sigdashes);
1083 				SET_ATTRIB(signature_repost);
1084 				SET_ATTRIB(start_editor_offset);
1085 				SET_ATTRIB(x_comment_to);
1086 				SET_ATTRIB(tex2iso_conv);
1087 				SET_ATTRIB(mime_forward);
1088 			}
1089 		}
1090 		if (found) {
1091 			/*
1092 			 * sort out conflicting settings
1093 			 */
1094 #ifdef CHARSET_CONVERSION
1095 			/*
1096 			 * check if we have a 7bit charset but a !7bit encoding
1097 			 * or a 8bit charset but a !8bit encoding, update encoding if needed
1098 			 */
1099 			is_7bit = FALSE;
1100 			for (j = 0; txt_mime_7bit_charsets[j] != NULL; j++) {
1101 				if (!strcasecmp(txt_mime_charsets[group->attribute->mm_network_charset], txt_mime_7bit_charsets[j])) {
1102 					is_7bit = TRUE;
1103 					break;
1104 				}
1105 			}
1106 			if (is_7bit) {
1107 				group->attribute->mail_mime_encoding = group->attribute->post_mime_encoding = MIME_ENCODING_7BIT;
1108 			} else {
1109 				if (group->attribute->mail_mime_encoding == MIME_ENCODING_7BIT)
1110 					group->attribute->mail_mime_encoding = MIME_ENCODING_QP;
1111 				if (group->attribute->post_mime_encoding == MIME_ENCODING_7BIT)
1112 					group->attribute->post_mime_encoding = MIME_ENCODING_8BIT;
1113 			}
1114 #endif /* CHARSET_CONVERSION */
1115 			/* do not use 8 bit headers if mime encoding is not 8bit */
1116 			if (group->attribute->mail_mime_encoding != MIME_ENCODING_8BIT)
1117 				group->attribute->mail_8bit_header = FALSE;
1118 			if (group->attribute->post_mime_encoding != MIME_ENCODING_8BIT)
1119 				group->attribute->post_8bit_header = FALSE;
1120 		} else {
1121 			if (group->attribute && !group->attribute->global)
1122 				free(group->attribute);
1123 			group->attribute = default_scope->attribute;
1124 		}
1125 	}
1126 #ifdef DEBUG
1127 	dump_attributes();
1128 #	if 0
1129 	debug_print_filter_attributes();
1130 #	endif /* 0 */
1131 #endif /* DEBUG */
1132 
1133 	if (!batch_mode || verbose)
1134 		my_fputc('\n', stdout);
1135 
1136 	if (!cmd_line && !batch_mode)
1137 		clear_message();
1138 }
1139 
1140 
1141 /*
1142  * (re)build scope->headers_to_[not_]display array
1143  */
1144 void
build_news_headers_array(struct t_attribute * scope,t_bool header_to_display)1145 build_news_headers_array(
1146 	struct t_attribute *scope,
1147 	t_bool header_to_display)
1148 {
1149 	if (header_to_display) {
1150 		if (scope->headers_to_display == NULL)
1151 			scope->headers_to_display = my_malloc(sizeof(struct t_newsheader));
1152 		else {
1153 			if (scope->headers_to_display->header)
1154 				FreeIfNeeded(*scope->headers_to_display->header);
1155 			FreeIfNeeded(scope->headers_to_display->header);
1156 		}
1157 		scope->headers_to_display->header = ulBuildArgv(scope->news_headers_to_display, &scope->headers_to_display->num);
1158 	} else {
1159 		if (scope->headers_to_not_display == NULL)
1160 			scope->headers_to_not_display = my_malloc(sizeof(struct t_newsheader));
1161 		else {
1162 			if (scope->headers_to_not_display->header)
1163 				FreeIfNeeded(*scope->headers_to_not_display->header);
1164 			FreeIfNeeded(scope->headers_to_not_display->header);
1165 		}
1166 		scope->headers_to_not_display->header = ulBuildArgv(scope->news_headers_to_not_display, &scope->headers_to_not_display->num);
1167 	}
1168 }
1169 
1170 
1171 /*
1172  * Save the scope attributes from scopes[] to ~/.tin/attributes
1173  */
1174 void
write_attributes_file(const char * file)1175 write_attributes_file(
1176 	const char *file)
1177 {
1178 	FILE *fp;
1179 	char *new_file;
1180 	int i;
1181 	long fpos;
1182 
1183 	if ((batch_mode || no_write || num_scope < 1) && file_size(file) != -1L)
1184 		return;
1185 
1186 	new_file = get_tmpfilename(file);
1187 
1188 	if ((fp = fopen(new_file, "w+")) == NULL) {
1189 		error_message(2, _(txt_filesystem_full_backup), ATTRIBUTES_FILE);
1190 		free(new_file);
1191 		return;
1192 	}
1193 
1194 	wait_message(0, _(txt_writing_attributes_file));
1195 
1196 #ifdef DEBUG
1197 	dump_scopes("SCOPES-W");
1198 #endif /* DEBUG */
1199 
1200 	/*
1201 	 * TODO: sort in a useful order
1202 	 *       move strings to lang.c
1203 	 */
1204 	fprintf(fp, "# Group attributes file V%s for the TIN newsreader\n", ATTRIBUTES_VERSION);
1205 	fprintf(fp, _("# Do not edit this comment block\n#\n"));
1206 	fprintf(fp, _("#  scope=STRING (eg. alt.*,!alt.bin*) [mandatory]\n"));
1207 	fprintf(fp, _("#  add_posted_to_filter=ON/OFF\n"));
1208 	fprintf(fp, _("#  advertising=ON/OFF\n"));
1209 	fprintf(fp, _("#  alternative_handling=ON/OFF\n"));
1210 	fprintf(fp, _("#  ask_for_metamail=ON/OFF\n"));
1211 	fprintf(fp, _("#  auto_cc_bcc=NUM\n"));
1212 	fprintf(fp, _("#    0=No, 1=Cc, 2=Bcc, 3=Cc and Bcc\n"));
1213 	fprintf(fp, _("#  auto_list_thread=ON/OFF\n"));
1214 	fprintf(fp, _("#  auto_save=ON/OFF\n"));
1215 	fprintf(fp, _("#  auto_select=ON/OFF\n"));
1216 	fprintf(fp, _("#  batch_save=ON/OFF\n"));
1217 	fprintf(fp, _("#  date_format=STRING (eg. %%a, %%d %%b %%Y %%H:%%M:%%S)\n"));
1218 	fprintf(fp, _("#  delete_tmp_files=ON/OFF\n"));
1219 	fprintf(fp, _("#  editor_format=STRING (eg. %%E +%%N %%F)\n"));
1220 	fprintf(fp, _("#  fcc=STRING (eg. =mailbox)\n"));
1221 	fprintf(fp, _("#  followup_to=STRING\n"));
1222 	fprintf(fp, _("#  from=STRING (just append wanted From:-line, don't use quotes)\n"));
1223 	fprintf(fp, _("#  group_catchup_on_exit=ON/OFF\n"));
1224 	fprintf(fp, _("#  group_format=STRING (eg. %%n %%m %%R %%L  %%s  %%F)\n"));
1225 	fprintf(fp, _("#  mail_8bit_header=ON/OFF\n"));
1226 	fprintf(fp, _("#  mail_mime_encoding=supported_encoding"));
1227 	for (i = 0; txt_mime_encodings[i] != NULL; i++) {
1228 		if (!(i % 5))
1229 			fprintf(fp, "\n#    ");
1230 		fprintf(fp, "%s, ", txt_mime_encodings[i]);
1231 	}
1232 	fprintf(fp, "\n");
1233 #ifdef HAVE_ISPELL
1234 	fprintf(fp, _("#  ispell=STRING\n"));
1235 #endif /* HAVE_ISPELL */
1236 	fprintf(fp, _("#  maildir=STRING (eg. ~/Mail)\n"));
1237 	fprintf(fp, _("#  mailing_list=STRING (eg. majordomo@example.org)\n"));
1238 	fprintf(fp, _("#  mime_types_to_save=STRING (eg. image/*,!image/bmp)\n"));
1239 	fprintf(fp, _("#  mark_ignore_tags=ON/OFF\n"));
1240 	fprintf(fp, _("#  mark_saved_read=ON/OFF\n"));
1241 	fprintf(fp, _("#  mime_forward=ON/OFF\n"));
1242 #ifdef CHARSET_CONVERSION
1243 	fprintf(fp, _("#  mm_network_charset=supported_charset"));
1244 	for (i = 0; txt_mime_charsets[i] != NULL; i++) {
1245 		if (!(i % 5)) /* start new line */
1246 			fprintf(fp, "\n#    ");
1247 		fprintf(fp, "%s, ", txt_mime_charsets[i]);
1248 	}
1249 	fprintf(fp, "\n");
1250 	fprintf(fp, _("#  undeclared_charset=STRING (default is US-ASCII)\n"));
1251 #endif /* CHARSET_CONVERSION */
1252 	fprintf(fp, _("#  news_headers_to_display=STRING\n"));
1253 	fprintf(fp, _("#  news_headers_to_not_display=STRING\n"));
1254 	fprintf(fp, _("#  news_quote_format=STRING\n"));
1255 	fprintf(fp, _("#  organization=STRING (if beginning with '/' read from file)\n"));
1256 	fprintf(fp, _("#  pos_first_unread=ON/OFF\n"));
1257 	fprintf(fp, _("#  post_8bit_header=ON/OFF\n"));
1258 	fprintf(fp, _("#  post_mime_encoding=supported_encoding"));
1259 	for (i = 0; txt_mime_encodings[i] != NULL; i++) {
1260 		if (!(i % 5))
1261 			fprintf(fp, "\n#    ");
1262 		fprintf(fp, "%s, ", txt_mime_encodings[i]);
1263 	}
1264 	fprintf(fp, "\n");
1265 	fprintf(fp, _("#  post_process_type=NUM\n"));
1266 	fprintf(fp, "#    %d=%s, %d=%s, %d=%s\n",
1267 		POST_PROC_NO, _(txt_post_process_types[POST_PROC_NO]),
1268 		POST_PROC_SHAR, _(txt_post_process_types[POST_PROC_SHAR]),
1269 		POST_PROC_YES, _(txt_post_process_types[POST_PROC_YES]));
1270 	fprintf(fp, _("#  post_process_view=ON/OFF\n"));
1271 	fprintf(fp, _("#  quick_kill_scope=STRING (ie. talk.*)\n"));
1272 	fprintf(fp, _("#  quick_kill_expire=ON/OFF\n"));
1273 	fprintf(fp, _("#  quick_kill_case=ON/OFF\n"));
1274 	fprintf(fp, _("#  quick_kill_header=NUM\n"));
1275 	fprintf(fp, _("#    0=Subject: (case sensitive)  1=Subject: (ignore case)\n"));
1276 	fprintf(fp, _("#    2=From: (case sensitive)     3=From: (ignore case)\n"));
1277 	fprintf(fp, _("#    4=Message-ID: & full References: line\n"));
1278 	fprintf(fp, _("#    5=Message-ID: & last References: entry only\n"));
1279 	fprintf(fp, _("#    6=Message-ID: entry only     7=Lines:\n"));
1280 	fprintf(fp, _("#  quick_select_scope=STRING\n"));
1281 	fprintf(fp, _("#  quick_select_expire=ON/OFF\n"));
1282 	fprintf(fp, _("#  quick_select_case=ON/OFF\n"));
1283 	fprintf(fp, _("#  quick_select_header=NUM\n"));
1284 	fprintf(fp, _("#    0=Subject: (case sensitive)  1=Subject: (ignore case)\n"));
1285 	fprintf(fp, _("#    2=From: (case sensitive)     3=From: (ignore case)\n"));
1286 	fprintf(fp, _("#    4=Message-ID: & full References: line\n"));
1287 	fprintf(fp, _("#    5=Message-ID: & last References: entry only\n"));
1288 	fprintf(fp, _("#    6=Message-ID: entry only     7=Lines:\n"));
1289 	fprintf(fp, _("#  quote_chars=STRING (%%I for initials)\n"));
1290 #ifndef DISABLE_PRINTING
1291 	fprintf(fp, _("#  print_header=ON/OFF\n"));
1292 #endif /* !DISABLE_PRINTING */
1293 	fprintf(fp, _("#  process_only_unread=ON/OFF\n"));
1294 	fprintf(fp, _("#  prompt_followupto=ON/OFF\n"));
1295 	fprintf(fp, _("#  savedir=STRING (eg. ~user/News)\n"));
1296 	fprintf(fp, _("#  savefile=STRING (eg. =linux)\n"));
1297 	fprintf(fp, _("#  sigfile=STRING (eg. $var/sig)\n"));
1298 	fprintf(fp, _("#  show_author=NUM\n"));
1299 	fprintf(fp, "#    %d=%s, %d=%s, %d=%s, %d=%s\n",
1300 		SHOW_FROM_NONE, _(txt_show_from[SHOW_FROM_NONE]),
1301 		SHOW_FROM_ADDR, _(txt_show_from[SHOW_FROM_ADDR]),
1302 		SHOW_FROM_NAME, _(txt_show_from[SHOW_FROM_NAME]),
1303 		SHOW_FROM_BOTH, _(txt_show_from[SHOW_FROM_BOTH]));
1304 	fprintf(fp, _("#  show_signatures=ON/OFF\n"));
1305 	fprintf(fp, _("#  show_only_unread_arts=ON/OFF\n"));
1306 	fprintf(fp, _("#  sigdashes=ON/OFF\n"));
1307 	fprintf(fp, _("#  signature_repost=ON/OFF\n"));
1308 	fprintf(fp, _("#  sort_article_type=NUM\n"));
1309 	fprintf(fp, "#    %d=%s,\n",
1310 		SORT_ARTICLES_BY_NOTHING, _(txt_sort_a_type[SORT_ARTICLES_BY_NOTHING]));
1311 	fprintf(fp, "#    %d=%s, %d=%s,\n",
1312 		SORT_ARTICLES_BY_SUBJ_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_SUBJ_DESCEND]),
1313 		SORT_ARTICLES_BY_SUBJ_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_SUBJ_ASCEND]));
1314 	fprintf(fp, "#    %d=%s, %d=%s,\n",
1315 		SORT_ARTICLES_BY_FROM_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_FROM_DESCEND]),
1316 		SORT_ARTICLES_BY_FROM_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_FROM_ASCEND]));
1317 	fprintf(fp, "#    %d=%s, %d=%s,\n",
1318 		SORT_ARTICLES_BY_DATE_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_DATE_DESCEND]),
1319 		SORT_ARTICLES_BY_DATE_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_DATE_ASCEND]));
1320 	fprintf(fp, "#    %d=%s, %d=%s,\n",
1321 		SORT_ARTICLES_BY_SCORE_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_SCORE_DESCEND]),
1322 		SORT_ARTICLES_BY_SCORE_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_SCORE_ASCEND]));
1323 	fprintf(fp, "#    %d=%s, %d=%s\n",
1324 		SORT_ARTICLES_BY_LINES_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_LINES_DESCEND]),
1325 		SORT_ARTICLES_BY_LINES_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_LINES_ASCEND]));
1326 	fprintf(fp, _("#  sort_threads_type=NUM\n"));
1327 	fprintf(fp, "#    %d=%s, %d=%s, %d=%s\n",
1328 		SORT_THREADS_BY_NOTHING, _(txt_sort_t_type[SORT_THREADS_BY_NOTHING]),
1329 		SORT_THREADS_BY_SCORE_DESCEND, _(txt_sort_t_type[SORT_THREADS_BY_SCORE_DESCEND]),
1330 		SORT_THREADS_BY_SCORE_ASCEND, _(txt_sort_t_type[SORT_THREADS_BY_SCORE_ASCEND]));
1331 	fprintf(fp, "#    %d=%s\n",
1332 		SORT_THREADS_BY_LAST_POSTING_DATE_DESCEND, _(txt_sort_t_type[SORT_THREADS_BY_LAST_POSTING_DATE_DESCEND]));
1333 	fprintf(fp, "#    %d=%s\n",
1334 		SORT_THREADS_BY_LAST_POSTING_DATE_ASCEND, _(txt_sort_t_type[SORT_THREADS_BY_LAST_POSTING_DATE_ASCEND]));
1335 	fprintf(fp, _("#  start_editor_offset=ON/OFF\n"));
1336 	fprintf(fp, _("#  tex2iso_conv=ON/OFF\n"));
1337 	fprintf(fp, _("#  thread_catchup_on_exit=ON/OFF\n"));
1338 	fprintf(fp, _("#  thread_articles=NUM"));
1339 	for (i = 0; i <= THREAD_MAX; i++) {
1340 		if (!(i % 2))
1341 			fprintf(fp, "\n#    ");
1342 		fprintf(fp, "%d=%s, ", i, _(txt_threading[i]));
1343 	}
1344 	fprintf(fp, "\n");
1345 	fprintf(fp, _("#  thread_format=STRING (eg. %%n %%m [%%L]  %%T  %%F)\n"));
1346 	fprintf(fp, _("#  thread_perc=NUM\n"));
1347 	fprintf(fp, _("#  trim_article_body=NUM\n"));
1348 	fprintf(fp, _("#    0 = Don't trim article body\n"));
1349 	fprintf(fp, _("#    1 = Skip leading blank lines\n"));
1350 	fprintf(fp, _("#    2 = Skip trailing blank lines\n"));
1351 	fprintf(fp, _("#    3 = Skip leading and trailing blank lines\n"));
1352 	fprintf(fp, _("#    4 = Compact multiple blank lines between text blocks\n"));
1353 	fprintf(fp, _("#    5 = Compact multiple blank lines between text blocks and skip\n#        leading blank lines\n"));
1354 	fprintf(fp, _("#    6 = Compact multiple blank lines between text blocks and skip\n#        trailing blank lines\n"));
1355 	fprintf(fp, _("#    7 = Compact multiple blank lines between text blocks and skip\n#        leading and trailing blank lines\n"));
1356 	fprintf(fp, _("#  verbatim_handling=ON/OFF\n"));
1357 #ifdef HAVE_COLOR
1358 	fprintf(fp, _("#  extquote_handling=ON/OFF\n"));
1359 #endif /* HAVE_COLOR */
1360 	fprintf(fp, _("#  wrap_on_next_unread=ON/OFF\n"));
1361 	fprintf(fp, _("#  x_body=STRING (eg. ~/.tin/extra-body-text)\n"));
1362 	fprintf(fp, _("#  x_comment_to=ON/OFF\n"));
1363 	fprintf(fp, _("#  x_headers=STRING (eg. ~/.tin/extra-headers)\n"));
1364 	fprintf(fp, _("#\n# Note that it is best to put general (global scoping)\n"));
1365 	fprintf(fp, _("# entries first followed by group specific entries.\n#\n"));
1366 	fprintf(fp, _("############################################################################\n"));
1367 
1368 	/*
1369 	 * determine the file offset
1370 	 * this is necessary because a changed locale setting
1371 	 * may lead to an invalid offset
1372 	 */
1373 	if ((fpos = ftell(fp)) <= 0) {
1374 		clearerr(fp);
1375 		fclose(fp);
1376 		unlink(new_file);
1377 		free(new_file);
1378 		error_message(2, _(txt_filesystem_full), ATTRIBUTES_FILE);
1379 		return;
1380 	}
1381 	rewind(fp);
1382 	attrib_file_offset = 1;
1383 	while ((i = fgetc(fp)) != EOF) {
1384 		if (i == '\n')
1385 			attrib_file_offset++;
1386 	}
1387 	if (fseek(fp, fpos, SEEK_SET)) {
1388 		clearerr(fp);
1389 		fclose(fp);
1390 		unlink(new_file);
1391 		free(new_file);
1392 		error_message(2, _(txt_filesystem_full), ATTRIBUTES_FILE);
1393 		return;
1394 	}
1395 
1396 	if ((num_scope > 0) && (scopes != NULL)) {
1397 		struct t_scope *scope;
1398 
1399 		for (i = 1; i < num_scope; i++) {
1400 			scope = &scopes[i];
1401 			if (!scope->global) {
1402 				fprintf(fp, "\nscope=%s\n", scope->scope);
1403 				if (scope->state->add_posted_to_filter)
1404 					fprintf(fp, "add_posted_to_filter=%s\n", print_boolean(scope->attribute->add_posted_to_filter));
1405 				if (scope->state->advertising)
1406 					fprintf(fp, "advertising=%s\n", print_boolean(scope->attribute->advertising));
1407 				if (scope->state->alternative_handling)
1408 					fprintf(fp, "alternative_handling=%s\n", print_boolean(scope->attribute->alternative_handling));
1409 				if (scope->state->ask_for_metamail)
1410 					fprintf(fp, "ask_for_metamail=%s\n", print_boolean(scope->attribute->ask_for_metamail));
1411 				if (scope->state->auto_cc_bcc)
1412 					fprintf(fp, "auto_cc_bcc=%u\n", scope->attribute->auto_cc_bcc);
1413 				if (scope->state->auto_list_thread)
1414 					fprintf(fp, "auto_list_thread=%s\n", print_boolean(scope->attribute->auto_list_thread));
1415 				if (scope->state->auto_select)
1416 					fprintf(fp, "auto_select=%s\n", print_boolean(scope->attribute->auto_select));
1417 				if (scope->state->auto_save)
1418 					fprintf(fp, "auto_save=%s\n", print_boolean(scope->attribute->auto_save));
1419 				if (scope->state->batch_save)
1420 					fprintf(fp, "batch_save=%s\n", print_boolean(scope->attribute->batch_save));
1421 				if (scope->state->date_format && scope->attribute->date_format)
1422 					fprintf(fp, "date_format=%s\n", scope->attribute->date_format);
1423 				if (scope->state->delete_tmp_files)
1424 					fprintf(fp, "delete_tmp_files=%s\n", print_boolean(scope->attribute->delete_tmp_files));
1425 				if (scope->state->editor_format && scope->attribute->editor_format)
1426 					fprintf(fp, "editor_format=%s\n", scope->attribute->editor_format);
1427 #ifdef HAVE_COLOR
1428 				if (scope->state->extquote_handling)
1429 					fprintf(fp, "extquote_handling=%s\n", print_boolean(scope->attribute->extquote_handling));
1430 #endif /* HAVE_COLOR */
1431 				if (scope->state->fcc && scope->attribute->fcc)
1432 					fprintf(fp, "fcc=%s\n", scope->attribute->fcc);
1433 				if (scope->state->followup_to && scope->attribute->followup_to)
1434 					fprintf(fp, "followup_to=%s\n", scope->attribute->followup_to);
1435 				if (scope->state->from && scope->attribute->from)
1436 					fprintf(fp, "from=%s\n", scope->attribute->from);
1437 				if (scope->state->group_catchup_on_exit)
1438 					fprintf(fp, "group_catchup_on_exit=%s\n", print_boolean(scope->attribute->group_catchup_on_exit));
1439 				if (scope->state->group_format && scope->attribute->group_format)
1440 					fprintf(fp, "group_format=%s\n", scope->attribute->group_format);
1441 				if (scope->state->mail_8bit_header)
1442 					fprintf(fp, "mail_8bit_header=%s\n", print_boolean(scope->attribute->mail_8bit_header));
1443 				if (scope->state->mail_mime_encoding)
1444 					fprintf(fp, "mail_mime_encoding=%s\n", txt_mime_encodings[scope->attribute->mail_mime_encoding]);
1445 #ifdef HAVE_ISPELL
1446 				if (scope->state->ispell && scope->attribute->ispell)
1447 					fprintf(fp, "ispell=%s\n", scope->attribute->ispell);
1448 #endif /* HAVE_ISPELL */
1449 				if (scope->state->maildir && scope->attribute->maildir)
1450 					fprintf(fp, "maildir=%s\n", scope->attribute->maildir);
1451 				if (scope->state->mailing_list && scope->attribute->mailing_list)
1452 					fprintf(fp, "mailing_list=%s\n", scope->attribute->mailing_list);
1453 				if (scope->state->mark_ignore_tags)
1454 					fprintf(fp, "mark_ignore_tags=%s\n", print_boolean(scope->attribute->mark_ignore_tags));
1455 				if (scope->state->mark_saved_read)
1456 					fprintf(fp, "mark_saved_read=%s\n", print_boolean(scope->attribute->mark_saved_read));
1457 				if (scope->state->mime_forward)
1458 					fprintf(fp, "mime_forward=%s\n", print_boolean(scope->attribute->mime_forward));
1459 				if (scope->state->mime_types_to_save && scope->attribute->mime_types_to_save)
1460 					fprintf(fp, "mime_types_to_save=%s\n", scope->attribute->mime_types_to_save);
1461 #ifdef CHARSET_CONVERSION
1462 				if (scope->state->mm_network_charset)
1463 					fprintf(fp, "mm_network_charset=%s\n", txt_mime_charsets[scope->attribute->mm_network_charset]);
1464 				if (scope->state->undeclared_charset && scope->attribute->undeclared_charset)
1465 					fprintf(fp, "undeclared_charset=%s\n", scope->attribute->undeclared_charset);
1466 #endif /* CHARSET_CONVERSION */
1467 				if (scope->state->news_headers_to_display && scope->attribute->news_headers_to_display)
1468 					fprintf(fp, "news_headers_to_display=%s\n", scope->attribute->news_headers_to_display);
1469 				if (scope->state->news_headers_to_not_display && scope->attribute->news_headers_to_not_display)
1470 					fprintf(fp, "news_headers_to_not_display=%s\n", scope->attribute->news_headers_to_not_display);
1471 				if (scope->state->news_quote_format && scope->attribute->news_quote_format)
1472 					fprintf(fp, "news_quote_format=%s\n", scope->attribute->news_quote_format);
1473 				if (scope->state->organization && scope->attribute->organization)
1474 					fprintf(fp, "organization=%s\n", scope->attribute->organization);
1475 				if (scope->state->pos_first_unread)
1476 					fprintf(fp, "pos_first_unread=%s\n", print_boolean(scope->attribute->pos_first_unread));
1477 				if (scope->state->post_8bit_header)
1478 					fprintf(fp, "post_8bit_header=%s\n", print_boolean(scope->attribute->post_8bit_header));
1479 				if (scope->state->post_mime_encoding)
1480 					fprintf(fp, "post_mime_encoding=%s\n", txt_mime_encodings[scope->attribute->post_mime_encoding]);
1481 				if (scope->state->post_process_view)
1482 					fprintf(fp, "post_process_view=%s\n", print_boolean(scope->attribute->post_process_view));
1483 				if (scope->state->post_process_type)
1484 					fprintf(fp, "post_process_type=%u\n", scope->attribute->post_process_type);
1485 #ifndef DISABLE_PRINTING
1486 				if (scope->state->print_header)
1487 					fprintf(fp, "print_header=%s\n", print_boolean(scope->attribute->print_header));
1488 #endif /* !DISABLE_PRINTING */
1489 				if (scope->state->process_only_unread)
1490 					fprintf(fp, "process_only_unread=%s\n", print_boolean(scope->attribute->process_only_unread));
1491 				if (scope->state->prompt_followupto)
1492 					fprintf(fp, "prompt_followupto=%s\n", print_boolean(scope->attribute->prompt_followupto));
1493 				if (scope->state->quick_kill_scope && scope->attribute->quick_kill_scope)
1494 					fprintf(fp, "quick_kill_scope=%s\n", scope->attribute->quick_kill_scope);
1495 				if (scope->state->quick_kill_case)
1496 					fprintf(fp, "quick_kill_case=%s\n", print_boolean(scope->attribute->quick_kill_case));
1497 				if (scope->state->quick_kill_expire)
1498 					fprintf(fp, "quick_kill_expire=%s\n", print_boolean(scope->attribute->quick_kill_expire));
1499 				if (scope->state->quick_kill_header)
1500 					fprintf(fp, "quick_kill_header=%u\n", scope->attribute->quick_kill_header);
1501 				if (scope->state->quick_select_scope && scope->attribute->quick_select_scope)
1502 					fprintf(fp, "quick_select_scope=%s\n", scope->attribute->quick_select_scope);
1503 				if (scope->state->quick_select_case)
1504 					fprintf(fp, "quick_select_case=%s\n", print_boolean(scope->attribute->quick_select_case));
1505 				if (scope->state->quick_select_expire)
1506 					fprintf(fp, "quick_select_expire=%s\n", print_boolean(scope->attribute->quick_select_expire));
1507 				if (scope->state->quick_select_header)
1508 					fprintf(fp, "quick_select_header=%u\n", scope->attribute->quick_select_header);
1509 				if (scope->state->quote_chars && scope->attribute->quote_chars)
1510 					fprintf(fp, "quote_chars=%s\n", quote_space_to_dash(scope->attribute->quote_chars));
1511 				if (scope->state->savedir && scope->attribute->savedir)
1512 					fprintf(fp, "savedir=%s\n", scope->attribute->savedir);
1513 				if (scope->state->savefile && scope->attribute->savefile)
1514 					fprintf(fp, "savefile=%s\n", scope->attribute->savefile);
1515 				if (scope->state->show_author)
1516 					fprintf(fp, "show_author=%u\n", scope->attribute->show_author);
1517 				if (scope->state->show_only_unread_arts)
1518 					fprintf(fp, "show_only_unread_arts=%s\n", print_boolean(scope->attribute->show_only_unread_arts));
1519 				if (scope->state->show_signatures)
1520 					fprintf(fp, "show_signatures=%s\n", print_boolean(scope->attribute->show_signatures));
1521 				if (scope->state->sigdashes)
1522 					fprintf(fp, "sigdashes=%s\n", print_boolean(scope->attribute->sigdashes));
1523 				if (scope->state->sigfile && scope->attribute->sigfile)
1524 					fprintf(fp, "sigfile=%s\n", scope->attribute->sigfile);
1525 				if (scope->state->signature_repost)
1526 					fprintf(fp, "signature_repost=%s\n", print_boolean(scope->attribute->signature_repost));
1527 				if (scope->state->sort_article_type)
1528 					fprintf(fp, "sort_article_type=%u\n", scope->attribute->sort_article_type);
1529 				if (scope->state->sort_threads_type)
1530 					fprintf(fp, "sort_threads_type=%u\n", scope->attribute->sort_threads_type);
1531 				if (scope->state->start_editor_offset)
1532 					fprintf(fp, "start_editor_offset=%s\n", print_boolean(scope->attribute->start_editor_offset));
1533 				if (scope->state->tex2iso_conv)
1534 					fprintf(fp, "tex2iso_conv=%s\n", print_boolean(scope->attribute->tex2iso_conv));
1535 				if (scope->state->thread_articles)
1536 					fprintf(fp, "thread_articles=%u\n", scope->attribute->thread_articles);
1537 				if (scope->state->thread_catchup_on_exit)
1538 					fprintf(fp, "thread_catchup_on_exit=%s\n", print_boolean(scope->attribute->thread_catchup_on_exit));
1539 				if (scope->state->thread_format && scope->attribute->thread_format)
1540 					fprintf(fp, "thread_format=%s\n", scope->attribute->thread_format);
1541 				if (scope->state->thread_perc)
1542 					fprintf(fp, "thread_perc=%u\n", scope->attribute->thread_perc);
1543 				if (scope->state->trim_article_body)
1544 					fprintf(fp, "trim_article_body=%u\n", scope->attribute->trim_article_body);
1545 				if (scope->state->verbatim_handling)
1546 					fprintf(fp, "verbatim_handling=%s\n", print_boolean(scope->attribute->verbatim_handling));
1547 				if (scope->state->wrap_on_next_unread)
1548 					fprintf(fp, "wrap_on_next_unread=%s\n", print_boolean(scope->attribute->wrap_on_next_unread));
1549 				if (scope->state->x_headers && scope->attribute->x_headers)
1550 					fprintf(fp, "x_headers=%s\n", scope->attribute->x_headers);
1551 				if (scope->state->x_body && scope->attribute->x_body)
1552 					fprintf(fp, "x_body=%s\n", scope->attribute->x_body);
1553 				if (scope->state->x_comment_to)
1554 					fprintf(fp, "x_comment_to=%s\n", print_boolean(scope->attribute->x_comment_to));
1555 			}
1556 		}
1557 	}
1558 
1559 	/* rename_file() preserves mode, so this is safe */
1560 #ifdef HAVE_FCHMOD
1561 	fchmod(fileno(fp), (mode_t) (S_IRUSR|S_IWUSR));
1562 #else
1563 #	ifdef HAVE_CHMOD
1564 	chmod(new_file, (mode_t) (S_IRUSR|S_IWUSR));
1565 #	endif /* HAVE_CHMOD */
1566 #endif /* HAVE_FCHMOD */
1567 
1568 	if ((i = ferror(fp)) || fclose(fp)) {
1569 		error_message(2, _(txt_filesystem_full), ATTRIBUTES_FILE);
1570 		unlink(new_file);
1571 		if (i) {
1572 			clearerr(fp);
1573 			fclose(fp);
1574 		}
1575 	} else
1576 		rename_file(new_file, file);
1577 
1578 	free(new_file);
1579 }
1580 
1581 
1582 #ifdef DEBUG
1583 #	if 0
1584 static void
1585 debug_print_filter_attributes(
1586 	void)
1587 {
1588 	if (debug & DEBUG_ATTRIB) {
1589 		int i;
1590 		struct t_group *group;
1591 
1592 		my_printf("\nBEG ***\n");
1593 
1594 		for_each_group(i) {
1595 			group = &active[i];
1596 			my_printf("Grp=[%s] KILL   header=[%d] scope=[%s] case=[%s] expire=[%s]\n",
1597 				group->name, group->attribute->quick_kill_header,
1598 				BlankIfNull(group->attribute->quick_kill_scope),
1599 				txt_onoff[group->attribute->quick_kill_case != FALSE ? 1 : 0],
1600 				txt_onoff[group->attribute->quick_kill_expire != FALSE ? 1 : 0]);
1601 			my_printf("Grp=[%s] SELECT header=[%d] scope=[%s] case=[%s] expire=[%s]\n",
1602 				group->name, group->attribute->quick_select_header,
1603 				BlankIfNull(group->attribute->quick_select_scope),
1604 				txt_onoff[group->attribute->quick_select_case != FALSE ? 1 : 0],
1605 				txt_onoff[group->attribute->quick_select_expire != FALSE ? 1 : 0]);
1606 		}
1607 		my_printf("END ***\n");
1608 	}
1609 }
1610 #	endif /* 0 */
1611 
1612 
1613 static void
dump_attributes(void)1614 dump_attributes(
1615 	void)
1616 {
1617 	if (debug & DEBUG_ATTRIB) {
1618 		int i, j;
1619 		struct t_group *group;
1620 
1621 		for_each_group(i) {
1622 			group = &active[i];
1623 			if (!group->attribute)
1624 				continue;
1625 			debug_print_file("ATTRIBUTES", "group=%s", BlankIfNull(group->name));
1626 			debug_print_file("ATTRIBUTES", "\tGlobal=%d", group->attribute->global);
1627 			debug_print_file("ATTRIBUTES", "\tmaildir=%s", BlankIfNull(group->attribute->maildir));
1628 			debug_print_file("ATTRIBUTES", "\tsavedir=%s", BlankIfNull(group->attribute->savedir));
1629 			debug_print_file("ATTRIBUTES", "\tsavefile=%s", BlankIfNull(group->attribute->savefile));
1630 			debug_print_file("ATTRIBUTES", "\tsigfile=%s", BlankIfNull(group->attribute->sigfile));
1631 			debug_print_file("ATTRIBUTES", "\torganization=%s", BlankIfNull(group->attribute->organization));
1632 			debug_print_file("ATTRIBUTES", "\tfollowup_to=%s", BlankIfNull(group->attribute->followup_to));
1633 			debug_print_file("ATTRIBUTES", "\tmailing_list=%s", BlankIfNull(group->attribute->mailing_list));
1634 			debug_print_file("ATTRIBUTES", "\tx_headers=%s", BlankIfNull(group->attribute->x_headers));
1635 			debug_print_file("ATTRIBUTES", "\tx_body=%s", BlankIfNull(group->attribute->x_body));
1636 			debug_print_file("ATTRIBUTES", "\tfrom=%s", BlankIfNull(group->attribute->from));
1637 			debug_print_file("ATTRIBUTES", "\tnews_quote_format=%s", BlankIfNull(group->attribute->news_quote_format));
1638 			debug_print_file("ATTRIBUTES", "\tquote_chars=%s", quote_space_to_dash(BlankIfNull(group->attribute->quote_chars)));
1639 			debug_print_file("ATTRIBUTES", "\tmime_types_to_save=%s", BlankIfNull(group->attribute->mime_types_to_save));
1640 #	ifdef HAVE_ISPELL
1641 			debug_print_file("ATTRIBUTES", "\tispell=%s", BlankIfNull(group->attribute->ispell));
1642 #	endif /* HAVE_ISPELL */
1643 			debug_print_file("ATTRIBUTES", "\tshow_only_unread_arts=%s", print_boolean(group->attribute->show_only_unread_arts));
1644 			debug_print_file("ATTRIBUTES", "\tthread_articles=%d", group->attribute->thread_articles);
1645 			debug_print_file("ATTRIBUTES", "\tthread_perc=%d", group->attribute->thread_perc);
1646 			debug_print_file("ATTRIBUTES", "\tadd_posted_to_filter=%s", print_boolean(group->attribute->add_posted_to_filter));
1647 			debug_print_file("ATTRIBUTES", "\tadvertising=%s", print_boolean(group->attribute->advertising));
1648 			debug_print_file("ATTRIBUTES", "\talternative_handling=%s", print_boolean(group->attribute->alternative_handling));
1649 			debug_print_file("ATTRIBUTES", "\task_for_metamail=%s", print_boolean(group->attribute->ask_for_metamail));
1650 			debug_print_file("ATTRIBUTES", "\tauto_cc_bcc=%d", group->attribute->auto_cc_bcc);
1651 			debug_print_file("ATTRIBUTES", "\tauto_list_thread=%s", print_boolean(group->attribute->auto_list_thread));
1652 			debug_print_file("ATTRIBUTES", "\tauto_select=%s", print_boolean(group->attribute->auto_select));
1653 			debug_print_file("ATTRIBUTES", "\tauto_save=%s", print_boolean(group->attribute->auto_save));
1654 			debug_print_file("ATTRIBUTES", "\tbatch_save=%s", print_boolean(group->attribute->batch_save));
1655 			debug_print_file("ATTRIBUTES", "\tdate_format=%s", BlankIfNull(group->attribute->date_format));
1656 			debug_print_file("ATTRIBUTES", "\tdelete_tmp_files=%s", print_boolean(group->attribute->delete_tmp_files));
1657 			debug_print_file("ATTRIBUTES", "\teditor_format=%s", BlankIfNull(group->attribute->editor_format));
1658 #	ifdef HAVE_COLOR
1659 			debug_print_file("ATTRIBUTES", "\textquote_handling=%s", print_boolean(group->attribute->extquote_handling));
1660 #	endif /* HAVE_COLOR */
1661 			debug_print_file("ATTRIBUTES", "\tgroup_catchup_on_exit=%s", print_boolean(group->attribute->group_catchup_on_exit));
1662 			debug_print_file("ATTRIBUTES", "\tgroup_format=%s", BlankIfNull(group->attribute->group_format));
1663 			debug_print_file("ATTRIBUTES", "\tmail_8bit_header=%s", print_boolean(group->attribute->mail_8bit_header));
1664 			debug_print_file("ATTRIBUTES", "\tmail_mime_encoding=%s", txt_mime_encodings[group->attribute->mail_mime_encoding]);
1665 			debug_print_file("ATTRIBUTES", "\tmark_ignore_tags=%s", print_boolean(group->attribute->mark_ignore_tags));
1666 			debug_print_file("ATTRIBUTES", "\tmark_saved_read=%s", print_boolean(group->attribute->mark_saved_read));
1667 			debug_print_file("ATTRIBUTES", "\tnews_headers_to_display=%s", BlankIfNull(group->attribute->news_headers_to_display));
1668 			if (group->attribute->headers_to_display) {
1669 				debug_print_file("ATTRIBUTES", "\theaders_to_display->num=%d", group->attribute->headers_to_display->num);
1670 				for (j = 0; j < group->attribute->headers_to_display->num; j++)
1671 					debug_print_file("ATTRIBUTES", "\theaders_to_display->header[%d]=%s", j, group->attribute->headers_to_display->header[j]);
1672 			}
1673 			debug_print_file("ATTRIBUTES", "\tnews_headers_to_not_display=%s", BlankIfNull(group->attribute->news_headers_to_not_display));
1674 			if (group->attribute->headers_to_not_display) {
1675 				debug_print_file("ATTRIBUTES", "\theaders_to_not_display->num=%d", group->attribute->headers_to_not_display->num);
1676 				for (j = 0; j < group->attribute->headers_to_not_display->num; j++)
1677 					debug_print_file("ATTRIBUTES", "\theaders_to_not_display->header[%d]=%s", j, group->attribute->headers_to_not_display->header[j]);
1678 			}
1679 			debug_print_file("ATTRIBUTES", "\tpos_first_unread=%s", print_boolean(group->attribute->pos_first_unread));
1680 			debug_print_file("ATTRIBUTES", "\tpost_8bit_header=%s", print_boolean(group->attribute->post_8bit_header));
1681 			debug_print_file("ATTRIBUTES", "\tpost_mime_encoding=%s", txt_mime_encodings[group->attribute->post_mime_encoding]);
1682 			debug_print_file("ATTRIBUTES", "\tpost_process_view=%s", print_boolean(group->attribute->post_process_view));
1683 #	ifndef DISABLE_PRINTING
1684 			debug_print_file("ATTRIBUTES", "\tprint_header=%s", print_boolean(group->attribute->print_header));
1685 #	endif /* !DISABLE_PRINTING */
1686 			debug_print_file("ATTRIBUTES", "\tprocess_only_unread=%s", print_boolean(group->attribute->process_only_unread));
1687 			debug_print_file("ATTRIBUTES", "\tprompt_followupto=%s", print_boolean(group->attribute->prompt_followupto));
1688 			debug_print_file("ATTRIBUTES", "\tsort_article_type=%d", group->attribute->sort_article_type);
1689 			debug_print_file("ATTRIBUTES", "\tsort_threads_type=%d", group->attribute->sort_threads_type);
1690 			debug_print_file("ATTRIBUTES", "\tshow_author=%d", group->attribute->show_author);
1691 			debug_print_file("ATTRIBUTES", "\tshow_signatures=%s", print_boolean(group->attribute->show_signatures));
1692 			debug_print_file("ATTRIBUTES", "\tsigdashes=%s", print_boolean(group->attribute->sigdashes));
1693 			debug_print_file("ATTRIBUTES", "\tsignature_repost=%s", print_boolean(group->attribute->signature_repost));
1694 			debug_print_file("ATTRIBUTES", "\tstart_editor_offset=%s", print_boolean(group->attribute->start_editor_offset));
1695 			debug_print_file("ATTRIBUTES", "\tthread_catchup_on_exit=%s", print_boolean(group->attribute->thread_catchup_on_exit));
1696 			debug_print_file("ATTRIBUTES", "\tthread_format=%s", BlankIfNull(group->attribute->thread_format));
1697 			debug_print_file("ATTRIBUTES", "\ttrim_article_body=%d", group->attribute->trim_article_body);
1698 			debug_print_file("ATTRIBUTES", "\tverbatim_handling=%s", print_boolean(group->attribute->verbatim_handling));
1699 			debug_print_file("ATTRIBUTES", "\twrap_on_next_unread=%s", print_boolean(group->attribute->wrap_on_next_unread));
1700 			debug_print_file("ATTRIBUTES", "\tpost_process_type=%d", group->attribute->post_process_type);
1701 			debug_print_file("ATTRIBUTES", "\tquick_kill_scope=%s", BlankIfNull(group->attribute->quick_kill_scope));
1702 			debug_print_file("ATTRIBUTES", "\tquick_kill_case=%s", print_boolean(group->attribute->quick_kill_case));
1703 			debug_print_file("ATTRIBUTES", "\tquick_kill_expire=%s", print_boolean(group->attribute->quick_kill_expire));
1704 			debug_print_file("ATTRIBUTES", "\tquick_kill_header=%d", group->attribute->quick_kill_header);
1705 			debug_print_file("ATTRIBUTES", "\tquick_select_scope=%s", BlankIfNull(group->attribute->quick_select_scope));
1706 			debug_print_file("ATTRIBUTES", "\tquick_select_case=%s", print_boolean(group->attribute->quick_select_case));
1707 			debug_print_file("ATTRIBUTES", "\tquick_select_expire=%s", print_boolean(group->attribute->quick_select_expire));
1708 			debug_print_file("ATTRIBUTES", "\tquick_select_header=%d", group->attribute->quick_select_header);
1709 			debug_print_file("ATTRIBUTES", "\tx_comment_to=%s", print_boolean(group->attribute->x_comment_to));
1710 			debug_print_file("ATTRIBUTES", "\tfcc=%s", BlankIfNull(group->attribute->fcc));
1711 			debug_print_file("ATTRIBUTES", "\ttex2iso_conv=%s", print_boolean(group->attribute->tex2iso_conv));
1712 			debug_print_file("ATTRIBUTES", "\tmime_forward=%s", print_boolean(group->attribute->mime_forward));
1713 #	ifdef CHARSET_CONVERSION
1714 			debug_print_file("ATTRIBUTES", "\tmm_network_charset=%s", txt_mime_charsets[group->attribute->mm_network_charset]);
1715 			debug_print_file("ATTRIBUTES", "\tundeclared_charset=%s", BlankIfNull(group->attribute->undeclared_charset));
1716 #	endif /* CHARSET_CONVERSION */
1717 			debug_print_file("ATTRIBUTES", "");
1718 		}
1719 	}
1720 }
1721 
1722 
1723 #define DEBUG_PRINT_STATE(attrib) (scope->state->attrib ? "+ " : "  ")
1724 #define DEBUG_PRINT_STRING(attrib) (scope->attribute->attrib ? scope->attribute->attrib : "NULL")
1725 
1726 
1727 static void
dump_scopes(const char * fname)1728 dump_scopes(
1729 	const char *fname)
1730 {
1731 	if (!scopes)
1732 		return;
1733 
1734 	if (debug & DEBUG_ATTRIB) {
1735 		int i, j;
1736 		struct t_scope *scope;
1737 
1738 		for (i = 0; i < num_scope; i++) {
1739 			scope = &scopes[i];
1740 			debug_print_file(fname, "scopes[%d]", i);
1741 			debug_print_file(fname, "scope=%s", scope->scope ? scope->scope : "NULL");
1742 			debug_print_file(fname, "\t  global=%d", scope->global);
1743 			debug_print_file(fname, "\t%smaildir=%s", DEBUG_PRINT_STATE(maildir), DEBUG_PRINT_STRING(maildir));
1744 			debug_print_file(fname, "\t%ssavedir=%s", DEBUG_PRINT_STATE(savedir), DEBUG_PRINT_STRING(savedir));
1745 			debug_print_file(fname, "\t%ssavefile=%s", DEBUG_PRINT_STATE(savefile), DEBUG_PRINT_STRING(savefile));
1746 			debug_print_file(fname, "\t%ssigfile=%s", DEBUG_PRINT_STATE(sigfile), DEBUG_PRINT_STRING(sigfile));
1747 			debug_print_file(fname, "\t%sorganization=%s", DEBUG_PRINT_STATE(organization), DEBUG_PRINT_STRING(organization));
1748 			debug_print_file(fname, "\t%sfollowup_to=%s", DEBUG_PRINT_STATE(followup_to), DEBUG_PRINT_STRING(followup_to));
1749 			debug_print_file(fname, "\t%smailing_list=%s", DEBUG_PRINT_STATE(mailing_list), DEBUG_PRINT_STRING(mailing_list));
1750 			debug_print_file(fname, "\t%sx_headers=%s", DEBUG_PRINT_STATE(x_headers), DEBUG_PRINT_STRING(x_headers));
1751 			debug_print_file(fname, "\t%sx_body=%s", DEBUG_PRINT_STATE(x_body), DEBUG_PRINT_STRING(x_body));
1752 			debug_print_file(fname, "\t%sfrom=%s", DEBUG_PRINT_STATE(from), DEBUG_PRINT_STRING(from));
1753 			debug_print_file(fname, "\t%snews_quote_format=%s", DEBUG_PRINT_STATE(news_quote_format), DEBUG_PRINT_STRING(news_quote_format));
1754 			debug_print_file(fname, "\t%squote_chars=%s", DEBUG_PRINT_STATE(quote_chars), quote_space_to_dash(DEBUG_PRINT_STRING(quote_chars)));
1755 			debug_print_file(fname, "\t%smime_types_to_save=%s", DEBUG_PRINT_STATE(mime_types_to_save), DEBUG_PRINT_STRING(mime_types_to_save));
1756 #	ifdef HAVE_ISPELL
1757 			debug_print_file(fname, "\t%sispell=%s", DEBUG_PRINT_STATE(ispell), DEBUG_PRINT_STRING(ispell));
1758 #	endif /* HAVE_ISPELL */
1759 			debug_print_file(fname, "\t%sshow_only_unread_arts=%s", DEBUG_PRINT_STATE(show_only_unread_arts), print_boolean(scope->attribute->show_only_unread_arts));
1760 			debug_print_file(fname, "\t%sthread_articles=%d", DEBUG_PRINT_STATE(thread_articles), scope->attribute->thread_articles);
1761 			debug_print_file(fname, "\t%sthread_perc=%d", DEBUG_PRINT_STATE(thread_perc), scope->attribute->thread_perc);
1762 			debug_print_file(fname, "\t%sadd_posted_to_filter=%s", DEBUG_PRINT_STATE(add_posted_to_filter), print_boolean(scope->attribute->add_posted_to_filter));
1763 			debug_print_file(fname, "\t%sadvertising=%s", DEBUG_PRINT_STATE(advertising), print_boolean(scope->attribute->advertising));
1764 			debug_print_file(fname, "\t%salternative_handling=%s", DEBUG_PRINT_STATE(alternative_handling), print_boolean(scope->attribute->alternative_handling));
1765 			debug_print_file(fname, "\t%sask_for_metamail=%s", DEBUG_PRINT_STATE(ask_for_metamail), print_boolean(scope->attribute->ask_for_metamail));
1766 			debug_print_file(fname, "\t%sauto_cc_bcc=%d", DEBUG_PRINT_STATE(auto_cc_bcc), scope->attribute->auto_cc_bcc);
1767 			debug_print_file(fname, "\t%sauto_list_thread=%s", DEBUG_PRINT_STATE(auto_list_thread), print_boolean(scope->attribute->auto_list_thread));
1768 			debug_print_file(fname, "\t%sauto_select=%s", DEBUG_PRINT_STATE(auto_select), print_boolean(scope->attribute->auto_select));
1769 			debug_print_file(fname, "\t%sauto_save=%s", DEBUG_PRINT_STATE(auto_save), print_boolean(scope->attribute->auto_save));
1770 			debug_print_file(fname, "\t%sbatch_save=%s", DEBUG_PRINT_STATE(batch_save), print_boolean(scope->attribute->batch_save));
1771 			debug_print_file(fname, "\t%sdate_format=%s", DEBUG_PRINT_STATE(date_format), DEBUG_PRINT_STRING(date_format));
1772 			debug_print_file(fname, "\t%sdelete_tmp_files=%s", DEBUG_PRINT_STATE(delete_tmp_files), print_boolean(scope->attribute->delete_tmp_files));
1773 			debug_print_file(fname, "\t%seditor_format=%s", DEBUG_PRINT_STATE(editor_format), DEBUG_PRINT_STRING(editor_format));
1774 #	ifdef HAVE_COLOR
1775 			debug_print_file(fname, "\t%sextquote_handling=%s", DEBUG_PRINT_STATE(extquote_handling), print_boolean(scope->attribute->extquote_handling));
1776 #	endif /* HAVE_COLOR */
1777 			debug_print_file(fname, "\t%sgroup_catchup_on_exit=%s", DEBUG_PRINT_STATE(group_catchup_on_exit), print_boolean(scope->attribute->group_catchup_on_exit));
1778 			debug_print_file(fname, "\t%sgroup_format=%s", DEBUG_PRINT_STATE(group_format), DEBUG_PRINT_STRING(group_format));
1779 			debug_print_file(fname, "\t%smail_8bit_header=%s", DEBUG_PRINT_STATE(mail_8bit_header), print_boolean(scope->attribute->mail_8bit_header));
1780 			debug_print_file(fname, "\t%smail_mime_encoding=%s", DEBUG_PRINT_STATE(mail_mime_encoding), txt_mime_encodings[scope->attribute->mail_mime_encoding]);
1781 			debug_print_file(fname, "\t%smark_ignore_tags=%s", DEBUG_PRINT_STATE(mark_ignore_tags), print_boolean(scope->attribute->mark_ignore_tags));
1782 			debug_print_file(fname, "\t%smark_saved_read=%s", DEBUG_PRINT_STATE(mark_saved_read), print_boolean(scope->attribute->mark_saved_read));
1783 			debug_print_file(fname, "\t%snews_headers_to_display=%s", DEBUG_PRINT_STATE(news_headers_to_display), DEBUG_PRINT_STRING(news_headers_to_display));
1784 			if (scope->attribute->headers_to_display) {
1785 				debug_print_file(fname, "\t    headers_to_display->num=%d", scope->attribute->headers_to_display->num);
1786 				for (j = 0; j < scope->attribute->headers_to_display->num; j++)
1787 					debug_print_file(fname, "\t    headers_to_display->header[%d]=%s", j, scope->attribute->headers_to_display->header[j]);
1788 			}
1789 			debug_print_file(fname, "\t%snews_headers_to_not_display=%s", DEBUG_PRINT_STATE(news_headers_to_not_display), DEBUG_PRINT_STRING(news_headers_to_not_display));
1790 			if (scope->attribute->headers_to_not_display) {
1791 				debug_print_file(fname, "\t    headers_to_not_display->num=%d", scope->attribute->headers_to_not_display->num);
1792 				for (j = 0; j < scope->attribute->headers_to_not_display->num; j++)
1793 					debug_print_file(fname, "\t    headers_to_not_display->header[%d]=%s", j, scope->attribute->headers_to_not_display->header[j]);
1794 			}
1795 			debug_print_file(fname, "\t%spos_first_unread=%s", DEBUG_PRINT_STATE(pos_first_unread), print_boolean(scope->attribute->pos_first_unread));
1796 			debug_print_file(fname, "\t%spost_8bit_header=%s", DEBUG_PRINT_STATE(post_8bit_header), print_boolean(scope->attribute->post_8bit_header));
1797 			debug_print_file(fname, "\t%spost_mime_encoding=%s", DEBUG_PRINT_STATE(post_mime_encoding), txt_mime_encodings[scope->attribute->post_mime_encoding]);
1798 			debug_print_file(fname, "\t%spost_process_view=%s", DEBUG_PRINT_STATE(post_process_view), print_boolean(scope->attribute->post_process_view));
1799 #	ifndef DISABLE_PRINTING
1800 			debug_print_file(fname, "\t%sprint_header=%s", DEBUG_PRINT_STATE(print_header), print_boolean(scope->attribute->print_header));
1801 #	endif /* !DISABLE_PRINTING */
1802 			debug_print_file(fname, "\t%sprocess_only_unread=%s", DEBUG_PRINT_STATE(process_only_unread), print_boolean(scope->attribute->process_only_unread));
1803 			debug_print_file(fname, "\t%sprompt_followupto=%s", DEBUG_PRINT_STATE(prompt_followupto), print_boolean(scope->attribute->prompt_followupto));
1804 			debug_print_file(fname, "\t%ssort_article_type=%d", DEBUG_PRINT_STATE(sort_article_type), scope->attribute->sort_article_type);
1805 			debug_print_file(fname, "\t%ssort_threads_type=%d", DEBUG_PRINT_STATE(sort_threads_type), scope->attribute->sort_threads_type);
1806 			debug_print_file(fname, "\t%sshow_author=%d", DEBUG_PRINT_STATE(show_author), scope->attribute->show_author);
1807 			debug_print_file(fname, "\t%sshow_signatures=%s", DEBUG_PRINT_STATE(show_signatures), print_boolean(scope->attribute->show_signatures));
1808 			debug_print_file(fname, "\t%ssigdashes=%s", DEBUG_PRINT_STATE(sigdashes), print_boolean(scope->attribute->sigdashes));
1809 			debug_print_file(fname, "\t%ssignature_repost=%s", DEBUG_PRINT_STATE(signature_repost), print_boolean(scope->attribute->signature_repost));
1810 			debug_print_file(fname, "\t%sstart_editor_offset=%s", DEBUG_PRINT_STATE(start_editor_offset), print_boolean(scope->attribute->start_editor_offset));
1811 			debug_print_file(fname, "\t%sthread_catchup_on_exit=%s", DEBUG_PRINT_STATE(thread_catchup_on_exit), print_boolean(scope->attribute->thread_catchup_on_exit));
1812 			debug_print_file(fname, "\t%sthread_format=%s", DEBUG_PRINT_STATE(thread_format), DEBUG_PRINT_STRING(thread_format));
1813 			debug_print_file(fname, "\t%strim_article_body=%d", DEBUG_PRINT_STATE(trim_article_body), scope->attribute->trim_article_body);
1814 			debug_print_file(fname, "\t%sverbatim_handling=%s", DEBUG_PRINT_STATE(verbatim_handling), print_boolean(scope->attribute->verbatim_handling));
1815 			debug_print_file(fname, "\t%swrap_on_next_unread=%s", DEBUG_PRINT_STATE(wrap_on_next_unread), print_boolean(scope->attribute->wrap_on_next_unread));
1816 			debug_print_file(fname, "\t%spost_process_type=%d", DEBUG_PRINT_STATE(post_process_type), scope->attribute->post_process_type);
1817 			debug_print_file(fname, "\t%squick_kill_scope=%s", DEBUG_PRINT_STATE(quick_kill_scope), DEBUG_PRINT_STRING(quick_kill_scope));
1818 			debug_print_file(fname, "\t%squick_kill_case=%s", DEBUG_PRINT_STATE(quick_kill_case), print_boolean(scope->attribute->quick_kill_case));
1819 			debug_print_file(fname, "\t%squick_kill_expire=%s", DEBUG_PRINT_STATE(quick_kill_expire), print_boolean(scope->attribute->quick_kill_expire));
1820 			debug_print_file(fname, "\t%squick_kill_header=%d", DEBUG_PRINT_STATE(quick_kill_header), scope->attribute->quick_kill_header);
1821 			debug_print_file(fname, "\t%squick_select_scope=%s", DEBUG_PRINT_STATE(quick_select_scope), DEBUG_PRINT_STRING(quick_select_scope));
1822 			debug_print_file(fname, "\t%squick_select_case=%s", DEBUG_PRINT_STATE(quick_select_case), print_boolean(scope->attribute->quick_select_case));
1823 			debug_print_file(fname, "\t%squick_select_expire=%s", DEBUG_PRINT_STATE(quick_select_expire), print_boolean(scope->attribute->quick_select_expire));
1824 			debug_print_file(fname, "\t%squick_select_header=%d", DEBUG_PRINT_STATE(quick_select_header), scope->attribute->quick_select_header);
1825 			debug_print_file(fname, "\t%sx_comment_to=%s", DEBUG_PRINT_STATE(x_comment_to), print_boolean(scope->attribute->x_comment_to));
1826 			debug_print_file(fname, "\t%sfcc=%s", DEBUG_PRINT_STATE(fcc), DEBUG_PRINT_STRING(fcc));
1827 			debug_print_file(fname, "\t%stex2iso_conv=%s", DEBUG_PRINT_STATE(tex2iso_conv), print_boolean(scope->attribute->tex2iso_conv));
1828 			debug_print_file(fname, "\t%smime_forward=%s", DEBUG_PRINT_STATE(mime_forward), print_boolean(scope->attribute->mime_forward));
1829 #	ifdef CHARSET_CONVERSION
1830 			debug_print_file(fname, "\t%smm_network_charset=%s", DEBUG_PRINT_STATE(mm_network_charset), txt_mime_charsets[scope->attribute->mm_network_charset]);
1831 			debug_print_file(fname, "\t%sundeclared_charset=%s", DEBUG_PRINT_STATE(undeclared_charset), DEBUG_PRINT_STRING(undeclared_charset));
1832 #	endif /* CHARSET_CONVERSION */
1833 			debug_print_file(fname, "");
1834 		}
1835 	}
1836 }
1837 #endif /* DEBUG */
1838