* clear out some warnings by gcc 9.3.1.
[alpine.git] / alpine / remote.c
blobac9e901d08bbd76705e5c525abd5e5aeb903659a
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: remote.c 1032 2008-04-11 00:30:04Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2006-2008 University of Washington
8 * Copyright 2013-2020 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 #include "headers.h"
20 #include "remote.h"
21 #include "keymenu.h"
22 #include "mailview.h"
23 #include "status.h"
24 #include "radio.h"
25 #include "../pith/msgno.h"
26 #include "../pith/filter.h"
27 #include "../pith/util.h"
28 #include "../pith/conf.h"
29 #include "../pith/tempfile.h"
30 #include "../pith/margin.h"
34 * Internal prototypes
36 int rd_answer_forge_warning(int, MSGNO_S *, SCROLL_S *);
39 int
40 rd_prompt_about_forged_remote_data(int reason, REMDATA_S *rd, char *extra)
42 char tmp[2000];
43 char *unknown = "<unknown>";
44 int rv = -1;
45 char *foldertype, *foldername, *special;
47 foldertype = (rd && rd->t.i.special_hdr && !strucmp(rd->t.i.special_hdr, REMOTE_ABOOK_SUBTYPE)) ? "address book" : (rd && rd->t.i.special_hdr && !strucmp(rd->t.i.special_hdr, REMOTE_PINERC_SUBTYPE)) ? "configuration" : "data";
48 foldername = (rd && rd->rn) ? rd->rn : unknown;
49 special = (rd && rd->t.i.special_hdr) ? rd->t.i.special_hdr : unknown;
51 dprint((1, "rd_check_out_forged_remote_data:\n"));
52 dprint((1, " reason=%d\n", reason));
53 dprint((1, " folder_type=%s\n", foldertype ? foldertype : "?"));
54 dprint((1, " remotename=%s\n\n", foldername ? foldername : "?"));
56 if(rd && rd->flags & USER_SAID_NO)
57 return rv;
59 if(reason == -2){
60 dprint((1, "The special header \"%s\" is missing from the last message in the folder.\nThis indicates that something is wrong.\nYou should probably answer \"No\"\nso that you don't use the corrupt data.\nThen you should investigate further.\n", special ? special : "?"));
62 else if(reason == -1){
63 dprint((1, "The last message in the folder contains \"Received\" headers.\nThis usually indicates that the message was put there by the mail\ndelivery system. Alpine does not add those Received headers.\nYou should probably answer \"No\" so that you don't use the corrupt data.\nThen you should investigate further.\n"));
65 else if(reason == 0){
66 dprint((1, "The special header \"%s\" in the last message\nin the folder has an unexpected value (%s)\nafter it. This could indicate that something is wrong.\nThis value should not normally be put there by Alpine.\nHowever, since there are no Received lines in the message we choose to\nbelieve that everything is ok and we will proceed.\n",
67 special ? special : "?", (extra && *extra) ? extra : "?"));
69 else if(reason == 1){
70 dprint((1, "The special header \"%s\" in the last message\nin the folder has an unexpected value (1)\nafter it. It appears that it may have been put there by an Pine\nwith a version number less than 4.50.\nSince there are no Received lines in the message we choose to believe that\nthe header was added by an old Pine and we will proceed.\n",
71 special ? special : "?"));
73 else if(reason > 1){
74 dprint((1, "The special header \"%s\" in the last message\nin the folder has an unexpected value (%s)\nafter it. This is the right sort of value that Alpine would normally put there,\nbut it doesn't match the value from the first message in the folder.\nThis may indicate that something is wrong.\nHowever, since there are no Received lines in the message we choose to\nbelieve that everything is ok and we will proceed.\n",
75 special ? special : "?", (extra && *extra) ? extra : "?"));
78 if(reason >= 0){
80 * This check should not really be here. We have a cookie that
81 * has the wrong value so something is possibly wrong.
82 * But we are worried that old pines will put the bad value in
83 * there (which they will) and then the questions will bother
84 * users and mystify them. So we're just going to pretend the user
85 * said Yes in this case, and we'll try to fix the cookie.
86 * We still catch Received lines and use that or the complete absence
87 * of a special header as indicators of trouble.
89 rd->flags |= USER_SAID_YES;
90 return(1);
93 if(ps_global->ttyo){
94 SCROLL_S sargs;
95 STORE_S *in_store, *out_store;
96 gf_io_t pc, gc;
97 HANDLE_S *handles = NULL;
98 int the_answer = 'n';
100 if(!(in_store = so_get(CharStar, NULL, EDIT_ACCESS)) ||
101 !(out_store = so_get(CharStar, NULL, EDIT_ACCESS)))
102 goto try_wantto;
104 /* TRANSLATORS: the first %s is the folder type, it may be address book or
105 configuration. The second %s is the folder name. Of course, the HTML
106 tags should be left as is. */
107 snprintf(tmp, sizeof(tmp), _("<HTML><P>The data in the remote %s folder<P><CENTER>%s</CENTER><P>looks suspicious. The reason for the suspicion is<P><CENTER>"),
108 foldertype, foldername);
109 tmp[sizeof(tmp)-1] = '\0';
110 so_puts(in_store, tmp);
112 if(reason == -2){
113 snprintf(tmp, sizeof(tmp), _("header \"%s\" is missing</CENTER><P>The special header \"%s\" is missing from the last message in the folder. This indicates that something is wrong. You should probably answer \"No\" so that you don't use the corrupt data. Then you should investigate further."),
114 special, special);
115 tmp[sizeof(tmp)-1] = '\0';
116 so_puts(in_store, tmp);
118 else if(reason == -1){
119 so_puts(in_store, _("\"Received\" headers detected</CENTER><P>The last message in the folder contains \"Received\" headers. This usually indicates that the message was put there by the mail delivery system. Alpine does not add those Received headers. You should probably answer \"No\" so that you don't use the corrupt data. Then you should investigate further."));
121 else if(reason == 0){
122 snprintf(tmp, sizeof(tmp), _("Unexpected value for header \"%s\"</CENTER><P>The special header \"%s\" in the last message in the folder has an unexpected value (%s) after it. This probably indicates that something is wrong. This value would not normally be put there by Alpine. You should probably answer \"No\" so that you don't use the corrupt data. Then you should investigate further."),
123 special, special, (extra && *extra) ? extra : "?");
124 tmp[sizeof(tmp)-1] = '\0';
125 so_puts(in_store, tmp);
127 else if(reason == 1){
128 snprintf(tmp, sizeof(tmp), _("Unexpected value for header \"%s\"</CENTER><P>The special header \"%s\" in the last message in the folder has an unexpected value (1) after it. It appears that it may have been put there by a Pine with a version number less than 4.50. If you believe that you have changed this data with an older Pine more recently than you've changed it with this version of Alpine, then you can probably safely answer \"Yes\". If you do not understand why this has happened, you should probably answer \"No\" so that you don't use the corrupt data. Then you should investigate further."),
129 special, special);
130 tmp[sizeof(tmp)-1] = '\0';
131 so_puts(in_store, tmp);
133 else if(reason > 1){
134 snprintf(tmp, sizeof(tmp), _("Unexpected value for header \"%s\"</CENTER><P>The special header \"%s\" in the last message in the folder has an unexpected value (%s) after it. This is the right sort of value that Alpine would normally put there, but it doesn't match the value from the first message in the folder. This may indicate that something is wrong. Unless you understand why this has happened, you should probably answer \"No\" so that you don't use the corrupt data. Then you should investigate further."),
135 special, special, (extra && *extra) ? extra : "?");
136 tmp[sizeof(tmp)-1] = '\0';
137 so_puts(in_store, tmp);
140 so_seek(in_store, 0L, 0);
141 init_handles(&handles);
142 gf_filter_init();
143 gf_link_filter(gf_html2plain,
144 gf_html2plain_opt(NULL,
145 ps_global->ttyo->screen_cols, non_messageview_margin(),
146 &handles, NULL, GFHP_LOCAL_HANDLES));
147 gf_set_so_readc(&gc, in_store);
148 gf_set_so_writec(&pc, out_store);
149 gf_pipe(gc, pc);
150 gf_clear_so_writec(out_store);
151 gf_clear_so_readc(in_store);
153 memset(&sargs, 0, sizeof(SCROLL_S));
154 sargs.text.handles = handles;
155 sargs.text.text = so_text(out_store);
156 sargs.text.src = CharStar;
157 sargs.bar.title = _("REMOTE DATA FORGERY WARNING");
158 sargs.proc.tool = rd_answer_forge_warning;
159 sargs.proc.data.p = (void *)&the_answer;
160 sargs.keys.menu = &forge_keymenu;
161 setbitmap(sargs.keys.bitmap);
163 scrolltool(&sargs);
165 if(the_answer == 'y'){
166 rv = 1;
167 rd->flags |= USER_SAID_YES;
169 else if(rd)
170 rd->flags |= USER_SAID_NO;
172 ps_global->mangled_screen = 1;
173 ps_global->painted_body_on_startup = 0;
174 ps_global->painted_footer_on_startup = 0;
175 so_give(&in_store);
176 so_give(&out_store);
177 free_handles(&handles);
179 else{
180 char *p = tmp;
182 snprintf(p, sizeof(tmp), _("\nThe data in the remote %s folder\n\n %s\n\nlooks suspicious. The reason for the suspicion is\n\n "),
183 foldertype, foldername);
184 tmp[sizeof(tmp)-1] = '\0';
185 p += strlen(p);
187 if(reason == -2){
188 snprintf(p, sizeof(tmp)-(p-tmp), _("header \"%s\" is missing\n\nThe special header \"%s\" is missing from the last message\nin the folder. This indicates that something is wrong.\nYou should probably answer \"No\" so that you don't use the corrupt data.\nThen you should investigate further.\n\n"),
189 special, special);
190 tmp[sizeof(tmp)-1] = '\0';
192 else if(reason == -1){
193 snprintf(p, sizeof(tmp)-(p-tmp), _("\"Received\" headers detected\n\nThe last message in the folder contains \"Received\" headers.\nThis usually indicates that the message was put there by the\nmail delivery system. Alpine does not add those Received headers.\nYou should probably answer \"No\" so that you don't use the corrupt data.\nThen you should investigate further.\n\n"));
194 tmp[sizeof(tmp)-1] = '\0';
196 else if(reason == 0){
197 snprintf(p, sizeof(tmp)-(p-tmp), _("Unexpected value for header \"%s\"\n\nThe special header \"%s\" in the last message in the folder\nhas an unexpected value (%s) after it. This probably\nindicates that something is wrong. This value would not normally be put\nthere by Alpine. You should probably answer \"No\" so that you don't use\nthe corrupt data. Then you should investigate further.\n\n"),
198 special, special, (extra && *extra) ? extra : "?");
199 tmp[sizeof(tmp)-1] = '\0';
201 else if(reason == 1){
202 snprintf(p, sizeof(tmp)-(p-tmp), _("Unexpected value for header \"%s\"\n\nThe special header \"%s\" in the last message in the folder\nhas an unexpected value (1) after it. It appears that it may have been\nput there by a Pine with a version number less than 4.50.\nIf you believe that you have changed this data with an older Pine more\nrecently than you've changed it with this version of Alpine, then you can\nprobably safely answer \"Yes\". If you do not understand why this has\nhappened, you should probably answer \"No\" so that you don't use the\ncorrupt data. Then you should investigate further.\n\n"),
203 special, special);
204 tmp[sizeof(tmp)-1] = '\0';
206 else if(reason > 1){
207 snprintf(p, sizeof(tmp)-(p-tmp), _("Unexpected value for header \"%s\"\n\nThe special header \"%s\" in the last message in the folder\nhas an unexpected\nvalue (%s) after it. This is\nthe right sort of value that Alpine would normally put there, but it\ndoesn't match the value from the first message in the folder. This may\nindicate that something is wrong. Unless you understand why this has happened,\nyou should probably answer \"No\" so that you don't use the\ncorrupt data. Then you should investigate further.\n\n"),
208 special, special, (extra && *extra) ? extra : "?");
209 tmp[sizeof(tmp)-1] = '\0';
212 try_wantto:
213 p += strlen(p);
214 snprintf(p, sizeof(tmp)-(p-tmp), _("Suspicious data in \"%s\": Continue anyway "),
215 (rd && rd->t.i.special_hdr) ? rd->t.i.special_hdr
216 : unknown);
217 tmp[sizeof(tmp)-1] = '\0';
218 if(want_to(tmp, 'n', 'x', NO_HELP, WT_NORM) == 'y'){
219 rv = 1;
220 rd->flags |= USER_SAID_YES;
222 else if(rd)
223 rd->flags |= USER_SAID_NO;
226 if(rv < 0)
227 q_status_message1(SM_ORDER, 1, 3, _("Can't open remote %s"),
228 (rd && rd->rn) ? rd->rn : "<noname>");
230 return(rv);
235 rd_answer_forge_warning(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
237 int rv = 1;
239 ps_global->next_screen = SCREEN_FUN_NULL;
241 switch(cmd){
242 case MC_YES :
243 *(int *)(sparms->proc.data.p) = 'y';
244 break;
246 case MC_NO :
247 *(int *)(sparms->proc.data.p) = 'n';
248 break;
250 default:
251 alpine_panic("Unexpected command in rd_answer_forge_warning");
252 break;
255 return(rv);
260 char *
261 rd_metadata_name(void)
263 char *p, *q, *metafile;
264 char path[MAXPATH], pinerc_dir[MAXPATH];
265 struct variable *vars = ps_global->vars;
267 dprint((9, "rd_metadata_name\n"));
269 pinerc_dir[0] = '\0';
270 if(ps_global->pinerc){
271 char *prcn = ps_global->pinerc;
272 char *lc;
274 if((lc = last_cmpnt(prcn)) != NULL){
275 int to_copy;
277 to_copy = (lc - prcn > 1) ? (lc - prcn - 1) : 1;
278 strncpy(pinerc_dir, prcn, MIN(to_copy, sizeof(pinerc_dir)-1));
279 pinerc_dir[MIN(to_copy, sizeof(pinerc_dir)-1)] = '\0';
281 else{
282 pinerc_dir[0] = '.';
283 pinerc_dir[1] = '\0';
288 * If there is no metadata file specified in the pinerc, create a filename.
290 if(!(VAR_REMOTE_ABOOK_METADATA && VAR_REMOTE_ABOOK_METADATA[0])){
291 if(pinerc_dir[0] && (p = tempfile_in_same_dir(ps_global->pinerc,
292 meta_prefix, NULL))){
293 /* fill in the pinerc variable */
294 q = p + strlen(pinerc_dir) + 1;
295 set_variable(V_REMOTE_ABOOK_METADATA, q, 1, 0, Main);
296 dprint((2, "creating name for metadata file: %s\n",
297 q ? q : "?"));
299 /* something's broken, return NULL rab */
300 if(!VAR_REMOTE_ABOOK_METADATA || !VAR_REMOTE_ABOOK_METADATA[0]){
301 our_unlink(p);
302 fs_give((void **)&p);
303 return(NULL);
306 fs_give((void **)&p);
308 else{
309 q_status_message(SM_ORDER, 3, 5,
310 "can't create metadata file in pinerc directory, continuing");
311 return(NULL);
315 build_path(path, pinerc_dir ? pinerc_dir : NULL,
316 VAR_REMOTE_ABOOK_METADATA, sizeof(path));
317 metafile = path;
320 * If the metadata file doesn't exist, create it.
322 if(can_access(metafile, ACCESS_EXISTS) != 0){
323 int fd;
325 if((fd = our_open(metafile, O_CREAT|O_EXCL|O_WRONLY|O_BINARY, 0600)) < 0){
327 set_variable(V_REMOTE_ABOOK_METADATA, NULL, 1, 0, Main);
329 q_status_message2(SM_ORDER, 3, 5,
330 "can't create cache file %.200s, continuing (%.200s)",
331 metafile, error_description(errno));
333 dprint((2, "can't create metafile %s: %s\n",
334 metafile ? metafile : "?", error_description(errno)));
336 return(NULL);
339 dprint((2, "created metadata file: %s\n",
340 metafile ? metafile : "?"));
342 (void)close(fd);
345 return(cpystr(metafile));;