* Remove some compilation warnings given by clang7.
[alpine.git] / alpine / xoauth2conf.c
blob97900d253164f9ab0cc7ba6fcb0b5eb01a3be5c5
1 /*
2 * ========================================================================
3 * Copyright 2006-2008 University of Washington
4 * Copyright 2013-2020 Eduardo Chappa
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
15 #include "headers.h"
16 #include "xoauth2conf.h"
17 #include "xoauth2.h"
18 #include "keymenu.h"
19 #include "status.h"
20 #include "confscroll.h"
21 #include "../pith/state.h"
22 #include "../pith/conf.h"
23 #include "../pith/list.h"
25 extern OAUTH2_S alpine_oauth2_list[];
27 XOAUTH2_INFO_S xoauth_default[] = {
28 { GMAIL_NAME, GMAIL_ID, GMAIL_SECRET},
29 #if 0
30 { OUTLOOK_NAME, OUTLOOK_ID, OUTLOOK_SECRET},
31 #endif
32 { NULL, NULL, NULL}
36 #define NXSERVERS (sizeof(xoauth_default)/sizeof(xoauth_default[0])-1)
37 #define XOAUTH2_CLIENT_ID _("Client-Id")
38 #define XOAUTH2_CLIENT_SECRET _("Client-Secret")
39 #define XNAME "/NAME="
40 #define XID "/ID="
41 #define XSECRET "/SECRET="
43 void write_xoauth_configuration(struct variable *, struct variable **, EditWhich);
45 char *
46 xoauth_config_line(char *server, char *id, char *secret)
48 size_t n;
49 char *rv;
51 n = strlen(XNAME) + strlen(XID) + strlen(XSECRET)
52 + strlen(server) + strlen(id) + strlen(secret) + 9;
53 rv = fs_get(n*sizeof(char));
54 sprintf(rv, "%s\"%s\" %s\"%s\" %s\"%s\"", XNAME, server, XID, id,
55 XSECRET, secret);
56 return rv;
59 /* call this function when id and secret are unknown.
60 * precedence is as follows:
61 * If the user has configured something, return that;
62 * else if we are already using a value, return that;
63 * else return default values.
65 void
66 oauth2_get_client_info(unsigned char *name, char **id, char **secret)
68 int i;
69 char **lval, *name_lval, *idp, *secretp;
71 *id = *secret = NULL;
73 /* first check the value configured by the user */
74 lval = ps_global->vars[V_XOAUTH2_INFO].current_val.l;
75 for(i = 0; lval && lval[i]; i++){
76 xoauth_parse_client_info(lval[i], &name_lval, &idp, &secretp);
77 if(name_lval && !strcmp(name_lval, name)){
78 *id = idp ? cpystr(idp) : NULL;
79 *secret = secretp ? cpystr(secretp) : NULL;
81 if(name_lval) fs_give((void **) &name_lval);
82 if(idp) fs_give((void **) &idp);
83 if(secretp) fs_give((void **) &secretp);
84 break;
87 if(*id && **id && *secret && **secret) return;
89 /* if not, now see if we already have a value set, and use that */
90 for(i = 0; alpine_oauth2_list[i].name != NULL; i++){
91 if(!strcmp(alpine_oauth2_list[i].name, name)){
92 *id = alpine_oauth2_list[i].param[OA2_Id].value
93 ? cpystr(alpine_oauth2_list[i].param[OA2_Id].value) : NULL;
94 *secret = alpine_oauth2_list[i].param[OA2_Secret].value
95 ? cpystr(alpine_oauth2_list[i].param[OA2_Secret].value) : NULL;
96 break;
100 if(*id && **id && *secret && **secret) return;
102 /* if nothing, use the default value */
103 for(i = 0; xoauth_default[i].name != NULL; i++)
104 if(!strcmp(xoauth_default[i].name, name)){
105 *id = cpystr(xoauth_default[i].client_id);
106 *secret = cpystr(xoauth_default[i].client_secret);
107 break;
111 /* write vlist to v
112 * Each vlist member is of type "p", while "v" is of type "l", so we
113 * each entry in "l" by using each of the "p" entries.
115 void
116 write_xoauth_configuration(struct variable *v, struct variable **vlist, EditWhich ew)
118 int i, j, k;
119 size_t n;
120 char ***alval, **lval, *p, *q, *l;
122 alval = ALVAL(v, ew);
123 for (i = 0, k = 0; vlist[i] != NULL;){
124 if(PVAL(vlist[i], ew)){
125 j = i/2; /* this is the location in the alpine_oauth2_list array */
126 i = 2*j; /* reset i */
127 p = PVAL(vlist[i], ew);
128 if(p == NULL) p = vlist[i]->current_val.p;
129 q = PVAL(vlist[i+1], ew);
130 if(q == NULL) q = vlist[i+1]->current_val.p;
131 if(k == 0) lval = fs_get((NXSERVERS +1)*sizeof(char *));
132 lval[k++] = xoauth_config_line(alpine_oauth2_list[j].name, p, q);
133 if(alpine_oauth2_list[j].param[OA2_Id].value)
134 fs_give((void **) &alpine_oauth2_list[j].param[OA2_Id].value);
135 if(alpine_oauth2_list[j].param[OA2_Secret].value)
136 fs_give((void **) &alpine_oauth2_list[j].param[OA2_Secret].value);
137 alpine_oauth2_list[j].param[OA2_Id].value = cpystr(p);
138 alpine_oauth2_list[j].param[OA2_Secret].value = cpystr(q);
139 i += 2;
141 else i++;
143 if(k > 0){
144 lval[k] = NULL;
145 if(*alval) free_list_array(alval);
146 *alval = lval;
148 else
149 *alval = NULL;
150 set_current_val(&ps_global->vars[V_XOAUTH2_INFO], FALSE, FALSE);
154 /* parse line of the form
155 /NAME="text" /ID="text" /SECRET="text"
157 void
158 xoauth_parse_client_info(char *lvalp, char **namep, char **idp, char **secretp)
160 char *s, *t, c;
161 *namep = *idp = *secretp = NULL;
163 if (lvalp == NULL) return;
165 if((s = strstr(lvalp, XNAME)) != NULL){
166 s += strlen(XNAME);
167 if(*s == '"') s++;
168 for(t = s; *t && *t != '"' && *t != ' '; t++);
169 c = *t;
170 *t = '\0';
171 *namep = cpystr(s);
172 *t = c;
175 if((s = strstr(lvalp, XID)) != NULL){
176 s += strlen(XID);
177 if(*s == '"') s++;
178 for(t = s; *t && *t != '"' && *t != ' '; t++);
179 c = *t;
180 *t = '\0';
181 *idp = cpystr(s);
182 *t = c;
185 if((s = strstr(lvalp, XSECRET)) != NULL){
186 s += strlen(XSECRET);
187 if(*s == '"') s++;
188 for(t = s; *t && *t != '"' && *t != ' '; t++);
189 c = *t;
190 *t = '\0';
191 *secretp = cpystr(s);
192 *t = c;
197 /*----------------------------------------------------------------------
198 Screen to add client_id and client_secret for a service
200 ---*/
201 void
202 alpine_xoauth2_configuration(struct pine *ps, int edit_exceptions)
204 struct variable gmail_client_id_var, gmail_client_secret_var;
205 #if 0
206 struct variable outlook_client_id_var, outlook_client_secret_var;
207 #endif
208 struct variable *varlist[2*NXSERVERS + 1];
209 char tmp[MAXPATH+1], *pval, **lval;
210 char *id, *secret;
211 char *name_lval, *id_lval, *id_conf, *id_def, *secret_lval, *secret_conf, *secret_def;
212 int i, j, k, l, ln = 0, readonly_warning = 0, pos;
213 CONF_S *ctmpa = NULL, *ctmpb, *first_line = NULL;
214 FEATURE_S *feature;
215 PINERC_S *prc = NULL;
216 OPT_SCREEN_S screen;
217 int expose_hidden_config, add_hidden_vars_title = 0;
218 SAVED_CONFIG_S *vsave;
220 dprint((3, "-- alpine_xoauth2_configuration --\n"));
222 expose_hidden_config = F_ON(F_EXPOSE_HIDDEN_CONFIG, ps_global);
223 ew = edit_exceptions ? ps_global->ew_for_except_vars : Main;
225 if(ps->restricted)
226 readonly_warning = 1;
227 else{
228 switch(ew){
229 case Main:
230 prc = ps->prc;
231 break;
232 case Post:
233 prc = ps->post_prc;
234 break;
235 default:
236 break;
239 readonly_warning = prc ? prc->readonly : 1;
242 ps->next_screen = SCREEN_FUN_NULL;
244 mailcap_free(); /* free resources we won't be using for a while */
246 varlist[0] = &gmail_client_id_var;
247 varlist[1] = &gmail_client_secret_var;
248 #if 0
249 varlist[2] = &outlook_client_id_var;
250 varlist[3] = &outlook_client_secret_var;
251 #endif
252 varlist[2*NXSERVERS] = NULL;
254 for(i = 0; i < 2*NXSERVERS; i++)
255 memset((void *) varlist[i], 0, sizeof(struct variable));
257 pos = -1;
258 do {
259 ctmpa = first_line = NULL;
261 ln = strlen(XOAUTH2_CLIENT_ID);
262 i = strlen(XOAUTH2_CLIENT_SECRET);
263 if(ln < i) ln = i;
265 lval = LVAL(&ps->vars[V_XOAUTH2_INFO], ew);
267 for(i = 0, l = 0; alpine_oauth2_list[i].name != NULL; i++){
268 id_conf = id_def = secret_conf = secret_def = NULL;
269 name_lval = id_lval = secret_lval = NULL;
271 id_conf = alpine_oauth2_list[i].param[OA2_Id].value;
272 secret_conf = alpine_oauth2_list[i].param[OA2_Secret].value;
274 for(j = 0; xoauth_default[j].name != NULL; j++)
275 if(!strcmp(alpine_oauth2_list[i].name, xoauth_default[j].name))
276 break;
278 if(xoauth_default[j].name != NULL){
279 id_def = xoauth_default[j].client_id;
280 secret_def = xoauth_default[j].client_secret;
283 /* fix this: the purpose is to search for the name in lval */
284 for(k = 0; lval && lval[k]; k++){
285 xoauth_parse_client_info(lval[k], &name_lval, &id_lval, &secret_lval);
286 if(name_lval && !strcmp(name_lval, alpine_oauth2_list[i].name))
287 break;
288 if (name_lval) fs_give((void **) &name_lval);
289 if (id_lval) fs_give((void **) &id_lval);
290 if (secret_lval) fs_give((void **) &secret_lval);
293 /* Here we have three values. The one being used by c-client in
294 * id_conf, secret_conf. The default value in Alpine, obtained
295 * by the programmer by registering Alpine, and the value
296 * configured in Alpine by the user in id_lval, and secret_lval.
298 * The rules are:
299 * 1. If id_lval && secret_lval are not null, we use those.
300 * 2. else we use the default values.
302 id = id_lval ? id_lval : id_def;
303 secret = secret_lval ? secret_lval : secret_def;
305 new_confline(&ctmpa)->var = NULL;
306 if(!first_line) first_line = ctmpa;
308 /* Write Name of provider first */
309 ctmpa->flags |= CF_NOSELECT;
310 ctmpa->help = NO_HELP;
311 ctmpa->valoffset = 1;
312 ctmpa->value = cpystr(alpine_oauth2_list[i].name);
313 ctmpa->varname = NULL;
314 ctmpa->varnamep = ctmpb = ctmpa;
317 /* Setup client-id variable */
318 varlist[l]->name = cpystr(XOAUTH2_CLIENT_ID);
319 varlist[l]->is_used = 1;
320 varlist[l]->is_user = 1;
321 varlist[l]->main_user_val.p = strcmp(id, id_def)? cpystr(id) : NULL;
322 varlist[l]->global_val.p = cpystr(id_def);
323 set_current_val(varlist[l], FALSE, FALSE);
325 /* Write client-id variable */
326 new_confline(&ctmpa)->var = varlist[l];
327 utf8_snprintf(tmp, sizeof(tmp), " %-*.100w =", ln, XOAUTH2_CLIENT_ID);
328 tmp[sizeof(tmp)-1] = '\0';
329 ctmpa->varname = cpystr(tmp);
330 ctmpa->varmem = l++;
331 ctmpa->valoffset = ln + 3 + 3;
332 ctmpa->value = pretty_value(ps, ctmpa);
333 ctmpa->keymenu = &config_text_keymenu;
334 ctmpa->help = h_config_xoauth2_client_id;
335 ctmpa->tool = text_tool;
336 ctmpa->varnamep = ctmpb;
338 /* Set up client-secret variable */
339 varlist[l]->name = cpystr(XOAUTH2_CLIENT_SECRET);
340 varlist[l]->is_used = 1;
341 varlist[l]->is_user = 1;
342 varlist[l]->main_user_val.p = strcmp(secret, secret_def) ? cpystr(secret) : NULL;
343 varlist[l]->global_val.p = cpystr(secret_def);
344 set_current_val(varlist[l], FALSE, FALSE);
346 /* Write client-secret variable */
347 new_confline(&ctmpa)->var = varlist[l];
348 utf8_snprintf(tmp, sizeof(tmp), " %-*.100w =", ln, XOAUTH2_CLIENT_SECRET);
349 tmp[sizeof(tmp)-1] = '\0';
350 ctmpa->varname = cpystr(tmp);
351 ctmpa->varmem = l++;
352 ctmpa->valoffset = ln + 3 + 3;
353 ctmpa->value = pretty_value(ps, ctmpa);
354 ctmpa->keymenu = &config_text_keymenu;
355 ctmpa->help = h_config_xoauth2_client_secret;
356 ctmpa->tool = text_tool;
357 ctmpa->varnamep = ctmpb;
359 /* Separate servers with a blank line */
360 new_confline(&ctmpa);
361 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
363 /* clean up the house */
364 if(id_lval) fs_give((void **) &id_lval);
365 if(secret_lval) fs_give((void **) &secret_lval);
366 if(name_lval) fs_give((void **) &name_lval);
369 vsave = save_config_vars(ps, expose_hidden_config);
370 first_line = pos < 0 ? first_sel_confline(first_line) : set_confline_number(first_line, pos);
371 pos = -1;
372 memset(&screen, 0, sizeof(screen));
373 screen.ro_warning = readonly_warning;
374 /* TRANSLATORS: Print something1 using something2.
375 "configuration" is something1 */
376 switch(conf_scroll_screen(ps, &screen, first_line, "XOAUTH2 Alpine Info",
377 _("configuration"), 0, &pos)){
378 case 0:
379 break;
381 case 1:
382 write_xoauth_configuration(&ps->vars[V_XOAUTH2_INFO], varlist, ew);
383 write_pinerc(ps, ew, WRP_NONE);
384 break;
386 case 10:
387 revert_to_saved_config(ps, vsave, expose_hidden_config);
388 if(prc)
389 prc->outstanding_pinerc_changes = 0;
390 break;
392 default:
393 q_status_message(SM_ORDER,7,10,
394 "conf_scroll_screen bad ret, not supposed to happen");
395 break;
397 } while (pos >= 0);
399 #ifdef _WINDOWS
400 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
401 #endif