Fix the build error with glibc 2.17.
[apps/core/preloaded/lockscreen.git] / src / complex-password.c
1 /*\r
2  * Copyright 2012  Samsung Electronics Co., Ltd\r
3  *\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
7  *\r
8  *  http://floralicense.org/license/\r
9  *\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
15  */\r
16 \r
17 #include <vconf.h>\r
18 \r
19 #include "lockscreen.h"\r
20 #include "util.h"\r
21 #include "log.h"\r
22 #include "complex-password.h"\r
23 #include "password-verification.h"\r
24 \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
33 \r
34 static Evas_Coord complex_pw_down_y = 0;\r
35 \r
36 static void __complex_password_keypad_process(void *data, Evas_Object *obj, const char *emission, const char *source)\r
37 {\r
38         struct appdata *ad = data;\r
39         if(ad == NULL)\r
40                 return;\r
41 \r
42         LOCK_SCREEN_TRACE_DBG("source = %s", source);\r
43 \r
44         if (strcmp("SOS", source) == 0) {\r
45                 launch_emgcall(ad);\r
46                 return;\r
47         }\r
48 \r
49         if (strcasecmp("function1", source) == 0 || strcasecmp("function2", source) == 0) {\r
50                 return ;\r
51         }\r
52 \r
53         if (strcasecmp("space", source) == 0) {\r
54                 if(ad->is_disabled) {\r
55                         return;\r
56                 }\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
64 \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
73                         }\r
74                 }\r
75         } else if (strcasecmp("enter", source) == 0) {\r
76                 if(ad->is_disabled) {\r
77                         return;\r
78                 }\r
79                 password_verification_verify(ad->h_password_policy, elm_entry_entry_get(ad->c_password_entry));\r
80         } else {\r
81                 if(ad->is_disabled) {\r
82                         return;\r
83                 }\r
84                 elm_entry_entry_insert(ad->c_password_entry, source);\r
85         }\r
86 }\r
87 \r
88 static void __complex_password_layout_destroy(void *data, Evas_Object *obj, const char *emission, const char *source)\r
89 {\r
90         struct appdata *ad = data;\r
91 \r
92         if(ad->ly_complex_password){\r
93                 evas_object_del(ad->ly_complex_password);\r
94                 ad->ly_complex_password = NULL;\r
95         }\r
96         password_verification_policy_destroy(ad->h_password_policy);\r
97         lockscreen_info_show(ad);\r
98 }\r
99 \r
100 static void __complex_password_mouse_down_cb(void *data, Evas * evas, Evas_Object * obj,\r
101                             void *event_info)\r
102 {\r
103         Evas_Event_Mouse_Down *ei = event_info;\r
104 \r
105         complex_pw_down_y = ei->output.y;\r
106 \r
107         LOCK_SCREEN_TRACE_DBG("complex_pw_down_y = %d", complex_pw_down_y);\r
108 }\r
109 \r
110 static void __complex_password_mouse_up_cb(void *data, Evas * evas, Evas_Object * obj,\r
111                           void *event_info)\r
112 {\r
113         struct appdata *ad = data;\r
114         Evas_Event_Mouse_Down *ei = event_info;\r
115 \r
116         Evas_Coord pos_up_y = ei->output.y;\r
117 \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
121         }\r
122 }\r
123 \r
124 static void __complex_password_mouse_move_cb(void *data, Evas * evas, Evas_Object * obj,\r
125                             void *event_info)\r
126 {\r
127         LOCK_SCREEN_TRACE_DBG("__complex_password_mouse_move_cb");\r
128 }\r
129 \r
130 void __complex_password_check_result(void *data)\r
131 {\r
132         struct appdata *ad = (struct appdata *) data;\r
133 \r
134         int value = -1;\r
135 \r
136         vconf_get_int(VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT, &value);\r
137         value--;\r
138 \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
142 \r
143                 vconf_set_int(VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT,\r
144                               value);\r
145                 if(value == 1)\r
146                 {\r
147                         snprintf(temp_left, sizeof(temp_left), _("IDS_IDLE_BODY_1_ATTEMPT_LEFT"));\r
148                 }\r
149                 else\r
150                 {\r
151                         snprintf(temp_left, sizeof(temp_left), _("IDS_IDLE_BODY_PD_ATTEMPTS_LEFT"), value);\r
152                 }\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
159 \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
164 \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
167         }\r
168 }\r
169 \r
170 static void __complex_password_check_result_cb (const char *event, void *data)\r
171 {\r
172         struct appdata *ad = (struct appdata *) data;\r
173         if (ad == NULL) {\r
174                 return;\r
175         }\r
176 \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
181         }else {\r
182                 __complex_password_check_result(data);\r
183         }\r
184 }\r
185 \r
186 static void __complex_password_results_update(void *data)\r
187 {\r
188         int value = -1;\r
189         int ret = 0;\r
190 \r
191         struct appdata *ad = (struct appdata *) data;\r
192 \r
193         if (ad == NULL) {\r
194                 return;\r
195         }\r
196         LOCK_SCREEN_TRACE_DBG("%s", __FUNCTION__);\r
197 \r
198         ret =\r
199             vconf_get_int(VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT,\r
200                           &value);\r
201 \r
202         if (ret != 0) {\r
203                 return;\r
204         }\r
205 \r
206         if (value == 0) {\r
207                 char timestamp_str[512] = {0};\r
208                 char *temp = NULL;\r
209                 int length = 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
217                 }else {\r
218                         timestamp_str[length] = '\0';\r
219                 }\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
225 \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
233                         } else {\r
234                                 ad->is_disabled = EINA_FALSE;\r
235                                 vconf_set_int(VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT, PASSWORD_ATTEMPTS_MAX_NUM);\r
236                         }\r
237                 }\r
238         }\r
239 }\r
240 \r
241 static Eina_Bool __complex_password_results_update_cb(void *data)\r
242 {\r
243         __complex_password_results_update(data);\r
244         return EINA_TRUE;\r
245 }\r
246 \r
247 static void __complex_password_check_vconf_value(void *data)\r
248 {\r
249         int phone_lock_value = -1;\r
250         struct appdata *ad = (struct appdata *) data;\r
251 \r
252         if (ad == NULL) {\r
253                 return;\r
254         }\r
255         LOCK_SCREEN_TRACE_DBG("%s", __FUNCTION__);\r
256 \r
257         vconf_get_int(VCONFKEY_SETAPPL_PASSWORD_ATTEMPTS_LEFT_INT, &phone_lock_value);\r
258 \r
259         if (phone_lock_value == 0) {\r
260                 if (ad->password_timer) {\r
261                         return;\r
262                 }\r
263                 ad->password_timer = ecore_timer_add(1, (Ecore_Task_Cb)__complex_password_results_update_cb, ad);\r
264         } else {\r
265                 if (ad->password_timer) {\r
266                         ecore_timer_del(ad->password_timer);\r
267                         ad->password_timer = NULL;\r
268                 }\r
269                 ad->is_disabled = EINA_FALSE;\r
270         }\r
271 }\r
272 \r
273 static void __complex_password_check_vconf_value_cb(keynode_t * key, void *data)\r
274 {\r
275         __complex_password_check_vconf_value(data);\r
276 }\r
277 \r
278 static void __complex_password_customize_entry(Evas_Object * entry)\r
279 {\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
290 }\r
291 \r
292 void complex_password_layout_create(void *data)\r
293 {\r
294         struct appdata *ad = (struct appdata *)data;\r
295         if(ad == NULL){\r
296                 return;\r
297         }\r
298 \r
299         Evas_Object *keypad_layout = NULL;\r
300 \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
308 \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
321 \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
331 \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
334 }\r