[Commits] Makefile.am 1.1 1.2 callbacks.c 1.5 1.6 contactwindow.c 1.3 1.4 mainwindow.c 1.3 1.4 plugin-loader.c 1.6 1.7 plugin-loader.h 1.4 1.5 plugin.h 1.5 1.6 utils.c 1.4 1.5 utils.h 1.4 1.5
miras at claws-mail.org
miras at claws-mail.org
Mon Nov 14 23:06:46 CET 2011
Update of /home/claws-mail/contacts/src
In directory claws-mail:/tmp/cvs-serv18563/src
Modified Files:
Makefile.am callbacks.c contactwindow.c mainwindow.c
plugin-loader.c plugin-loader.h plugin.h utils.c utils.h
Log Message:
Lots of bug fixes and read-only support for LDAP. No searching implemented though
Index: contactwindow.c
===================================================================
RCS file: /home/claws-mail/contacts/src/contactwindow.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- contactwindow.c 4 Oct 2011 20:21:40 -0000 1.3
+++ contactwindow.c 14 Nov 2011 22:06:43 -0000 1.4
@@ -895,6 +895,7 @@
g_signal_connect(GTK_TREE_MODEL(list), "row-deleted",
G_CALLBACK(row_deleted_cb), cw);
cw->email_list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list));
+ g_object_unref(list);
gtk_widget_set_tooltip_text(GTK_WIDGET(cw->email_list),
_("Double-click, enter, or space on cell will activate edit mode\n"
"Mouse-Left-click to drag and drop for reordering email list\n"
Index: utils.h
===================================================================
RCS file: /home/claws-mail/contacts/src/utils.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- utils.h 4 Oct 2011 20:21:40 -0000 1.4
+++ utils.h 14 Nov 2011 22:06:44 -0000 1.5
@@ -125,6 +125,13 @@
gint gslist_compare_gchar(gconstpointer a, gconstpointer b);
GPtrArray* g_value_email_new();
void dbus_contact_print(DBusContact* contact, FILE* f);
+gchar* aes256_encrypt(const gchar* plain, gboolean base64_enc);
+gchar* aes256_decrypt(const gchar* cipher_text, gboolean base64_enc);
+gchar* sha256(const gchar* plain);
+void extra_config_free(gpointer data);
+gpointer extra_config_copy(gpointer data);
+ExtraConfig* get_extra_config(GSList* list, const gchar* name);
+GSList* find_name(GtkContainer* container, const gchar* name);
G_END_DECLS
Index: plugin-loader.h
===================================================================
RCS file: /home/claws-mail/contacts/src/plugin-loader.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- plugin-loader.h 4 Oct 2011 20:21:40 -0000 1.4
+++ plugin-loader.h 14 Nov 2011 22:06:43 -0000 1.5
@@ -46,14 +46,16 @@
gchar* id;
//gchar* addrbook_name;
GModule *module;
- gboolean (*init) (gchar** error);
+ gboolean (*init) (gpointer self, gchar** error);
void (*reset) (gchar** error);
const gchar* (*name) (void);
const gchar* (*desc) (void);
const gchar* (*version) (void);
- const gchar* (*type) (void);
+ PluginType (*type) (void);
const gchar* (*license) (void);
- const gchar* (*filter) (void);
+ const gchar* (*file_filter) (void);
+ gboolean (*need_credentials) (void);
+ GSList* (*extra_config) (void);
gchar* (*default_url) (const gchar* name);
GSList* (*remaining_attribs) (void);
GSList* (*inactive_attribs) (void);
Index: plugin.h
===================================================================
RCS file: /home/claws-mail/contacts/src/plugin.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- plugin.h 4 Oct 2011 20:21:40 -0000 1.5
+++ plugin.h 14 Nov 2011 22:06:43 -0000 1.6
@@ -48,6 +48,50 @@
#define IS_READ_WRITE(X) ((X & PLUGIN_READ_WRITE) == PLUGIN_READ_WRITE)
#define HAS_ADV_SEARCH(X) ((X & PLUGIN_ADVANCED_SEARCH) == PLUGIN_ADVANCED_SEARCH)
+typedef enum {
+ PLUGIN_CONFIG_EXTRA_ENTRY,
+ PLUGIN_CONFIG_EXTRA_CHECKBOX,
+ PLUGIN_CONFIG_EXTRA_SPINBUTTON
+} ExtraConfigType;
+
+typedef struct {
+ ExtraConfigType type;
+ gchar* label;
+ gchar* tooltip;
+ union {
+ gchar* entry;
+ gboolean check_btn;
+ gint spin_btn;
+ } value;
+ union {
+ gchar* entry;
+ gboolean check_btn;
+ gint spin_btn;
+ } default_value;
+} ExtraConfig;
+
+typedef enum {
+ /*
+ * Address books configured with this plugin only requires
+ * the following input to function
+ * Name: Address book name (Name must be uniq within this plugin)
+ * (URI|URL): Reference to storage (URI => File in local file system,
+ * URL => TCP based reference). If 'plugin_file_filter' returns NULL
+ * then this plugin uses URL type storage reference.
+ *
+ * Optional
+ * - Username
+ * - Password
+ */
+ PLUGIN_TYPE_SIMPLE,
+ /*
+ * Address books configured with this plugin requires additional
+ * input to function in which case the function 'plugin_extra_config'
+ * MUST return a GSList of ExtraConfig
+ */
+ PLUGIN_TYPE_ADVANCED
+} PluginType;
+
typedef struct {
guint support; /* One or more of the plugin features or'ed */
const gchar* subtype;
@@ -92,6 +136,8 @@
GList* contacts; /* contacts is expected to be a list of Contact */
gboolean dirty;
gulong next_uid;
+ gboolean open;
+ GSList* extra_config; /* List of ExtraConfig */
} AddressBook;
typedef struct {
@@ -122,16 +168,20 @@
/* Functions which must be implemented by any plugin */
-gboolean plugin_init(gchar** error);
+gboolean plugin_init(gpointer self, gchar** error);
void plugin_reset(gchar** error);
gboolean plugin_done(void);
const PluginFeature* plugin_provides(void);
const gchar* plugin_name(void);
const gchar* plugin_desc(void);
const gchar* plugin_version(void);
-const gchar* plugin_type(void);
+PluginType plugin_type(void);
+const gchar* plugin_file_filter(void);
const gchar* plugin_license(void);
+gboolean plugin_need_credentials(void);
gchar* plugin_default_url(const gchar* name);
+GSList* plugin_extra_config(void);
+
/*
* Returning NULL means list of supported attributes are infinite
* Returning an empty list means that no more supported attributes
Index: plugin-loader.c
===================================================================
RCS file: /home/claws-mail/contacts/src/plugin-loader.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- plugin-loader.c 4 Oct 2011 20:21:40 -0000 1.6
+++ plugin-loader.c 14 Nov 2011 22:06:43 -0000 1.7
@@ -402,22 +402,7 @@
g_free(plugin);
}
-static gchar* format_hash(const guchar* md_string) {
- int len = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
- int i;
- gchar* hex = g_new0(gchar, 2 * len + 1);
-
- for (i = 0; i < len; i++)
- sprintf(hex + 2 * i, "%02x", md_string[i]);
-
- return hex;
-}
-
-#define key "claws-mail address book"
static void compute_hash(Plugin* plugin) {
- gcry_error_t err = 0;
- gcry_md_hd_t digest = NULL;
- guchar* md_string = NULL;
gchar* cipher;
gchar* plain = g_strconcat(
@@ -425,30 +410,12 @@
plugin->desc(), " ",
plugin->version(), NULL);
- err = gcry_md_open(
- &digest, GCRY_MD_SHA256,
- GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC);
- if (err) {
- g_printerr("%s\n", gcry_strerror(err));
- goto done;
- }
- err = gcry_md_setkey(digest, key, strlen(key));
- if (err) {
- g_printerr("%s\n", gcry_strerror(err));
- goto done;
- }
-
- gcry_md_write(digest, plain, strlen(plain));
-
- md_string = gcry_md_read(digest, 0);
- cipher = format_hash(md_string);
+ cipher = sha256(plain);
+ g_free(plain);
debug_print("Computed hash: %s\n", cipher);
+
plugin->id = g_strdup(cipher);
g_free(cipher);
-
- done:
- gcry_md_close(digest);
- g_free(plain);
}
static Plugin* plugin_allready_loaded(Plugin* plugin, gchar** error) {
@@ -479,7 +446,7 @@
if (found) {
g_free(found->error);
found->error = NULL;
- if (found->init(error)) {
+ if (found->init(found, error)) {
if (*error)
found->error = g_strdup(*error);
else
@@ -637,9 +604,9 @@
get_contact, set_contact, delete_contact, search_contact, update_contact,
plugin_abook_open, plugin_abook_close, plugin_abook_delete,
plugin_addrbook_all_get, plugin_abook_set_config, plugin_type,
- plugin_url, plugin_attribs_set, plugin_commit_all,
+ plugin_file_filter, plugin_url, plugin_attribs_set, plugin_commit_all,
plugin_remaining_attribs, plugin_inactive_attribs,
- plugin_closed_books_get;
+ plugin_closed_books_get, plugin_need_credentials, plugin_extra_config;
plugin = g_new0(Plugin, 1);
if (plugin == NULL) {
@@ -659,6 +626,7 @@
!g_module_symbol(plugin->module, "plugin_desc", &plugin_desc) ||
!g_module_symbol(plugin->module, "plugin_default_url", &plugin_url) ||
!g_module_symbol(plugin->module, "plugin_type", &plugin_type) ||
+ !g_module_symbol(plugin->module, "plugin_file_filter", &plugin_file_filter) ||
!g_module_symbol(plugin->module, "plugin_version", &plugin_version) ||
!g_module_symbol(plugin->module, "plugin_provides", &plugin_provides) ||
!g_module_symbol(plugin->module, "plugin_license", &plugin_license) ||
@@ -672,6 +640,8 @@
!g_module_symbol(plugin->module, "plugin_abook_set_config", &plugin_abook_set_config) ||
!g_module_symbol(plugin->module, "plugin_commit_all", &plugin_commit_all) ||
!g_module_symbol(plugin->module, "plugin_init", &plugin_init) ||
+ !g_module_symbol(plugin->module, "plugin_need_credentials", &plugin_need_credentials) ||
+ !g_module_symbol(plugin->module, "plugin_extra_config", &plugin_extra_config) ||
!g_module_symbol(plugin->module, "plugin_closed_books_get", &plugin_closed_books_get) ||
!g_module_symbol(plugin->module, "plugin_remaining_attribs", &plugin_remaining_attribs) ||
!g_module_symbol(plugin->module, "plugin_inactive_attribs", &plugin_inactive_attribs)) {
@@ -728,7 +698,7 @@
}
plugin->init = plugin_init;
- plugin->filter = plugin_type;
+ plugin->file_filter = plugin_file_filter;
plugin->reset = plugin_reset;
plugin->name = plugin_name;
plugin->desc = plugin_desc;
@@ -736,6 +706,8 @@
plugin->type = plugin_type;
plugin->license = plugin_license;
plugin->filename = g_strdup(filename);
+ plugin->need_credentials = plugin_need_credentials;
+ plugin->extra_config = plugin_extra_config;
plugin->error = NULL;
plugin->abook_open = plugin_abook_open;
plugin->abook_close = plugin_abook_close;
@@ -773,7 +745,7 @@
}
}
else {
- if (plugin->init(error)) {
+ if (plugin->init(plugin, error)) {
if (*error)
plugin->error = g_strdup(*error);
else
Index: mainwindow.c
===================================================================
RCS file: /home/claws-mail/contacts/src/mainwindow.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- mainwindow.c 4 Oct 2011 20:21:40 -0000 1.3
+++ mainwindow.c 14 Nov 2011 22:06:43 -0000 1.4
@@ -360,6 +360,7 @@
mainwindow->abook_list =
gtk_tree_view_new_with_model(GTK_TREE_MODEL(list));
+ g_object_unref(list);
gtk_widget_set_name(mainwindow->abook_list, "abook_list");
gtk_widget_set_tooltip_text(mainwindow->abook_list,
_("Address book in BOLD is the default address book"));
@@ -412,6 +413,7 @@
mainwindow->contact_list =
gtk_tree_view_new_with_model(GTK_TREE_MODEL(list));
+ g_object_unref(list);
gtk_widget_set_tooltip_text(GTK_WIDGET(mainwindow->contact_list),
_("Double-click, enter, or space on cell will activate edit mode"));
gtk_tree_view_set_rules_hint(
Index: utils.c
===================================================================
RCS file: /home/claws-mail/contacts/src/utils.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- utils.c 4 Oct 2011 20:21:40 -0000 1.4
+++ utils.c 14 Nov 2011 22:06:44 -0000 1.5
@@ -44,6 +44,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
+#include <gcrypt.h>
#include "utils.h"
#include "gtk-utils.h"
@@ -66,6 +67,11 @@
} CompareSListData;
*/
+typedef struct {
+ size_t size;
+ guchar* block;
+} NormBlock;
+
#define ERRBUFSIZ 255
/* Forward declarations */
@@ -352,6 +358,9 @@
void attrib_def_free(gpointer attrdef) {
AttribDef* a = (AttribDef *) attrdef;
+ if (! a)
+ return;
+
if (a->attrib_name) {
g_free(a->attrib_name);
a->attrib_name = NULL;
@@ -415,24 +424,28 @@
cl_books = config->closed_books;
if (cf_books && cf_books->group) {
- if (cf_books->books)
+ if (cf_books->books) {
list = gslist_to_array(cf_books->books, &num);
+ g_key_file_set_string_list(config->key_file, cf_books->group,
+ "books", (const gchar* const *) list, num);
+ g_strfreev(list);
+ }
else {
- list = g_new0(gchar *, 1);
+ g_key_file_set_string(config->key_file, cf_books->group,
+ "books", "");
}
- g_key_file_set_string_list(config->key_file, cf_books->group,
- "books", (const gchar* const *) list, num);
- g_strfreev(list);
}
if (cl_books && cl_books->group) {
- if (cl_books->books)
+ if (cl_books->books) {
list = gslist_to_array(cl_books->books, &num);
+ g_key_file_set_string_list(config->key_file, cl_books->group,
+ "books", (const gchar* const *) list, num);
+ g_strfreev(list);
+ }
else {
- list = g_new0(gchar *, 1);
+ g_key_file_set_string(config->key_file, cl_books->group,
+ "books", "");
}
- g_key_file_set_string_list(config->key_file, cl_books->group,
- "books", (const gchar* const *) list, num);
- g_strfreev(list);
}
}
@@ -497,7 +510,7 @@
}
static void config_close(ConfigFile* config, gchar** error) {
- gchar* data;
+ gchar *data, *dir;
GError* err = NULL;
FILE* fp;
gsize len;
@@ -510,13 +523,30 @@
g_clear_error(&err);
}
else {
- gchar* old = g_strconcat(config->path, ".bak", NULL);
- g_rename(config->path, old);
- g_free(old);
+ dir = g_path_get_dirname(config->path);
+ if (strcmp(".", dir) != 0) {
+ if (!g_file_test(dir, G_FILE_TEST_EXISTS)) {
+ if (g_mkdir(dir, 0700)) {
+ *error = g_strconcat(dir, ": Could not create", NULL);
+ goto end;
+ }
+ }
+ }
+ g_free(dir);
+ if (g_file_test(config->path, G_FILE_TEST_EXISTS)) {
+ gchar* old = g_strconcat(config->path, ".bak", NULL);
+ g_rename(config->path, old);
+ g_free(old);
+ }
fp = g_fopen(config->path, "w");
- fwrite(data, len, 1, fp);
- fclose(fp);
+ if (fp) {
+ fwrite(data, len, 1, fp);
+ fclose(fp);
+ }
+ else
+ *error = g_strconcat(config->path, ": Could not create", NULL);
}
+end:
g_free(data);
g_key_file_free(config->key_file);
config->key_file = NULL;
@@ -536,9 +566,9 @@
if (g_file_test(config->path, G_FILE_TEST_EXISTS)) {
g_key_file_load_from_file(
config->key_file, config->path, G_KEY_FILE_KEEP_COMMENTS, &err);
- if (err) {
+ if (err && err->code > 1) {
config_close(config, error);
- g_free(error);
+ g_free(*error);
if (error)
*error = g_strdup(err->message);
g_clear_error(&err);
@@ -564,7 +594,7 @@
}
g_strfreev(str);
- return TRUE;
+ return (len > 0);
}
gboolean config_set_value(ConfigFile* config, const gchar* group,
@@ -585,13 +615,14 @@
}
void plugin_config_free(ConfigFile** config_file) {
- ConfigFile* config = *config_file;
+ ConfigFile* config;
ConfiguredBooks* cf_books;
ClosedBooks* cl_books;
- if (config == NULL)
+ if (! config_file || ! *config_file)
return;
+ config = *config_file;
cf_books = config->configured_books;
cl_books = config->closed_books;
@@ -629,7 +660,9 @@
}
gchar* str = g_string_free(buf, FALSE);
gchar* tmp = str;
- tmp[strlen(tmp) - 1] = 0;
+ if (strlen(str) > 0 && str[strlen(str) - 1] == '|') {
+ tmp[strlen(tmp) - 1] = 0;
+ }
array = g_strsplit_set(tmp, "|", 0);
g_free(str);
@@ -776,6 +809,9 @@
void address_book_contacts_free(AddressBook* address_book) {
GList* cur;
+ if (! address_book)
+ return;
+
for (cur = address_book->contacts; cur; cur = g_list_next(cur)) {
Contact* c = (Contact *) cur->data;
contact_free(c);
@@ -787,16 +823,18 @@
}
void address_book_free(AddressBook** address_book) {
- AddressBook* a = *address_book;
+ AddressBook* a;
- if (! a)
+ if (! address_book || ! *address_book)
return;
-
+
+ a = *address_book;
g_free(a->abook_name);
g_free(a->URL);
g_free(a->username);
g_free(a->password);
address_book_contacts_free(a);
+ gslist_free(&a->extra_config, extra_config_free);
*address_book = NULL;
}
@@ -854,6 +892,7 @@
b->password = g_strdup(a->password);
b->next_uid = a->next_uid;
b->dirty = a->dirty;
+
if (deep) {
for (cur = a->contacts; cur; cur = g_list_next(cur)) {
b->contacts = g_list_prepend(
@@ -862,6 +901,9 @@
}
else
b->contacts = g_list_copy(a->contacts);
+
+ b->extra_config = g_slist_reverse(gslist_deep_copy(
+ a->extra_config, extra_config_copy));
debug_print("from: %d contacts to: %d contacts\n",
g_list_length(a->contacts), g_list_length(b->contacts));
@@ -969,6 +1011,9 @@
GValue* email_member;
guint i;
+ if (! email)
+ return;
+
for (i = 0; i < email->n_values; i++) {
email_member = g_value_array_get_nth(email, i);
g_value_unset(email_member);
@@ -1269,4 +1314,251 @@
index = g_slist_index(list, data);
return index;
+}
+
+#define KEY "This is abook I1"
+static gboolean aes_init(gcry_cipher_hd_t* digest) {
+ gcry_error_t err = 0;
+ const gchar iv[] = "AbC1234567890xYz";
+
+ err = gcry_cipher_open(digest, GCRY_CIPHER_AES256,
+ GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_SECURE | GCRY_CIPHER_CBC_MAC);
+ if (err) {
+ g_printerr("%s\n", gcry_strerror(err));
+ gcry_cipher_close(*digest);
+ return FALSE;
+ }
+
+ err = gcry_cipher_setkey(*digest, KEY, strlen(KEY));
+ if (err) {
+ g_printerr("%s\n", gcry_strerror(err));
+ gcry_cipher_close(*digest);
+ return FALSE;
+ }
+
+ err = gcry_cipher_setiv(*digest, iv, gcry_cipher_get_algo_blklen(GCRY_CIPHER_AES256));
+ if (err) {
+ g_printerr("%s\n", gcry_strerror(err));
+ gcry_cipher_close(*digest);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static NormBlock* normalize(const gchar* text) {
+ size_t blk_size = gcry_cipher_get_algo_blklen(GCRY_CIPHER_AES256);
+ gint passes = strlen(text) / blk_size;
+ gint rest = strlen(text) % blk_size;
+ NormBlock* norm_block = g_new0(NormBlock, 1);
+ norm_block->size = (passes * blk_size) + (rest) ? blk_size : 0;
+ gint i;
+
+ norm_block->block = g_new0(guchar, norm_block->size);
+ for (i = 0; i < strlen(text); i++) {
+ norm_block->block[i] = text[i];
+ }
+
+ return norm_block;
+}
+
+gchar* aes256_encrypt(const gchar* plain, gboolean base64_enc) {
+ gcry_error_t err = 0;
+ gcry_cipher_hd_t digest = NULL;
+ guchar *cipher;
+ NormBlock* text;
+ gchar* base64 = NULL;
+
+ if (! plain)
+ return NULL;
+
+ if (aes_init(&digest)) {
+ text = normalize(plain);
+ cipher = g_new0(guchar, text->size);
+ err = gcry_cipher_encrypt(digest, cipher, text->size, text->block, text->size);
+ if (err) {
+ g_printerr("%s\n", gcry_strerror(err));
+ }
+ else {
+ if (base64_enc)
+ base64 = g_base64_encode(cipher, text->size);
+ else
+ base64 = g_memdup(cipher, text->size);
+ }
+
+ g_free(cipher);
+ g_free(text->block);
+ g_free(text);
+ gcry_cipher_close(digest);
+ }
+
+ return base64;
+}
+
+gchar* aes256_decrypt(const gchar* cipher_text, gboolean base64_enc) {
+ gcry_error_t err = 0;
+ gcry_cipher_hd_t digest = NULL;
+ size_t size;
+ guchar* cipher;
+ guchar* plain = NULL;
+
+ if (! cipher_text)
+ return NULL;
+
+ if (base64_enc)
+ cipher = g_base64_decode(cipher_text, &size);
+ else
+ cipher = (guchar *) g_strdup(cipher_text);
+
+ if (aes_init(&digest)) {
+ plain = g_new0(guchar, size + 1);
+ err = gcry_cipher_decrypt(digest, plain, size + 1, cipher, size);
+ if (err) {
+ g_printerr("%s\n", gcry_strerror(err));
+ g_free(plain);
+ plain = NULL;
+ }
+
+ g_free(cipher);
+ gcry_cipher_close(digest);
+ }
+
+ return (gchar *) plain;
+}
+
+static gchar* format_hash(const guchar* md_string) {
+ int len = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
+ int i;
+ gchar* hex = g_new0(gchar, 2 * len + 1);
+
+ for (i = 0; i < len; i++)
+ sprintf(hex + 2 * i, "%02x", md_string[i]);
+
+ return hex;
+}
+
+#define key "claws-mail address book"
+gchar* sha256(const gchar* plain) {
+ gcry_error_t err = 0;
+ gcry_md_hd_t digest = NULL;
+ guchar* md_string = NULL;
+ gchar* cipher;
+
+ if (! plain)
+ return NULL;
+
+ err = gcry_md_open(
+ &digest, GCRY_MD_SHA256,
+ GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC);
+ if (err) {
+ g_printerr("%s\n", gcry_strerror(err));
+ gcry_md_close(digest);
+ }
+
+ err = gcry_md_setkey(digest, key, strlen(key));
+ if (err) {
+ g_printerr("%s\n", gcry_strerror(err));
+ gcry_md_close(digest);
+ }
+
+ gcry_md_write(digest, plain, strlen(plain));
+
+ md_string = gcry_md_read(digest, 0);
+ cipher = format_hash(md_string);
+ gcry_md_close(digest);
+
+ return cipher;
+}
+
+void extra_config_free(gpointer data) {
+ ExtraConfig* ec;
+
+ if (! data)
+ return;
+
+ ec = (ExtraConfig *) data;
+ g_free(ec->label);
+ g_free(ec->tooltip);
+ if (ec->type == PLUGIN_CONFIG_EXTRA_ENTRY) {
+ g_free(ec->value.entry);
+ g_free(ec->default_value.entry);
+ }
+ g_free(ec);
+ ec = NULL;
+}
+
+gpointer extra_config_copy(gpointer data) {
+ ExtraConfig *a, *b;
+
+ if (! data)
+ return NULL;
+
+ a = (ExtraConfig *) data;
+ b = g_new0(ExtraConfig, 1);
+
+ b->label = g_strdup(a->label);
+ b->tooltip = g_strdup(a->tooltip);
+ b->type = a->type;
+ if (a->type == PLUGIN_CONFIG_EXTRA_ENTRY) {
+ b->value.entry = g_strdup(a->value.entry);
+ b->default_value.entry = g_strdup(a->default_value.entry);
+ }
+ else {
+ b->value = a->value;
+ b->default_value = a->default_value;
+ }
+
+ return b;
+}
+
+typedef struct {
+ GSList* list;
+ const gchar* name;
+} GtkIteratorData;
+
+static void gtk_iterator(GtkWidget* widget, gpointer data) {
+ GtkIteratorData* iter_data = (GtkIteratorData *) data;
+ const gchar* name;
+
+ if (GTK_IS_CONTAINER(widget))
+ gtk_container_foreach(GTK_CONTAINER(widget), gtk_iterator, iter_data);
+ name = gtk_widget_get_name(widget);
+ if (name && strcmp(name, iter_data->name) == 0)
+ iter_data->list = g_slist_prepend(iter_data->list, widget);
+}
+
+GSList* find_name(GtkContainer* container, const gchar* name) {
+ GSList* list = NULL;
+ GtkIteratorData* data;
+
+ if (! container || ! name)
+ return list;
+
+ data = g_new0(GtkIteratorData, 1);
+ data->name = name;
+
+ gtk_container_foreach(container, gtk_iterator, data);
+ list = data->list;
+ g_free(data);
+
+ return list;
+}
+
+ExtraConfig* get_extra_config(GSList* list, const gchar* name) {
+ GSList* cur;
+ ExtraConfig* conf = NULL;
+ gboolean found = FALSE;
+
+ if (! list || ! name)
+ return conf;
+
+ for (cur = list; cur && !found; cur = g_slist_next(cur)) {
+ conf = (ExtraConfig *) cur->data;
+ if (conf->label && strcmp(conf->label, name) == 0)
+ found = TRUE;
+ else
+ conf = NULL;
+ }
+
+ return extra_config_copy(conf);
}
\ No newline at end of file
Index: Makefile.am
===================================================================
RCS file: /home/claws-mail/contacts/src/Makefile.am,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Makefile.am 7 Sep 2011 17:35:29 -0000 1.1
+++ Makefile.am 14 Nov 2011 22:06:43 -0000 1.2
@@ -16,7 +16,8 @@
AM_CPPFLAGS = \
-DG_LOG_DOMAIN=\"Claws-Contacts\" \
- -DPLUGINDIR=\"@PLUGINDIR@\"
+ -DPLUGINDIR=\"@PLUGINDIR@\" \
+ $(LIBGCRYPT_CFLAGS)
claws_contacts_SOURCES = \
claws-contacts.c \
@@ -48,7 +49,7 @@
claws_contacts_LDADD= \
@GLIB_LIBS@ \
@GTK_LIBS@ \
- @GCRYPT_LIBS@ \
+ $(LIBGCRYPT_LIBS) \
@LIBXML_LIBS@ \
${top_builddir}/xmllib/libcontactxml.la \
${top_builddir}/src/dbus/libdbus.la
Index: callbacks.c
===================================================================
RCS file: /home/claws-mail/contacts/src/callbacks.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- callbacks.c 4 Oct 2011 20:21:40 -0000 1.5
+++ callbacks.c 14 Nov 2011 22:06:43 -0000 1.6
@@ -185,7 +185,7 @@
GtkFileFilter* filter;
gchar* home;
- file_filter = cur.plugin->filter();
+ file_filter = cur.plugin->file_filter();
if (file_filter) {
gchar* f = g_strconcat("*.", file_filter, NULL);
filter = gtk_file_filter_new();
@@ -204,8 +204,10 @@
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
home = cur.plugin->default_url(NULL);
- gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), home);
- g_free(home);
+ if (home) {
+ gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), home);
+ g_free(home);
+ }
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
@@ -669,7 +671,7 @@
}
else {
show_message(win->window, GTK_UTIL_MESSAGE_INFO,
- _("Please highlight desired address book for deletion"));
+ _("Please highlight desired address book to edit"));
}
}
@@ -851,7 +853,8 @@
plugin = plugin_get_plugin(plugin_name);
if (plugin) {
if (address_book_edit(win->window, plugin, &book)) {
- if (g_file_test(book->URL, G_FILE_TEST_EXISTS)) {
+ if (plugin->file_filter() && strcmp("xml", plugin->file_filter()) == 0 &&
+ g_file_test(book->URL, G_FILE_TEST_EXISTS)) {
AddressBook* abook =
address_book_get(plugin, book->abook_name);
if (abook) {
@@ -874,7 +877,8 @@
}
}
}
- if (! addr_book_set_config(book, &error)) {
+ if (! plugin->abook_set_config(book, NULL, &error)) {
+ /*if (! addr_book_set_config(book, &error)) {*/
if (plugin->abook_open(book, &error))
update_abook_list(win);
}
@@ -990,19 +994,188 @@
}
}
+static void add_advanced_page(GtkNotebook* notebook,
+ Plugin* plugin,
+ AddressBook* address_book) {
+ GSList *cur, *extra;
+ GtkWidget *widget, *hbox, *vbox, *label;
+ gboolean new;
+
+ if (address_book->extra_config) {
+ extra = address_book->extra_config;
+ new = FALSE;
+ }
+ else {
+ extra = plugin->extra_config();
+ new = TRUE;
+ }
+
+ if (extra) {
+ vbox = gtk_vbox_new(FALSE, 0);
+ for (cur = extra; cur; cur = g_slist_next(cur)) {
+ ExtraConfig* ec = (ExtraConfig *) cur->data;
+ hbox = gtk_hbox_new(FALSE, 5);
+ switch (ec->type) {
+ case PLUGIN_CONFIG_EXTRA_CHECKBOX:
+ widget = gtk_check_button_new();
+ if (ec->label)
+ gtk_button_set_label(GTK_BUTTON(widget), ec->label);
+ if (ec->tooltip)
+ gtk_widget_set_tooltip_text(widget, ec->tooltip);
+ if (new)
+ gtk_toggle_button_set_active(
+ GTK_TOGGLE_BUTTON(widget), ec->default_value.check_btn);
+ else
+ gtk_toggle_button_set_active(
+ GTK_TOGGLE_BUTTON(widget), ec->value.check_btn);
+ label = gtk_label_new("");
+ break;
+ case PLUGIN_CONFIG_EXTRA_ENTRY:
+ widget = gtk_entry_new();
+ if (ec->label)
+ label = gtk_label_new(ec->label);
+ else
+ label = gtk_label_new("");
+ if (ec->tooltip)
+ gtk_widget_set_tooltip_text(widget, ec->tooltip);
+ if (ec->value.entry)
+ gtk_entry_set_text(GTK_ENTRY(widget), ec->value.entry);
+ else if (ec->default_value.entry)
+ gtk_entry_set_text(GTK_ENTRY(widget), ec->default_value.entry);
+ break;
+ case PLUGIN_CONFIG_EXTRA_SPINBUTTON:
+ widget = gtk_spin_button_new_with_range(0.0, 100.0, 1.0);
+ if (ec->label)
+ label = gtk_label_new(ec->label);
+ else
+ label = gtk_label_new("");
+ if (ec->tooltip)
+ gtk_widget_set_tooltip_text(widget, ec->tooltip);
+ if (new)
+ gtk_spin_button_set_value(
+ GTK_SPIN_BUTTON(widget), ec->default_value.spin_btn);
+ else
+ gtk_spin_button_set_value(
+ GTK_SPIN_BUTTON(widget), ec->value.spin_btn);
+ break;
+ }
+ gtk_widget_set_name(widget, ec->label);
+ gtk_widget_set_size_request(label, 100, -1);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
+ if (ec->type == PLUGIN_CONFIG_EXTRA_SPINBUTTON)
+ gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 2);
+ else
+ gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 2);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+ }
+ label = gtk_label_new(_("Advanced settings"));
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
+ if (! address_book->extra_config)
+ gslist_free(&extra, extra_config_free);
+ }
+}
+
+static void set_advanced_config(Plugin* plugin,
+ AddressBook* address_book,
+ GtkNotebook* notebook) {
+ GtkWidget *page, *widget;
+ GSList *config, *cur, *widgets = NULL, *ptr;
+ gboolean found;
+
+ config = plugin->extra_config();
+ page = gtk_notebook_get_nth_page(notebook, 1);
+
+ if (config && page) {
+ for (cur = config; cur; cur = g_slist_next(cur)) {
+ ExtraConfig* ec = (ExtraConfig *) cur->data;
+ gslist_free(&widgets, NULL);
+ widgets = find_name(GTK_CONTAINER(notebook), ec->label);
+ if (! widgets)
+ continue;
+
+ switch (ec->type) {
+ case PLUGIN_CONFIG_EXTRA_CHECKBOX:
+ found = FALSE;
+ for (ptr = widgets; ptr && !found; ptr = g_slist_next(ptr)) {
+ widget = (GtkWidget *) widgets->data;
+ if (debug_get_mode()) {
+ gchar* text = gtk_widget_get_tooltip_text(widget);
+ debug_print("%s\n", (text) ? text: "(NULL)");
+ g_free(text);
+ }
+ if (GTK_IS_CHECK_BUTTON(widget))
+ found = TRUE;
+ else
+ widget = NULL;
+ }
+ if (widget) {
+ ec->value.check_btn =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+ }
+ break;
+ case PLUGIN_CONFIG_EXTRA_ENTRY:
+ found = FALSE;
+ for (ptr = widgets; ptr && !found; ptr = g_slist_next(ptr)) {
+ widget = (GtkWidget *) widgets->data;
+ if (debug_get_mode()) {
+ gchar* text = gtk_widget_get_tooltip_text(widget);
+ debug_print("%s\n", (text) ? text: "(NULL)");
+ g_free(text);
+ }
+ if (GTK_IS_ENTRY(widget))
+ found = TRUE;
+ else
+ widget = NULL;
+ }
+ if (widget) {
+ g_free(ec->value.entry);
+ ec->value.entry =
+ gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1);
+ }
+ break;
+ case PLUGIN_CONFIG_EXTRA_SPINBUTTON:
+ found = FALSE;
+ for (ptr = widgets; ptr && !found; ptr = g_slist_next(ptr)) {
+ widget = (GtkWidget *) widgets->data;
+ if (debug_get_mode()) {
+ gchar* text = gtk_widget_get_tooltip_text(widget);
+ debug_print("%s\n", (text) ? text: "(NULL)");
+ g_free(text);
+ }
+ if (GTK_IS_SPIN_BUTTON(widget))
+ found = TRUE;
+ else
+ widget = NULL;
+ }
+ if (widget) {
+ ec->value.spin_btn =
+ gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+ }
+ break;
+ }
+ }
+ address_book->extra_config = config;
+ }
+ else
+ gslist_free(&config, extra_config_free);
+}
+
#define GTK_ENTRIES 4
-gboolean address_book_edit(
- GtkWidget* parent, Plugin* plugin, AddressBook** address_book) {
+gboolean address_book_edit(GtkWidget* parent,
+ Plugin* plugin,
+ AddressBook** address_book) {
GtkWidget* dialog;
GtkWidget* file_btn;
AddressBook* book;
GtkWidget* input[GTK_ENTRIES] = {NULL, NULL, NULL, NULL};
- GtkWidget *hbox, *vbox, *label = NULL, *frame;
+ GtkWidget *hbox, *vbox, *label = NULL, *frame, *notebook;
int i;
gboolean response = FALSE;
gboolean use_button = FALSE;
struct DataContainer data;
gboolean show_url = TRUE;
+ gchar* title = NULL;
for (i = 0; i < GTK_ENTRIES; i++) {
input[i] = gtk_entry_new();
@@ -1019,19 +1192,23 @@
if (book->password)
gtk_entry_set_text(GTK_ENTRY(input[3]), book->password);
gtk_entry_set_visibility(GTK_ENTRY(input[3]), FALSE);
+ title = g_strdup(_("Edit address book"));
}
else {
book = *address_book = address_book_new();
- show_url = FALSE;
+ title = g_strdup(_("New address book"));
+ /*if (! plugin->file_filter())
+ show_url = FALSE;*/
}
dialog = gtk_dialog_new_with_buttons(
- _("Edit address book"),
+ title,
GTK_WINDOW(parent),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_STOCK_OK, GTK_RESPONSE_OK,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
NULL);
+ g_free(title);
gtk_widget_set_size_request(dialog, 360, -1);
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
@@ -1048,16 +1225,19 @@
if (show_url) {
label = gtk_label_new(_("URL"));
gtk_widget_set_tooltip_text(
- input[i], _("URL or path to this address book"));
- file_btn = gtk_button_new_from_stock(GTK_STOCK_OPEN);
- gtk_widget_set_tooltip_text(
- file_btn, _("Open file dialog"));
- data.plugin = plugin;
- data.addressbook = address_book;
- data.widget = input[i];
- g_signal_connect(file_btn, "clicked",
- G_CALLBACK(select_addr_book_cb), &data);
- use_button = TRUE;
+ input[i], _("URL or path to this address book\n"
+ "Must conform to plugin requirements."));
+ if (plugin->file_filter()) {
+ file_btn = gtk_button_new_from_stock(GTK_STOCK_OPEN);
+ gtk_widget_set_tooltip_text(
+ file_btn, _("Open file dialog"));
+ data.plugin = plugin;
+ data.addressbook = address_book;
+ data.widget = input[i];
+ g_signal_connect(file_btn, "clicked",
+ G_CALLBACK(select_addr_book_cb), &data);
+ use_button = TRUE;
+ }
}
else {
gtk_widget_destroy(input[i]);
@@ -1068,15 +1248,20 @@
label = gtk_label_new(_("Username"));
gtk_widget_set_tooltip_text(
input[i], _("And optional username"));
+ if (!plugin->need_credentials())
+ gtk_widget_set_sensitive(input[i], FALSE);
break;
case 3:
label = gtk_label_new(_("Password"));
gtk_widget_set_tooltip_text(
input[i], _("And optional password"));
+ gtk_entry_set_visibility(GTK_ENTRY(input[i]), FALSE);
+ if (!plugin->need_credentials())
+ gtk_widget_set_sensitive(input[i], FALSE);
break;
}
if (input[i]) {
- gtk_widget_set_size_request(label, 60, -1);
+ gtk_widget_set_size_request(label, 100, -1);
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
gtk_box_pack_start(GTK_BOX(hbox), input[i], TRUE, TRUE, 2);
@@ -1087,10 +1272,20 @@
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
}
}
- frame = gtk_frame_new(_("Address book settings"));
- gtk_container_add(GTK_CONTAINER(frame), vbox);
- gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), frame);
- gtk_widget_show_all(frame);
+ if (plugin->extra_config()) {
+ notebook = gtk_notebook_new();
+ label = gtk_label_new(_("Basic settings"));
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
+ add_advanced_page(GTK_NOTEBOOK(notebook), plugin, book);
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), notebook);
+ gtk_widget_show_all(notebook);
+ }
+ else {
+ frame = gtk_frame_new(_("Address book settings"));
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), frame);
+ gtk_widget_show_all(frame);
+ }
dialog_set_focus(GTK_DIALOG(dialog), GTK_STOCK_CANCEL);
gint result = gtk_dialog_run(GTK_DIALOG(dialog));
@@ -1119,6 +1314,10 @@
book->password =
gtk_editable_get_chars(GTK_EDITABLE(input[3]), 0, -1);
response = TRUE;
+ if (plugin->extra_config()) {
+ //gslist_free(&book->extra_config, extra_config_free);
+ set_advanced_config(plugin, book, GTK_NOTEBOOK(notebook));
+ }
break;
case GTK_RESPONSE_CANCEL:
break;
More information about the Commits
mailing list