From a9bfd0ef30ce1cf9c0957e0adeef7594f0e95873 Mon Sep 17 00:00:00 2001 From: discomfitor Date: Sat, 26 Oct 2013 18:02:20 +0100 Subject: [PATCH] feature: add PIN-style desklock for lokker module accessible from the normal screen lock dialog --- src/bin/e_config.c | 1 + src/bin/e_config.h | 1 + src/bin/e_desklock.h | 1 + .../conf_display/e_int_config_desklock.c | 47 +++- src/modules/lokker/e_mod_main.h | 8 +- src/modules/lokker/lokker.c | 242 ++++++++++++++++-- 6 files changed, 282 insertions(+), 18 deletions(-) diff --git a/src/bin/e_config.c b/src/bin/e_config.c index 46ffc283b..475a31fdd 100644 --- a/src/bin/e_config.c +++ b/src/bin/e_config.c @@ -569,6 +569,7 @@ _e_config_edd_init(Eina_Bool old) E_CONFIG_LIST(D, T, shelves, _e_config_shelf_edd); E_CONFIG_VAL(D, T, font_hinting, INT); /**/ E_CONFIG_VAL(D, T, desklock_passwd, INT); + E_CONFIG_VAL(D, T, desklock_pin, INT); E_CONFIG_LIST(D, T, desklock_backgrounds, _e_config_desklock_bg_edd); /**/ E_CONFIG_VAL(D, T, desklock_auth_method, INT); E_CONFIG_VAL(D, T, desklock_login_box_zone, INT); diff --git a/src/bin/e_config.h b/src/bin/e_config.h index 59612ba3c..267830235 100644 --- a/src/bin/e_config.h +++ b/src/bin/e_config.h @@ -207,6 +207,7 @@ struct _E_Config int font_hinting; // GUI int desklock_passwd; // GUI // hashed + int desklock_pin; // GUI // hashed Eina_List *desklock_backgrounds; // GUI int desklock_auth_method; // GUI int desklock_login_box_zone; // GUI diff --git a/src/bin/e_desklock.h b/src/bin/e_desklock.h index f534fc006..982f69cbd 100644 --- a/src/bin/e_desklock.h +++ b/src/bin/e_desklock.h @@ -16,6 +16,7 @@ typedef enum E_DESKLOCK_AUTH_METHOD_SYSTEM = 0, E_DESKLOCK_AUTH_METHOD_PERSONAL = 1, E_DESKLOCK_AUTH_METHOD_EXTERNAL = 2, + E_DESKLOCK_AUTH_METHOD_PIN = 3, } E_Desklock_Auth_Method; #else diff --git a/src/modules/conf_display/e_int_config_desklock.c b/src/modules/conf_display/e_int_config_desklock.c index 0a6aa96a6..b0426d155 100644 --- a/src/modules/conf_display/e_int_config_desklock.c +++ b/src/modules/conf_display/e_int_config_desklock.c @@ -17,7 +17,7 @@ static void _cb_bg_mouse_down(void *data, Evas *evas, Evas_Object *obj, struct _E_Config_Dialog_Data { - Evas_Object *lock_cmd_entry, *passwd_entry; + Evas_Object *lock_cmd_entry, *passwd_entry, *pin_entry; E_Config_Dialog *cfd, *bg_fsel; /* Common vars */ @@ -32,6 +32,7 @@ struct _E_Config_Dialog_Data int login_zone; int zone; char *desklock_personal_passwd; + char *pin_str; char *custom_lock_cmd; /* Layout */ @@ -173,6 +174,7 @@ _free_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata) e_object_del(E_OBJECT(cfdata->bg_fsel)); E_FREE(cfdata->custom_lock_cmd); E_FREE(cfdata->desklock_personal_passwd); + E_FREE(cfdata->pin_str); EINA_LIST_FREE(cfdata->bgs, bg) eina_stringshare_del(bg); E_FREE(cfdata); @@ -210,6 +212,9 @@ _basic_create(E_Config_Dialog *cfd __UNUSED__, Evas *evas, E_Config_Dialog_Data ow = e_widget_radio_add(evas, _("Use Personal Screenlock Password"), E_DESKLOCK_AUTH_METHOD_PERSONAL, rg); evas_object_smart_callback_add(ow, "changed", _login_method_change, cfdata); e_widget_list_object_append(ol, ow, 1, 1, 0.5); + ow = e_widget_radio_add(evas, _("Use PIN"), E_DESKLOCK_AUTH_METHOD_PIN, rg); + evas_object_smart_callback_add(ow, "changed", _login_method_change, cfdata); + e_widget_list_object_append(ol, ow, 1, 1, 0.5); ow = e_widget_radio_add(evas, _("Use External Screenlock Command"), E_DESKLOCK_AUTH_METHOD_EXTERNAL, rg); evas_object_smart_callback_add(ow, "changed", _login_method_change, cfdata); e_widget_list_object_append(ol, ow, 1, 1, 0.5); @@ -220,12 +225,20 @@ _basic_create(E_Config_Dialog *cfd __UNUSED__, Evas *evas, E_Config_Dialog_Data e_widget_framelist_object_append(of, ow); e_widget_list_object_append(ol, of, 1, 1, 0.5); + of = e_widget_framelist_add(evas, _("PIN Entry"), 0); + cfdata->pin_entry = ow = e_widget_entry_add(evas, &(cfdata->pin_str), NULL, NULL, NULL); + e_widget_entry_password_set(ow, 1); + e_widget_framelist_object_append(of, ow); + e_widget_list_object_append(ol, of, 1, 1, 0.5); + of = e_widget_framelist_add(evas, _("External Screenlock Command"), 0); cfdata->lock_cmd_entry = ow = e_widget_entry_add(evas, &(cfdata->custom_lock_cmd), NULL, NULL, NULL); e_widget_framelist_object_append(of, ow); e_widget_disabled_set(cfdata->passwd_entry, (cfdata->desklock_auth_method != E_DESKLOCK_AUTH_METHOD_PERSONAL)); + e_widget_disabled_set(cfdata->pin_entry, + (cfdata->desklock_auth_method != E_DESKLOCK_AUTH_METHOD_PIN)); e_widget_disabled_set(cfdata->lock_cmd_entry, (cfdata->desklock_auth_method != E_DESKLOCK_AUTH_METHOD_EXTERNAL)); @@ -397,6 +410,24 @@ _basic_apply(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata) eina_hash_djb2(cfdata->desklock_personal_passwd, strlen(cfdata->desklock_personal_passwd)); } + else if (cfdata->desklock_auth_method == E_DESKLOCK_AUTH_METHOD_PIN) + { + if (cfdata->pin_str && cfdata->pin_str[0]) + { + int test; + char *pp; + + errno = 0; + test = strtol(cfdata->pin_str, &pp, 10); + if (errno) return 0; //NAN + if (pp && pp[0]) return 0; + if (test < 1) return 0; + e_config->desklock_pin = eina_hash_djb2(cfdata->pin_str, strlen(cfdata->pin_str)); + } + else + /* dumb, but let them do what they want... */ + e_config->desklock_pin = 0; + } e_config->desklock_start_locked = cfdata->start_locked; e_config->desklock_on_suspend = cfdata->lock_on_suspend; e_config->desklock_autolock_idle = cfdata->auto_lock; @@ -480,6 +511,13 @@ _basic_check_changed(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfda strlen(cfdata->desklock_personal_passwd))) return 1; } + if (e_config->desklock_auth_method == E_DESKLOCK_AUTH_METHOD_PIN) + { + if (e_config->desklock_pin != + eina_hash_djb2(cfdata->pin_str, + strlen(cfdata->pin_str))) + return 1; + } if (e_config->desklock_autolock_screensaver != cfdata->screensaver_lock) return 1; @@ -644,6 +682,13 @@ _login_method_change(void *data, Evas_Object *obj EINA_UNUSED, void *event_info e_widget_entry_select_all(cfdata->passwd_entry); e_widget_focus_set(cfdata->passwd_entry, 1); } + e_widget_disabled_set(cfdata->pin_entry, + (cfdata->desklock_auth_method != E_DESKLOCK_AUTH_METHOD_PIN)); + if (!e_widget_disabled_get(cfdata->pin_entry)) + { + e_widget_entry_select_all(cfdata->pin_entry); + e_widget_focus_set(cfdata->pin_entry, 1); + } e_widget_disabled_set(cfdata->lock_cmd_entry, (cfdata->desklock_auth_method != E_DESKLOCK_AUTH_METHOD_EXTERNAL)); if (!e_widget_disabled_get(cfdata->lock_cmd_entry)) diff --git a/src/modules/lokker/e_mod_main.h b/src/modules/lokker/e_mod_main.h index 7b885254c..111235ff1 100644 --- a/src/modules/lokker/e_mod_main.h +++ b/src/modules/lokker/e_mod_main.h @@ -18,7 +18,13 @@ #define ERR(...) EINA_LOG_DOM_ERR(_e_lokker_log_dom, __VA_ARGS__) #define CRIT(...) EINA_LOG_DOM_CRIT(_e_lokker_log_dom, __VA_ARGS__) + +typedef enum +{ + E_DESKLOCK_AUTH_METHOD_LINES = 4, +} E_Desklock_Auth_Method2; + EINTERN Eina_Bool lokker_lock(void); EINTERN void lokker_unlock(void); - +EAPI E_Config_Dialog *e_int_config_lokker(E_Comp *comp, const char *params EINA_UNUSED); #endif diff --git a/src/modules/lokker/lokker.c b/src/modules/lokker/lokker.c index d42c0b9d2..827f7302f 100644 --- a/src/modules/lokker/lokker.c +++ b/src/modules/lokker/lokker.c @@ -34,6 +34,14 @@ static E_Zone *last_active_zone = NULL; static Lokker_Data *edd = NULL; +static int _lokker_check_auth(void); + +static Eina_Bool +lokker_is_pin(void) +{ + return e_config->desklock_auth_method == E_DESKLOCK_AUTH_METHOD_PIN; +} + static int _zone_count_get(void) { @@ -156,6 +164,147 @@ _lokker_delete(void) _lokker_backspace(); } +static Eina_Bool +_pin_mouse_button_down(Lokker_Popup *lp, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev) +{ + Evas *e; + + if (ev->buttons != 1) return ECORE_CALLBACK_DONE; + e = e_comp_get(lp->zone)->evas; + evas_event_feed_mouse_move(e, + e_comp_canvas_x_root_adjust(lp->zone->comp, ev->root.x), + e_comp_canvas_y_root_adjust(lp->zone->comp, ev->root.y), + 0, NULL); + evas_event_feed_mouse_down(e, 1, 0, 0, NULL); + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_pin_mouse_button_up(Lokker_Popup *lp, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev) +{ + if (ev->buttons != 1) return ECORE_CALLBACK_DONE; + evas_event_feed_mouse_up(evas_object_evas_get(lp->comp_object), 1, 0, 0, NULL); + return ECORE_CALLBACK_RENEW; +} + +static void +_pin_click(void *data EINA_UNUSED, Evas_Object *obj, const char *sig EINA_UNUSED, const char *src EINA_UNUSED) +{ + const char *name; + int num; + + name = edje_object_part_text_get(obj, "e.text.label"); + if (!name) //wtf + return; + if (!e_util_strcmp(name, "Login")) + { + _lokker_check_auth(); + return; + } + if (!e_util_strcmp(name, "Delete")) + { + _lokker_backspace(); + return; + } + num = strtol(name, NULL, 10); + if (num < 0) return; + if (num > 9) return; + if (edd->selected) + { + _lokker_null(); + _lokker_unselect(); + } + if ((strlen(edd->passwd) < (PASSWD_LEN - strlen(name)))) + { + strcat(edd->passwd, name); + _text_passwd_update(); + } +} + +static void +_pin_box_add(Lokker_Popup *lp) +{ + int mw, mh; + Evas *evas; + Evas_Object *table, *o, *o2; + int x, a = 0, b = 0; + + evas = evas_object_evas_get(lp->bg_object); + lp->login_box = edje_object_add(evas); + evas_object_name_set(lp->login_box, "desklock->login_box"); + e_theme_edje_object_set(lp->login_box, + "base/theme/desklock", + "e/desklock/pin_box"); + edje_object_part_text_set(lp->login_box, "e.text.title", + _("Please enter your PIN")); + table = e_table_add(evas); + e_comp_object_util_del_list_append(lp->login_box, table); + e_table_homogenous_set(table, 1); + e_table_freeze(table); + for (x = 1; x < 11; x++) + { + char buf[8]; + + o = edje_object_add(evas); + e_comp_object_util_del_list_append(lp->login_box, o); + e_theme_edje_object_set(o, "base/theme/desklock", "e/desklock/pin_button"); + snprintf(buf, sizeof(buf), "%d", x % 10); + edje_object_part_text_set(o, "e.text.label", buf); + evas_object_show(o); + edje_object_signal_callback_add(o, "e,action,click", "*", _pin_click, lp); + if (x == 10) a = 1; + e_table_pack(table, o, a, b, 1, 1); + e_table_pack_options_set(o, 1, 1, 0, 0, 0.5, 0.5, + 48 * e_scale, 48 * e_scale, 48 * e_scale, 48 * e_scale); + if (++a >= 3) + { + a = 0; + b++; + } + } + + /* delete */ + o = edje_object_add(evas); + e_comp_object_util_del_list_append(lp->login_box, o); + e_theme_edje_object_set(o, "base/theme/desklock", "e/desklock/pin_button"); + edje_object_part_text_set(o, "e.text.label", "Delete"); + o2 = e_icon_add(evas); + e_comp_object_util_del_list_append(lp->login_box, o2); + e_util_icon_theme_set(o2, "list-remove"); + edje_object_part_swallow(o, "e.swallow.icon", o2); + evas_object_show(o2); + evas_object_show(o); + edje_object_signal_callback_add(o, "e,action,click", "*", _pin_click, lp); + e_table_pack(table, o, 0, 3, 1, 1); + e_table_pack_options_set(o, 1, 1, 0, 0, 0.5, 0.5, + 48 * e_scale, 48 * e_scale, 48 * e_scale, 48 * e_scale); + + /* login */ + o = edje_object_add(evas); + e_comp_object_util_del_list_append(lp->login_box, o); + e_theme_edje_object_set(o, "base/theme/desklock", "e/desklock/pin_button"); + edje_object_part_text_set(o, "e.text.label", "Login"); + o2 = e_icon_add(evas); + e_comp_object_util_del_list_append(lp->login_box, o2); + e_util_icon_theme_set(o2, "preferences-applications-screen-unlock"); + edje_object_part_swallow(o, "e.swallow.icon", o2); + evas_object_show(o2); + evas_object_show(o); + edje_object_signal_callback_add(o, "e,action,click", "*", _pin_click, lp); + e_table_pack(table, o, 2, 3, 1, 1); + e_table_pack_options_set(o, 1, 1, 0, 0, 0.5, 0.5, + 48 * e_scale, 48 * e_scale, 48 * e_scale, 48 * e_scale); + + e_table_thaw(table); + evas_object_show(table); + e_table_size_min_get(table, &mw, &mh); + edje_extern_object_min_size_set(table, mw, mh); + edje_extern_object_max_size_set(table, mw, mh); + edje_object_part_swallow(lp->login_box, "e.swallow.buttons", table); + edje_object_size_min_calc(lp->login_box, &mw, &mh); + edje_extern_object_min_size_set(lp->login_box, mw, mh); + edje_extern_object_max_size_set(lp->login_box, mw, mh); +} static void _text_login_box_add(Lokker_Popup *lp) @@ -205,10 +354,13 @@ _text_login_box_add(Lokker_Popup *lp) static void _lokker_popup_add(E_Zone *zone) { + E_Zone *current_zone; + int total_zone_num; Lokker_Popup *lp; E_Config_Desklock_Background *cbg; Eina_Stringshare *bg; Evas *evas; + int nocreate = 0; lp = E_NEW(Lokker_Popup, 1); cbg = eina_list_nth(e_config->desklock_backgrounds, zone->num); @@ -265,7 +417,37 @@ _lokker_popup_add(E_Zone *zone) evas_object_layer_set(lp->comp_object, E_LAYER_DESKLOCK); evas_object_clip_set(lp->comp_object, lp->zone->bg_clip_object); - _text_login_box_add(lp); + last_active_zone = current_zone = e_util_zone_current_get(e_manager_current_get()); + total_zone_num = _zone_count_get(); + if (total_zone_num > 1) + { + if ((e_config->desklock_login_box_zone == -2) && (zone != current_zone)) + nocreate = 1; + else if ((e_config->desklock_login_box_zone > -1) && (e_config->desklock_login_box_zone != (int)eina_list_count(edd->elock_wnd_list))) + nocreate = 1; + } + + if (!nocreate) + { + switch (e_config->desklock_auth_method) + { + case E_DESKLOCK_AUTH_METHOD_SYSTEM: + case E_DESKLOCK_AUTH_METHOD_PERSONAL: + _text_login_box_add(lp); + break; + case E_DESKLOCK_AUTH_METHOD_PIN: + _pin_box_add(lp); + edje_object_part_swallow(lp->bg_object, "e.swallow.login_box", lp->login_box); + + evas_object_clip_set(lp->login_box, lp->zone->bg_clip_object); + + E_LIST_HANDLER_APPEND(edd->handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN, _pin_mouse_button_down, lp); + E_LIST_HANDLER_APPEND(edd->handlers, ECORE_EVENT_MOUSE_BUTTON_UP, _pin_mouse_button_up, lp); + break; + case E_DESKLOCK_AUTH_METHOD_EXTERNAL: //handled by e_desklock + default: break; + } + } evas_event_thaw(evas); @@ -436,8 +618,7 @@ static int _lokker_check_auth(void) { if (!edd) return 0; -#ifdef HAVE_PAM - if (e_config->desklock_auth_method == 0) + if (e_desklock_is_system()) { int ret; @@ -446,22 +627,32 @@ _lokker_check_auth(void) _lokker_null(); return ret; } - else if (e_config->desklock_auth_method == 1) + else if (e_desklock_is_personal()) { -#endif - if ((e_config->desklock_passwd) && (edd->passwd && edd->passwd[0]) && - (e_config->desklock_passwd == eina_hash_djb2(edd->passwd, strlen(edd->passwd)))) - { - /* password ok */ - /* security - null out passwd string once we are done with it */ - _lokker_null(); - e_desklock_hide(); - return 1; + if ((e_config->desklock_passwd) && (edd->passwd && edd->passwd[0]) && + (e_config->desklock_passwd == eina_hash_djb2(edd->passwd, strlen(edd->passwd)))) + { + /* password ok */ + /* security - null out passwd string once we are done with it */ + _lokker_null(); + e_desklock_hide(); + return 1; + } + } + else if (lokker_is_pin()) + { + if (edd->passwd && edd->passwd[0]) + { + if (eina_hash_djb2(edd->passwd, strlen(edd->passwd)) == + e_config->desklock_pin) + { + _lokker_null(); + e_desklock_hide(); + return 1; + } + } } -#ifdef HAVE_PAM -} -#endif /* password is definitely wrong */ _lokker_state_set(LOKKER_STATE_INVALID); _lokker_null(); @@ -518,6 +709,16 @@ _lokker_cb_key_down(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) /* here we have to grab a password */ if (ev->compose) { + if (lokker_is_pin()) + { + /* block non-digits */ + const char *c; + + for (c = ev->compose; c[0]; c++) + { + if (!isdigit(c[0])) return ECORE_CALLBACK_RENEW; + } + } if (edd->selected) { _lokker_null(); @@ -542,6 +743,15 @@ lokker_lock(void) E_Comp *comp; if (edd) return EINA_TRUE; + + if (lokker_is_pin()) + { + if (!e_config->desklock_pin) + { + e_configure_registry_call("screen/screen_lock", NULL, NULL); + return EINA_FALSE; + } + } edd = E_NEW(Lokker_Data, 1); if (!edd) return EINA_FALSE;