+static rights_type users_get_rights(void) {
+ rights_type r = 0;
+ int n;
+
+ /* Extract the rights value */
+ for(n = 0; n < 32; ++n) {
+ if(users_details_rights[n])
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(users_details_rights[n])))
+ r |= 1 << n;
+ }
+ /* Throw out redundant bits */
+ if(r & RIGHT_REMOVE_ANY)
+ r &= ~(rights_type)(RIGHT_REMOVE_MINE|RIGHT_REMOVE_RANDOM);
+ if(r & RIGHT_MOVE_ANY)
+ r &= ~(rights_type)(RIGHT_MOVE_MINE|RIGHT_MOVE_RANDOM);
+ if(r & RIGHT_SCRATCH_ANY)
+ r &= ~(rights_type)(RIGHT_SCRATCH_MINE|RIGHT_SCRATCH_RANDOM);
+ return r;
+}
+
+/** @brief Called when various things fail */
+static void users_op_failed(struct callbackdata attribute((unused)) *cbd,
+ int attribute((unused)) code,
+ const char *msg) {
+ popup_submsg(users_window, GTK_MESSAGE_ERROR, msg);
+}
+
+/** @brief Called when a new user has been created */
+static void users_adduser_completed(void *v) {
+ struct callbackdata *cbd = v;
+
+ /* Now the user is created we can go ahead and set the email address */
+ if(*cbd->u.edituser.email) {
+ struct callbackdata *ncbd = xmalloc(sizeof *cbd);
+ ncbd->onerror = users_op_failed;
+ disorder_eclient_edituser(client, NULL, cbd->u.edituser.user,
+ "email", cbd->u.edituser.email, ncbd);
+ }
+ /* Refresh the list of users */
+ disorder_eclient_users(client, users_got_list, 0);
+ /* We'll select the newly created user */
+ users_deferred_select = cbd->u.edituser.user;
+}
+
+/** @brief Called if creating a new user fails */
+static void users_adduser_failed(struct callbackdata attribute((unused)) *cbd,
+ int attribute((unused)) code,
+ const char *msg) {
+ popup_submsg(users_window, GTK_MESSAGE_ERROR, msg);
+ mode(ADD); /* Let the user try again */
+}
+
+/** @brief Called when the 'Apply' button is pressed */
+static void users_apply(GtkButton attribute((unused)) *button,
+ gpointer attribute((unused)) userdata) {
+ struct callbackdata *cbd;
+ const char *password;
+ const char *password2;
+ const char *name;
+ const char *email;
+
+ switch(users_mode) {
+ case MODE_NONE:
+ return;
+ case MODE_ADD:
+ name = xstrdup(gtk_entry_get_text(GTK_ENTRY(users_details_name)));
+ email = xstrdup(gtk_entry_get_text(GTK_ENTRY(users_details_email)));
+ password = xstrdup(gtk_entry_get_text(GTK_ENTRY(users_details_password)));
+ password2 = xstrdup(gtk_entry_get_text(GTK_ENTRY(users_details_password2)));
+ if(!*name) {
+ /* No username. Really we wanted to desensitize the Apply button when
+ * there's no userame but there doesn't seem to be a signal to detect
+ * changes to the entry text. Consequently we have error messages
+ * instead. */
+ popup_submsg(users_window, GTK_MESSAGE_ERROR, "Must enter a username");
+ return;
+ }
+ if(strcmp(password, password2)) {
+ popup_submsg(users_window, GTK_MESSAGE_ERROR, "Passwords do not match");
+ return;
+ }
+ if(*email && !strchr(email, '@')) {
+ /* The server will complain about this but we can give a better error
+ * message this way */
+ popup_submsg(users_window, GTK_MESSAGE_ERROR, "Invalid email address");
+ return;
+ }
+ cbd = xmalloc(sizeof *cbd);
+ cbd->onerror = users_adduser_failed;
+ cbd->u.edituser.user = name;
+ cbd->u.edituser.email = email;
+ disorder_eclient_adduser(client, users_adduser_completed,
+ name,
+ password,
+ rights_string(users_get_rights()),
+ cbd);
+ /* We switch to no-op mode while creating the user */
+ mode(NONE);
+ break;
+ case MODE_EDIT:
+ /* Ugh, can we de-dupe with above? */
+ email = xstrdup(gtk_entry_get_text(GTK_ENTRY(users_details_email)));
+ password = xstrdup(gtk_entry_get_text(GTK_ENTRY(users_details_password)));
+ password2 = xstrdup(gtk_entry_get_text(GTK_ENTRY(users_details_password2)));
+ if(strcmp(password, password2)) {
+ popup_submsg(users_window, GTK_MESSAGE_ERROR, "Passwords do not match");
+ return;
+ }
+ if(*email && !strchr(email, '@')) {
+ popup_submsg(users_window, GTK_MESSAGE_ERROR, "Invalid email address");
+ return;
+ }
+ cbd = xmalloc(sizeof *cbd);
+ cbd->onerror = users_op_failed;
+ disorder_eclient_edituser(client, NULL, users_selected,
+ "email", email, cbd);
+ disorder_eclient_edituser(client, NULL, users_selected,
+ "password", password, cbd);
+ disorder_eclient_edituser(client, NULL, users_selected,
+ "rights", rights_string(users_get_rights()), cbd);
+ /* We remain in edit mode */
+ break;
+ }