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 		num = 25;
641 		set_attrib(OPT_ATTRIB_MM_NETWORK_CHARSET, "*", "", (char *) &num);
642 		set_attrib(OPT_ATTRIB_UNDECLARED_CHARSET, "*", "", "Big5");
643 
644 		add_scope("*sources*");
645 		num = POST_PROC_SHAR;
646 		set_attrib(OPT_ATTRIB_POST_PROCESS_TYPE, "*sources*", "", &num);
647 
648 		add_scope("*binaries*");
649 		num = POST_PROC_YES;
650 		set_attrib(OPT_ATTRIB_POST_PROCESS_TYPE, "*binaries*", "", &num);
651 		num = FALSE;
652 		set_attrib(OPT_ATTRIB_TEX2ISO_CONV, "*binaries*", "", &num);
653 		num = TRUE;
654 		set_attrib(OPT_ATTRIB_DELETE_TMP_FILES, "*binaries*", "", &num);
655 		snprintf(buf, sizeof(buf), "%s", "poster");
656 		set_attrib(OPT_ATTRIB_FOLLOWUP_TO, "*binaries*", "", buf);
657 
658 		write_attributes_file(file);
659 	}
660 	if (!global_file && startup)
661 		startup = FALSE;
662 #ifdef DEBUG
663 	if (!global_file)
664 		dump_scopes("SCOPES-R");
665 #endif /* DEBUG */
666 }
667 
668 
669 #define SET_STRING(string) \
670 	FreeIfNeeded(curr_scope->attribute->string); \
671 	curr_scope->attribute->string = my_strdup((char *) data); \
672 	curr_scope->state->string = TRUE; \
673 	break
674 #define SET_INTEGER(integer) \
675 	curr_scope->attribute->integer = *((int *) data); \
676 	curr_scope->state->integer = TRUE; \
677 	break
678 
679 
680 static void
set_attrib(int type,const char * scope,const char * line,void * data)681 set_attrib(
682 	int type,
683 	const char *scope,
684 	const char *line,
685 	void *data)
686 {
687 	struct t_scope *curr_scope;
688 
689 	if (scope == NULL || *scope == '\0') {	/* No active scope set yet */
690 		error_message(2, _(txt_attrib_no_scope), line);
691 #ifdef DEBUG
692 		if (debug & DEBUG_ATTRIB)
693 			debug_print_file("ATTRIBUTES", txt_attrib_no_scope, line);
694 #endif /* DEBUG */
695 		return;
696 	}
697 
698 	if (num_scope > 1) {
699 		curr_scope = &scopes[num_scope - 1];
700 		/*
701 		 * Now set the required attribute
702 		 */
703 		switch (type) {
704 			case OPT_ATTRIB_MAILDIR:
705 				SET_STRING(maildir);
706 
707 			case OPT_ATTRIB_SAVEDIR:
708 				SET_STRING(savedir);
709 
710 			case OPT_ATTRIB_SAVEFILE:
711 				SET_STRING(savefile);
712 
713 			case OPT_ATTRIB_ORGANIZATION:
714 				SET_STRING(organization);
715 
716 			case OPT_ATTRIB_FROM:
717 				SET_STRING(from);
718 
719 			case OPT_ATTRIB_SIGFILE:
720 				SET_STRING(sigfile);
721 
722 			case OPT_ATTRIB_FOLLOWUP_TO:
723 				SET_STRING(followup_to);
724 
725 			case OPT_ATTRIB_ADD_POSTED_TO_FILTER:
726 				SET_INTEGER(add_posted_to_filter);
727 
728 			case OPT_ATTRIB_ADVERTISING:
729 				SET_INTEGER(advertising);
730 
731 			case OPT_ATTRIB_ALTERNATIVE_HANDLING:
732 				SET_INTEGER(alternative_handling);
733 
734 			case OPT_ATTRIB_ASK_FOR_METAMAIL:
735 				SET_INTEGER(ask_for_metamail);
736 
737 			case OPT_ATTRIB_AUTO_CC_BCC:
738 				SET_INTEGER(auto_cc_bcc);
739 
740 			case OPT_ATTRIB_AUTO_LIST_THREAD:
741 				SET_INTEGER(auto_list_thread);
742 
743 			case OPT_ATTRIB_AUTO_SELECT:
744 				SET_INTEGER(auto_select);
745 
746 			case OPT_ATTRIB_AUTO_SAVE:
747 				SET_INTEGER(auto_save);
748 
749 			case OPT_ATTRIB_BATCH_SAVE:
750 				SET_INTEGER(batch_save);
751 
752 			case OPT_ATTRIB_DATE_FORMAT:
753 				SET_STRING(date_format);
754 
755 			case OPT_ATTRIB_DELETE_TMP_FILES:
756 				SET_INTEGER(delete_tmp_files);
757 
758 			case OPT_ATTRIB_EDITOR_FORMAT:
759 				SET_STRING(editor_format);
760 
761 			case OPT_ATTRIB_GROUP_CATCHUP_ON_EXIT:
762 				SET_INTEGER(group_catchup_on_exit);
763 
764 			case OPT_ATTRIB_GROUP_FORMAT:
765 				SET_STRING(group_format);
766 
767 			case OPT_ATTRIB_MAIL_8BIT_HEADER:
768 				SET_INTEGER(mail_8bit_header);
769 
770 			case OPT_ATTRIB_MAIL_MIME_ENCODING:
771 				SET_INTEGER(mail_mime_encoding);
772 
773 			case OPT_ATTRIB_MARK_IGNORE_TAGS:
774 				SET_INTEGER(mark_ignore_tags);
775 
776 			case OPT_ATTRIB_MARK_SAVED_READ:
777 				SET_INTEGER(mark_saved_read);
778 
779 			case OPT_ATTRIB_NEWS_HEADERS_TO_DISPLAY:
780 				FreeIfNeeded(curr_scope->attribute->news_headers_to_display);
781 				curr_scope->attribute->news_headers_to_display = my_strdup((char *) data);
782 				build_news_headers_array(curr_scope->attribute, TRUE);
783 				curr_scope->state->news_headers_to_display = TRUE;
784 				break;
785 
786 			case OPT_ATTRIB_NEWS_HEADERS_TO_NOT_DISPLAY:
787 				FreeIfNeeded(curr_scope->attribute->news_headers_to_not_display);
788 				curr_scope->attribute->news_headers_to_not_display = my_strdup((char *) data);
789 				build_news_headers_array(curr_scope->attribute, FALSE);
790 				curr_scope->state->news_headers_to_not_display = TRUE;
791 				break;
792 
793 			case OPT_ATTRIB_POS_FIRST_UNREAD:
794 				SET_INTEGER(pos_first_unread);
795 
796 			case OPT_ATTRIB_POST_8BIT_HEADER:
797 				SET_INTEGER(post_8bit_header);
798 
799 			case OPT_ATTRIB_POST_MIME_ENCODING:
800 				SET_INTEGER(post_mime_encoding);
801 
802 			case OPT_ATTRIB_POST_PROCESS_VIEW:
803 				SET_INTEGER(post_process_view);
804 
805 #ifndef DISABLE_PRINTING
806 			case OPT_ATTRIB_PRINT_HEADER:
807 				SET_INTEGER(print_header);
808 #endif /* !DISABLE_PRINTING */
809 
810 			case OPT_ATTRIB_PROCESS_ONLY_UNREAD:
811 				SET_INTEGER(process_only_unread);
812 
813 			case OPT_ATTRIB_PROMPT_FOLLOWUPTO:
814 				SET_INTEGER(prompt_followupto);
815 
816 #ifdef HAVE_COLOR
817 			case OPT_ATTRIB_EXTQUOTE_HANDLING:
818 				SET_INTEGER(extquote_handling);
819 #endif /* HAVE_COLOR */
820 
821 			case OPT_ATTRIB_SHOW_ONLY_UNREAD_ARTS:
822 				SET_INTEGER(show_only_unread_arts);
823 
824 			case OPT_ATTRIB_SIGDASHES:
825 				SET_INTEGER(sigdashes);
826 
827 			case OPT_ATTRIB_SIGNATURE_REPOST:
828 				SET_INTEGER(signature_repost);
829 
830 			case OPT_ATTRIB_START_EDITOR_OFFSET:
831 				SET_INTEGER(start_editor_offset);
832 
833 			case OPT_ATTRIB_THREAD_ARTICLES:
834 				SET_INTEGER(thread_articles);
835 
836 			case OPT_ATTRIB_THREAD_CATCHUP_ON_EXIT:
837 				SET_INTEGER(thread_catchup_on_exit);
838 
839 			case OPT_ATTRIB_THREAD_FORMAT:
840 				SET_STRING(thread_format);
841 
842 			case OPT_ATTRIB_THREAD_PERC:
843 				SET_INTEGER(thread_perc);
844 
845 			case OPT_ATTRIB_SHOW_AUTHOR:
846 				SET_INTEGER(show_author);
847 
848 			case OPT_ATTRIB_SHOW_SIGNATURES:
849 				SET_INTEGER(show_signatures);
850 
851 			case OPT_ATTRIB_TRIM_ARTICLE_BODY:
852 				SET_INTEGER(trim_article_body);
853 
854 			case OPT_ATTRIB_VERBATIM_HANDLING:
855 				SET_INTEGER(verbatim_handling);
856 
857 			case OPT_ATTRIB_WRAP_ON_NEXT_UNREAD:
858 				SET_INTEGER(wrap_on_next_unread);
859 
860 			case OPT_ATTRIB_SORT_ARTICLE_TYPE:
861 				SET_INTEGER(sort_article_type);
862 
863 			case OPT_ATTRIB_SORT_THREADS_TYPE:
864 				SET_INTEGER(sort_threads_type);
865 
866 			case OPT_ATTRIB_POST_PROCESS_TYPE:
867 				SET_INTEGER(post_process_type);
868 
869 			case OPT_ATTRIB_QUICK_KILL_HEADER:
870 				SET_INTEGER(quick_kill_header);
871 
872 			case OPT_ATTRIB_QUICK_KILL_SCOPE:
873 				SET_STRING(quick_kill_scope);
874 
875 			case OPT_ATTRIB_QUICK_KILL_EXPIRE:
876 				SET_INTEGER(quick_kill_expire);
877 
878 			case OPT_ATTRIB_QUICK_KILL_CASE:
879 				SET_INTEGER(quick_kill_case);
880 
881 			case OPT_ATTRIB_QUICK_SELECT_HEADER:
882 				SET_INTEGER(quick_select_header);
883 
884 			case OPT_ATTRIB_QUICK_SELECT_SCOPE:
885 				SET_STRING(quick_select_scope);
886 
887 			case OPT_ATTRIB_QUICK_SELECT_EXPIRE:
888 				SET_INTEGER(quick_select_expire);
889 
890 			case OPT_ATTRIB_QUICK_SELECT_CASE:
891 				SET_INTEGER(quick_select_case);
892 
893 			case OPT_ATTRIB_MAILING_LIST:
894 				SET_STRING(mailing_list);
895 
896 #ifdef CHARSET_CONVERSION
897 			case OPT_ATTRIB_MM_NETWORK_CHARSET:
898 				SET_INTEGER(mm_network_charset);
899 
900 			case OPT_ATTRIB_UNDECLARED_CHARSET:
901 				SET_STRING(undeclared_charset);
902 #endif /* CHARSET_CONVERSION */
903 
904 			case OPT_ATTRIB_X_HEADERS:
905 				SET_STRING(x_headers);
906 
907 			case OPT_ATTRIB_X_BODY:
908 				SET_STRING(x_body);
909 
910 			case OPT_ATTRIB_X_COMMENT_TO:
911 				SET_INTEGER(x_comment_to);
912 
913 			case OPT_ATTRIB_FCC:
914 				SET_STRING(fcc);
915 
916 			case OPT_ATTRIB_NEWS_QUOTE_FORMAT:
917 				SET_STRING(news_quote_format);
918 
919 			case OPT_ATTRIB_QUOTE_CHARS:
920 				SET_STRING(quote_chars);
921 
922 			case OPT_ATTRIB_MIME_TYPES_TO_SAVE:
923 				SET_STRING(mime_types_to_save);
924 
925 			case OPT_ATTRIB_MIME_FORWARD:
926 				SET_INTEGER(mime_forward);
927 
928 #ifdef HAVE_ISPELL
929 			case OPT_ATTRIB_ISPELL:
930 				SET_STRING(ispell);
931 #endif /* HAVE_ISPELL */
932 
933 			case OPT_ATTRIB_TEX2ISO_CONV:
934 				SET_INTEGER(tex2iso_conv);
935 
936 			default:
937 				break;
938 		}
939 	}
940 }
941 
942 
943 /*
944  * Insert a new scope entry into scopes[] and return the index.
945  */
946 int
add_scope(const char * scope)947 add_scope(
948 	const char *scope)
949 {
950 	if (!scope || !*scope)
951 		return 0;
952 
953 	if ((num_scope >= max_scope) || (num_scope < 0) || (scopes == NULL))
954 		expand_scope();
955 
956 	scopes[num_scope].scope = my_strdup(scope);
957 	scopes[num_scope].attribute = my_malloc(sizeof(struct t_attribute));
958 	set_default_attributes(scopes[num_scope].attribute, NULL, FALSE);
959 	scopes[num_scope].state = my_malloc(sizeof(struct t_attribute_state));
960 	set_default_state(scopes[num_scope].state);
961 	scopes[num_scope].global = FALSE;
962 	return num_scope++;
963 }
964 
965 
966 #define SET_ATTRIB(attr) do { \
967 		if (curr_scope->state->attr) \
968 			group->attribute->attr = curr_scope->attribute->attr; \
969 	} while (0)
970 
971 
972 /*
973  * Set the attributes of all groups
974  */
975 void
assign_attributes_to_groups(void)976 assign_attributes_to_groups(
977 	void)
978 {
979 	struct t_group *group;
980 	struct t_scope *default_scope, *curr_scope;
981 	t_bool found;
982 	int i, j;
983 	long processed = 0L;
984 #ifdef CHARSET_CONVERSION
985 	t_bool is_7bit;
986 #endif /* CHARSET_CONVERSION */
987 
988 	if (!batch_mode || verbose)
989 		wait_message(0, _("Processing attributes... ")); /* TODO: -> lang.c */
990 
991 	default_scope = &scopes[0];
992 	for_each_group(i) {
993 		if (++processed % (MODULO_COUNT_NUM) == 0)
994 			spin_cursor();
995 		group = &active[i];
996 		found = FALSE;
997 		for (j = 1; j < num_scope; j++) {
998 			curr_scope = &scopes[j];
999 			if (match_group_list(group->name, curr_scope->scope)) {
1000 				if (group->attribute == NULL || group->attribute == default_scope->attribute) {
1001 					group->attribute = my_malloc(sizeof(struct t_attribute));
1002 					set_default_attributes(group->attribute, default_scope->attribute, FALSE);
1003 					found = TRUE;
1004 				}
1005 				if (!found) {
1006 					set_default_attributes(group->attribute, default_scope->attribute, FALSE);
1007 					found = TRUE;
1008 				}
1009 				SET_ATTRIB(maildir);
1010 				SET_ATTRIB(savedir);
1011 				SET_ATTRIB(savefile);
1012 				SET_ATTRIB(sigfile);
1013 				SET_ATTRIB(group_format);
1014 				SET_ATTRIB(thread_format);
1015 				SET_ATTRIB(date_format);
1016 				SET_ATTRIB(editor_format);
1017 				SET_ATTRIB(organization);
1018 				SET_ATTRIB(fcc);
1019 				SET_ATTRIB(followup_to);
1020 				SET_ATTRIB(mailing_list);
1021 				SET_ATTRIB(x_headers);
1022 				SET_ATTRIB(x_body);
1023 				SET_ATTRIB(from);
1024 				SET_ATTRIB(news_quote_format);
1025 				SET_ATTRIB(quote_chars);
1026 				SET_ATTRIB(mime_types_to_save);
1027 #ifdef HAVE_ISPELL
1028 				SET_ATTRIB(ispell);
1029 #endif /* HAVE_ISPELL */
1030 #ifdef CHARSET_CONVERSION
1031 				SET_ATTRIB(mm_network_charset);
1032 				SET_ATTRIB(undeclared_charset);
1033 #endif /* CHARSET_CONVERSION */
1034 				SET_ATTRIB(quick_kill_scope);
1035 				SET_ATTRIB(quick_kill_header);
1036 				SET_ATTRIB(quick_kill_case);
1037 				SET_ATTRIB(quick_kill_expire);
1038 				SET_ATTRIB(quick_select_scope);
1039 				SET_ATTRIB(quick_select_header);
1040 				SET_ATTRIB(quick_select_case);
1041 				SET_ATTRIB(quick_select_expire);
1042 				SET_ATTRIB(show_only_unread_arts);
1043 				SET_ATTRIB(thread_articles);
1044 				SET_ATTRIB(thread_catchup_on_exit);
1045 				SET_ATTRIB(thread_perc);
1046 				SET_ATTRIB(sort_article_type);
1047 				SET_ATTRIB(sort_threads_type);
1048 				SET_ATTRIB(show_author);
1049 				SET_ATTRIB(show_signatures);
1050 				SET_ATTRIB(trim_article_body);
1051 				SET_ATTRIB(verbatim_handling);
1052 #ifdef HAVE_COLOR
1053 				SET_ATTRIB(extquote_handling);
1054 #endif /* HAVE_COLOR */
1055 				SET_ATTRIB(wrap_on_next_unread);
1056 				SET_ATTRIB(add_posted_to_filter);
1057 				SET_ATTRIB(advertising);
1058 				SET_ATTRIB(alternative_handling);
1059 				SET_ATTRIB(ask_for_metamail);
1060 				SET_ATTRIB(auto_cc_bcc);
1061 				SET_ATTRIB(auto_list_thread);
1062 				SET_ATTRIB(auto_save);
1063 				SET_ATTRIB(auto_select);
1064 				SET_ATTRIB(batch_save);
1065 				SET_ATTRIB(delete_tmp_files);
1066 				SET_ATTRIB(group_catchup_on_exit);
1067 				SET_ATTRIB(mail_8bit_header);
1068 				SET_ATTRIB(mail_mime_encoding);
1069 				SET_ATTRIB(mark_ignore_tags);
1070 				SET_ATTRIB(mark_saved_read);
1071 				if (curr_scope->state->news_headers_to_display)
1072 					group->attribute->headers_to_display = curr_scope->attribute->headers_to_display;
1073 				if (curr_scope->state->news_headers_to_not_display)
1074 					group->attribute->headers_to_not_display = curr_scope->attribute->headers_to_not_display;
1075 				SET_ATTRIB(pos_first_unread);
1076 				SET_ATTRIB(post_8bit_header);
1077 				SET_ATTRIB(post_mime_encoding);
1078 				SET_ATTRIB(post_process_view);
1079 				SET_ATTRIB(post_process_type);
1080 #ifndef DISABLE_PRINTING
1081 				SET_ATTRIB(print_header);
1082 #endif /* !DISABLE_PRINTING */
1083 				SET_ATTRIB(process_only_unread);
1084 				SET_ATTRIB(prompt_followupto);
1085 				SET_ATTRIB(sigdashes);
1086 				SET_ATTRIB(signature_repost);
1087 				SET_ATTRIB(start_editor_offset);
1088 				SET_ATTRIB(x_comment_to);
1089 				SET_ATTRIB(tex2iso_conv);
1090 				SET_ATTRIB(mime_forward);
1091 			}
1092 		}
1093 		if (found) {
1094 			/*
1095 			 * sort out conflicting settings
1096 			 */
1097 #ifdef CHARSET_CONVERSION
1098 			/*
1099 			 * check if we have a 7bit charset but a !7bit encoding
1100 			 * or a 8bit charset but a !8bit encoding, update encoding if needed
1101 			 */
1102 			is_7bit = FALSE;
1103 			for (j = 0; txt_mime_7bit_charsets[j] != NULL; j++) {
1104 				if (!strcasecmp(txt_mime_charsets[group->attribute->mm_network_charset], txt_mime_7bit_charsets[j])) {
1105 					is_7bit = TRUE;
1106 					break;
1107 				}
1108 			}
1109 			if (is_7bit) {
1110 				group->attribute->mail_mime_encoding = group->attribute->post_mime_encoding = MIME_ENCODING_7BIT;
1111 			} else {
1112 				if (group->attribute->mail_mime_encoding == MIME_ENCODING_7BIT)
1113 					group->attribute->mail_mime_encoding = MIME_ENCODING_QP;
1114 				if (group->attribute->post_mime_encoding == MIME_ENCODING_7BIT)
1115 					group->attribute->post_mime_encoding = MIME_ENCODING_8BIT;
1116 			}
1117 #endif /* CHARSET_CONVERSION */
1118 			/* do not use 8 bit headers if mime encoding is not 8bit */
1119 			if (group->attribute->mail_mime_encoding != MIME_ENCODING_8BIT)
1120 				group->attribute->mail_8bit_header = FALSE;
1121 			if (group->attribute->post_mime_encoding != MIME_ENCODING_8BIT)
1122 				group->attribute->post_8bit_header = FALSE;
1123 		} else {
1124 			if (group->attribute && !group->attribute->global)
1125 				free(group->attribute);
1126 			group->attribute = default_scope->attribute;
1127 		}
1128 	}
1129 #ifdef DEBUG
1130 	dump_attributes();
1131 #	if 0
1132 	debug_print_filter_attributes();
1133 #	endif /* 0 */
1134 #endif /* DEBUG */
1135 
1136 	if (!batch_mode || verbose)
1137 		my_fputc('\n', stdout);
1138 
1139 	if (!cmd_line && !batch_mode)
1140 		clear_message();
1141 }
1142 
1143 
1144 /*
1145  * (re)build scope->headers_to_[not_]display array
1146  */
1147 void
build_news_headers_array(struct t_attribute * scope,t_bool header_to_display)1148 build_news_headers_array(
1149 	struct t_attribute *scope,
1150 	t_bool header_to_display)
1151 {
1152 	if (header_to_display) {
1153 		if (scope->headers_to_display == NULL)
1154 			scope->headers_to_display = my_malloc(sizeof(struct t_newsheader));
1155 		else {
1156 			if (scope->headers_to_display->header)
1157 				FreeIfNeeded(*scope->headers_to_display->header);
1158 			FreeIfNeeded(scope->headers_to_display->header);
1159 		}
1160 		scope->headers_to_display->header = ulBuildArgv(scope->news_headers_to_display, &scope->headers_to_display->num);
1161 	} else {
1162 		if (scope->headers_to_not_display == NULL)
1163 			scope->headers_to_not_display = my_malloc(sizeof(struct t_newsheader));
1164 		else {
1165 			if (scope->headers_to_not_display->header)
1166 				FreeIfNeeded(*scope->headers_to_not_display->header);
1167 			FreeIfNeeded(scope->headers_to_not_display->header);
1168 		}
1169 		scope->headers_to_not_display->header = ulBuildArgv(scope->news_headers_to_not_display, &scope->headers_to_not_display->num);
1170 	}
1171 }
1172 
1173 
1174 /*
1175  * Save the scope attributes from scopes[] to ~/.tin/attributes
1176  */
1177 void
write_attributes_file(const char * file)1178 write_attributes_file(
1179 	const char *file)
1180 {
1181 	FILE *fp;
1182 	char *new_file;
1183 	int i;
1184 	long fpos;
1185 
1186 	if ((batch_mode || no_write || num_scope < 1) && file_size(file) != -1L)
1187 		return;
1188 
1189 	new_file = get_tmpfilename(file);
1190 
1191 	if ((fp = fopen(new_file, "w+")) == NULL) {
1192 		error_message(2, _(txt_filesystem_full_backup), ATTRIBUTES_FILE);
1193 		free(new_file);
1194 		return;
1195 	}
1196 
1197 	wait_message(0, _(txt_writing_attributes_file));
1198 
1199 #ifdef DEBUG
1200 	dump_scopes("SCOPES-W");
1201 #endif /* DEBUG */
1202 
1203 	/*
1204 	 * TODO: sort in a useful order
1205 	 *       move strings to lang.c
1206 	 */
1207 	fprintf(fp, "# Group attributes file V%s for the TIN newsreader\n", ATTRIBUTES_VERSION);
1208 	fprintf(fp, _("# Do not edit this comment block\n#\n"));
1209 	fprintf(fp, _("#  scope=STRING (eg. alt.*,!alt.bin*) [mandatory]\n"));
1210 	fprintf(fp, _("#  add_posted_to_filter=ON/OFF\n"));
1211 	fprintf(fp, _("#  advertising=ON/OFF\n"));
1212 	fprintf(fp, _("#  alternative_handling=ON/OFF\n"));
1213 	fprintf(fp, _("#  ask_for_metamail=ON/OFF\n"));
1214 	fprintf(fp, _("#  auto_cc_bcc=NUM\n"));
1215 	fprintf(fp, _("#    0=No, 1=Cc, 2=Bcc, 3=Cc and Bcc\n"));
1216 	fprintf(fp, _("#  auto_list_thread=ON/OFF\n"));
1217 	fprintf(fp, _("#  auto_save=ON/OFF\n"));
1218 	fprintf(fp, _("#  auto_select=ON/OFF\n"));
1219 	fprintf(fp, _("#  batch_save=ON/OFF\n"));
1220 	fprintf(fp, _("#  date_format=STRING (eg. %%a, %%d %%b %%Y %%H:%%M:%%S)\n"));
1221 	fprintf(fp, _("#  delete_tmp_files=ON/OFF\n"));
1222 	fprintf(fp, _("#  editor_format=STRING (eg. %%E +%%N %%F)\n"));
1223 	fprintf(fp, _("#  fcc=STRING (eg. =mailbox)\n"));
1224 	fprintf(fp, _("#  followup_to=STRING\n"));
1225 	fprintf(fp, _("#  from=STRING (just append wanted From:-line, don't use quotes)\n"));
1226 	fprintf(fp, _("#  group_catchup_on_exit=ON/OFF\n"));
1227 	fprintf(fp, _("#  group_format=STRING (eg. %%n %%m %%R %%L  %%s  %%F)\n"));
1228 	fprintf(fp, _("#  mail_8bit_header=ON/OFF\n"));
1229 	fprintf(fp, _("#  mail_mime_encoding=supported_encoding"));
1230 	for (i = 0; txt_mime_encodings[i] != NULL; i++) {
1231 		if (!(i % 5))
1232 			fprintf(fp, "\n#    ");
1233 		fprintf(fp, "%s, ", txt_mime_encodings[i]);
1234 	}
1235 	fprintf(fp, "\n");
1236 #ifdef HAVE_ISPELL
1237 	fprintf(fp, _("#  ispell=STRING\n"));
1238 #endif /* HAVE_ISPELL */
1239 	fprintf(fp, _("#  maildir=STRING (eg. ~/Mail)\n"));
1240 	fprintf(fp, _("#  mailing_list=STRING (eg. majordomo@example.org)\n"));
1241 	fprintf(fp, _("#  mime_types_to_save=STRING (eg. image/*,!image/bmp)\n"));
1242 	fprintf(fp, _("#  mark_ignore_tags=ON/OFF\n"));
1243 	fprintf(fp, _("#  mark_saved_read=ON/OFF\n"));
1244 	fprintf(fp, _("#  mime_forward=ON/OFF\n"));
1245 #ifdef CHARSET_CONVERSION
1246 	fprintf(fp, _("#  mm_network_charset=supported_charset"));
1247 	for (i = 0; txt_mime_charsets[i] != NULL; i++) {
1248 		if (!(i % 5)) /* start new line */
1249 			fprintf(fp, "\n#    ");
1250 		fprintf(fp, "%s, ", txt_mime_charsets[i]);
1251 	}
1252 	fprintf(fp, "\n");
1253 	fprintf(fp, _("#  undeclared_charset=STRING (default is US-ASCII)\n"));
1254 #endif /* CHARSET_CONVERSION */
1255 	fprintf(fp, _("#  news_headers_to_display=STRING\n"));
1256 	fprintf(fp, _("#  news_headers_to_not_display=STRING\n"));
1257 	fprintf(fp, _("#  news_quote_format=STRING\n"));
1258 	fprintf(fp, _("#  organization=STRING (if beginning with '/' read from file)\n"));
1259 	fprintf(fp, _("#  pos_first_unread=ON/OFF\n"));
1260 	fprintf(fp, _("#  post_8bit_header=ON/OFF\n"));
1261 	fprintf(fp, _("#  post_mime_encoding=supported_encoding"));
1262 	for (i = 0; txt_mime_encodings[i] != NULL; i++) {
1263 		if (!(i % 5))
1264 			fprintf(fp, "\n#    ");
1265 		fprintf(fp, "%s, ", txt_mime_encodings[i]);
1266 	}
1267 	fprintf(fp, "\n");
1268 	fprintf(fp, _("#  post_process_type=NUM\n"));
1269 	fprintf(fp, "#    %d=%s, %d=%s, %d=%s\n",
1270 		POST_PROC_NO, _(txt_post_process_types[POST_PROC_NO]),
1271 		POST_PROC_SHAR, _(txt_post_process_types[POST_PROC_SHAR]),
1272 		POST_PROC_YES, _(txt_post_process_types[POST_PROC_YES]));
1273 	fprintf(fp, _("#  post_process_view=ON/OFF\n"));
1274 	fprintf(fp, _("#  quick_kill_scope=STRING (ie. talk.*)\n"));
1275 	fprintf(fp, _("#  quick_kill_expire=ON/OFF\n"));
1276 	fprintf(fp, _("#  quick_kill_case=ON/OFF\n"));
1277 	fprintf(fp, _("#  quick_kill_header=NUM\n"));
1278 	fprintf(fp, _("#    0=Subject: (case sensitive)  1=Subject: (ignore case)\n"));
1279 	fprintf(fp, _("#    2=From: (case sensitive)     3=From: (ignore case)\n"));
1280 	fprintf(fp, _("#    4=Message-ID: & full References: line\n"));
1281 	fprintf(fp, _("#    5=Message-ID: & last References: entry only\n"));
1282 	fprintf(fp, _("#    6=Message-ID: entry only     7=Lines:\n"));
1283 	fprintf(fp, _("#  quick_select_scope=STRING\n"));
1284 	fprintf(fp, _("#  quick_select_expire=ON/OFF\n"));
1285 	fprintf(fp, _("#  quick_select_case=ON/OFF\n"));
1286 	fprintf(fp, _("#  quick_select_header=NUM\n"));
1287 	fprintf(fp, _("#    0=Subject: (case sensitive)  1=Subject: (ignore case)\n"));
1288 	fprintf(fp, _("#    2=From: (case sensitive)     3=From: (ignore case)\n"));
1289 	fprintf(fp, _("#    4=Message-ID: & full References: line\n"));
1290 	fprintf(fp, _("#    5=Message-ID: & last References: entry only\n"));
1291 	fprintf(fp, _("#    6=Message-ID: entry only     7=Lines:\n"));
1292 	fprintf(fp, _("#  quote_chars=STRING (%%I for initials)\n"));
1293 #ifndef DISABLE_PRINTING
1294 	fprintf(fp, _("#  print_header=ON/OFF\n"));
1295 #endif /* !DISABLE_PRINTING */
1296 	fprintf(fp, _("#  process_only_unread=ON/OFF\n"));
1297 	fprintf(fp, _("#  prompt_followupto=ON/OFF\n"));
1298 	fprintf(fp, _("#  savedir=STRING (eg. ~user/News)\n"));
1299 	fprintf(fp, _("#  savefile=STRING (eg. =linux)\n"));
1300 	fprintf(fp, _("#  sigfile=STRING (eg. $var/sig)\n"));
1301 	fprintf(fp, _("#  show_author=NUM\n"));
1302 	fprintf(fp, "#    %d=%s, %d=%s, %d=%s, %d=%s\n",
1303 		SHOW_FROM_NONE, _(txt_show_from[SHOW_FROM_NONE]),
1304 		SHOW_FROM_ADDR, _(txt_show_from[SHOW_FROM_ADDR]),
1305 		SHOW_FROM_NAME, _(txt_show_from[SHOW_FROM_NAME]),
1306 		SHOW_FROM_BOTH, _(txt_show_from[SHOW_FROM_BOTH]));
1307 	fprintf(fp, _("#  show_signatures=ON/OFF\n"));
1308 	fprintf(fp, _("#  show_only_unread_arts=ON/OFF\n"));
1309 	fprintf(fp, _("#  sigdashes=ON/OFF\n"));
1310 	fprintf(fp, _("#  signature_repost=ON/OFF\n"));
1311 	fprintf(fp, _("#  sort_article_type=NUM\n"));
1312 	fprintf(fp, "#    %d=%s,\n",
1313 		SORT_ARTICLES_BY_NOTHING, _(txt_sort_a_type[SORT_ARTICLES_BY_NOTHING]));
1314 	fprintf(fp, "#    %d=%s, %d=%s,\n",
1315 		SORT_ARTICLES_BY_SUBJ_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_SUBJ_DESCEND]),
1316 		SORT_ARTICLES_BY_SUBJ_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_SUBJ_ASCEND]));
1317 	fprintf(fp, "#    %d=%s, %d=%s,\n",
1318 		SORT_ARTICLES_BY_FROM_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_FROM_DESCEND]),
1319 		SORT_ARTICLES_BY_FROM_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_FROM_ASCEND]));
1320 	fprintf(fp, "#    %d=%s, %d=%s,\n",
1321 		SORT_ARTICLES_BY_DATE_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_DATE_DESCEND]),
1322 		SORT_ARTICLES_BY_DATE_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_DATE_ASCEND]));
1323 	fprintf(fp, "#    %d=%s, %d=%s,\n",
1324 		SORT_ARTICLES_BY_SCORE_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_SCORE_DESCEND]),
1325 		SORT_ARTICLES_BY_SCORE_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_SCORE_ASCEND]));
1326 	fprintf(fp, "#    %d=%s, %d=%s\n",
1327 		SORT_ARTICLES_BY_LINES_DESCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_LINES_DESCEND]),
1328 		SORT_ARTICLES_BY_LINES_ASCEND, _(txt_sort_a_type[SORT_ARTICLES_BY_LINES_ASCEND]));
1329 	fprintf(fp, _("#  sort_threads_type=NUM\n"));
1330 	fprintf(fp, "#    %d=%s, %d=%s, %d=%s\n",
1331 		SORT_THREADS_BY_NOTHING, _(txt_sort_t_type[SORT_THREADS_BY_NOTHING]),
1332 		SORT_THREADS_BY_SCORE_DESCEND, _(txt_sort_t_type[SORT_THREADS_BY_SCORE_DESCEND]),
1333 		SORT_THREADS_BY_SCORE_ASCEND, _(txt_sort_t_type[SORT_THREADS_BY_SCORE_ASCEND]));
1334 	fprintf(fp, "#    %d=%s\n",
1335 		SORT_THREADS_BY_LAST_POSTING_DATE_DESCEND, _(txt_sort_t_type[SORT_THREADS_BY_LAST_POSTING_DATE_DESCEND]));
1336 	fprintf(fp, "#    %d=%s\n",
1337 		SORT_THREADS_BY_LAST_POSTING_DATE_ASCEND, _(txt_sort_t_type[SORT_THREADS_BY_LAST_POSTING_DATE_ASCEND]));
1338 	fprintf(fp, _("#  start_editor_offset=ON/OFF\n"));
1339 	fprintf(fp, _("#  tex2iso_conv=ON/OFF\n"));
1340 	fprintf(fp, _("#  thread_catchup_on_exit=ON/OFF\n"));
1341 	fprintf(fp, _("#  thread_articles=NUM"));
1342 	for (i = 0; i <= THREAD_MAX; i++) {
1343 		if (!(i % 2))
1344 			fprintf(fp, "\n#    ");
1345 		fprintf(fp, "%d=%s, ", i, _(txt_threading[i]));
1346 	}
1347 	fprintf(fp, "\n");
1348 	fprintf(fp, _("#  thread_format=STRING (eg. %%n %%m [%%L]  %%T  %%F)\n"));
1349 	fprintf(fp, _("#  thread_perc=NUM\n"));
1350 	fprintf(fp, _("#  trim_article_body=NUM\n"));
1351 	fprintf(fp, _("#    0 = Don't trim article body\n"));
1352 	fprintf(fp, _("#    1 = Skip leading blank lines\n"));
1353 	fprintf(fp, _("#    2 = Skip trailing blank lines\n"));
1354 	fprintf(fp, _("#    3 = Skip leading and trailing blank lines\n"));
1355 	fprintf(fp, _("#    4 = Compact multiple blank lines between text blocks\n"));
1356 	fprintf(fp, _("#    5 = Compact multiple blank lines between text blocks and skip\n#        leading blank lines\n"));
1357 	fprintf(fp, _("#    6 = Compact multiple blank lines between text blocks and skip\n#        trailing blank lines\n"));
1358 	fprintf(fp, _("#    7 = Compact multiple blank lines between text blocks and skip\n#        leading and trailing blank lines\n"));
1359 	fprintf(fp, _("#  verbatim_handling=ON/OFF\n"));
1360 #ifdef HAVE_COLOR
1361 	fprintf(fp, _("#  extquote_handling=ON/OFF\n"));
1362 #endif /* HAVE_COLOR */
1363 	fprintf(fp, _("#  wrap_on_next_unread=ON/OFF\n"));
1364 	fprintf(fp, _("#  x_body=STRING (eg. ~/.tin/extra-body-text)\n"));
1365 	fprintf(fp, _("#  x_comment_to=ON/OFF\n"));
1366 	fprintf(fp, _("#  x_headers=STRING (eg. ~/.tin/extra-headers)\n"));
1367 	fprintf(fp, _("#\n# Note that it is best to put general (global scoping)\n"));
1368 	fprintf(fp, _("# entries first followed by group specific entries.\n#\n"));
1369 	fprintf(fp, _("############################################################################\n"));
1370 
1371 	/*
1372 	 * determine the file offset
1373 	 * this is necessary because a changed locale setting
1374 	 * may lead to an invalid offset
1375 	 */
1376 	if ((fpos = ftell(fp)) <= 0) {
1377 		clearerr(fp);
1378 		fclose(fp);
1379 		unlink(new_file);
1380 		free(new_file);
1381 		error_message(2, _(txt_filesystem_full), ATTRIBUTES_FILE);
1382 		return;
1383 	}
1384 	rewind(fp);
1385 	attrib_file_offset = 1;
1386 	while ((i = fgetc(fp)) != EOF) {
1387 		if (i == '\n')
1388 			attrib_file_offset++;
1389 	}
1390 	if (fseek(fp, fpos, SEEK_SET)) {
1391 		clearerr(fp);
1392 		fclose(fp);
1393 		unlink(new_file);
1394 		free(new_file);
1395 		error_message(2, _(txt_filesystem_full), ATTRIBUTES_FILE);
1396 		return;
1397 	}
1398 
1399 	if ((num_scope > 0) && (scopes != NULL)) {
1400 		struct t_scope *scope;
1401 
1402 		for (i = 1; i < num_scope; i++) {
1403 			scope = &scopes[i];
1404 			if (!scope->global) {
1405 				fprintf(fp, "\nscope=%s\n", scope->scope);
1406 				if (scope->state->add_posted_to_filter)
1407 					fprintf(fp, "add_posted_to_filter=%s\n", print_boolean(scope->attribute->add_posted_to_filter));
1408 				if (scope->state->advertising)
1409 					fprintf(fp, "advertising=%s\n", print_boolean(scope->attribute->advertising));
1410 				if (scope->state->alternative_handling)
1411 					fprintf(fp, "alternative_handling=%s\n", print_boolean(scope->attribute->alternative_handling));
1412 				if (scope->state->ask_for_metamail)
1413 					fprintf(fp, "ask_for_metamail=%s\n", print_boolean(scope->attribute->ask_for_metamail));
1414 				if (scope->state->auto_cc_bcc)
1415 					fprintf(fp, "auto_cc_bcc=%u\n", scope->attribute->auto_cc_bcc);
1416 				if (scope->state->auto_list_thread)
1417 					fprintf(fp, "auto_list_thread=%s\n", print_boolean(scope->attribute->auto_list_thread));
1418 				if (scope->state->auto_select)
1419 					fprintf(fp, "auto_select=%s\n", print_boolean(scope->attribute->auto_select));
1420 				if (scope->state->auto_save)
1421 					fprintf(fp, "auto_save=%s\n", print_boolean(scope->attribute->auto_save));
1422 				if (scope->state->batch_save)
1423 					fprintf(fp, "batch_save=%s\n", print_boolean(scope->attribute->batch_save));
1424 				if (scope->state->date_format && scope->attribute->date_format)
1425 					fprintf(fp, "date_format=%s\n", scope->attribute->date_format);
1426 				if (scope->state->delete_tmp_files)
1427 					fprintf(fp, "delete_tmp_files=%s\n", print_boolean(scope->attribute->delete_tmp_files));
1428 				if (scope->state->editor_format && scope->attribute->editor_format)
1429 					fprintf(fp, "editor_format=%s\n", scope->attribute->editor_format);
1430 #ifdef HAVE_COLOR
1431 				if (scope->state->extquote_handling)
1432 					fprintf(fp, "extquote_handling=%s\n", print_boolean(scope->attribute->extquote_handling));
1433 #endif /* HAVE_COLOR */
1434 				if (scope->state->fcc && scope->attribute->fcc)
1435 					fprintf(fp, "fcc=%s\n", scope->attribute->fcc);
1436 				if (scope->state->followup_to && scope->attribute->followup_to)
1437 					fprintf(fp, "followup_to=%s\n", scope->attribute->followup_to);
1438 				if (scope->state->from && scope->attribute->from)
1439 					fprintf(fp, "from=%s\n", scope->attribute->from);
1440 				if (scope->state->group_catchup_on_exit)
1441 					fprintf(fp, "group_catchup_on_exit=%s\n", print_boolean(scope->attribute->group_catchup_on_exit));
1442 				if (scope->state->group_format && scope->attribute->group_format)
1443 					fprintf(fp, "group_format=%s\n", scope->attribute->group_format);
1444 				if (scope->state->mail_8bit_header)
1445 					fprintf(fp, "mail_8bit_header=%s\n", print_boolean(scope->attribute->mail_8bit_header));
1446 				if (scope->state->mail_mime_encoding)
1447 					fprintf(fp, "mail_mime_encoding=%s\n", txt_mime_encodings[scope->attribute->mail_mime_encoding]);
1448 #ifdef HAVE_ISPELL
1449 				if (scope->state->ispell && scope->attribute->ispell)
1450 					fprintf(fp, "ispell=%s\n", scope->attribute->ispell);
1451 #endif /* HAVE_ISPELL */
1452 				if (scope->state->maildir && scope->attribute->maildir)
1453 					fprintf(fp, "maildir=%s\n", scope->attribute->maildir);
1454 				if (scope->state->mailing_list && scope->attribute->mailing_list)
1455 					fprintf(fp, "mailing_list=%s\n", scope->attribute->mailing_list);
1456 				if (scope->state->mark_ignore_tags)
1457 					fprintf(fp, "mark_ignore_tags=%s\n", print_boolean(scope->attribute->mark_ignore_tags));
1458 				if (scope->state->mark_saved_read)
1459 					fprintf(fp, "mark_saved_read=%s\n", print_boolean(scope->attribute->mark_saved_read));
1460 				if (scope->state->mime_forward)
1461 					fprintf(fp, "mime_forward=%s\n", print_boolean(scope->attribute->mime_forward));
1462 				if (scope->state->mime_types_to_save && scope->attribute->mime_types_to_save)
1463 					fprintf(fp, "mime_types_to_save=%s\n", scope->attribute->mime_types_to_save);
1464 #ifdef CHARSET_CONVERSION
1465 				if (scope->state->mm_network_charset)
1466 					fprintf(fp, "mm_network_charset=%s\n", txt_mime_charsets[scope->attribute->mm_network_charset]);
1467 				if (scope->state->undeclared_charset && scope->attribute->undeclared_charset)
1468 					fprintf(fp, "undeclared_charset=%s\n", scope->attribute->undeclared_charset);
1469 #endif /* CHARSET_CONVERSION */
1470 				if (scope->state->news_headers_to_display && scope->attribute->news_headers_to_display)
1471 					fprintf(fp, "news_headers_to_display=%s\n", scope->attribute->news_headers_to_display);
1472 				if (scope->state->news_headers_to_not_display && scope->attribute->news_headers_to_not_display)
1473 					fprintf(fp, "news_headers_to_not_display=%s\n", scope->attribute->news_headers_to_not_display);
1474 				if (scope->state->news_quote_format && scope->attribute->news_quote_format)
1475 					fprintf(fp, "news_quote_format=%s\n", scope->attribute->news_quote_format);
1476 				if (scope->state->organization && scope->attribute->organization)
1477 					fprintf(fp, "organization=%s\n", scope->attribute->organization);
1478 				if (scope->state->pos_first_unread)
1479 					fprintf(fp, "pos_first_unread=%s\n", print_boolean(scope->attribute->pos_first_unread));
1480 				if (scope->state->post_8bit_header)
1481 					fprintf(fp, "post_8bit_header=%s\n", print_boolean(scope->attribute->post_8bit_header));
1482 				if (scope->state->post_mime_encoding)
1483 					fprintf(fp, "post_mime_encoding=%s\n", txt_mime_encodings[scope->attribute->post_mime_encoding]);
1484 				if (scope->state->post_process_view)
1485 					fprintf(fp, "post_process_view=%s\n", print_boolean(scope->attribute->post_process_view));
1486 				if (scope->state->post_process_type)
1487 					fprintf(fp, "post_process_type=%u\n", scope->attribute->post_process_type);
1488 #ifndef DISABLE_PRINTING
1489 				if (scope->state->print_header)
1490 					fprintf(fp, "print_header=%s\n", print_boolean(scope->attribute->print_header));
1491 #endif /* !DISABLE_PRINTING */
1492 				if (scope->state->process_only_unread)
1493 					fprintf(fp, "process_only_unread=%s\n", print_boolean(scope->attribute->process_only_unread));
1494 				if (scope->state->prompt_followupto)
1495 					fprintf(fp, "prompt_followupto=%s\n", print_boolean(scope->attribute->prompt_followupto));
1496 				if (scope->state->quick_kill_scope && scope->attribute->quick_kill_scope)
1497 					fprintf(fp, "quick_kill_scope=%s\n", scope->attribute->quick_kill_scope);
1498 				if (scope->state->quick_kill_case)
1499 					fprintf(fp, "quick_kill_case=%s\n", print_boolean(scope->attribute->quick_kill_case));
1500 				if (scope->state->quick_kill_expire)
1501 					fprintf(fp, "quick_kill_expire=%s\n", print_boolean(scope->attribute->quick_kill_expire));
1502 				if (scope->state->quick_kill_header)
1503 					fprintf(fp, "quick_kill_header=%u\n", scope->attribute->quick_kill_header);
1504 				if (scope->state->quick_select_scope && scope->attribute->quick_select_scope)
1505 					fprintf(fp, "quick_select_scope=%s\n", scope->attribute->quick_select_scope);
1506 				if (scope->state->quick_select_case)
1507 					fprintf(fp, "quick_select_case=%s\n", print_boolean(scope->attribute->quick_select_case));
1508 				if (scope->state->quick_select_expire)
1509 					fprintf(fp, "quick_select_expire=%s\n", print_boolean(scope->attribute->quick_select_expire));
1510 				if (scope->state->quick_select_header)
1511 					fprintf(fp, "quick_select_header=%u\n", scope->attribute->quick_select_header);
1512 				if (scope->state->quote_chars && scope->attribute->quote_chars)
1513 					fprintf(fp, "quote_chars=%s\n", quote_space_to_dash(scope->attribute->quote_chars));
1514 				if (scope->state->savedir && scope->attribute->savedir)
1515 					fprintf(fp, "savedir=%s\n", scope->attribute->savedir);
1516 				if (scope->state->savefile && scope->attribute->savefile)
1517 					fprintf(fp, "savefile=%s\n", scope->attribute->savefile);
1518 				if (scope->state->show_author)
1519 					fprintf(fp, "show_author=%u\n", scope->attribute->show_author);
1520 				if (scope->state->show_only_unread_arts)
1521 					fprintf(fp, "show_only_unread_arts=%s\n", print_boolean(scope->attribute->show_only_unread_arts));
1522 				if (scope->state->show_signatures)
1523 					fprintf(fp, "show_signatures=%s\n", print_boolean(scope->attribute->show_signatures));
1524 				if (scope->state->sigdashes)
1525 					fprintf(fp, "sigdashes=%s\n", print_boolean(scope->attribute->sigdashes));
1526 				if (scope->state->sigfile && scope->attribute->sigfile)
1527 					fprintf(fp, "sigfile=%s\n", scope->attribute->sigfile);
1528 				if (scope->state->signature_repost)
1529 					fprintf(fp, "signature_repost=%s\n", print_boolean(scope->attribute->signature_repost));
1530 				if (scope->state->sort_article_type)
1531 					fprintf(fp, "sort_article_type=%u\n", scope->attribute->sort_article_type);
1532 				if (scope->state->sort_threads_type)
1533 					fprintf(fp, "sort_threads_type=%u\n", scope->attribute->sort_threads_type);
1534 				if (scope->state->start_editor_offset)
1535 					fprintf(fp, "start_editor_offset=%s\n", print_boolean(scope->attribute->start_editor_offset));
1536 				if (scope->state->tex2iso_conv)
1537 					fprintf(fp, "tex2iso_conv=%s\n", print_boolean(scope->attribute->tex2iso_conv));
1538 				if (scope->state->thread_articles)
1539 					fprintf(fp, "thread_articles=%u\n", scope->attribute->thread_articles);
1540 				if (scope->state->thread_catchup_on_exit)
1541 					fprintf(fp, "thread_catchup_on_exit=%s\n", print_boolean(scope->attribute->thread_catchup_on_exit));
1542 				if (scope->state->thread_format && scope->attribute->thread_format)
1543 					fprintf(fp, "thread_format=%s\n", scope->attribute->thread_format);
1544 				if (scope->state->thread_perc)
1545 					fprintf(fp, "thread_perc=%u\n", scope->attribute->thread_perc);
1546 				if (scope->state->trim_article_body)
1547 					fprintf(fp, "trim_article_body=%u\n", scope->attribute->trim_article_body);
1548 				if (scope->state->verbatim_handling)
1549 					fprintf(fp, "verbatim_handling=%s\n", print_boolean(scope->attribute->verbatim_handling));
1550 				if (scope->state->wrap_on_next_unread)
1551 					fprintf(fp, "wrap_on_next_unread=%s\n", print_boolean(scope->attribute->wrap_on_next_unread));
1552 				if (scope->state->x_headers && scope->attribute->x_headers)
1553 					fprintf(fp, "x_headers=%s\n", scope->attribute->x_headers);
1554 				if (scope->state->x_body && scope->attribute->x_body)
1555 					fprintf(fp, "x_body=%s\n", scope->attribute->x_body);
1556 				if (scope->state->x_comment_to)
1557 					fprintf(fp, "x_comment_to=%s\n", print_boolean(scope->attribute->x_comment_to));
1558 			}
1559 		}
1560 	}
1561 
1562 	/* rename_file() preserves mode, so this is safe */
1563 #ifdef HAVE_FCHMOD
1564 	fchmod(fileno(fp), (mode_t) (S_IRUSR|S_IWUSR));
1565 #else
1566 #	ifdef HAVE_CHMOD
1567 	chmod(new_file, (mode_t) (S_IRUSR|S_IWUSR));
1568 #	endif /* HAVE_CHMOD */
1569 #endif /* HAVE_FCHMOD */
1570 
1571 	if ((i = ferror(fp)) || fclose(fp)) {
1572 		error_message(2, _(txt_filesystem_full), ATTRIBUTES_FILE);
1573 		unlink(new_file);
1574 		if (i) {
1575 			clearerr(fp);
1576 			fclose(fp);
1577 		}
1578 	} else
1579 		rename_file(new_file, file);
1580 
1581 	free(new_file);
1582 }
1583 
1584 
1585 #ifdef DEBUG
1586 #	if 0
1587 static void
1588 debug_print_filter_attributes(
1589 	void)
1590 {
1591 	if (debug & DEBUG_ATTRIB) {
1592 		int i;
1593 		struct t_group *group;
1594 
1595 		my_printf("\nBEG ***\n");
1596 
1597 		for_each_group(i) {
1598 			group = &active[i];
1599 			my_printf("Grp=[%s] KILL   header=[%d] scope=[%s] case=[%s] expire=[%s]\n",
1600 				group->name, group->attribute->quick_kill_header,
1601 				BlankIfNull(group->attribute->quick_kill_scope),
1602 				txt_onoff[group->attribute->quick_kill_case != FALSE ? 1 : 0],
1603 				txt_onoff[group->attribute->quick_kill_expire != FALSE ? 1 : 0]);
1604 			my_printf("Grp=[%s] SELECT header=[%d] scope=[%s] case=[%s] expire=[%s]\n",
1605 				group->name, group->attribute->quick_select_header,
1606 				BlankIfNull(group->attribute->quick_select_scope),
1607 				txt_onoff[group->attribute->quick_select_case != FALSE ? 1 : 0],
1608 				txt_onoff[group->attribute->quick_select_expire != FALSE ? 1 : 0]);
1609 		}
1610 		my_printf("END ***\n");
1611 	}
1612 }
1613 #	endif /* 0 */
1614 
1615 
1616 static void
dump_attributes(void)1617 dump_attributes(
1618 	void)
1619 {
1620 	if (debug & DEBUG_ATTRIB) {
1621 		int i, j;
1622 		struct t_group *group;
1623 
1624 		for_each_group(i) {
1625 			group = &active[i];
1626 			if (!group->attribute)
1627 				continue;
1628 			debug_print_file("ATTRIBUTES", "group=%s", BlankIfNull(group->name));
1629 			debug_print_file("ATTRIBUTES", "\tGlobal=%d", group->attribute->global);
1630 			debug_print_file("ATTRIBUTES", "\tmaildir=%s", BlankIfNull(group->attribute->maildir));
1631 			debug_print_file("ATTRIBUTES", "\tsavedir=%s", BlankIfNull(group->attribute->savedir));
1632 			debug_print_file("ATTRIBUTES", "\tsavefile=%s", BlankIfNull(group->attribute->savefile));
1633 			debug_print_file("ATTRIBUTES", "\tsigfile=%s", BlankIfNull(group->attribute->sigfile));
1634 			debug_print_file("ATTRIBUTES", "\torganization=%s", BlankIfNull(group->attribute->organization));
1635 			debug_print_file("ATTRIBUTES", "\tfollowup_to=%s", BlankIfNull(group->attribute->followup_to));
1636 			debug_print_file("ATTRIBUTES", "\tmailing_list=%s", BlankIfNull(group->attribute->mailing_list));
1637 			debug_print_file("ATTRIBUTES", "\tx_headers=%s", BlankIfNull(group->attribute->x_headers));
1638 			debug_print_file("ATTRIBUTES", "\tx_body=%s", BlankIfNull(group->attribute->x_body));
1639 			debug_print_file("ATTRIBUTES", "\tfrom=%s", BlankIfNull(group->attribute->from));
1640 			debug_print_file("ATTRIBUTES", "\tnews_quote_format=%s", BlankIfNull(group->attribute->news_quote_format));
1641 			debug_print_file("ATTRIBUTES", "\tquote_chars=%s", quote_space_to_dash(BlankIfNull(group->attribute->quote_chars)));
1642 			debug_print_file("ATTRIBUTES", "\tmime_types_to_save=%s", BlankIfNull(group->attribute->mime_types_to_save));
1643 #	ifdef HAVE_ISPELL
1644 			debug_print_file("ATTRIBUTES", "\tispell=%s", BlankIfNull(group->attribute->ispell));
1645 #	endif /* HAVE_ISPELL */
1646 			debug_print_file("ATTRIBUTES", "\tshow_only_unread_arts=%s", print_boolean(group->attribute->show_only_unread_arts));
1647 			debug_print_file("ATTRIBUTES", "\tthread_articles=%d", group->attribute->thread_articles);
1648 			debug_print_file("ATTRIBUTES", "\tthread_perc=%d", group->attribute->thread_perc);
1649 			debug_print_file("ATTRIBUTES", "\tadd_posted_to_filter=%s", print_boolean(group->attribute->add_posted_to_filter));
1650 			debug_print_file("ATTRIBUTES", "\tadvertising=%s", print_boolean(group->attribute->advertising));
1651 			debug_print_file("ATTRIBUTES", "\talternative_handling=%s", print_boolean(group->attribute->alternative_handling));
1652 			debug_print_file("ATTRIBUTES", "\task_for_metamail=%s", print_boolean(group->attribute->ask_for_metamail));
1653 			debug_print_file("ATTRIBUTES", "\tauto_cc_bcc=%d", group->attribute->auto_cc_bcc);
1654 			debug_print_file("ATTRIBUTES", "\tauto_list_thread=%s", print_boolean(group->attribute->auto_list_thread));
1655 			debug_print_file("ATTRIBUTES", "\tauto_select=%s", print_boolean(group->attribute->auto_select));
1656 			debug_print_file("ATTRIBUTES", "\tauto_save=%s", print_boolean(group->attribute->auto_save));
1657 			debug_print_file("ATTRIBUTES", "\tbatch_save=%s", print_boolean(group->attribute->batch_save));
1658 			debug_print_file("ATTRIBUTES", "\tdate_format=%s", BlankIfNull(group->attribute->date_format));
1659 			debug_print_file("ATTRIBUTES", "\tdelete_tmp_files=%s", print_boolean(group->attribute->delete_tmp_files));
1660 			debug_print_file("ATTRIBUTES", "\teditor_format=%s", BlankIfNull(group->attribute->editor_format));
1661 #	ifdef HAVE_COLOR
1662 			debug_print_file("ATTRIBUTES", "\textquote_handling=%s", print_boolean(group->attribute->extquote_handling));
1663 #	endif /* HAVE_COLOR */
1664 			debug_print_file("ATTRIBUTES", "\tgroup_catchup_on_exit=%s", print_boolean(group->attribute->group_catchup_on_exit));
1665 			debug_print_file("ATTRIBUTES", "\tgroup_format=%s", BlankIfNull(group->attribute->group_format));
1666 			debug_print_file("ATTRIBUTES", "\tmail_8bit_header=%s", print_boolean(group->attribute->mail_8bit_header));
1667 			debug_print_file("ATTRIBUTES", "\tmail_mime_encoding=%s", txt_mime_encodings[group->attribute->mail_mime_encoding]);
1668 			debug_print_file("ATTRIBUTES", "\tmark_ignore_tags=%s", print_boolean(group->attribute->mark_ignore_tags));
1669 			debug_print_file("ATTRIBUTES", "\tmark_saved_read=%s", print_boolean(group->attribute->mark_saved_read));
1670 			debug_print_file("ATTRIBUTES", "\tnews_headers_to_display=%s", BlankIfNull(group->attribute->news_headers_to_display));
1671 			if (group->attribute->headers_to_display) {
1672 				debug_print_file("ATTRIBUTES", "\theaders_to_display->num=%d", group->attribute->headers_to_display->num);
1673 				for (j = 0; j < group->attribute->headers_to_display->num; j++)
1674 					debug_print_file("ATTRIBUTES", "\theaders_to_display->header[%d]=%s", j, group->attribute->headers_to_display->header[j]);
1675 			}
1676 			debug_print_file("ATTRIBUTES", "\tnews_headers_to_not_display=%s", BlankIfNull(group->attribute->news_headers_to_not_display));
1677 			if (group->attribute->headers_to_not_display) {
1678 				debug_print_file("ATTRIBUTES", "\theaders_to_not_display->num=%d", group->attribute->headers_to_not_display->num);
1679 				for (j = 0; j < group->attribute->headers_to_not_display->num; j++)
1680 					debug_print_file("ATTRIBUTES", "\theaders_to_not_display->header[%d]=%s", j, group->attribute->headers_to_not_display->header[j]);
1681 			}
1682 			debug_print_file("ATTRIBUTES", "\tpos_first_unread=%s", print_boolean(group->attribute->pos_first_unread));
1683 			debug_print_file("ATTRIBUTES", "\tpost_8bit_header=%s", print_boolean(group->attribute->post_8bit_header));
1684 			debug_print_file("ATTRIBUTES", "\tpost_mime_encoding=%s", txt_mime_encodings[group->attribute->post_mime_encoding]);
1685 			debug_print_file("ATTRIBUTES", "\tpost_process_view=%s", print_boolean(group->attribute->post_process_view));
1686 #	ifndef DISABLE_PRINTING
1687 			debug_print_file("ATTRIBUTES", "\tprint_header=%s", print_boolean(group->attribute->print_header));
1688 #	endif /* !DISABLE_PRINTING */
1689 			debug_print_file("ATTRIBUTES", "\tprocess_only_unread=%s", print_boolean(group->attribute->process_only_unread));
1690 			debug_print_file("ATTRIBUTES", "\tprompt_followupto=%s", print_boolean(group->attribute->prompt_followupto));
1691 			debug_print_file("ATTRIBUTES", "\tsort_article_type=%d", group->attribute->sort_article_type);
1692 			debug_print_file("ATTRIBUTES", "\tsort_threads_type=%d", group->attribute->sort_threads_type);
1693 			debug_print_file("ATTRIBUTES", "\tshow_author=%d", group->attribute->show_author);
1694 			debug_print_file("ATTRIBUTES", "\tshow_signatures=%s", print_boolean(group->attribute->show_signatures));
1695 			debug_print_file("ATTRIBUTES", "\tsigdashes=%s", print_boolean(group->attribute->sigdashes));
1696 			debug_print_file("ATTRIBUTES", "\tsignature_repost=%s", print_boolean(group->attribute->signature_repost));
1697 			debug_print_file("ATTRIBUTES", "\tstart_editor_offset=%s", print_boolean(group->attribute->start_editor_offset));
1698 			debug_print_file("ATTRIBUTES", "\tthread_catchup_on_exit=%s", print_boolean(group->attribute->thread_catchup_on_exit));
1699 			debug_print_file("ATTRIBUTES", "\tthread_format=%s", BlankIfNull(group->attribute->thread_format));
1700 			debug_print_file("ATTRIBUTES", "\ttrim_article_body=%d", group->attribute->trim_article_body);
1701 			debug_print_file("ATTRIBUTES", "\tverbatim_handling=%s", print_boolean(group->attribute->verbatim_handling));
1702 			debug_print_file("ATTRIBUTES", "\twrap_on_next_unread=%s", print_boolean(group->attribute->wrap_on_next_unread));
1703 			debug_print_file("ATTRIBUTES", "\tpost_process_type=%d", group->attribute->post_process_type);
1704 			debug_print_file("ATTRIBUTES", "\tquick_kill_scope=%s", BlankIfNull(group->attribute->quick_kill_scope));
1705 			debug_print_file("ATTRIBUTES", "\tquick_kill_case=%s", print_boolean(group->attribute->quick_kill_case));
1706 			debug_print_file("ATTRIBUTES", "\tquick_kill_expire=%s", print_boolean(group->attribute->quick_kill_expire));
1707 			debug_print_file("ATTRIBUTES", "\tquick_kill_header=%d", group->attribute->quick_kill_header);
1708 			debug_print_file("ATTRIBUTES", "\tquick_select_scope=%s", BlankIfNull(group->attribute->quick_select_scope));
1709 			debug_print_file("ATTRIBUTES", "\tquick_select_case=%s", print_boolean(group->attribute->quick_select_case));
1710 			debug_print_file("ATTRIBUTES", "\tquick_select_expire=%s", print_boolean(group->attribute->quick_select_expire));
1711 			debug_print_file("ATTRIBUTES", "\tquick_select_header=%d", group->attribute->quick_select_header);
1712 			debug_print_file("ATTRIBUTES", "\tx_comment_to=%s", print_boolean(group->attribute->x_comment_to));
1713 			debug_print_file("ATTRIBUTES", "\tfcc=%s", BlankIfNull(group->attribute->fcc));
1714 			debug_print_file("ATTRIBUTES", "\ttex2iso_conv=%s", print_boolean(group->attribute->tex2iso_conv));
1715 			debug_print_file("ATTRIBUTES", "\tmime_forward=%s", print_boolean(group->attribute->mime_forward));
1716 #	ifdef CHARSET_CONVERSION
1717 			debug_print_file("ATTRIBUTES", "\tmm_network_charset=%s", txt_mime_charsets[group->attribute->mm_network_charset]);
1718 			debug_print_file("ATTRIBUTES", "\tundeclared_charset=%s", BlankIfNull(group->attribute->undeclared_charset));
1719 #	endif /* CHARSET_CONVERSION */
1720 			debug_print_file("ATTRIBUTES", "");
1721 		}
1722 	}
1723 }
1724 
1725 
1726 #define DEBUG_PRINT_STATE(attrib) (scope->state->attrib ? "+ " : "  ")
1727 #define DEBUG_PRINT_STRING(attrib) (scope->attribute->attrib ? scope->attribute->attrib : "NULL")
1728 
1729 
1730 static void
dump_scopes(const char * fname)1731 dump_scopes(
1732 	const char *fname)
1733 {
1734 	if (!scopes)
1735 		return;
1736 
1737 	if (debug & DEBUG_ATTRIB) {
1738 		int i, j;
1739 		struct t_scope *scope;
1740 
1741 		for (i = 0; i < num_scope; i++) {
1742 			scope = &scopes[i];
1743 			debug_print_file(fname, "scopes[%d]", i);
1744 			debug_print_file(fname, "scope=%s", scope->scope ? scope->scope : "NULL");
1745 			debug_print_file(fname, "\t  global=%d", scope->global);
1746 			debug_print_file(fname, "\t%smaildir=%s", DEBUG_PRINT_STATE(maildir), DEBUG_PRINT_STRING(maildir));
1747 			debug_print_file(fname, "\t%ssavedir=%s", DEBUG_PRINT_STATE(savedir), DEBUG_PRINT_STRING(savedir));
1748 			debug_print_file(fname, "\t%ssavefile=%s", DEBUG_PRINT_STATE(savefile), DEBUG_PRINT_STRING(savefile));
1749 			debug_print_file(fname, "\t%ssigfile=%s", DEBUG_PRINT_STATE(sigfile), DEBUG_PRINT_STRING(sigfile));
1750 			debug_print_file(fname, "\t%sorganization=%s", DEBUG_PRINT_STATE(organization), DEBUG_PRINT_STRING(organization));
1751 			debug_print_file(fname, "\t%sfollowup_to=%s", DEBUG_PRINT_STATE(followup_to), DEBUG_PRINT_STRING(followup_to));
1752 			debug_print_file(fname, "\t%smailing_list=%s", DEBUG_PRINT_STATE(mailing_list), DEBUG_PRINT_STRING(mailing_list));
1753 			debug_print_file(fname, "\t%sx_headers=%s", DEBUG_PRINT_STATE(x_headers), DEBUG_PRINT_STRING(x_headers));
1754 			debug_print_file(fname, "\t%sx_body=%s", DEBUG_PRINT_STATE(x_body), DEBUG_PRINT_STRING(x_body));
1755 			debug_print_file(fname, "\t%sfrom=%s", DEBUG_PRINT_STATE(from), DEBUG_PRINT_STRING(from));
1756 			debug_print_file(fname, "\t%snews_quote_format=%s", DEBUG_PRINT_STATE(news_quote_format), DEBUG_PRINT_STRING(news_quote_format));
1757 			debug_print_file(fname, "\t%squote_chars=%s", DEBUG_PRINT_STATE(quote_chars), quote_space_to_dash(DEBUG_PRINT_STRING(quote_chars)));
1758 			debug_print_file(fname, "\t%smime_types_to_save=%s", DEBUG_PRINT_STATE(mime_types_to_save), DEBUG_PRINT_STRING(mime_types_to_save));
1759 #	ifdef HAVE_ISPELL
1760 			debug_print_file(fname, "\t%sispell=%s", DEBUG_PRINT_STATE(ispell), DEBUG_PRINT_STRING(ispell));
1761 #	endif /* HAVE_ISPELL */
1762 			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));
1763 			debug_print_file(fname, "\t%sthread_articles=%d", DEBUG_PRINT_STATE(thread_articles), scope->attribute->thread_articles);
1764 			debug_print_file(fname, "\t%sthread_perc=%d", DEBUG_PRINT_STATE(thread_perc), scope->attribute->thread_perc);
1765 			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));
1766 			debug_print_file(fname, "\t%sadvertising=%s", DEBUG_PRINT_STATE(advertising), print_boolean(scope->attribute->advertising));
1767 			debug_print_file(fname, "\t%salternative_handling=%s", DEBUG_PRINT_STATE(alternative_handling), print_boolean(scope->attribute->alternative_handling));
1768 			debug_print_file(fname, "\t%sask_for_metamail=%s", DEBUG_PRINT_STATE(ask_for_metamail), print_boolean(scope->attribute->ask_for_metamail));
1769 			debug_print_file(fname, "\t%sauto_cc_bcc=%d", DEBUG_PRINT_STATE(auto_cc_bcc), scope->attribute->auto_cc_bcc);
1770 			debug_print_file(fname, "\t%sauto_list_thread=%s", DEBUG_PRINT_STATE(auto_list_thread), print_boolean(scope->attribute->auto_list_thread));
1771 			debug_print_file(fname, "\t%sauto_select=%s", DEBUG_PRINT_STATE(auto_select), print_boolean(scope->attribute->auto_select));
1772 			debug_print_file(fname, "\t%sauto_save=%s", DEBUG_PRINT_STATE(auto_save), print_boolean(scope->attribute->auto_save));
1773 			debug_print_file(fname, "\t%sbatch_save=%s", DEBUG_PRINT_STATE(batch_save), print_boolean(scope->attribute->batch_save));
1774 			debug_print_file(fname, "\t%sdate_format=%s", DEBUG_PRINT_STATE(date_format), DEBUG_PRINT_STRING(date_format));
1775 			debug_print_file(fname, "\t%sdelete_tmp_files=%s", DEBUG_PRINT_STATE(delete_tmp_files), print_boolean(scope->attribute->delete_tmp_files));
1776 			debug_print_file(fname, "\t%seditor_format=%s", DEBUG_PRINT_STATE(editor_format), DEBUG_PRINT_STRING(editor_format));
1777 #	ifdef HAVE_COLOR
1778 			debug_print_file(fname, "\t%sextquote_handling=%s", DEBUG_PRINT_STATE(extquote_handling), print_boolean(scope->attribute->extquote_handling));
1779 #	endif /* HAVE_COLOR */
1780 			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));
1781 			debug_print_file(fname, "\t%sgroup_format=%s", DEBUG_PRINT_STATE(group_format), DEBUG_PRINT_STRING(group_format));
1782 			debug_print_file(fname, "\t%smail_8bit_header=%s", DEBUG_PRINT_STATE(mail_8bit_header), print_boolean(scope->attribute->mail_8bit_header));
1783 			debug_print_file(fname, "\t%smail_mime_encoding=%s", DEBUG_PRINT_STATE(mail_mime_encoding), txt_mime_encodings[scope->attribute->mail_mime_encoding]);
1784 			debug_print_file(fname, "\t%smark_ignore_tags=%s", DEBUG_PRINT_STATE(mark_ignore_tags), print_boolean(scope->attribute->mark_ignore_tags));
1785 			debug_print_file(fname, "\t%smark_saved_read=%s", DEBUG_PRINT_STATE(mark_saved_read), print_boolean(scope->attribute->mark_saved_read));
1786 			debug_print_file(fname, "\t%snews_headers_to_display=%s", DEBUG_PRINT_STATE(news_headers_to_display), DEBUG_PRINT_STRING(news_headers_to_display));
1787 			if (scope->attribute->headers_to_display) {
1788 				debug_print_file(fname, "\t    headers_to_display->num=%d", scope->attribute->headers_to_display->num);
1789 				for (j = 0; j < scope->attribute->headers_to_display->num; j++)
1790 					debug_print_file(fname, "\t    headers_to_display->header[%d]=%s", j, scope->attribute->headers_to_display->header[j]);
1791 			}
1792 			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));
1793 			if (scope->attribute->headers_to_not_display) {
1794 				debug_print_file(fname, "\t    headers_to_not_display->num=%d", scope->attribute->headers_to_not_display->num);
1795 				for (j = 0; j < scope->attribute->headers_to_not_display->num; j++)
1796 					debug_print_file(fname, "\t    headers_to_not_display->header[%d]=%s", j, scope->attribute->headers_to_not_display->header[j]);
1797 			}
1798 			debug_print_file(fname, "\t%spos_first_unread=%s", DEBUG_PRINT_STATE(pos_first_unread), print_boolean(scope->attribute->pos_first_unread));
1799 			debug_print_file(fname, "\t%spost_8bit_header=%s", DEBUG_PRINT_STATE(post_8bit_header), print_boolean(scope->attribute->post_8bit_header));
1800 			debug_print_file(fname, "\t%spost_mime_encoding=%s", DEBUG_PRINT_STATE(post_mime_encoding), txt_mime_encodings[scope->attribute->post_mime_encoding]);
1801 			debug_print_file(fname, "\t%spost_process_view=%s", DEBUG_PRINT_STATE(post_process_view), print_boolean(scope->attribute->post_process_view));
1802 #	ifndef DISABLE_PRINTING
1803 			debug_print_file(fname, "\t%sprint_header=%s", DEBUG_PRINT_STATE(print_header), print_boolean(scope->attribute->print_header));
1804 #	endif /* !DISABLE_PRINTING */
1805 			debug_print_file(fname, "\t%sprocess_only_unread=%s", DEBUG_PRINT_STATE(process_only_unread), print_boolean(scope->attribute->process_only_unread));
1806 			debug_print_file(fname, "\t%sprompt_followupto=%s", DEBUG_PRINT_STATE(prompt_followupto), print_boolean(scope->attribute->prompt_followupto));
1807 			debug_print_file(fname, "\t%ssort_article_type=%d", DEBUG_PRINT_STATE(sort_article_type), scope->attribute->sort_article_type);
1808 			debug_print_file(fname, "\t%ssort_threads_type=%d", DEBUG_PRINT_STATE(sort_threads_type), scope->attribute->sort_threads_type);
1809 			debug_print_file(fname, "\t%sshow_author=%d", DEBUG_PRINT_STATE(show_author), scope->attribute->show_author);
1810 			debug_print_file(fname, "\t%sshow_signatures=%s", DEBUG_PRINT_STATE(show_signatures), print_boolean(scope->attribute->show_signatures));
1811 			debug_print_file(fname, "\t%ssigdashes=%s", DEBUG_PRINT_STATE(sigdashes), print_boolean(scope->attribute->sigdashes));
1812 			debug_print_file(fname, "\t%ssignature_repost=%s", DEBUG_PRINT_STATE(signature_repost), print_boolean(scope->attribute->signature_repost));
1813 			debug_print_file(fname, "\t%sstart_editor_offset=%s", DEBUG_PRINT_STATE(start_editor_offset), print_boolean(scope->attribute->start_editor_offset));
1814 			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));
1815 			debug_print_file(fname, "\t%sthread_format=%s", DEBUG_PRINT_STATE(thread_format), DEBUG_PRINT_STRING(thread_format));
1816 			debug_print_file(fname, "\t%strim_article_body=%d", DEBUG_PRINT_STATE(trim_article_body), scope->attribute->trim_article_body);
1817 			debug_print_file(fname, "\t%sverbatim_handling=%s", DEBUG_PRINT_STATE(verbatim_handling), print_boolean(scope->attribute->verbatim_handling));
1818 			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));
1819 			debug_print_file(fname, "\t%spost_process_type=%d", DEBUG_PRINT_STATE(post_process_type), scope->attribute->post_process_type);
1820 			debug_print_file(fname, "\t%squick_kill_scope=%s", DEBUG_PRINT_STATE(quick_kill_scope), DEBUG_PRINT_STRING(quick_kill_scope));
1821 			debug_print_file(fname, "\t%squick_kill_case=%s", DEBUG_PRINT_STATE(quick_kill_case), print_boolean(scope->attribute->quick_kill_case));
1822 			debug_print_file(fname, "\t%squick_kill_expire=%s", DEBUG_PRINT_STATE(quick_kill_expire), print_boolean(scope->attribute->quick_kill_expire));
1823 			debug_print_file(fname, "\t%squick_kill_header=%d", DEBUG_PRINT_STATE(quick_kill_header), scope->attribute->quick_kill_header);
1824 			debug_print_file(fname, "\t%squick_select_scope=%s", DEBUG_PRINT_STATE(quick_select_scope), DEBUG_PRINT_STRING(quick_select_scope));
1825 			debug_print_file(fname, "\t%squick_select_case=%s", DEBUG_PRINT_STATE(quick_select_case), print_boolean(scope->attribute->quick_select_case));
1826 			debug_print_file(fname, "\t%squick_select_expire=%s", DEBUG_PRINT_STATE(quick_select_expire), print_boolean(scope->attribute->quick_select_expire));
1827 			debug_print_file(fname, "\t%squick_select_header=%d", DEBUG_PRINT_STATE(quick_select_header), scope->attribute->quick_select_header);
1828 			debug_print_file(fname, "\t%sx_comment_to=%s", DEBUG_PRINT_STATE(x_comment_to), print_boolean(scope->attribute->x_comment_to));
1829 			debug_print_file(fname, "\t%sfcc=%s", DEBUG_PRINT_STATE(fcc), DEBUG_PRINT_STRING(fcc));
1830 			debug_print_file(fname, "\t%stex2iso_conv=%s", DEBUG_PRINT_STATE(tex2iso_conv), print_boolean(scope->attribute->tex2iso_conv));
1831 			debug_print_file(fname, "\t%smime_forward=%s", DEBUG_PRINT_STATE(mime_forward), print_boolean(scope->attribute->mime_forward));
1832 #	ifdef CHARSET_CONVERSION
1833 			debug_print_file(fname, "\t%smm_network_charset=%s", DEBUG_PRINT_STATE(mm_network_charset), txt_mime_charsets[scope->attribute->mm_network_charset]);
1834 			debug_print_file(fname, "\t%sundeclared_charset=%s", DEBUG_PRINT_STATE(undeclared_charset), DEBUG_PRINT_STRING(undeclared_charset));
1835 #	endif /* CHARSET_CONVERSION */
1836 			debug_print_file(fname, "");
1837 		}
1838 	}
1839 }
1840 #endif /* DEBUG */
1841