Commit | Line | Data |
---|---|---|
eb54b70d | 1 | /* |
2 | * Dolda Connect - Modular multiuser Direct Connect-style client | |
714e16fb | 3 | * Copyright (C) 2007 Fredrik Tolf <fredrik@dolda2000.com> |
eb54b70d | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation; either version 2 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | */ | |
19 | ||
20 | #include <stdlib.h> | |
21 | #include <stdio.h> | |
22 | #include <unistd.h> | |
23 | #include <string.h> | |
24 | #include <ctype.h> | |
25 | #include <signal.h> | |
26 | #include <errno.h> | |
27 | #include <gtk/gtk.h> | |
c8394dc9 | 28 | #include <gdk/gdkkeysyms.h> |
eb54b70d | 29 | #include <locale.h> |
30 | #include <libintl.h> | |
31 | #include <pwd.h> | |
32 | #include <stdarg.h> | |
48b166ff | 33 | #include <arpa/inet.h> |
c3aa1aa0 | 34 | #include <doldaconnect/uilib.h> |
35 | #include <doldaconnect/uimisc.h> | |
eb54b70d | 36 | |
37 | #ifdef HAVE_CONFIG_H | |
38 | #include <config.h> | |
39 | #endif | |
40 | #include <utils.h> | |
41 | ||
42 | struct validation { | |
43 | int (*check)(const char *val); | |
44 | char *invmsg; | |
45 | }; | |
46 | ||
47 | struct cfvar { | |
48 | char *name; | |
49 | char *rname; | |
50 | char *val; | |
51 | struct validation *vld; | |
0fbd8398 | 52 | GtkWidget **astw, **cfww; |
eb54b70d | 53 | }; |
54 | ||
55 | char *cfname; | |
56 | GtkWindow *rootwnd = NULL; | |
57 | GtkListStore *shares; | |
c8394dc9 | 58 | int state, dirty = 1; |
0fbd8398 | 59 | int ignoreclose = 0; |
60 | ||
0fbd8398 | 61 | #define _(text) gettext(text) |
62 | ||
b1099f1f FT |
63 | #include "dolconf-assistant.gtkh" |
64 | #include "dolconf-wnd.gtkh" | |
eb54b70d | 65 | |
66 | int v_nonempty(const char *val) | |
67 | { | |
68 | return(strlen(val) > 0); | |
69 | } | |
70 | ||
71 | int v_dcstring(const char *val) | |
72 | { | |
73 | return((strchr(val, ' ') == NULL) && | |
74 | (strchr(val, '|') == NULL) && | |
75 | (strchr(val, '$') == NULL)); | |
76 | } | |
77 | ||
48b166ff | 78 | int v_natural(const char *val) |
eb54b70d | 79 | { |
48b166ff | 80 | if(!*val) |
81 | return(0); | |
82 | for(; *val; val++) { | |
83 | if(!isdigit(*val)) | |
eb54b70d | 84 | return(0); |
85 | } | |
86 | return(1); | |
87 | } | |
88 | ||
48b166ff | 89 | int v_integer(const char *val) |
90 | { | |
91 | int f, d; | |
92 | ||
93 | for(f = 1, d = 0; *val; val++, f = 0) { | |
94 | if(isdigit(*val)) { | |
95 | d = 1; | |
96 | } else if(f && (*val == '-')) { | |
97 | } else { | |
98 | return(0); | |
99 | } | |
100 | } | |
101 | return(d); | |
102 | } | |
103 | ||
104 | int v_ipv4(const char *val) | |
105 | { | |
106 | struct in_addr buf; | |
107 | ||
108 | return(inet_aton(val, &buf) != 0); | |
109 | } | |
110 | ||
0fbd8398 | 111 | #undef _ |
eb54b70d | 112 | #define _(text) text |
113 | ||
114 | struct validation nonempty = { | |
115 | .check = v_nonempty, | |
116 | .invmsg = _("%s must not be empty"), | |
117 | }; | |
118 | ||
119 | struct validation dcstring = { | |
120 | .check = v_dcstring, | |
121 | .invmsg = _("%s must not contain spaces, `|' or `$'"), | |
122 | }; | |
123 | ||
48b166ff | 124 | struct validation natural = { |
125 | .check = v_natural, | |
126 | .invmsg = _("%s must be a natural number"), | |
127 | }; | |
128 | ||
129 | struct validation integer = { | |
130 | .check = v_integer, | |
131 | .invmsg = _("%s must be an integer"), | |
132 | }; | |
133 | ||
134 | struct validation ipv4 = { | |
135 | .check = v_ipv4, | |
136 | .invmsg = _("%s must be an IP address"), | |
eb54b70d | 137 | }; |
138 | ||
139 | struct validation *vldxlate[] = { | |
48b166ff | 140 | &nonempty, &dcstring, &natural, &integer, &ipv4, |
eb54b70d | 141 | NULL |
142 | }; | |
143 | ||
144 | struct cfvar config[] = { | |
0fbd8398 | 145 | {"cli.defnick", _("Screen name"), "", &dcstring, &ast_nick, &cfw_nick}, |
48b166ff | 146 | {"net.mode", NULL, "0", &natural}, |
0fbd8398 | 147 | {"net.visibleipv4", "IP address", "0.0.0.0", &ipv4, NULL, &cfw_extip}, |
48b166ff | 148 | {"ui.onlylocal", NULL, "0", &natural}, |
149 | {"ui.port", NULL, "-1", &integer}, | |
150 | {"auth.authless", NULL, "0", &natural}, | |
151 | {"transfer.slots", _("Upload slots"), "6", &natural}, | |
0fbd8398 | 152 | {"dc.speedstring", _("Connection speed"), "DSL", &dcstring, NULL, &cfw_cntype}, |
153 | {"dc.email", _("E-mail address"), "spam@spam.net", &dcstring, NULL, &cfw_mail}, | |
154 | {"dc.desc", _("Share description"), "", NULL, &ast_desc, &cfw_desc}, | |
155 | {"dc.tcpport", _("Direct Connect TCP port"), "0", &natural, NULL, &cfw_tcpport}, | |
156 | {"dc.udpport", _("Direct Connect UDP port"), "0", &natural, NULL, &cfw_udpport}, | |
eb54b70d | 157 | {NULL} |
158 | }; | |
159 | ||
160 | #undef _ | |
161 | #define _(text) gettext(text) | |
162 | ||
eb54b70d | 163 | struct cfvar *findcfvar(char *name) |
164 | { | |
165 | struct cfvar *v; | |
166 | ||
167 | for(v = config; v->name != NULL; v++) { | |
168 | if(!strcmp(v->name, name)) | |
169 | return(v); | |
170 | } | |
171 | return(NULL); | |
172 | } | |
173 | ||
174 | void setcfvar(char *name, const char *val) | |
175 | { | |
176 | struct cfvar *v; | |
177 | ||
178 | v = findcfvar(name); | |
c8394dc9 | 179 | if(!strcmp(v->val, val)) |
180 | return; | |
eb54b70d | 181 | free(v->val); |
182 | v->val = sstrdup(val); | |
c8394dc9 | 183 | dirty = 1; |
eb54b70d | 184 | } |
185 | ||
186 | int msgbox(int type, int buttons, char *format, ...) | |
187 | { | |
188 | GtkWidget *swnd; | |
189 | va_list args; | |
190 | char *buf; | |
191 | int resp; | |
192 | ||
193 | va_start(args, format); | |
194 | buf = vsprintf2(format, args); | |
195 | va_end(args); | |
196 | swnd = gtk_message_dialog_new(rootwnd, GTK_DIALOG_MODAL, type, buttons, "%s", buf); | |
197 | gtk_window_set_title(GTK_WINDOW(swnd), _("Dolda Connect configurator")); | |
198 | resp = gtk_dialog_run(GTK_DIALOG(swnd)); | |
199 | gtk_widget_destroy(swnd); | |
200 | free(buf); | |
201 | return(resp); | |
202 | } | |
203 | ||
204 | void prepstatic(void) | |
205 | { | |
206 | struct validation **v; | |
207 | struct cfvar *c; | |
208 | ||
209 | for(v = vldxlate; *v != NULL; v++) | |
210 | (*v)->invmsg = gettext((*v)->invmsg); | |
211 | for(c = config; c->name != NULL; c++) { | |
212 | if(c->rname != NULL) | |
213 | c->rname = gettext(c->rname); | |
214 | c->val = sstrdup(c->val); | |
215 | } | |
216 | } | |
217 | ||
218 | char *getword(char **p) | |
219 | { | |
220 | char *buf, *p2, delim; | |
221 | size_t len; | |
222 | ||
223 | if(**p == '\"') | |
224 | delim = '\"'; | |
225 | else | |
226 | delim = ' '; | |
227 | p2 = *p; | |
228 | while((p2 = strchr(p2 + 1, delim)) != NULL) { | |
229 | if(p2[-1] != '\\') | |
230 | break; | |
231 | } | |
232 | if(p2 == NULL) | |
233 | p2 = *p + strlen(*p); | |
0fbd8398 | 234 | len = p2 - *p - ((*p2 == '\"')?1:0); |
eb54b70d | 235 | buf = smalloc(len + 1); |
42aa110f | 236 | memcpy(buf, *p + ((delim == '\"')?1:0), len); |
eb54b70d | 237 | buf[len] = 0; |
238 | *p = p2 + ((*p2 == '\"')?1:0); | |
239 | for(p2 = buf; *p2; p2++, len--) { | |
240 | if(*p2 == '\\') | |
241 | memmove(p2, p2 + 1, len--); | |
242 | } | |
243 | return(buf); | |
244 | } | |
245 | ||
246 | char *quoteword(char *word) | |
247 | { | |
248 | char *wp, *buf, *bp; | |
249 | int dq, numbs, numc; | |
250 | ||
251 | dq = 0; | |
252 | numbs = 0; | |
253 | numc = 0; | |
254 | if(*word == '\0') | |
255 | { | |
256 | dq = 1; | |
257 | } else { | |
258 | for(wp = word; *wp != '\0'; wp++) | |
259 | { | |
260 | if(!dq && isspace(*wp)) | |
261 | dq = 1; | |
262 | if((*wp == '\\') || (*wp == '\"')) | |
263 | numbs++; | |
264 | numc++; | |
265 | } | |
266 | } | |
267 | if(!dq && !numbs) | |
268 | return(NULL); | |
269 | bp = buf = smalloc(sizeof(wchar_t) * (numc + numbs + (dq?2:0) + 1)); | |
270 | if(dq) | |
271 | *(bp++) = '\"'; | |
272 | for(wp = word; *wp != '\0'; wp++) | |
273 | { | |
274 | if((*wp == '\\') || (*wp == '\"')) | |
275 | *(bp++) = '\\'; | |
276 | *(bp++) = *wp; | |
277 | } | |
278 | if(dq) | |
279 | *(bp++) = '\"'; | |
280 | *(bp++) = '\0'; | |
281 | return(buf); | |
282 | } | |
283 | ||
284 | int readconfig(void) | |
285 | { | |
286 | int rv; | |
287 | FILE *cf; | |
288 | char lbuf[1024]; | |
289 | char *key, *val, *p; | |
290 | size_t len; | |
291 | struct cfvar *var; | |
292 | GtkTreeIter iter; | |
293 | ||
294 | rv = 0; | |
295 | if((cf = fopen(cfname, "r")) == NULL) { | |
296 | msgbox(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("Could not open the configuration file for reading: %s"), strerror(errno)); | |
297 | return(-1); | |
298 | } | |
299 | key = val = NULL; | |
300 | while(fgets(lbuf, sizeof(lbuf), cf) != NULL) { | |
301 | len = strlen(lbuf); | |
302 | if(lbuf[len - 1] == '\n') | |
303 | lbuf[len - 1] = 0; | |
304 | if(key != NULL) { | |
305 | free(key); | |
306 | key = NULL; | |
307 | } | |
308 | if(val != NULL) { | |
309 | free(val); | |
310 | val = NULL; | |
311 | } | |
312 | if(!strncmp(lbuf, "set ", 4)) { | |
313 | p = lbuf + 4; | |
314 | if(((key = getword(&p)) == NULL) || (*(p++) != ' ') || ((val = getword(&p)) == NULL)) { | |
315 | rv = 1; | |
316 | continue; | |
317 | } | |
318 | for(var = config; var->name != NULL; var++) { | |
319 | if(!strcmp(var->name, key)) { | |
320 | free(var->val); | |
321 | var->val = sstrdup(val); | |
322 | break; | |
323 | } | |
324 | } | |
325 | if(var->name == NULL) | |
326 | rv = 1; | |
327 | } else if(!strncmp(lbuf, "share ", 6)) { | |
328 | p = lbuf + 6; | |
329 | if(((key = getword(&p)) == NULL) || (*(p++) != ' ') || ((val = getword(&p)) == NULL)) { | |
330 | rv = 1; | |
331 | continue; | |
332 | } | |
333 | gtk_list_store_append(shares, &iter); | |
334 | gtk_list_store_set(shares, &iter, 0, key, 1, val, -1); | |
335 | } else if(!lbuf[0] || lbuf[0] == '#') { | |
336 | } else { | |
337 | rv = 1; | |
338 | } | |
339 | } | |
340 | if(key != NULL) | |
341 | free(key); | |
342 | if(val != NULL) | |
343 | free(val); | |
344 | fclose(cf); | |
c8394dc9 | 345 | dirty = 0; |
eb54b70d | 346 | return(rv); |
347 | } | |
348 | ||
5668485c | 349 | int writeconfig(void) |
eb54b70d | 350 | { |
351 | FILE *cf; | |
352 | struct cfvar *var; | |
353 | GtkTreeIter iter; | |
354 | char *buf, *buf2; | |
355 | ||
356 | if((cf = fopen(cfname, "w")) == NULL) { | |
357 | msgbox(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("Could not open the configuration file for writing: %s"), strerror(errno)); | |
5668485c | 358 | return(-1); |
eb54b70d | 359 | } |
360 | fputs("# This file was generated by dolconf v" VERSION "\n\n", cf); | |
361 | for(var = config; var->name != NULL; var++) { | |
362 | fprintf(cf, "set %s ", var->name); | |
363 | if((buf = quoteword(var->val)) == NULL) { | |
364 | fputs(var->val, cf); | |
365 | } else { | |
366 | fputs(buf, cf); | |
367 | free(buf); | |
368 | } | |
369 | fputc('\n', cf); | |
370 | } | |
371 | if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(shares), &iter)) { | |
372 | fputc('\n', cf); | |
373 | do { | |
374 | fputs("share ", cf); | |
375 | gtk_tree_model_get(GTK_TREE_MODEL(shares), &iter, 0, &buf2, -1); | |
376 | if((buf = quoteword(buf2)) == NULL) { | |
377 | fputs(buf2, cf); | |
378 | } else { | |
379 | fputs(buf, cf); | |
380 | free(buf); | |
381 | } | |
382 | g_free(buf2); | |
383 | fputc(' ', cf); | |
384 | gtk_tree_model_get(GTK_TREE_MODEL(shares), &iter, 1, &buf2, -1); | |
385 | if((buf = quoteword(buf2)) == NULL) { | |
386 | fputs(buf2, cf); | |
387 | } else { | |
388 | fputs(buf, cf); | |
389 | free(buf); | |
390 | } | |
391 | g_free(buf2); | |
392 | fputc('\n', cf); | |
393 | } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(shares), &iter)); | |
394 | } | |
395 | fclose(cf); | |
c8394dc9 | 396 | dirty = 0; |
5668485c | 397 | return(0); |
eb54b70d | 398 | } |
399 | ||
0fbd8398 | 400 | void fillcfw(void) |
eb54b70d | 401 | { |
0fbd8398 | 402 | struct cfvar *var; |
403 | ||
404 | for(var = config; var->name != NULL; var++) { | |
405 | if(var->cfww != NULL) | |
406 | gtk_entry_set_text(GTK_ENTRY(*(var->cfww)), var->val); | |
407 | } | |
408 | if(atoi(findcfvar("dc.tcpport")->val) || atoi(findcfvar("dc.udpport")->val)) | |
409 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_orport), TRUE); | |
410 | else | |
411 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_orport), FALSE); | |
412 | if(strcmp(findcfvar("net.visibleipv4")->val, "0.0.0.0")) | |
413 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_oraddr), TRUE); | |
414 | else | |
415 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_oraddr), FALSE); | |
416 | if(strcmp(findcfvar("ui.port")->val, "-1")) { | |
417 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_uinet), TRUE); | |
418 | if(strcmp(findcfvar("auth.authless")->val, "1")) | |
419 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_authless), FALSE); | |
420 | else | |
421 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_authless), TRUE); | |
422 | } else { | |
423 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_uinet), FALSE); | |
424 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfw_authless), FALSE); | |
425 | } | |
eb54b70d | 426 | } |
427 | ||
0fbd8398 | 428 | void ast2conf(void) |
eb54b70d | 429 | { |
eb54b70d | 430 | setcfvar("cli.defnick", gtk_entry_get_text(GTK_ENTRY(ast_nick))); |
431 | setcfvar("dc.desc", gtk_entry_get_text(GTK_ENTRY(ast_desc))); | |
48b166ff | 432 | if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ast_mode_psv))) { |
433 | setcfvar("net.mode", "1"); | |
434 | } else { | |
435 | setcfvar("net.mode", "0"); | |
436 | if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ast_mode_nat))) { | |
437 | setcfvar("net.visibleipv4", gtk_entry_get_text(GTK_ENTRY(ast_extip))); | |
438 | setcfvar("dc.tcpport", gtk_entry_get_text(GTK_ENTRY(ast_udpport))); | |
439 | setcfvar("dc.udpport", gtk_entry_get_text(GTK_ENTRY(ast_tcpport))); | |
440 | } else { | |
441 | setcfvar("net.visibleipv4", "0.0.0.0"); | |
442 | setcfvar("dc.tcpport", "0"); | |
443 | setcfvar("dc.udpport", "0"); | |
444 | } | |
445 | } | |
0fbd8398 | 446 | } |
447 | ||
448 | void cfw2conf(void) | |
449 | { | |
450 | struct cfvar *var; | |
c8394dc9 | 451 | const char *val; |
0fbd8398 | 452 | |
453 | for(var = config; var->name != NULL; var++) { | |
454 | if(var->cfww != NULL) { | |
c8394dc9 | 455 | val = gtk_entry_get_text(GTK_ENTRY(*(var->cfww))); |
456 | if(!strcmp(var->val, val)) | |
457 | continue; | |
0fbd8398 | 458 | free(var->val); |
c8394dc9 | 459 | var->val = sstrdup(val); |
460 | dirty = 1; | |
0fbd8398 | 461 | } |
462 | } | |
463 | if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cfw_mode_act))) { | |
464 | setcfvar("net.mode", "0"); | |
465 | if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cfw_orport))) { | |
466 | setcfvar("dc.tcpport", "0"); | |
467 | setcfvar("dc.udpport", "0"); | |
468 | } | |
469 | if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cfw_oraddr))) { | |
470 | setcfvar("net.visibleipv4", "0.0.0.0"); | |
471 | } | |
472 | } else { | |
473 | setcfvar("net.mode", "1"); | |
474 | } | |
475 | if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cfw_uinet))) { | |
476 | setcfvar("ui.port", "1500"); | |
477 | if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cfw_authless))) | |
478 | setcfvar("auth.authless", "1"); | |
479 | else | |
480 | setcfvar("auth.authless", "0"); | |
481 | } else { | |
482 | setcfvar("ui.port", "-1"); | |
483 | setcfvar("auth.authless", "0"); | |
484 | } | |
485 | } | |
486 | ||
958a04bd | 487 | struct cfvar *cfwvalid(void) |
488 | { | |
489 | struct cfvar *cv; | |
490 | ||
491 | for(cv = config; cv->name != NULL; cv++) { | |
492 | if((cv->vld != NULL) && !cv->vld->check(cv->val)) { | |
493 | if(cv->rname) { | |
494 | return(cv); | |
495 | } else { | |
496 | msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Internal error (Auto-generated variable %s has an invalid value \"%s\")"), cv->name, cv->val); | |
497 | abort(); | |
498 | } | |
499 | } | |
500 | } | |
501 | return(NULL); | |
502 | } | |
503 | ||
0fbd8398 | 504 | void astcancel(GtkWidget *widget, gpointer uudata) |
505 | { | |
506 | if(ignoreclose) | |
507 | return; | |
508 | gtk_main_quit(); | |
509 | state = -1; | |
510 | } | |
511 | ||
512 | #define bufcats(buf, str) bufcat(buf, str, strlen(str)) | |
513 | ||
514 | void astupdate(GtkWidget *widget, GtkWidget *page, gpointer uudata) | |
515 | { | |
516 | char *s, *buf; | |
517 | size_t sdata, ssize; | |
518 | struct cfvar *var; | |
519 | GtkTreeIter iter; | |
520 | ||
521 | ast2conf(); | |
eb54b70d | 522 | s = NULL; |
523 | sdata = ssize = 0; | |
524 | for(var = config; var->name != NULL; var++) { | |
525 | if(var->rname == NULL) | |
526 | continue; | |
527 | bufcats(s, var->rname); | |
528 | bufcats(s, ": "); | |
529 | bufcat(s, var->val, strlen(var->val)); | |
530 | addtobuf(s, '\n'); | |
531 | } | |
532 | if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(shares), &iter)) { | |
533 | addtobuf(s, '\n'); | |
534 | bufcats(s, _("Shares:\n")); | |
535 | do { | |
536 | addtobuf(s, '\t'); | |
537 | gtk_tree_model_get(GTK_TREE_MODEL(shares), &iter, 1, &buf, -1); | |
538 | bufcats(s, buf); | |
539 | g_free(buf); | |
540 | addtobuf(s, '\n'); | |
541 | } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(shares), &iter)); | |
542 | } | |
543 | gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(ast_summary)), s, sdata); | |
544 | free(s); | |
545 | } | |
546 | ||
547 | void cb_ast_wnd_apply(GtkWidget *widget, gpointer uudata) | |
548 | { | |
549 | writeconfig(); | |
550 | gtk_main_quit(); | |
0fbd8398 | 551 | if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ast_action_dolcon))) |
552 | state = 2; | |
553 | else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ast_action_exit))) | |
554 | state = -1; | |
555 | else | |
556 | state = 0; | |
557 | ignoreclose = 1; | |
eb54b70d | 558 | } |
559 | ||
560 | void cb_ast_nick_changed(GtkWidget *widget, gpointer uudata) | |
561 | { | |
562 | if(v_dcstring(gtk_entry_get_text(GTK_ENTRY(ast_nick)))) | |
563 | gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page1, TRUE); | |
564 | else | |
565 | gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page1, FALSE); | |
566 | } | |
567 | ||
568 | int hasshare(int col, char *name) | |
569 | { | |
570 | GtkTreeIter iter; | |
571 | char *buf; | |
572 | ||
573 | if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(shares), &iter)) { | |
574 | do { | |
575 | gtk_tree_model_get(GTK_TREE_MODEL(shares), &iter, col, &buf, -1); | |
576 | if(!strcmp(buf, name)) { | |
577 | g_free(buf); | |
578 | return(1); | |
579 | } | |
580 | g_free(buf); | |
581 | } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(shares), &iter)); | |
582 | } | |
583 | return(0); | |
584 | } | |
585 | ||
0fbd8398 | 586 | int shareadd(void) |
eb54b70d | 587 | { |
0fbd8398 | 588 | int i, ret; |
eb54b70d | 589 | GSList *fns, *next; |
590 | char *fn, *sn, *p; | |
591 | GtkTreeIter iter; | |
592 | GtkWidget *chd; | |
593 | int resp; | |
594 | ||
595 | chd = gtk_file_chooser_dialog_new(_("Shared directories"), rootwnd, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); | |
596 | gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(chd), TRUE); | |
597 | gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(chd), TRUE); | |
598 | resp = gtk_dialog_run(GTK_DIALOG(chd)); | |
599 | if(resp != GTK_RESPONSE_ACCEPT) { | |
600 | gtk_widget_destroy(chd); | |
0fbd8398 | 601 | return(0); |
eb54b70d | 602 | } |
0fbd8398 | 603 | ret = 0; |
eb54b70d | 604 | fns = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(chd)); |
605 | gtk_widget_destroy(chd); | |
606 | while(fns != NULL) { | |
607 | fn = fns->data; | |
608 | if(!hasshare(1, fn)) { | |
609 | if((p = strrchr(fn, '/')) == NULL) | |
610 | p = fn; | |
611 | else | |
612 | p++; | |
613 | sn = sstrdup(p); | |
614 | if(hasshare(0, sn)) { | |
615 | for(i = 2; 1; i++) { | |
616 | free(sn); | |
617 | sn = sprintf2("%s%i", p, i); | |
618 | if(!hasshare(0, sn)) | |
619 | break; | |
620 | } | |
621 | } | |
622 | gtk_list_store_append(shares, &iter); | |
623 | gtk_list_store_set(shares, &iter, 0, sn, 1, fn, -1); | |
624 | free(sn); | |
0fbd8398 | 625 | ret = 1; |
eb54b70d | 626 | } |
627 | g_free(fn); | |
628 | next = fns->next; | |
629 | g_slist_free_1(fns); | |
630 | fns = next; | |
631 | } | |
0fbd8398 | 632 | return(ret); |
633 | } | |
634 | ||
635 | void cb_ast_shareadd_clicked(GtkWidget *widget, gpointer uudata) | |
636 | { | |
637 | if(shareadd()) | |
638 | gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page2, TRUE); | |
639 | } | |
640 | ||
641 | void cb_cfw_shareadd_clicked(GtkWidget *widget, gpointer uudata) | |
642 | { | |
c335e21c FT |
643 | if(shareadd()) |
644 | dirty = 1; | |
eb54b70d | 645 | } |
646 | ||
647 | void cb_ast_sharerem_clicked(GtkWidget *widget, gpointer uudata) | |
648 | { | |
649 | GtkTreeIter iter; | |
650 | ||
651 | if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(ast_sharelist)), NULL, &iter)) | |
652 | gtk_list_store_remove(shares, &iter); | |
653 | if(gtk_tree_model_iter_n_children(GTK_TREE_MODEL(shares), NULL) == 0) | |
654 | gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page2, FALSE); | |
655 | } | |
656 | ||
0fbd8398 | 657 | void cb_cfw_sharerem_clicked(GtkWidget *widget, gpointer uudata) |
658 | { | |
659 | GtkTreeIter iter; | |
660 | ||
c335e21c | 661 | if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(cfw_sharelist)), NULL, &iter)) { |
0fbd8398 | 662 | gtk_list_store_remove(shares, &iter); |
c335e21c FT |
663 | dirty = 1; |
664 | } | |
0fbd8398 | 665 | } |
666 | ||
48b166ff | 667 | void cb_ast_checkports(GtkWidget *widget, gpointer uudata) |
668 | { | |
669 | gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page3, | |
670 | v_natural(gtk_entry_get_text(GTK_ENTRY(ast_tcpport))) && | |
0fbd8398 | 671 | (atoi(gtk_entry_get_text(GTK_ENTRY(ast_tcpport))) >= 1024) && |
48b166ff | 672 | v_natural(gtk_entry_get_text(GTK_ENTRY(ast_udpport))) && |
0fbd8398 | 673 | (atoi(gtk_entry_get_text(GTK_ENTRY(ast_udpport))) >= 1024) && |
48b166ff | 674 | v_ipv4(gtk_entry_get_text(GTK_ENTRY(ast_extip)))); |
675 | } | |
676 | ||
677 | void cb_ast_mode_nat_toggled(GtkWidget *widget, gpointer uudata) | |
678 | { | |
679 | if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { | |
680 | gtk_widget_set_sensitive(GTK_WIDGET(ast_portbox), TRUE); | |
681 | cb_ast_checkports(widget, NULL); | |
682 | } else { | |
683 | gtk_widget_set_sensitive(GTK_WIDGET(ast_portbox), FALSE); | |
684 | gtk_assistant_set_page_complete(GTK_ASSISTANT(ast_wnd), ast_page3, TRUE); | |
685 | } | |
686 | } | |
687 | ||
0fbd8398 | 688 | void cb_cfw_mode_act_toggled(GtkWidget *widget, gpointer uudata) |
689 | { | |
690 | gtk_widget_set_sensitive(GTK_WIDGET(cfw_natbox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))); | |
691 | } | |
692 | ||
693 | void cb_cfw_orport_toggled(GtkWidget *widget, gpointer uudata) | |
694 | { | |
695 | gtk_widget_set_sensitive(GTK_WIDGET(cfw_portbox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))); | |
696 | } | |
697 | ||
698 | void cb_cfw_oraddr_toggled(GtkWidget *widget, gpointer uudata) | |
699 | { | |
700 | gtk_widget_set_sensitive(GTK_WIDGET(cfw_addrbox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))); | |
701 | } | |
702 | ||
703 | void cb_cfw_uinet_toggled(GtkWidget *widget, gpointer uudata) | |
704 | { | |
705 | gtk_widget_set_sensitive(GTK_WIDGET(cfw_uibox), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))); | |
706 | } | |
707 | ||
5668485c | 708 | int hupserver(int disperr) |
c3aa1aa0 | 709 | { |
5668485c | 710 | int tag, ret; |
c3aa1aa0 | 711 | struct dc_response *resp; |
712 | ||
713 | if(dc_connectsync2(dc_srv_local, DC_LATEST) < 0) { | |
5668485c FT |
714 | if(disperr) |
715 | msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not connect to server")); | |
716 | return(-1); | |
c3aa1aa0 | 717 | } |
718 | if(dc_login(NULL, 1, dc_convnone, NULL) != DC_LOGIN_ERR_SUCCESS) { | |
719 | dc_disconnect(); | |
5668485c FT |
720 | if(disperr) |
721 | msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not connect to server")); | |
722 | return(-1); | |
c3aa1aa0 | 723 | } |
5668485c | 724 | ret = 0; |
c3aa1aa0 | 725 | tag = dc_queuecmd(NULL, NULL, L"hup", NULL); |
726 | if((resp = dc_gettaggedrespsync(tag)) != NULL) { | |
5668485c FT |
727 | if(resp->code != 200) { |
728 | if(disperr) | |
729 | msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not connect to server")); | |
730 | ret = -1; | |
731 | } | |
c3aa1aa0 | 732 | dc_freeresp(resp); |
733 | } | |
734 | dc_disconnect(); | |
5668485c FT |
735 | return(ret); |
736 | } | |
737 | ||
738 | int saveconfig(void) | |
739 | { | |
740 | struct cfvar *cv; | |
741 | ||
42aa110f | 742 | cfw2conf(); |
5668485c FT |
743 | if((cv = cfwvalid()) != NULL) { |
744 | msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, cv->vld->invmsg, cv->rname); | |
745 | return(-1); | |
746 | } | |
5668485c FT |
747 | return(writeconfig()); |
748 | } | |
749 | ||
750 | /* | |
751 | void cb_cfw_hup_activate(GtkWidget *widget, gpointer uudata) | |
752 | { | |
753 | hupserver(1); | |
c3aa1aa0 | 754 | } |
755 | ||
c8394dc9 | 756 | void cb_cfw_save_activate(GtkWidget *widget, gpointer uudata) |
0fbd8398 | 757 | { |
758 | struct cfvar *cv; | |
759 | ||
958a04bd | 760 | if((cv = cfwvalid()) != NULL) { |
761 | msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, cv->vld->invmsg, cv->rname); | |
762 | return; | |
0fbd8398 | 763 | } |
764 | cfw2conf(); | |
765 | writeconfig(); | |
766 | } | |
767 | ||
c8394dc9 | 768 | void cb_cfw_quit_activate(GtkWidget *widget, gpointer uudata) |
0fbd8398 | 769 | { |
958a04bd | 770 | cfw2conf(); |
771 | if(dirty) { | |
1a724a90 | 772 | if(msgbox(GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("There are unsaved changes. Do you wish to discard the changes and exit anyway?")) == GTK_RESPONSE_NO) |
958a04bd | 773 | return; |
774 | } | |
0fbd8398 | 775 | gtk_main_quit(); |
776 | state = -1; | |
777 | } | |
5668485c FT |
778 | */ |
779 | ||
42aa110f | 780 | void cb_cfw_ok_clicked(GtkWidget *widget, gpointer uudata) |
5668485c FT |
781 | { |
782 | if(saveconfig()) | |
783 | return; | |
784 | hupserver(0); | |
785 | gtk_main_quit(); | |
786 | state = -1; | |
787 | } | |
788 | ||
42aa110f | 789 | void cb_cfw_cancel_clicked(GtkWidget *widget, gpointer uudata) |
5668485c FT |
790 | { |
791 | gtk_main_quit(); | |
792 | state = -1; | |
793 | } | |
794 | ||
42aa110f | 795 | void cb_cfw_apply_clicked(GtkWidget *widget, gpointer uudata) |
5668485c FT |
796 | { |
797 | if(saveconfig()) | |
798 | return; | |
799 | hupserver(1); | |
800 | } | |
0fbd8398 | 801 | |
eb54b70d | 802 | int main(int argc, char **argv) |
803 | { | |
714e16fb | 804 | int i, c, ex; |
eb54b70d | 805 | struct passwd *pwd; |
806 | ||
807 | setlocale(LC_ALL, ""); | |
808 | bindtextdomain(PACKAGE, LOCALEDIR); | |
809 | textdomain(PACKAGE); | |
810 | prepstatic(); | |
c3aa1aa0 | 811 | dc_init(); |
eb54b70d | 812 | |
813 | gtk_init(&argc, &argv); | |
714e16fb | 814 | state = -1; |
8af979f3 | 815 | while((c = getopt(argc, argv, "hawV")) != -1) { |
714e16fb | 816 | switch(c) { |
817 | case 'a': | |
818 | state = 1; | |
819 | break; | |
820 | case 'w': | |
821 | state = 0; | |
ee20b80b | 822 | break; |
714e16fb | 823 | case 'h': |
289fa2ea | 824 | printf("usage: dolconf [-haw]\n"); |
825 | printf("\t-h\tDisplay this help message\n"); | |
826 | printf("\t-a\tGo directly to the assistant\n"); | |
827 | printf("\t-w\tGo directly to the standard window\n"); | |
8af979f3 FT |
828 | printf("\t-V\tDisplay version info and exit\n"); |
829 | exit(0); | |
830 | case 'V': | |
831 | printf("%s", RELEASEINFO); | |
289fa2ea | 832 | exit(0); |
714e16fb | 833 | default: |
8af979f3 | 834 | fprintf(stderr, "usage: dolconf [-hawV]\n"); |
289fa2ea | 835 | exit(1); |
714e16fb | 836 | } |
837 | } | |
838 | ||
eb54b70d | 839 | create_ast_wnd(); |
0fbd8398 | 840 | create_cfw_wnd(); |
eb54b70d | 841 | shares = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); |
842 | gtk_tree_view_set_model(GTK_TREE_VIEW(ast_sharelist), GTK_TREE_MODEL(shares)); | |
0fbd8398 | 843 | gtk_tree_view_set_model(GTK_TREE_VIEW(cfw_sharelist), GTK_TREE_MODEL(shares)); |
eb54b70d | 844 | |
845 | cfname = NULL; | |
846 | if(getenv("HOME") != NULL) { | |
847 | cfname = sprintf2("%s/.doldacond.conf", getenv("HOME")); | |
848 | } else { | |
849 | if((pwd = getpwuid(getuid())) != NULL) | |
850 | cfname = sprintf2("%s/.doldacond.conf", pwd->pw_dir); | |
851 | } | |
852 | if(cfname == NULL) { | |
853 | msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not get your home directory!")); | |
854 | exit(1); | |
855 | } | |
856 | ||
714e16fb | 857 | ex = !access(cfname, F_OK); |
c8394dc9 | 858 | if(state == -1) { |
859 | if(!ex) { | |
860 | if(msgbox(GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("It appears that you have not run this setup program before. Would you like to run the first-time setup assistant?")) == GTK_RESPONSE_YES) | |
861 | state = 1; | |
862 | else | |
863 | state = 0; | |
864 | } else { | |
0fbd8398 | 865 | state = 0; |
c8394dc9 | 866 | } |
714e16fb | 867 | } |
868 | ||
869 | if(ex && (state == 0)) { | |
eb54b70d | 870 | if(readconfig() == 1) { |
871 | if(msgbox(GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("The configuration file appears to have been edited outside the control of this program. If you continue using this program, all settings not handled by it will be lost. Do you wish to continue?")) == GTK_RESPONSE_NO) | |
872 | exit(1); | |
873 | } | |
874 | } | |
714e16fb | 875 | |
0fbd8398 | 876 | while(state != -1) { |
877 | if(state == 0) { | |
878 | gtk_window_set_default_size(GTK_WINDOW(cfw_wnd), 500, 350); | |
879 | gtk_widget_show(cfw_wnd); | |
880 | fillcfw(); | |
881 | rootwnd = GTK_WINDOW(cfw_wnd); | |
882 | gtk_main(); | |
883 | gtk_widget_hide(cfw_wnd); | |
884 | rootwnd = NULL; | |
885 | } else if(state == 1) { | |
886 | gtk_window_set_default_size(GTK_WINDOW(ast_wnd), 500, 350); | |
887 | gtk_widget_show(ast_wnd); | |
888 | rootwnd = GTK_WINDOW(ast_wnd); | |
889 | gtk_main(); | |
890 | gtk_widget_hide(ast_wnd); | |
891 | ignoreclose = 0; | |
892 | rootwnd = NULL; | |
893 | } else if(state == 2) { | |
894 | for(i = 3; i < FD_SETSIZE; i++) | |
895 | close(i); | |
11146491 FT |
896 | execlp("dolcon-launch", "dolcon-launch", NULL); |
897 | perror("dolcon-launch"); | |
0fbd8398 | 898 | exit(127); |
899 | } else { | |
900 | msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Internal error (Unknown state)")); | |
901 | abort(); | |
902 | } | |
903 | } | |
eb54b70d | 904 | return(0); |
905 | } | |
b1099f1f FT |
906 | |
907 | #include "dolconf-assistant.gtk" | |
908 | #include "dolconf-wnd.gtk" |