2 * Copyright 2012 Samsung Electronics Co., Ltd
\r
4 * Licensed under the Flora License, Version 1.1 (the License);
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://floralicense.org/license/
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an AS IS BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
19 #include "lockscreen.h"
\r
22 #include "complex-password.h"
\r
23 #include "password-verification.h"
\r
25 #define MIN_PASSWORD_NUM 4
\r
26 #define MAX_PASSWORD_NUM 16
\r
27 #define PASSWORD_ATTEMPTS_MAX_NUM 5
\r
28 #define VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT VCONFKEY_SETAPPL_PREFIX"/phone_lock_attempts_left"
\r
29 #define VCONFKEY_SETAPPL_PASSWORD_TIMESTAMP_STR VCONFKEY_SETAPPL_PREFIX"/phone_lock_timestamp"
\r
30 #define PASSWORD_TIMESTAMP_STR_LENGTH 512
\r
31 #define PASSWORD_BLOCK_SECONDS 30
\r
32 #define EDJ_LOCKSCREEN_ENTRY EDJDIR"/lockscreen-entry.edj"
\r
34 static Evas_Coord complex_pw_down_y = 0;
\r
36 static void __complex_password_keypad_process(void *data, Evas_Object *obj, const char *emission, const char *source)
\r
38 struct appdata *ad = data;
\r
42 LOCK_SCREEN_TRACE_DBG("source = %s", source);
\r
44 if (strcmp("SOS", source) == 0) {
\r
49 if (strcasecmp("function1", source) == 0 || strcasecmp("function2", source) == 0) {
\r
53 if (strcasecmp("space", source) == 0) {
\r
54 if(ad->is_disabled) {
\r
57 elm_entry_entry_insert(ad->c_password_entry, " ");
\r
58 } else if (strcasecmp("bs", source) == 0) {
\r
59 elm_entry_entry_insert(ad->c_password_entry, "");
\r
60 const char *input_entry_str = NULL;
\r
61 input_entry_str = elm_entry_entry_get(ad->c_password_entry);
\r
62 if (input_entry_str != NULL && strlen(input_entry_str) > 0 ) {
\r
63 int cursor_pos = elm_entry_cursor_pos_get(ad->c_password_entry);
\r
65 if (cursor_pos > 0) {
\r
66 Eina_Strbuf *temp_str_buf = eina_strbuf_new();
\r
67 eina_strbuf_append(temp_str_buf, input_entry_str);
\r
68 eina_strbuf_remove(temp_str_buf, cursor_pos - 1, cursor_pos);
\r
69 elm_entry_entry_set(ad->c_password_entry, eina_strbuf_string_get(temp_str_buf));
\r
70 elm_entry_cursor_pos_set(ad->c_password_entry,
\r
71 (cursor_pos - 1 > 0) ? cursor_pos -1 : 0);
\r
72 eina_strbuf_free(temp_str_buf);
\r
75 } else if (strcasecmp("enter", source) == 0) {
\r
76 if(ad->is_disabled) {
\r
79 password_verification_verify(ad->h_password_policy, elm_entry_entry_get(ad->c_password_entry));
\r
81 if(ad->is_disabled) {
\r
84 elm_entry_entry_insert(ad->c_password_entry, source);
\r
88 static void __complex_password_layout_destroy(void *data, Evas_Object *obj, const char *emission, const char *source)
\r
90 struct appdata *ad = data;
\r
92 if(ad->ly_complex_password){
\r
93 evas_object_del(ad->ly_complex_password);
\r
94 ad->ly_complex_password = NULL;
\r
96 password_verification_policy_destroy(ad->h_password_policy);
\r
97 lockscreen_info_show(ad);
\r
100 static void __complex_password_mouse_down_cb(void *data, Evas * evas, Evas_Object * obj,
\r
103 Evas_Event_Mouse_Down *ei = event_info;
\r
105 complex_pw_down_y = ei->output.y;
\r
107 LOCK_SCREEN_TRACE_DBG("complex_pw_down_y = %d", complex_pw_down_y);
\r
110 static void __complex_password_mouse_up_cb(void *data, Evas * evas, Evas_Object * obj,
\r
113 struct appdata *ad = data;
\r
114 Evas_Event_Mouse_Down *ei = event_info;
\r
116 Evas_Coord pos_up_y = ei->output.y;
\r
118 if((pos_up_y - complex_pw_down_y) > _X(300)){
\r
119 edje_object_signal_emit(_EDJ(ad->ly_complex_password), "hide,qwertykeyboard", "sw.keypad.qwerty");
\r
120 edje_object_signal_callback_add(_EDJ(ad->ly_complex_password), "hide,complexpw", "event", __complex_password_layout_destroy, ad);
\r
124 static void __complex_password_mouse_move_cb(void *data, Evas * evas, Evas_Object * obj,
\r
127 LOCK_SCREEN_TRACE_DBG("__complex_password_mouse_move_cb");
\r
130 void __complex_password_check_result(void *data)
\r
132 struct appdata *ad = (struct appdata *) data;
\r
136 vconf_get_int(VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT, &value);
\r
139 if (value > 0 && value <= PASSWORD_ATTEMPTS_MAX_NUM) {
\r
140 char temp_str[200] = {0};
\r
141 char temp_left[50] = {0};
\r
143 vconf_set_int(VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT,
\r
147 snprintf(temp_left, sizeof(temp_left), _("IDS_IDLE_BODY_1_ATTEMPT_LEFT"));
\r
151 snprintf(temp_left, sizeof(temp_left), _("IDS_IDLE_BODY_PD_ATTEMPTS_LEFT"), value);
\r
153 snprintf(temp_str, sizeof(temp_str), "%s, %s", _("IDS_IDLE_BODY_INCORRECT_PASSWORD"), temp_left);
\r
154 edje_object_part_text_set(_EDJ(ad->ly_complex_password), "txt.result", temp_str);
\r
155 } else if (value == 0) {
\r
156 time_t cur_time = time(NULL);
\r
157 char cur_timestamp[64] = {0};
\r
158 char temp_str[512] = {0};
\r
160 snprintf(cur_timestamp, sizeof(cur_timestamp), "%ld", cur_time);
\r
161 vconf_set_str(VCONFKEY_SETAPPL_PASSWORD_TIMESTAMP_STR, cur_timestamp);
\r
162 vconf_set_int(VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT, value);
\r
163 ad->block_seconds = PASSWORD_BLOCK_SECONDS;
\r
165 snprintf(temp_str, sizeof(temp_str), _L("Input password again after %d seconds."), ad->block_seconds);
\r
166 edje_object_part_text_set(_EDJ(ad->ly_complex_password), "txt.result", temp_str);
\r
170 static void __complex_password_check_result_cb (const char *event, void *data)
\r
172 struct appdata *ad = (struct appdata *) data;
\r
177 if(strcasecmp("empty", event) == 0 || strcasecmp("overlength", event) == 0) {
\r
178 char temp_str[100] = {0};
\r
179 snprintf(temp_str, sizeof(temp_str), _L("%d to %d digits or letters required"), MIN_PASSWORD_NUM, MAX_PASSWORD_NUM);
\r
180 edje_object_part_text_set(_EDJ(ad->ly_complex_password), "txt.result", temp_str);
\r
182 __complex_password_check_result(data);
\r
186 static void __complex_password_results_update(void *data)
\r
191 struct appdata *ad = (struct appdata *) data;
\r
196 LOCK_SCREEN_TRACE_DBG("%s", __FUNCTION__);
\r
199 vconf_get_int(VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT,
\r
207 char timestamp_str[512] = {0};
\r
210 int temp_length = 0;
\r
211 temp = vconf_get_str(VCONFKEY_SETAPPL_PASSWORD_TIMESTAMP_STR);
\r
212 temp_length = strlen(temp);
\r
213 length = (temp_length <= PASSWORD_TIMESTAMP_STR_LENGTH) ? temp_length : PASSWORD_TIMESTAMP_STR_LENGTH;
\r
214 strncpy(timestamp_str, temp, length);
\r
215 if(length == PASSWORD_TIMESTAMP_STR_LENGTH) {
\r
216 timestamp_str[length-1] = '\0';
\r
218 timestamp_str[length] = '\0';
\r
220 if ((strcmp(timestamp_str, "") != 0)
\r
221 || (strlen(timestamp_str) != 0)) {
\r
222 time_t cur_time = time(NULL);
\r
223 time_t last_lock_time;
\r
224 sscanf(timestamp_str, "%ld", &last_lock_time);
\r
226 if ((cur_time - last_lock_time) < PASSWORD_BLOCK_SECONDS) {
\r
227 ad->block_seconds = PASSWORD_BLOCK_SECONDS - (cur_time - last_lock_time);
\r
228 LOCK_SCREEN_TRACE_DBG("ad->block_seconds = %d", ad->block_seconds);
\r
229 ad->is_disabled = EINA_TRUE;
\r
230 char temp_str[512] = {0};
\r
231 snprintf(temp_str, sizeof(temp_str), _L("Input password again after %d seconds."), ad->block_seconds);
\r
232 edje_object_part_text_set(_EDJ(ad->ly_complex_password), "txt.result", temp_str);
\r
234 ad->is_disabled = EINA_FALSE;
\r
235 vconf_set_int(VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT, PASSWORD_ATTEMPTS_MAX_NUM);
\r
241 static Eina_Bool __complex_password_results_update_cb(void *data)
\r
243 __complex_password_results_update(data);
\r
247 static void __complex_password_check_vconf_value(void *data)
\r
249 int phone_lock_value = -1;
\r
250 struct appdata *ad = (struct appdata *) data;
\r
255 LOCK_SCREEN_TRACE_DBG("%s", __FUNCTION__);
\r
257 vconf_get_int(VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT, &phone_lock_value);
\r
259 if (phone_lock_value == 0) {
\r
260 if (ad->password_timer) {
\r
263 ad->password_timer = ecore_timer_add(1, (Ecore_Task_Cb)__complex_password_results_update_cb, ad);
\r
265 if (ad->password_timer) {
\r
266 ecore_timer_del(ad->password_timer);
\r
267 ad->password_timer = NULL;
\r
269 ad->is_disabled = EINA_FALSE;
\r
273 static void __complex_password_check_vconf_value_cb(keynode_t * key, void *data)
\r
275 __complex_password_check_vconf_value(data);
\r
278 static void __complex_password_customize_entry(Evas_Object * entry)
\r
280 static Elm_Entry_Filter_Limit_Size limit_filter_data_alpha;
\r
281 Elm_Theme *th = elm_theme_new();
\r
282 elm_theme_ref_set(th, NULL);
\r
283 elm_theme_extension_add(th, EDJ_LOCKSCREEN_ENTRY);
\r
284 elm_object_theme_set(entry, th);
\r
285 elm_object_style_set(entry, "lockscreen_complex_password_style");
\r
286 limit_filter_data_alpha.max_char_count = MAX_PASSWORD_NUM;
\r
287 limit_filter_data_alpha.max_byte_count = 0;
\r
288 elm_entry_markup_filter_append(entry, elm_entry_filter_limit_size,
\r
289 &limit_filter_data_alpha);
\r
292 void complex_password_layout_create(void *data)
\r
294 struct appdata *ad = (struct appdata *)data;
\r
299 Evas_Object *keypad_layout = NULL;
\r
301 ad->h_password_policy = password_verification_policy_create();
\r
302 password_verification_callback_set(ad->h_password_policy, __complex_password_check_result_cb, ad);
\r
303 lockscreen_info_hide(ad);
\r
304 ad->ly_complex_password = elm_layout_add(ad->ly_main);
\r
305 elm_layout_file_set(ad->ly_complex_password, EDJEFILE, "lock-complex-password");
\r
306 elm_object_part_content_set(ad->ly_main, "sw.phone-lock", ad->ly_complex_password);
\r
307 edje_object_part_text_set(_EDJ(ad->ly_complex_password), "txt.title", _S("IDS_COM_BODY_ENTER_PASSWORD"));
\r
309 Evas_Object *entry = NULL;
\r
310 entry = elm_entry_add(ad->ly_complex_password);
\r
311 __complex_password_customize_entry(entry);
\r
312 elm_entry_single_line_set(entry, EINA_TRUE);
\r
313 elm_entry_password_set(entry, EINA_TRUE);
\r
314 elm_entry_entry_set(entry, "");
\r
315 elm_entry_cursor_end_set(entry);
\r
316 elm_entry_scrollable_set(entry, EINA_TRUE);
\r
317 elm_object_part_content_set(ad->ly_complex_password, "sw.password", entry);
\r
318 Ecore_IMF_Context *imf_context = elm_entry_imf_context_get(entry);
\r
319 ecore_imf_context_input_panel_enabled_set(imf_context, EINA_FALSE);
\r
320 ad->c_password_entry = entry;
\r
322 keypad_layout = elm_layout_add(ad->ly_complex_password);
\r
323 elm_layout_file_set(keypad_layout, EDJEFILE, "lock-keypad-qwerty");
\r
324 elm_object_part_content_set(ad->ly_complex_password, "sw.keypad.qwerty", keypad_layout);
\r
325 edje_object_signal_emit(_EDJ(ad->ly_complex_password), "show,qwertykeyboard", "sw.keypad.qwerty");
\r
326 edje_object_signal_callback_add(_EDJ(keypad_layout), "pad_qwerty_clicked", "*", __complex_password_keypad_process, ad);
\r
327 evas_object_event_callback_add(ad->ly_complex_password, EVAS_CALLBACK_MOUSE_DOWN, __complex_password_mouse_down_cb, ad);
\r
328 evas_object_event_callback_add(ad->ly_complex_password, EVAS_CALLBACK_MOUSE_MOVE, __complex_password_mouse_move_cb, ad);
\r
329 evas_object_event_callback_add(ad->ly_complex_password, EVAS_CALLBACK_MOUSE_UP, __complex_password_mouse_up_cb, ad);
\r
330 evas_object_show(keypad_layout);
\r
332 vconf_notify_key_changed(VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT, __complex_password_check_vconf_value_cb, ad);
\r
333 __complex_password_check_vconf_value(ad);
\r