A couple of bugfixes in dolconf.
[doldaconnect.git] / config / util / 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#include <doldaconnect/uilib.h>
35#include <doldaconnect/uimisc.h>
36
37#ifdef HAVE_CONFIG_H
38#include <config.h>
39#endif
40#include <utils.h>
41
42struct validation {
43 int (*check)(const char *val);
44 char *invmsg;
45};
46
47struct cfvar {
48 char *name;
49 char *rname;
50 char *val;
51 struct validation *vld;
52 GtkWidget **astw, **cfww;
53};
54
55char *cfname;
56GtkWindow *rootwnd = NULL;
57GtkListStore *shares;
58int state, dirty = 1;
59int ignoreclose = 0;
60
61#define _(text) gettext(text)
62
63#include "dolconf-assistant.gtkh"
64#include "dolconf-wnd.gtkh"
65
66int v_nonempty(const char *val)
67{
68 return(strlen(val) > 0);
69}
70
71int v_dcstring(const char *val)
72{
73 return((strchr(val, ' ') == NULL) &&
74 (strchr(val, '|') == NULL) &&
75 (strchr(val, '$') == NULL));
76}
77
78int v_natural(const char *val)
79{
80 if(!*val)
81 return(0);
82 for(; *val; val++) {
83 if(!isdigit(*val))
84 return(0);
85 }
86 return(1);
87}
88
89int 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
104int v_ipv4(const char *val)
105{
106 struct in_addr buf;
107
108 return(inet_aton(val, &buf) != 0);
109}
110
111#undef _
112#define _(text) text
113
114struct validation nonempty = {
115 .check = v_nonempty,
116 .invmsg = _("%s must not be empty"),
117};
118
119struct validation dcstring = {
120 .check = v_dcstring,
121 .invmsg = _("%s must not contain spaces, `|' or `$'"),
122};
123
124struct validation natural = {
125 .check = v_natural,
126 .invmsg = _("%s must be a natural number"),
127};
128
129struct validation integer = {
130 .check = v_integer,
131 .invmsg = _("%s must be an integer"),
132};
133
134struct validation ipv4 = {
135 .check = v_ipv4,
136 .invmsg = _("%s must be an IP address"),
137};
138
139struct validation *vldxlate[] = {
140 &nonempty, &dcstring, &natural, &integer, &ipv4,
141 NULL
142};
143
144struct cfvar config[] = {
145 {"cli.defnick", _("Screen name"), "", &dcstring, &ast_nick, &cfw_nick},
146 {"net.mode", NULL, "0", &natural},
147 {"net.visibleipv4", "IP address", "0.0.0.0", &ipv4, NULL, &cfw_extip},
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},
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},
157 {NULL}
158};
159
160#undef _
161#define _(text) gettext(text)
162
163struct 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
174void setcfvar(char *name, const char *val)
175{
176 struct cfvar *v;
177
178 v = findcfvar(name);
179 if(!strcmp(v->val, val))
180 return;
181 free(v->val);
182 v->val = sstrdup(val);
183 dirty = 1;
184}
185
186int 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
204void 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
218char *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);
234 len = p2 - *p - ((*p2 == '\"')?1:0);
235 buf = smalloc(len + 1);
236 memcpy(buf, *p + ((delim == '\"')?1:0), len);
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
246char *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
284int 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);
345 dirty = 0;
346 return(rv);
347}
348
349int writeconfig(void)
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));
358 return(-1);
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);
396 dirty = 0;
397 return(0);
398}
399
400void fillcfw(void)
401{
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 }
426}
427
428void ast2conf(void)
429{
430 setcfvar("cli.defnick", gtk_entry_get_text(GTK_ENTRY(ast_nick)));
431 setcfvar("dc.desc", gtk_entry_get_text(GTK_ENTRY(ast_desc)));
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 }
446}
447
448void cfw2conf(void)
449{
450 struct cfvar *var;
451 const char *val;
452
453 for(var = config; var->name != NULL; var++) {
454 if(var->cfww != NULL) {
455 val = gtk_entry_get_text(GTK_ENTRY(*(var->cfww)));
456 if(!strcmp(var->val, val))
457 continue;
458 free(var->val);
459 var->val = sstrdup(val);
460 dirty = 1;
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
487struct 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
504void 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
514void 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();
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
547void cb_ast_wnd_apply(GtkWidget *widget, gpointer uudata)
548{
549 writeconfig();
550 gtk_main_quit();
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;
558}
559
560void 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
568int 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
586int shareadd(void)
587{
588 int i, ret;
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);
601 return(0);
602 }
603 ret = 0;
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);
625 ret = 1;
626 }
627 g_free(fn);
628 next = fns->next;
629 g_slist_free_1(fns);
630 fns = next;
631 }
632 return(ret);
633}
634
635void 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
641void cb_cfw_shareadd_clicked(GtkWidget *widget, gpointer uudata)
642{
643 if(shareadd())
644 dirty = 1;
645}
646
647void 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
657void cb_cfw_sharerem_clicked(GtkWidget *widget, gpointer uudata)
658{
659 GtkTreeIter iter;
660
661 if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(cfw_sharelist)), NULL, &iter)) {
662 gtk_list_store_remove(shares, &iter);
663 dirty = 1;
664 }
665}
666
667void 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))) &&
671 (atoi(gtk_entry_get_text(GTK_ENTRY(ast_tcpport))) >= 1024) &&
672 v_natural(gtk_entry_get_text(GTK_ENTRY(ast_udpport))) &&
673 (atoi(gtk_entry_get_text(GTK_ENTRY(ast_udpport))) >= 1024) &&
674 v_ipv4(gtk_entry_get_text(GTK_ENTRY(ast_extip))));
675}
676
677void 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
688void 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
693void 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
698void 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
703void 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
708int hupserver(int disperr)
709{
710 int tag, ret;
711 struct dc_response *resp;
712
713 if(dc_connectsync2(dc_srv_local, DC_LATEST) < 0) {
714 if(disperr)
715 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not connect to server"));
716 return(-1);
717 }
718 if(dc_login(NULL, 1, dc_convnone, NULL) != DC_LOGIN_ERR_SUCCESS) {
719 dc_disconnect();
720 if(disperr)
721 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not connect to server"));
722 return(-1);
723 }
724 ret = 0;
725 tag = dc_queuecmd(NULL, NULL, L"hup", NULL);
726 if((resp = dc_gettaggedrespsync(tag)) != NULL) {
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 }
732 dc_freeresp(resp);
733 }
734 dc_disconnect();
735 return(ret);
736}
737
738int saveconfig(void)
739{
740 struct cfvar *cv;
741
742 cfw2conf();
743 if((cv = cfwvalid()) != NULL) {
744 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, cv->vld->invmsg, cv->rname);
745 return(-1);
746 }
747 return(writeconfig());
748}
749
750/*
751void cb_cfw_hup_activate(GtkWidget *widget, gpointer uudata)
752{
753 hupserver(1);
754}
755
756void cb_cfw_save_activate(GtkWidget *widget, gpointer uudata)
757{
758 struct cfvar *cv;
759
760 if((cv = cfwvalid()) != NULL) {
761 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, cv->vld->invmsg, cv->rname);
762 return;
763 }
764 cfw2conf();
765 writeconfig();
766}
767
768void cb_cfw_quit_activate(GtkWidget *widget, gpointer uudata)
769{
770 cfw2conf();
771 if(dirty) {
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)
773 return;
774 }
775 gtk_main_quit();
776 state = -1;
777}
778*/
779
780void cb_cfw_ok_clicked(GtkWidget *widget, gpointer uudata)
781{
782 if(saveconfig())
783 return;
784 hupserver(0);
785 gtk_main_quit();
786 state = -1;
787}
788
789void cb_cfw_cancel_clicked(GtkWidget *widget, gpointer uudata)
790{
791 gtk_main_quit();
792 state = -1;
793}
794
795void cb_cfw_apply_clicked(GtkWidget *widget, gpointer uudata)
796{
797 if(saveconfig())
798 return;
799 hupserver(1);
800}
801
802int main(int argc, char **argv)
803{
804 int i, c, ex;
805 struct passwd *pwd;
806
807 setlocale(LC_ALL, "");
808 bindtextdomain(PACKAGE, LOCALEDIR);
809 textdomain(PACKAGE);
810 prepstatic();
811 dc_init();
812
813 gtk_init(&argc, &argv);
814 state = -1;
815 while((c = getopt(argc, argv, "hawV")) != -1) {
816 switch(c) {
817 case 'a':
818 state = 1;
819 break;
820 case 'w':
821 state = 0;
822 break;
823 case 'h':
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");
828 printf("\t-V\tDisplay version info and exit\n");
829 exit(0);
830 case 'V':
831 printf("%s", RELEASEINFO);
832 exit(0);
833 default:
834 fprintf(stderr, "usage: dolconf [-hawV]\n");
835 exit(1);
836 }
837 }
838
839 create_ast_wnd();
840 create_cfw_wnd();
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));
843 gtk_tree_view_set_model(GTK_TREE_VIEW(cfw_sharelist), GTK_TREE_MODEL(shares));
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
857 ex = !access(cfname, F_OK);
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 {
865 state = 0;
866 }
867 }
868
869 if(ex && (state == 0)) {
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 }
875
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);
896 execlp("dolcon-launch", "dolcon-launch", NULL);
897 perror("dolcon-launch");
898 exit(127);
899 } else {
900 msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Internal error (Unknown state)"));
901 abort();
902 }
903 }
904 return(0);
905}
906
907#include "dolconf-assistant.gtk"
908#include "dolconf-wnd.gtk"