2 * This file is part of DisOrder
3 * Copyright (C) 2007, 2008 Richard Kettlewell
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.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
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
20 /** @file disobedience/login.c
21 * @brief Login box for Disobedience
24 #include "disobedience.h"
27 #include <sys/types.h>
31 /** @brief One field in the login window */
32 struct login_window_item
{
33 /** @brief Description label */
34 const char *description
;
36 /** @brief Return the current value */
37 const char *(*get
)(void);
39 /** @brief Set a new value */
40 void (*set
)(const char *value
);
44 * - @ref LWI_HIDDEN - this is a password
50 /** @brief This is a password */
51 #define LWI_HIDDEN 0x0001
53 /** @brief Current login window */
54 static GtkWidget
*login_window
;
56 /** @brief Set connection defaults */
57 static void default_connect(void) {
58 if(!config
->connect
.n
) {
59 config
->connect
.n
= 2;
60 config
->connect
.s
= xcalloc(2, sizeof (char *));
61 config
->connect
.s
[0] = xstrdup("localhost");
62 config
->connect
.s
[1] = xstrdup("9999"); /* whatever */
66 static const char *get_hostname(void) { return config
->connect
.s
[0]; }
67 static const char *get_service(void) { return config
->connect
.s
[1]; }
68 static const char *get_username(void) { return config
->username
; }
69 static const char *get_password(void) { return config
->password ? config
->password
: ""; }
71 static void set_hostname(const char *s
) { config
->connect
.s
[0] = (char *)s
; }
72 static void set_service(const char *s
) { config
->connect
.s
[1] = (char *)s
; }
73 static void set_username(const char *s
) { config
->username
= s
; }
74 static void set_password(const char *s
) { config
->password
= s
; }
76 /** @brief Table used to generate the form */
77 static const struct login_window_item lwis
[] = {
78 { "Hostname", get_hostname
, set_hostname
, 0 },
79 { "Service", get_service
, set_service
, 0 },
80 { "User name", get_username
, set_username
, 0 },
81 { "Password", get_password
, set_password
, LWI_HIDDEN
},
83 #define NLWIS (sizeof lwis / sizeof *lwis)
85 static GtkWidget
*lwi_entry
[NLWIS
];
87 static void update_config(void) {
90 for(n
= 0; n
< NLWIS
; ++n
)
91 lwis
[n
].set(xstrdup(gtk_entry_get_text(GTK_ENTRY(lwi_entry
[n
]))));
95 static int modified_config(void) {
98 for(n
= 0; n
< NLWIS
; ++n
) {
99 const char *entered
= gtk_entry_get_text(GTK_ENTRY(lwi_entry
[n
]));
100 const char *current
= lwis
[n
].get();
101 if(strcmp(entered
, current
))
108 static void login_ok(GtkButton
attribute((unused
)) *button
,
109 gpointer
attribute((unused
)) userdata
) {
114 static void login_save(GtkButton
attribute((unused
)) *button
,
115 gpointer
attribute((unused
)) userdata
) {
116 char *path
= config_userconf(0, 0), *tmp
;
121 /* See if the file already exists */
122 if(access(path
, F_OK
) == 0) {
123 yorn
= gtk_message_dialog_new
124 (GTK_WINDOW(login_window
),
125 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
126 GTK_MESSAGE_QUESTION
,
128 "File %s already exists.", path
);
129 gtk_window_set_title(GTK_WINDOW(yorn
),
130 "Configuration file already exists");
131 gtk_dialog_add_buttons(GTK_DIALOG(yorn
),
132 "Overwrite it", GTK_RESPONSE_ACCEPT
,
133 "Don't save after all", GTK_RESPONSE_REJECT
,
135 if(gtk_dialog_run(GTK_DIALOG(yorn
)) != GTK_RESPONSE_ACCEPT
)
137 gtk_widget_destroy(yorn
);
140 byte_xasprintf(&tmp
, "%s.tmp", path
);
141 /* Make sure the directory exists; don't care if it already exists. */
142 mkdir(d_dirname(tmp
), 02700);
143 /* Write out the file */
144 if(!(fp
= fopen(tmp
, "w"))) {
145 fpopup_msg(GTK_MESSAGE_ERROR
, "error opening %s: %s",
146 tmp
, strerror(errno
));
149 if(fprintf(fp
, "username %s\n"
152 quoteutf8(config
->username
),
153 quoteutf8(config
->password
),
154 quoteutf8(config
->connect
.s
[0]),
155 quoteutf8(config
->connect
.s
[1])) < 0) {
156 fpopup_msg(GTK_MESSAGE_ERROR
, "error writing to %s: %s",
157 tmp
, strerror(errno
));
162 fpopup_msg(GTK_MESSAGE_ERROR
, "error closing %s: %s",
163 tmp
, strerror(errno
));
166 /* Rename into place */
167 if(rename(tmp
, path
) < 0) {
168 fpopup_msg(GTK_MESSAGE_ERROR
, "error renaming %s: %s",
169 tmp
, strerror(errno
));
172 fpopup_msg(GTK_MESSAGE_INFO
, "Saved login configuration to %s", path
);
173 gtk_widget_destroy(login_window
);
176 gtk_widget_destroy(yorn
);
179 static void login_cancel(GtkButton
attribute((unused
)) *button
,
180 gpointer
attribute((unused
)) userdata
) {
181 gtk_widget_destroy(login_window
);
184 /* Buttons that appear at the bottom of the window */
185 static const struct button buttons
[] = {
189 "(Re-)connect using these settings",
194 "Save these settings and close window",
199 "Discard changes and close window"
203 #define NBUTTONS (int)(sizeof buttons / sizeof *buttons)
205 /** @brief Pop up a login box */
206 void login_box(void) {
207 GtkWidget
*table
, *label
, *entry
, *buttonbox
, *vbox
;
210 /* If there's one already then bring it to the front */
212 gtk_window_present(GTK_WINDOW(login_window
));
216 /* Create a new login window */
217 login_window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
218 gtk_widget_set_style(login_window
, tool_style
);
219 g_signal_connect(login_window
, "destroy",
220 G_CALLBACK(gtk_widget_destroyed
), &login_window
);
221 gtk_window_set_title(GTK_WINDOW(login_window
), "Login Details");
222 /* Construct the form */
223 table
= gtk_table_new(NLWIS
+ 1/*rows*/, 2/*columns*/, FALSE
/*homogenous*/);
224 gtk_widget_set_style(table
, tool_style
);
225 for(n
= 0; n
< NLWIS
; ++n
) {
226 label
= gtk_label_new(lwis
[n
].description
);
227 gtk_widget_set_style(label
, tool_style
);
228 gtk_misc_set_alignment(GTK_MISC(label
), 1/*right*/, 0/*bottom*/);
229 gtk_table_attach(GTK_TABLE(table
), label
,
230 0, 1, /* left/right_attach */
231 n
, n
+1, /* top/bottom_attach */
232 GTK_FILL
, 0, /* x/yoptions */
233 1, 1); /* x/ypadding */
234 entry
= gtk_entry_new();
235 gtk_widget_set_style(entry
, tool_style
);
236 gtk_entry_set_visibility(GTK_ENTRY(entry
),
237 lwis
[n
].flags
& LWI_HIDDEN ? FALSE
: TRUE
);
238 gtk_entry_set_text(GTK_ENTRY(entry
), lwis
[n
].get());
239 gtk_table_attach(GTK_TABLE(table
), entry
,
240 1, 2, /* left/right_attach */
241 n
, n
+1, /* top/bottom_attach */
242 GTK_EXPAND
|GTK_FILL
, 0, /* x/yoptions */
243 1, 1); /* x/ypadding */
244 lwi_entry
[n
] = entry
;
246 buttonbox
= create_buttons(buttons
, NBUTTONS
);
247 vbox
= gtk_vbox_new(FALSE
, 1);
248 gtk_box_pack_start(GTK_BOX(vbox
), table
,
249 TRUE
/*expand*/, TRUE
/*fill*/, 1/*padding*/);
250 gtk_box_pack_start(GTK_BOX(vbox
), buttonbox
,
251 FALSE
/*expand*/, FALSE
/*fill*/, 1/*padding*/);
252 gtk_container_add(GTK_CONTAINER(login_window
), vbox
);
253 gtk_window_set_transient_for(GTK_WINDOW(login_window
),
254 GTK_WINDOW(toplevel
));
255 gtk_widget_show_all(login_window
);