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