From 1eb4de6377fc00a38af7ba2d1fb18c97aa19b156 Mon Sep 17 00:00:00 2001 From: Christopher Michael Date: Thu, 8 Jun 2006 20:20:07 +0000 Subject: [PATCH] Ok, mail module can now do multiple accounts per instance. Remove old module.mail.cfg before running or bad things will happen. SVN revision: 23310 --- e_mod_config.c | 352 ++++++++++++++++ e_mod_main.c | 1041 ++++++++++++++++++++++++++++++++++++++++++++++++ e_mod_main.h | 71 ++++ mail.edc | 233 +++++++++++ 4 files changed, 1697 insertions(+) create mode 100644 e_mod_config.c create mode 100644 e_mod_main.c create mode 100644 e_mod_main.h create mode 100644 mail.edc diff --git a/e_mod_config.c b/e_mod_config.c new file mode 100644 index 0000000..47582f5 --- /dev/null +++ b/e_mod_config.c @@ -0,0 +1,352 @@ +#include +#include "e_mod_main.h" + +struct _E_Config_Dialog_Data +{ + int show_label; + double check_time; + Evas_List *boxes; + + /* Evas Object References */ + Evas_Object *il; + Evas_Object *del; + Evas_Object *configure; +}; + +static void *_create_data(E_Config_Dialog *cfd); +static void _free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata); +static Evas_Object *_basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata); +static int _basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata); + +//static void _use_exec_cb_change(void *data, Evas_Object *obj); +static void _load_boxes(E_Config_Dialog *cfd); +static int _ilist_header_exists(Evas_Object *il, const char *name); +static void _ilist_cb_selected(void *data); +static void _cb_add_box(void *data, void *data2); +static void _cb_edit_box(void *data, void *data2); +static void _cb_del_box(void *data, void *data2); + +void +_config_mail_module(Config_Item *ci) +{ + E_Config_Dialog *cfd; + E_Config_Dialog_View *v; + E_Container *con; + + v = E_NEW(E_Config_Dialog_View, 1); + if (!v) return; + + v->create_cfdata = _create_data; + v->free_cfdata = _free_data; + v->basic.apply_cfdata = _basic_apply_data; + v->basic.create_widgets = _basic_create_widgets; + + con = e_container_current_get(e_manager_current_get()); + cfd = e_config_dialog_new(con, _("Mail Configuration"), NULL, 0, v, ci); + mail_config->config_dialog = cfd; +} + +static void +_fill_data(Config_Item *ci, E_Config_Dialog_Data *cfdata) +{ + cfdata->show_label = ci->show_label; + //cfdata->use_exec = ci->use_exec; + + //cfdata->exec = NULL; + //if (ci->exec) + // cfdata->exec = strdup(ci->exec); + + cfdata->check_time = ci->check_time; + + cfdata->boxes = ci->boxes; +} + +static void * +_create_data(E_Config_Dialog *cfd) +{ + E_Config_Dialog_Data *cfdata; + Config_Item *ci; + + ci = cfd->data; + cfdata = E_NEW(E_Config_Dialog_Data, 1); + _fill_data(ci, cfdata); + return cfdata; +} + +static void +_free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) +{ + if (!mail_config) return; + mail_config->config_dialog = NULL; + free(cfdata); +} + +static Evas_Object * +_basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata) +{ + Evas_Object *o, *of, *ob, *ot; + E_Radio_Group *rg; + + o = e_widget_list_add(evas, 0, 0); + of = e_widget_framelist_add(evas, _("General Settings"), 0); + ob = e_widget_check_add(evas, _("Always Show Labels"), &(cfdata->show_label)); + e_widget_framelist_object_append(of, ob); + ob = e_widget_label_add(evas, _("Check Interval")); + e_widget_framelist_object_append(of, ob); + ob = e_widget_slider_add(evas, 1, 0, _("%2.0f minutes"), 1.0, 60.0, 1.0, 0, &(cfdata->check_time), NULL, 100); + e_widget_framelist_object_append(of, ob); + e_widget_list_object_append(o, of, 1, 1, 0.5); + + of = e_widget_frametable_add(evas, _("Mail Boxes"), 0); + ob = e_widget_ilist_add(evas, 32, 32, NULL); + e_widget_ilist_selector_set(ob, 1); + cfdata->il = ob; + _load_boxes(cfd); + e_widget_min_size_set(ob, 160, 140); + e_widget_frametable_object_append(of, ob, 0, 0, 1, 4, 1, 1, 1, 1); + + ot = e_widget_table_add(evas, 0); + ob = e_widget_button_add(evas, _("Add"), "widget/add", _cb_add_box, cfd, NULL); + e_widget_table_object_append(ot, ob, 0, 0, 1, 1, 1, 1, 1, 0); + ob = e_widget_button_add(evas, _("Delete"), "widget/del", _cb_del_box, cfd, NULL); + e_widget_disabled_set(ob, 1); + cfdata->del = ob; + e_widget_table_object_append(ot, ob, 0, 1, 1, 1, 1, 1, 1, 0); + ob = e_widget_button_add(evas, _("Configure..."), "widget/config", _cb_edit_box, cfd, NULL); + e_widget_disabled_set(ob, 1); + cfdata->configure = ob; + e_widget_table_object_append(ot, ob, 0, 2, 1, 1, 1, 1, 1, 0); + e_widget_frametable_object_append(of, ot, 1, 0, 1, 1, 1, 0, 1, 0); + + e_widget_list_object_append(o, of, 1, 1, 0.5); + + return o; +} + +static int +_basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) +{ + Config_Item *ci; + + ci = cfd->data; + ci->show_label = cfdata->show_label; + ci->check_time = cfdata->check_time; + e_config_save_queue(); + _mail_config_updated(ci->id); + return 1; +} + +static void +_load_boxes(E_Config_Dialog *cfd) +{ + E_Config_Dialog_Data *cfdata; + Evas_Object *il; + Config_Item *ci; + int i; + char buf[4096]; + + cfdata = cfd->cfdata; + il = cfdata->il; + if (!il) return; + + ci = cfd->data; + if (!ci) return; + if (!ci->boxes) return; + if (evas_list_count(ci->boxes) <= 0) return; + + snprintf(buf, sizeof(buf), "%s/module.eap", e_module_dir_get(mail_config->module)); + + e_widget_ilist_clear(il); + + for (i = 0; i <= 3; i++) + { + Evas_List *box; + int found = -1; + char *name; + + switch (i) + { + case MAIL_TYPE_POP: + name = "Pop3"; + break; + case MAIL_TYPE_IMAP: + name = "Imap"; + break; + case MAIL_TYPE_MDIR: + name = "Maildir"; + break; + case MAIL_TYPE_MBOX: + name = "Mailbox"; + break; + } + found = _ilist_header_exists(il, name); + if (found < 0) + e_widget_ilist_header_append(il, NULL, name); + + for (box = ci->boxes; box; box = box->next) + { + Config_Box *cb; + Evas_Object *ic; + + cb = box->data; + if (cb->type != i) continue; + if (!cb->name) continue; + ic = edje_object_add(cfd->dia->win->evas); + edje_object_file_set(ic, buf, "icon"); + e_widget_ilist_append(il, ic, cb->name, _ilist_cb_selected, cfd, NULL); + } + } + e_widget_ilist_go(il); +} + +static int +_ilist_header_exists(Evas_Object *il, const char *name) +{ + int c, i, found = 0; + + if (!il) return -1; + + c = e_widget_ilist_count(il); + if (c <= 0) return -1; + + for (i = 0; i < c; i++) + { + const char *n; + + n = e_widget_ilist_nth_label_get(il, i); + if (!n) continue; + if (!strcmp(n, name)) + { + found = 1; + break; + } + } + if (found) return i; + return -1; +} + +static void +_ilist_cb_selected(void *data) +{ + E_Config_Dialog *cfd; + E_Config_Dialog_Data *cfdata; + + cfd = data; + cfdata = cfd->cfdata; + + e_widget_disabled_set(cfdata->del, 0); + e_widget_disabled_set(cfdata->configure, 0); +} + +static void +_cb_add_box(void *data, void *data2) +{ + E_Config_Dialog *cfd; + E_Config_Dialog_Data *cfdata; + Config_Item *ci; + + cfd = data; + if (!cfd) return; + + ci = cfd->data; + cfdata = cfd->cfdata; + _config_box(ci, NULL, cfd); +} + +static void +_cb_edit_box(void *data, void *data2) +{ + E_Config_Dialog *cfd; + E_Config_Dialog_Data *cfdata; + Evas_Object *il; + Evas_List *l; + Config_Item *ci; + const char *s; + + cfd = data; + if (!cfd) return; + + ci = cfd->data; + cfdata = cfd->cfdata; + il = cfdata->il; + s = e_widget_ilist_selected_label_get(il); + +<<<<<<< e_mod_config.c + for (l = ci->boxes; l; l = l->next) +======= + cfdata = data; + if (cfdata->type == 0) +>>>>>>> 1.5 + { + Config_Box *cb; + + cb = l->data; + if (!cb->name) continue; + if (!strcmp(s, cb->name)) + { + _config_box(ci, cb, cfd); + break; + } + } +<<<<<<< e_mod_config.c +} + +static void +_cb_del_box(void *data, void *data2) +{ + E_Config_Dialog *cfd; + E_Config_Dialog_Data *cfdata; + Evas_Object *il; + Evas_List *l; + Config_Item *ci; + const char *s; + + cfd = data; + if (!cfd) return; + + ci = cfd->data; + cfdata = cfd->cfdata; + il = cfdata->il; + s = e_widget_ilist_selected_label_get(il); + + for (l = ci->boxes; l; l = l->next) +======= + else if (cfdata->type == 1) + { + e_widget_disabled_set(cfdata->new_path_label, 0); + e_widget_disabled_set(cfdata->new_path_entry, 0); + e_widget_disabled_set(cfdata->cur_path_label, 1); + e_widget_disabled_set(cfdata->cur_path_entry, 1); + e_widget_entry_text_set(cfdata->cur_path_entry, ""); + } + else if (cfdata->type == 3) + { + e_widget_disabled_set(cfdata->new_path_label, 0); + e_widget_disabled_set(cfdata->new_path_entry, 0); + e_widget_disabled_set(cfdata->cur_path_label, 1); + e_widget_disabled_set(cfdata->cur_path_entry, 1); + e_widget_entry_text_set(cfdata->cur_path_entry, ""); + } + else if (cfdata->type == 2) +>>>>>>> 1.5 + { + Config_Box *cb; + + cb = l->data; + if (!cb->name) continue; + if (!strcmp(s, cb->name)) + { + ci->boxes = evas_list_remove(ci->boxes, cb); + e_config_save_queue(); + break; + } + } + _load_boxes(cfd); +} + +void +_mail_box_config_updated(E_Config_Dialog *cfd) +{ + _load_boxes(cfd); + return; +} diff --git a/e_mod_main.c b/e_mod_main.c new file mode 100644 index 0000000..123b017 --- /dev/null +++ b/e_mod_main.c @@ -0,0 +1,1041 @@ +/* + * Copyright (C) 2006 Christopher Michael + * + * Portions of this code Copyright (C) 2004 Embrace project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include "e_mod_main.h" + +typedef enum +{ + STATE_DISCONNECTED, + STATE_CONNECTED, + STATE_SERVER_READY, + STATE_LOGGED_IN, + STATE_USER_OK, + STATE_PASS_OK, + STATE_STATUS_OK +} State; + +typedef struct _Instance Instance; +typedef struct _Mail Mail; +typedef struct _Mailbox Mailbox; + +struct _Instance +{ + E_Gadcon_Client *gcc; + Evas_Object *mail_obj; + Mail *mail; + Ecore_Timer *check_timer; + Evas_List *mboxes; +}; + +struct _Mail +{ + Instance *inst; + Evas_Object *mail_obj; +}; + +struct _Mailbox +{ + Instance *inst; + Config_Box *config; + int state; + int cmd; + int has_mail; + int num_new; + int num_total; + + Ecore_Exe *exe; + Ecore_Con_Server *server; + Ecore_Event_Handler *add_handler; + Ecore_Event_Handler *del_handler; + Ecore_Event_Handler *data_handler; + Ecore_File_Monitor *monitor; + Ecore_Event_Handler *exit_handler; +}; + +/* Func Protos for Gadcon */ +static E_Gadcon_Client *_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style); +static void _gc_shutdown(E_Gadcon_Client *gcc); +static void _gc_orient(E_Gadcon_Client *gcc); +static char *_gc_label(void); +static Evas_Object *_gc_icon(Evas *evas); + +/* Func Protos for Module */ +static void _mail_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info); +static void _mail_cb_mouse_in(void *data, Evas *e, Evas_Object *obj, void *event_info); +static void _mail_cb_mouse_out(void *data, Evas *e, Evas_Object *obj, void *event_info); +static void _mail_menu_cb_configure(void *data, E_Menu *m, E_Menu_Item *mi); +static void _mail_menu_cb_post(void *data, E_Menu *m); +static void _mail_menu_cb_exec(void *data, E_Menu *m, E_Menu_Item *mi); +static Config_Item *_mail_config_item_get(const char *id); +static Mail *_mail_new(Evas *evas); +static void _mail_free(Mail *mail); +static int _mail_cb_check(void *data); +static int _mail_server_add(void *data, int type, void *event); +static int _mail_server_del(void *data, int type, void *event); +static int _mail_server_data(void *data, int type, void *event); +static int _mail_parse_pop(void *data, void *data2); +static int _mail_parse_imap(void *data, void *data2); +static void _mail_mbox_check(void *data, Ecore_File_Monitor *monitor, Ecore_File_Event event, const char *path); +static void _mail_mdir_check(void *data, Ecore_File_Monitor *monitor, Ecore_File_Event event, const char *path); +static int _mail_mdir_get_files(const char *path); +static void _mail_set_text(void *data); +static int _mail_cb_exe_exit(void *data, int type, void *event); + +static E_Config_DD *conf_edd = NULL; +static E_Config_DD *conf_item_edd = NULL; +static E_Config_DD *conf_box_edd = NULL; + +Config *mail_config = NULL; + +static const E_Gadcon_Client_Class _gc_class = +{ + GADCON_CLIENT_CLASS_VERSION, + "mail", {_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon} +}; + +static E_Gadcon_Client * +_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style) +{ + Evas_Object *o; + E_Gadcon_Client *gcc; + Instance *inst; + Mail *mail; + Config_Item *ci; + Evas_List *l; + char buf[4096]; + + inst = E_NEW(Instance, 1); + ci = _mail_config_item_get(id); + if (!ci->id) ci->id = evas_stringshare_add(id); + + mail = _mail_new(gc->evas); + mail->inst = inst; + inst->mail = mail; + + o = mail->mail_obj; + gcc = e_gadcon_client_new(gc, name, id, style, o); + gcc->data = inst; + inst->gcc = gcc; + inst->mail_obj = o; + + evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _mail_cb_mouse_down, inst); + evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_IN, _mail_cb_mouse_in, inst); + evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_OUT, _mail_cb_mouse_out, inst); + + if (ci->show_label) + edje_object_signal_emit(inst->mail_obj, "label_active", ""); + else + edje_object_signal_emit(inst->mail_obj, "label_passive", ""); + + mail_config->instances = evas_list_append(mail_config->instances, inst); + + if (!ci->boxes) return gcc; + + for (l = ci->boxes; l; l = l->next) + { + Mailbox *mb; + Config_Box *cb; + + cb = l->data; + mb = E_NEW(Mailbox, 1); + mb->inst = inst; + mb->config = cb; + mb->server = NULL; + mb->state = STATE_DISCONNECTED; + mb->cmd = 0; + inst->mboxes = evas_list_append(inst->mboxes, mb); + + if (cb->type == MAIL_TYPE_MDIR) + mb->monitor = ecore_file_monitor_add(cb->new_path, _mail_mdir_check, mb); + else if (cb->type == MAIL_TYPE_MBOX) + mb->monitor = ecore_file_monitor_add(cb->new_path, _mail_mbox_check, mb); + else + { + _mail_cb_check(inst); + if (!inst->check_timer) + inst->check_timer = ecore_timer_add((ci->check_time * 60.0), _mail_cb_check, inst); + } + } + return gcc; +} + +static void +_gc_shutdown(E_Gadcon_Client *gcc) +{ + Instance *inst; + + inst = gcc->data; + if (inst->check_timer) ecore_timer_del(inst->check_timer); + while (inst->mboxes) + { + Mailbox *mb; + + mb = inst->mboxes->data; + if (mb->monitor) ecore_file_monitor_del(mb->monitor); + if (mb->add_handler) ecore_event_handler_del(mb->add_handler); + if (mb->data_handler) ecore_event_handler_del(mb->data_handler); + if (mb->del_handler) ecore_event_handler_del(mb->del_handler); + if (mb->server) ecore_con_server_del(mb->server); + mb->server = NULL; + inst->mboxes = evas_list_remove_list(inst->mboxes, inst->mboxes); + free(mb); + } + + evas_object_event_callback_del(inst->mail->mail_obj, EVAS_CALLBACK_MOUSE_DOWN, _mail_cb_mouse_down); + evas_object_event_callback_del(inst->mail->mail_obj, EVAS_CALLBACK_MOUSE_IN, _mail_cb_mouse_in); + evas_object_event_callback_del(inst->mail->mail_obj, EVAS_CALLBACK_MOUSE_OUT, _mail_cb_mouse_out); + + mail_config->instances = evas_list_remove(mail_config->instances, inst); + _mail_free(inst->mail); + free(inst); +} + +static void +_gc_orient(E_Gadcon_Client *gcc) +{ + e_gadcon_client_aspect_set(gcc, 16, 16); + e_gadcon_client_min_size_set(gcc, 16, 16); +} + +static char * +_gc_label(void) +{ + return D_("Mail"); +} + +static Evas_Object * +_gc_icon(Evas *evas) +{ + Evas_Object *o; + char buf[4096]; + + o = edje_object_add(evas); + snprintf(buf, sizeof(buf), "%s/module.eap", e_module_dir_get(mail_config->module)); + edje_object_file_set(o, buf, "icon"); + return o; +} + +static void +_mail_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Instance *inst; + Evas_Event_Mouse_Down *ev; + Config_Item *ci; + Evas_List *l; + + inst = data; + if (!inst) return; + + ci = _mail_config_item_get(inst->gcc->id); + + ev = event_info; + if ((ev->button == 3) && (!mail_config->menu)) + { + E_Menu *mn, *sn; + E_Menu_Item *mi; + int x, y, w, h; + char buf[1024]; + + mn = e_menu_new(); + e_menu_post_deactivate_callback_set(mn, _mail_menu_cb_post, inst); + mail_config->menu = mn; + + if ((inst->mboxes) && (evas_list_count(inst->mboxes) > 0)) + { + E_Menu_Item *mm; + + snprintf(buf, sizeof(buf), "%s/module.eap", e_module_dir_get(mail_config->module)); + mm = e_menu_item_new(mn); + e_menu_item_label_set(mm, _("Mailboxes")); + e_menu_item_icon_edje_set(mm, buf, "icon"); + + sn = e_menu_new(); + for (l = inst->mboxes; l; l = l->next) + { + Mailbox *mb; + + mb = l->data; + if (!mb) continue; + + mi = e_menu_item_new(sn); + snprintf(buf, sizeof(buf), "%s: %d/%d", mb->config->name, mb->num_new, mb->num_total); + e_menu_item_label_set(mi, buf); + if (mb->config->exec) + e_menu_item_callback_set(mi, _mail_menu_cb_exec, mb); + } + e_menu_item_submenu_set(mm, sn); + mi = e_menu_item_new(mn); + e_menu_item_separator_set(mi, 1); + } + + mi = e_menu_item_new(mn); + e_menu_item_label_set(mi, _("Configuration")); + e_util_menu_item_edje_icon_set(mi, "enlightenment/configuration"); + e_menu_item_callback_set(mi, _mail_menu_cb_configure, inst); + + mi = e_menu_item_new(mn); + e_menu_item_separator_set(mi, 1); + + e_gadcon_client_util_menu_items_append(inst->gcc, mn, 0); + e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &x, &y, &w, &h); + e_menu_activate_mouse(mn, + e_util_zone_current_get(e_manager_current_get()), + x + ev->output.x, y + ev->output.y, 1, 1, E_MENU_POP_DIRECTION_DOWN, + ev->timestamp); + evas_event_feed_mouse_up(inst->gcc->gadcon->evas, ev->button, EVAS_BUTTON_NONE, ev->timestamp, NULL); + } + else if ((ev->button == 1) && (inst)) + _mail_cb_check(inst); +} + +static void +_mail_cb_mouse_in(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Instance *inst; + + inst = data; + edje_object_signal_emit(inst->mail_obj, "label_active", ""); +} + +static void +_mail_cb_mouse_out(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Instance *inst; + Config_Item *ci; + + inst = data; + ci = _mail_config_item_get(inst->gcc->id); + if (!ci->show_label) + edje_object_signal_emit(inst->mail_obj, "label_passive", ""); +} + +static void +_mail_menu_cb_post(void *data, E_Menu *m) +{ + if (!mail_config->menu) return; + e_object_del(E_OBJECT(mail_config->menu)); + mail_config->menu = NULL; +} + +static void +_mail_menu_cb_configure(void *data, E_Menu *m, E_Menu_Item *mi) +{ + Instance *inst; + Config_Item *ci; + + inst = data; + ci = _mail_config_item_get(inst->gcc->id); + _config_mail_module(ci); +} + +static Config_Item * +_mail_config_item_get(const char *id) +{ + Evas_List *l; + Config_Item *ci; + + for (l = mail_config->items; l; l = l->next) + { + ci = l->data; + if (!ci->id) continue; + if (!strcmp(ci->id, id)) return ci; + } + + ci = E_NEW(Config_Item, 1); + ci->id = evas_stringshare_add(id); + ci->show_label = 1; + ci->check_time = 15.0; + ci->boxes = NULL; + + mail_config->items = evas_list_append(mail_config->items, ci); + return ci; +} + +EAPI E_Module_Api e_modapi = +{ + E_MODULE_API_VERSION, + "Mail" +}; + +EAPI void * +e_modapi_init(E_Module *m) +{ + conf_box_edd = E_CONFIG_DD_NEW("Mail_Box_Config", Config_Box); + #undef T + #undef D + #define T Config_Box + #define D conf_box_edd + E_CONFIG_VAL(D, T, name, STR); + E_CONFIG_VAL(D, T, type, INT); + E_CONFIG_VAL(D, T, port, INT); + E_CONFIG_VAL(D, T, ssl, UCHAR); + E_CONFIG_VAL(D, T, host, STR); + E_CONFIG_VAL(D, T, user, STR); + E_CONFIG_VAL(D, T, pass, STR); + E_CONFIG_VAL(D, T, new_path, STR); + E_CONFIG_VAL(D, T, cur_path, STR); + E_CONFIG_VAL(D, T, use_exec, UCHAR); + E_CONFIG_VAL(D, T, exec, STR); + + conf_item_edd = E_CONFIG_DD_NEW("Mail_Config_Item", Config_Item); + #undef T + #undef D + #define T Config_Item + #define D conf_item_edd + E_CONFIG_VAL(D, T, id, STR); + E_CONFIG_VAL(D, T, show_label, UCHAR); + E_CONFIG_VAL(D, T, check_time, DOUBLE); + E_CONFIG_LIST(D, T, boxes, conf_box_edd); + + conf_edd = E_CONFIG_DD_NEW("Mail_Config", Config); + #undef T + #undef D + #define T Config + #define D conf_edd + E_CONFIG_LIST(D, T, items, conf_item_edd); + + mail_config = e_config_domain_load("module.mail", conf_edd); + if (!mail_config) + { + Config_Item *ci; + + mail_config = E_NEW(Config, 1); + ci = E_NEW(Config_Item, 1); + + ci->id = evas_stringshare_add("0"); + ci->show_label = 1; + ci->check_time = 15.0; + ci->boxes = NULL; + + mail_config->items = evas_list_append(mail_config->items, ci); + } + mail_config->module = m; + e_gadcon_provider_register(&_gc_class); + return 1; +} + +EAPI int +e_modapi_shutdown(E_Module *m) +{ + mail_config->module = NULL; + e_gadcon_provider_unregister(&_gc_class); + + if (mail_config->config_dialog) + e_object_del(E_OBJECT(mail_config->config_dialog)); + if (mail_config->menu) + { + e_menu_post_deactivate_callback_set(mail_config->menu, NULL, NULL); + e_object_del(E_OBJECT(mail_config->menu)); + mail_config->menu = NULL; + } + while (mail_config->items) + { + Config_Item *ci; + + ci = mail_config->items->data; + while (ci->boxes) + { + Config_Box *cb; + + cb = ci->boxes->data; + if (cb->name) evas_stringshare_del(cb->name); + if (cb->host) evas_stringshare_del(cb->host); + if (cb->user) evas_stringshare_del(cb->user); + if (cb->pass) evas_stringshare_del(cb->pass); + if (cb->new_path) evas_stringshare_del(cb->new_path); + if (cb->cur_path) evas_stringshare_del(cb->cur_path); + if (cb->exec) evas_stringshare_del(cb->exec); + ci->boxes = evas_list_remove_list(ci->boxes, ci->boxes); + free(cb); + } + if (ci->id) evas_stringshare_del(ci->id); + mail_config->items = evas_list_remove_list(mail_config->items, mail_config->items); + free(ci); + } + free(mail_config); + mail_config = NULL; + E_CONFIG_DD_FREE(conf_box_edd); + E_CONFIG_DD_FREE(conf_item_edd); + E_CONFIG_DD_FREE(conf_edd); + return 1; +} + +EAPI int +e_modapi_save(E_Module *m) +{ + Evas_List *l; + + for (l = mail_config->instances; l; l = l->next) + { + Instance *inst; + Config_Item *ci; + + inst = l->data; + ci = _mail_config_item_get(inst->gcc->id); + if (ci->id) evas_stringshare_del(ci->id); + ci->id = evas_stringshare_add(inst->gcc->id); + } + e_config_domain_save("module.mail", conf_edd, mail_config); + return 1; +} + +EAPI int +e_modapi_about(E_Module *m) +{ + e_module_dialog_show(D_("Enlightenment Mail Module"), + D_("This is a module to notify when you have new mail.")); + return 1; +} + +static Mail * +_mail_new(Evas *evas) +{ + Mail *mail; + char buf[4096]; + + mail = E_NEW(Mail, 1); + mail->mail_obj = edje_object_add(evas); + + snprintf(buf, sizeof(buf), "%s/mail.edj", e_module_dir_get(mail_config->module)); + if (!e_theme_edje_object_set(mail->mail_obj, "base/theme/modules/mail", "modules/mail/main")) + edje_object_file_set(mail->mail_obj, buf, "modules/mail/main"); + evas_object_show(mail->mail_obj); + + return mail; +} + +static void +_mail_free(Mail *mail) +{ + evas_object_del(mail->mail_obj); + free(mail); +} + +static int +_mail_cb_check(void *data) +{ + Instance *inst; + Evas_List *l; + Ecore_Con_Type type; + + inst = data; + if (!inst->mboxes) return; + + for (l = inst->mboxes; l; l = l->next) + { + Mailbox *mb; + Config_Box *cb; + + mb = l->data; + mb->server = NULL; + mb->inst = inst; + + cb = mb->config; + if (!cb->host) continue; + if (cb->port <= 0) continue; + if (cb->type > 1) continue; + + if (!mb->add_handler) + mb->add_handler = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, _mail_server_add, mb); + if (!mb->del_handler) + mb->del_handler = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, _mail_server_del, mb); + if (!mb->data_handler) + mb->data_handler = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, _mail_server_data, mb); + + type = ECORE_CON_REMOTE_SYSTEM; + if (cb->ssl) + type |= ECORE_CON_USE_SSL; + mb->server = ecore_con_server_connect(type, cb->host, cb->port, mb); + mb->state = STATE_CONNECTED; + } + return 1; +} + +static int +_mail_server_add(void *data, int type, void *event) +{ + Mailbox *mb; + Ecore_Con_Event_Server_Add *ev; + + mb = data; + if (!mb) return 1; + + ev = event; + if ((!mb->server) || (mb->server != ev->server)) return 1; + mb->state = STATE_CONNECTED; + mb->cmd = 0; + return 1; +} + +static int +_mail_server_del(void *data, int type, void *event) +{ + Mailbox *mb; + Config_Box *cb; + Ecore_Con_Event_Server_Del *ev; + + mb = data; + if (!mb) return 1; + + ev = event; + if ((!mb->server) || (mb->server != ev->server)) return 1; + + cb = mb->config; + if (!cb->host) return 1; + + if (mb->state == STATE_DISCONNECTED) + printf("Cannot Connect to %s\n", cb->host); + else + mb->state = STATE_DISCONNECTED; + + ecore_con_server_del(mb->server); + mb->server = NULL; + mb->cmd = 0; + + return 1; +} + +static int +_mail_server_data(void *data, int type, void *event) +{ + Mailbox *mb; + Config_Box *cb; + Ecore_Con_Event_Server_Data *ev; + + mb = data; + if (!mb) return 1; + + ev = event; + if ((!mb->server) || (mb->server != ev->server)) return 1; + + cb = mb->config; + if (cb->type == MAIL_TYPE_POP) + return _mail_parse_pop(mb, ev); + else if (cb->type == MAIL_TYPE_IMAP) + return _mail_parse_imap(mb, ev); + + return 1; +} + +static int +_mail_parse_pop(void *data, void *data2) +{ + Mailbox *mb; + Config_Box *cb; + Ecore_Con_Event_Server_Data *ev; + char in[2048], out[2048]; + int len; + + mb = data; + if (!mb) return; + + cb = mb->config; + + ev = data2; + if (!ev) return; + if ((!mb->server) || (mb->server != ev->server)) return; + +<<<<<<< e_mod_main.c +======= + if ((!inst->server) || (inst->server != ev->server)) return; + + ci = _mail_config_item_get(inst->gcc->id); + +>>>>>>> 1.10 + len = sizeof(in) -1; + len = (((len) > (ev->size)) ? ev->size : len); + memcpy(in, ev->data, len); + in[len] = 0; + + if (!strncmp(in, "-ERR", 4)) + { + printf("ERROR: %s\n", in); + mb->state = STATE_DISCONNECTED; + ecore_con_server_del(mb->server); + mb->server = NULL; + return 0; + } + else if (strncmp(in, "+OK", 3)) + { + printf("Unexpected reply: %s\n", in); + mb->state = STATE_DISCONNECTED; + ecore_con_server_del(mb->server); + mb->server = NULL; + return 0; + } + + if (mb->state == STATE_CONNECTED) + mb->state++; + + switch (mb->state) + { + case STATE_SERVER_READY: + len = snprintf(out, sizeof(out), "USER %s\r\n", cb->user); + ecore_con_server_send(mb->server, out, len); + mb->state = STATE_USER_OK; + break; + case STATE_USER_OK: + len = snprintf(out, sizeof(out), "PASS %s\r\n", cb->pass); + ecore_con_server_send(mb->server, out, len); + mb->state = STATE_PASS_OK; + break; + case STATE_PASS_OK: + len = snprintf(out, sizeof(out), "STAT\r\n"); + ecore_con_server_send(mb->server, out, len); + mb->state = STATE_STATUS_OK; + break; + case STATE_STATUS_OK: + mb->has_mail = 0; + mb->num_new = 0; + mb->num_total = 0; + if (sscanf(in, "+OK %i %i", &mb->num_new, &mb->num_total) == 2) + { + if (mb->num_new > 0) + mb->has_mail = 1; + } + /* Reset total to be new mail as total above gets set to msg size */ + mb->num_total = mb->num_new; + + _mail_set_text(mb->inst); + + mb->state = STATE_DISCONNECTED; + ecore_con_server_del(mb->server); + mb->server = NULL; + if ((cb->use_exec) && (cb->exec != NULL)) + { + if (mb->num_new <= 0) break; + if (!mb->exe) + { + mb->exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _mail_cb_exe_exit, mb); + mb->exe = ecore_exe_run(cb->exec, mb); + } + } + break; + default: + break; + } + return 0; +} + +static int +_mail_parse_imap(void *data, void *data2) +{ + Mailbox *mb; + Config_Box *cb; + Ecore_Con_Event_Server_Data *ev; + char in[2048], out[2048]; + char *spc; + size_t slen; + int len; + + mb = data; + if (!mb) return; + + cb = mb->config; + + ev = data2; + if (!ev) return; + if ((!mb->server) || (mb->server != ev->server)) return; + +<<<<<<< e_mod_main.c +======= + if ((!inst->server) || (inst->server != ev->server)) return; + + ci = _mail_config_item_get(inst->gcc->id); + +>>>>>>> 1.10 + len = sizeof(in) -1; + len = (((len) > (ev->size)) ? ev->size : len); + memcpy(in, ev->data, len); + in[len] = 0; + + if (spc = strchr(in, ' ')) + { + slen = strlen(spc); + if ((slen > 5) && (!strncmp(spc + 1, "NO ", 3))) + { + len = snprintf(out, sizeof(out), "A%03i LOGOUT", ++mb->cmd); + ecore_con_server_send(mb->server, out, len); + printf("Imap Failure: %s\n", spc + 4); + mb->state = STATE_DISCONNECTED; + mb->cmd = 0; + return 0; + } + else if ((slen > 6) && (!strncmp(spc + 1, "BAD ", 4))) + { + len = snprintf(out, sizeof(out), "A%03i LOGOUT", ++mb->cmd); + ecore_con_server_send(mb->server, out, len); + printf("Imap Bad Command: %s\n", spc + 5); + mb->state = STATE_DISCONNECTED; + mb->cmd = 0; + return 0; + } + } + + if (mb->state == STATE_CONNECTED) + mb->state++; + + switch (mb->state) + { + case STATE_SERVER_READY: + len = snprintf(out, sizeof(out), "A%03i LOGIN %s %s\r\n", ++mb->cmd, cb->user, cb->pass); + ecore_con_server_send(mb->server, out, len); + mb->state = STATE_LOGGED_IN; + break; + case STATE_LOGGED_IN: + len = snprintf(out, sizeof(out), "A%03i STATUS %s (MESSAGES UNSEEN)\r\n",++mb->cmd, cb->new_path); + ecore_con_server_send(mb->server, out, len); + mb->state = STATE_STATUS_OK; + break; + case STATE_STATUS_OK: + mb->has_mail = 0; + mb->num_new = 0; + mb->num_total = 0; + + if (sscanf(in, "* STATUS %*s (MESSAGES %i UNSEEN %i)", &mb->num_total, &mb->num_new) == 2) + { + if (mb->num_new > 0) + mb->has_mail = 1; + } + + _mail_set_text(mb->inst); + + mb->state = STATE_DISCONNECTED; + mb->cmd = 0; + len = snprintf(out, sizeof(out), "A%03i LOGOUT", ++mb->cmd); + ecore_con_server_send(mb->server, out, len); + if ((cb->use_exec) && (cb->exec != NULL)) + { + if (mb->num_new <= 0) break; + if (!mb->exe) + { + mb->exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _mail_cb_exe_exit, mb); + mb->exe = ecore_exe_run(cb->exec, mb); + } + } + break; + case STATE_DISCONNECTED: + mb->server = NULL; + break; + default: + break; + } + return 0; +} + +static void +_mail_mbox_check(void *data, Ecore_File_Monitor *monitor, Ecore_File_Event event, const char *path) +{ + Mailbox *mb; + Config_Box *cb; + FILE *f; + char buf[1024]; + int total = 0, unread = 0; + int header; + + mb = data; + if (!mb) return; + cb = mb->config; + + if (!(f = fopen(cb->new_path, "r"))) + return; + + mb->has_mail = 0; + mb->num_new = 0; + mb->num_total = 0; + + while (fgets(buf, sizeof(buf), f)) + { + if (buf[0] == '\n') + header = 0; + else if (!strncmp(buf, "From ", 5)) + { + header = 1; + mb->num_total++; + mb->num_new++; + } + else if ((header) && (!strncmp(buf, "Status: ", 7)) && (strchr(buf, 'R'))) + mb->num_new--; + } + fclose(f); + + if (mb->num_new > 0) + mb->has_mail = 1; + + _mail_set_text(mb->inst); +} + +static void +_mail_mdir_check(void *data, Ecore_File_Monitor *monitor, Ecore_File_Event event, const char *path) +{ + Mailbox *mb; + + mb = data; + if (!mb) return; + + mb->has_mail = 0; + mb->num_total = 0; + mb->num_new = 0; + + mb->num_total = _mail_mdir_get_files(mb->config->cur_path); + mb->num_new = _mail_mdir_get_files(mb->config->new_path); + + if (mb->num_new > 0) + mb->has_mail = 1; + + _mail_set_text(mb->inst); +} + +static int +_mail_mdir_get_files(const char *path) +{ + Ecore_List *l; + char *item; + int i = 0; + + l = ecore_file_ls(path); + ecore_list_goto_first(l); + while ((item = (char *)ecore_list_next(l)) != NULL) + { + if ((!strcmp(item, ".")) || (!strcmp(item, ".."))) continue; + i++; + } + + ecore_list_destroy(l); + return 0; +} + +static void +_mail_set_text(void *data) +{ + Instance *inst; + Evas_List *l; + char buf[4096]; + + inst = data; + if (!inst) return; + + edje_object_part_text_set(inst->mail->mail_obj, "name", ""); + +<<<<<<< e_mod_main.c + snprintf(buf, sizeof(buf), "New: 0"); +======= + snprintf(buf, sizeof(buf), "%d/%d", n, t); +>>>>>>> 1.10 + edje_object_part_text_set(inst->mail->mail_obj, "new_label", buf); +<<<<<<< e_mod_main.c + + snprintf(buf, sizeof(buf), "Total: 0"); + edje_object_part_text_set(inst->mail->mail_obj, "total_label", buf); + + edje_object_signal_emit(inst->mail->mail_obj, "no_mail", ""); + + for (l = inst->mboxes; l; l = l->next) + { + Mailbox *mb; + Config_Box *cb; + + mb = l->data; + cb = mb->config; + if (mb->has_mail) + { + edje_object_part_text_set(inst->mail->mail_obj, "name", cb->user); + + snprintf(buf, sizeof(buf), "New: %d", mb->num_new); + edje_object_part_text_set(inst->mail->mail_obj, "new_label", buf); + + snprintf(buf, sizeof(buf), "Total: %d", mb->num_total); + edje_object_part_text_set(inst->mail->mail_obj, "total_label", buf); + + edje_object_signal_emit(inst->mail->mail_obj, "new_mail", ""); + + break; + } + } +======= + + if (n > 0) + edje_object_signal_emit(inst->mail->mail_obj, "new_mail", ""); + else + edje_object_signal_emit(inst->mail->mail_obj, "no_mail", ""); +>>>>>>> 1.10 +} + +static int +_mail_cb_exe_exit(void *data, int type, void *event) +{ + Mailbox *mb; + + mb = data; + if (!mb) return; + mb->exe = NULL; + ecore_event_handler_del(mb->exit_handler); +} + +void +_mail_config_updated(const char *id) +{ + Evas_List *l; + Config_Item *ci; + + if (!mail_config) return; + + ci = _mail_config_item_get(id); + for (l = mail_config->instances; l; l = l->next) + { + Instance *inst; + + inst = l->data; + if (!inst->gcc->id) continue; + if (!strcmp(inst->gcc->id, ci->id)) + { + if (inst->check_timer) + { + ecore_timer_del(inst->check_timer); + inst->check_timer = ecore_timer_add((ci->check_time * 60.0), _mail_cb_check, inst); + } + + if (ci->show_label) + edje_object_signal_emit(inst->mail_obj, "label_active", ""); + else + edje_object_signal_emit(inst->mail_obj, "label_passive", ""); + break; + } + } +} + +static void +_mail_menu_cb_exec(void *data, E_Menu *m, E_Menu_Item *mi) +{ + Mailbox *mb; + Config_Box *cb; + + mb = data; + if (!mb) return; + if (mb->exe) return; + cb = mb->config; + + mb->exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _mail_cb_exe_exit, mb); + mb->exe = ecore_exe_run(cb->exec, mb); +} diff --git a/e_mod_main.h b/e_mod_main.h new file mode 100644 index 0000000..d18147d --- /dev/null +++ b/e_mod_main.h @@ -0,0 +1,71 @@ +#define D_(str) dgettext(PACKAGE, str) + +#ifndef E_MOD_MAIN_H +#define E_MOD_MAIN_H + +//IMAP: 143 +//POP: 110 + +typedef enum +{ + MAIL_TYPE_POP, + MAIL_TYPE_IMAP, + MAIL_TYPE_MDIR, + MAIL_TYPE_MBOX +} MailType; + +typedef struct _Config Config; +typedef struct _Config_Item Config_Item; +typedef struct _Config_Box Config_Box; + +struct _Config +{ + E_Module *module; + E_Config_Dialog *config_dialog; + E_Menu *menu; + Evas_List *instances; + Evas_List *items; + Ecore_Event_Handler *exe_exit_handler; +}; + +struct _Config_Item +{ + const char *id; + + unsigned char show_label; + double check_time; + + Evas_List *boxes; +}; + +struct _Config_Box +{ + const char *name; + + int type; + int port; + unsigned char ssl; + const char *host; + const char *user; + const char *pass; + const char *new_path; + const char *cur_path; + + unsigned char use_exec; + const char *exec; +}; + +EAPI extern E_Module_Api e_modapi; + +EAPI void *e_modapi_init(E_Module *m); +EAPI int e_modapi_shutdown(E_Module *m); +EAPI int e_modapi_save(E_Module *m); +EAPI int e_modapi_about(E_Module *m); + +void _config_mail_module(Config_Item *ci); +void _mail_config_updated(const char *id); +void _mail_box_config_updated(E_Config_Dialog *cfd); + +extern Config *mail_config; + +#endif diff --git a/mail.edc b/mail.edc new file mode 100644 index 0000000..00a696b --- /dev/null +++ b/mail.edc @@ -0,0 +1,233 @@ +fonts +{ + font: "VeraBd.ttf" "VeraBold"; +} +images +{ + image: "module_icon.png" COMP; + image: "newmail.png" COMP; +} + +collections +{ + group + { + name: "modules/mail/main"; + max: 128 128; + parts + { + part + { + name: "clip"; + type: RECT; + mouse_events: 1; + description + { + state: "default" 0.0; + color: 255 255 255 255; + rel1 + { + relative: 0.0 0.0; + offset: 0 0; + } + rel2 + { + relative: 1.0 1.0; + offset: -1 -1; + } + } + } + part + { + name: "logo"; + type: IMAGE; + clip_to: "clip"; + mouse_events: 1; + description + { + state: "default" 0.0; + aspect: 1.0 1.0; + rel1 + { + relative: 0.0 0.0; + offset: 0 0; + } + rel2 + { + relative: 1.0 1.0; + offset: -1 -1; + } + image + { + normal: "module_icon.png"; + } + color: 255 255 255 255; + } + description + { + state: "new" 0.0; + inherit: "default" 0.0; + image + { + normal: "newmail.png"; + } + } + } + part + { + name: "name"; + type: TEXT; + clip_to: "clip"; + effect: SOFT_SHADOW; + mouse_events: 0; + description + { + state: "default" 0.0; + color: 0 0 0 255; + color3: 255 255 255 42; + visible: 0; + rel1 + { + relative: 0.0 0.9; + offset: 0 0; + to: "logo"; + } + rel2 + { + relative: 1.0 1.0; + offset: -1 -1; + to: "logo"; + } + text + { + text: ""; + font: "VeraBold"; + size: 10; + min: 1 1; + align: 1.0 0.5; + text_class: "module_normal"; + } + } + description + { + state: "visible" 0.0; + inherit: "default" 0.0; + visible: 1; + color: 0 0 0 255; + color3: 255 255 255 42; + } + } + part + { + name: "new_label"; + type: TEXT; + clip_to: "clip"; + effect: SOFT_SHADOW; + mouse_events: 0; + description + { + state: "default" 0.0; + color: 0 0 0 255; + color3: 255 255 255 42; + visible: 0; + rel1 + { + relative: 0.0 0.3; + offset: 0 0; + to: "logo"; + } + rel2 + { + relative: 1.0 0.5; + offset: -1 -1; + to: "logo"; + } + text + { +<<<<<<< mail.edc + text: ""; + font: "VeraBold"; + size: 9; + min: 1 1; + align: 1.0 0.5; + text_class: "module_small"; + } + } + description + { + state: "visible" 0.0; + inherit: "default" 0.0; + visible: 1; + color: 0 0 0 255; + color3: 255 255 255 42; + } + } +======= + text: "New:"; + font: "VeraBold"; + size: 9; + min: 1 1; + align: 1.0 0.5; + text_class: "module_small"; + } + } + description + { + state: "visible" 0.0; + inherit: "default" 0.0; + visible: 1; + color: 0 0 0 255; + color3: 255 255 255 42; + } + } +>>>>>>> 1.4 + } + programs + { + program + { + name: "go_active"; + signal: "label_active"; + source: ""; + action: STATE_SET "visible" 0.0; + transition: SINUSOIDAL 0.5; + target: "name"; + target: "new_label"; + } + program + { + name: "go_passive2"; + signal: "label_passive2"; + source: ""; + action: ACTION_STOP; + target: "go_active"; + } + program + { + name: "go_passive"; + signal: "label_passive"; + source: ""; + action: STATE_SET "default" 0.0; + transition: SINUSOIDAL 1.0; + target: "name"; + target: "new_label"; + } + program + { + name: "go_new"; + signal: "new_mail"; + action: STATE_SET "new" 0.0; + transition: SINUSOIDAL 0.5; + target: "logo"; + } + program + { + name: "go_no"; + signal: "no_mail"; + action: STATE_SET "default" 0.0; + transition: SINUSOIDAL 1.0; + target: "logo"; + } + } + } +}