4 * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
26 #include <image_util.h>
28 #include <vconf-keys.h>
29 #include <unicode/ulocdata.h>
30 #include <unicode/uset.h>
31 #include <unicode/ustring.h>
32 #include <libexif/exif-data.h>
35 #include "ctsvc_internal.h"
36 #include "ctsvc_utils.h"
37 #include "ctsvc_mutex.h"
38 #include "ctsvc_sqlite.h"
39 #include "ctsvc_schema.h"
40 #include "ctsvc_notification.h"
41 #include "ctsvc_struct.h"
42 #include "ctsvc_normalize.h"
43 #include "ctsvc_localize.h"
44 #include "ctsvc_localize_utils.h"
45 #include "ctsvc_setting.h"
46 #include "ctsvc_notify.h"
48 #ifdef _CONTACTS_IPC_SERVER
49 #include "ctsvc_server_change_subject.h"
52 static __thread int transaction_count = 0;
53 static __thread int transaction_ver = 0;
54 static __thread bool version_up = false;
56 #define CTS_SECURITY_IMAGE_PERMISSION 0440
57 #define CTS_IMAGE_ENCODE_QUALITY 50
59 #define CTS_COMMIT_TRY_MAX 500000 // For 3second
61 int ctsvc_begin_trans(void)
63 int ret = -1, progress;
65 #ifndef _CONTACTS_IPC_SERVER
66 ctsvc_mutex_lock(CTS_MUTEX_TRANSACTION);
68 if (transaction_count <= 0) {
69 ret = ctsvc_query_exec("BEGIN IMMEDIATE TRANSACTION");
71 while (CONTACTS_ERROR_DB == ret && progress < CTS_COMMIT_TRY_MAX) {
73 ret = ctsvc_query_exec("BEGIN IMMEDIATE TRANSACTION");
76 if(CONTACTS_ERROR_NONE != ret) {
77 CTS_ERR("ctsvc_query_exec() Failed(%d)", ret);
78 #ifndef _CONTACTS_IPC_SERVER
79 ctsvc_mutex_unlock(CTS_MUTEX_TRANSACTION);
84 transaction_count = 0;
86 const char *query = "SELECT ver FROM "CTS_TABLE_VERSION;
87 ret = ctsvc_query_get_first_int_result(query, &transaction_ver);
91 INFO("transaction_count : %d.", transaction_count);
92 #ifndef _CONTACTS_IPC_SERVER
93 ctsvc_mutex_unlock(CTS_MUTEX_TRANSACTION);
95 return CONTACTS_ERROR_NONE;
98 int ctsvc_end_trans(bool is_success)
100 int ret = -1, progress;
101 char query[CTS_SQL_MIN_LEN] = {0};
103 #ifndef _CONTACTS_IPC_SERVER
104 ctsvc_mutex_lock(CTS_MUTEX_TRANSACTION);
108 INFO("%s, transaction_count : %d", is_success?"True": "False", transaction_count);
110 if (0 != transaction_count) {
111 CTS_DBG("contact transaction_count : %d.", transaction_count);
112 #ifndef _CONTACTS_IPC_SERVER
113 ctsvc_mutex_unlock(CTS_MUTEX_TRANSACTION);
115 return CONTACTS_ERROR_NONE;
118 if (false == is_success) {
119 ctsvc_nofitication_cancel();
120 #ifdef _CONTACTS_IPC_SERVER
121 ctsvc_change_subject_clear_changed_info();
123 ret = ctsvc_query_exec("ROLLBACK TRANSACTION");
125 #ifndef _CONTACTS_IPC_SERVER
126 ctsvc_mutex_unlock(CTS_MUTEX_TRANSACTION);
128 return CONTACTS_ERROR_NONE;
133 snprintf(query, sizeof(query), "UPDATE %s SET ver = %d",
134 CTS_TABLE_VERSION, transaction_ver);
135 ret = ctsvc_query_exec(query);
136 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_query_exec(version up) Failed(%d)", ret);
139 INFO("start commit");
141 ret = ctsvc_query_exec("COMMIT TRANSACTION");
142 while (CONTACTS_ERROR_DB == ret && progress<CTS_COMMIT_TRY_MAX) {
144 ret = ctsvc_query_exec("COMMIT TRANSACTION");
147 INFO("%s", (CONTACTS_ERROR_NONE == ret)?"commit": "rollback");
149 if (CONTACTS_ERROR_NONE != ret) {
151 CTS_ERR("ctsvc_query_exec() Failed(%d)", ret);
152 ctsvc_nofitication_cancel();
153 #ifdef _CONTACTS_IPC_SERVER
154 ctsvc_change_subject_clear_changed_info();
156 tmp_ret = ctsvc_query_exec("ROLLBACK TRANSACTION");
157 WARN_IF(CONTACTS_ERROR_NONE != tmp_ret, "ctsvc_query_exec(ROLLBACK) Failed(%d)", tmp_ret);
158 #ifndef _CONTACTS_IPC_SERVER
159 ctsvc_mutex_unlock(CTS_MUTEX_TRANSACTION);
164 ctsvc_notification_send();
165 #ifdef _CONTACTS_IPC_SERVER
166 ctsvc_change_subject_publish_changed_info();
169 #ifndef _CONTACTS_IPC_SERVER
170 ctsvc_mutex_unlock(CTS_MUTEX_TRANSACTION);
173 CTS_DBG("Transaction shut down! : (%d)\n", transaction_ver);
175 return CONTACTS_ERROR_NONE;
178 const char* ctsvc_get_display_column(void)
180 contacts_name_display_order_e order;
182 contacts_setting_get_name_display_order(&order);
183 if (CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST == order)
184 return "display_name";
186 return "reverse_display_name";
189 const char* ctsvc_get_sort_name_column(void)
191 contacts_name_sorting_order_e order;
193 contacts_setting_get_name_sorting_order(&order);
194 if (CONTACTS_NAME_SORTING_ORDER_FIRSTLAST == order)
195 return "sort_name, display_name_language";
197 return "reverse_sort_name, reverse_display_name_language";
200 const char* ctsvc_get_sort_column(void)
202 contacts_name_sorting_order_e order;
204 contacts_setting_get_name_sorting_order(&order);
205 if (CONTACTS_NAME_SORTING_ORDER_FIRSTLAST == order)
206 return "display_name_language, sortkey";
208 return "reverse_display_name_language, reverse_sortkey";
211 void ctsvc_utils_make_image_file_name(int parent_id, int id, char *src_img, char *dest, int dest_size)
217 ext = strrchr(src_img, '.');
218 if (NULL == ext || strchr(ext, '/'))
221 lower_ext = strdup(ext);
224 *temp = tolower(*temp);
229 snprintf(dest, dest_size, "%d_%d%s", parent_id, id, lower_ext);
231 snprintf(dest, dest_size, "%d%s", id, ext);
235 static inline bool ctsvc_check_available_image_space(void){
239 ret = statfs(CTSVC_NOTI_IMG_REPERTORY, &buf);
241 RETVM_IF(ret!=0, false, "statfs Failed(%d)", ret);
243 size = (long long)buf.f_bavail * (buf.f_bsize);
245 if (size > 1024*1024) // if available space to copy a image is larger than 1M
250 static image_util_rotation_e __ctsvc_get_rotation_info(const char *path)
254 image_util_rotation_e rotation = IMAGE_UTIL_ROTATION_NONE;
257 ed = exif_data_new_from_file(path);
259 CTS_ERR("exif_data_new_from_file : ExifData is NULL");
260 return IMAGE_UTIL_ROTATION_NONE;
263 entry = exif_data_get_entry(ed, EXIF_TAG_ORIENTATION);
265 ExifByteOrder mByteOrder = exif_data_get_byte_order(ed);
266 orientation = (int)exif_get_short(entry->data, mByteOrder);
267 if (orientation < 0 || orientation > 8)
274 switch(orientation) {
276 rotation = IMAGE_UTIL_ROTATION_NONE;
279 rotation = IMAGE_UTIL_ROTATION_FLIP_HORZ;
281 case 3: // Bottom-right
282 rotation = IMAGE_UTIL_ROTATION_180;
284 case 4: // Bottom-left
285 rotation = IMAGE_UTIL_ROTATION_FLIP_VERT;
288 rotation = IMAGE_UTIL_ROTATION_90;
290 case 8: // Left-bottom
291 rotation = IMAGE_UTIL_ROTATION_270;
294 case 7: // Right-bottom
303 static int image_size = 480;
311 static bool __ctsvc_image_util_supported_jpeg_colorspace_cb(image_util_colorspace_e colorspace, void *user_data)
313 image_info *info = (image_info*)user_data;
314 image_util_error_e ret;
315 int width = 0, height = 0;
316 unsigned int size_decode = 0;
317 int resized_width, resized_height;
318 unsigned char * img_target = 0;
319 unsigned char * img_source = 0;
321 image_util_rotation_e rotation;
324 if (colorspace == IMAGE_UTIL_COLORSPACE_YV12 || colorspace == IMAGE_UTIL_COLORSPACE_I420) {
325 info->ret = CONTACTS_ERROR_SYSTEM;
329 rotation = __ctsvc_get_rotation_info(info->src);
331 // load jpeg sample file
332 CTS_DBG("colorspace %d src : %s, dest : %s", colorspace, info->src, info->dest);
333 ret = image_util_decode_jpeg( info->src, colorspace, &img_source, &width, &height, &size_decode );
334 if (ret!=IMAGE_UTIL_ERROR_NONE) {
335 info->ret = CONTACTS_ERROR_SYSTEM;
342 ecore_x_window_size_get(
343 ecore_x_window_root_get(ecore_x_window_focus_get())
354 if (width > image_size || height > image_size) {
356 if (image_size<=0 || width <=0 || height <= 0) {
358 CTS_ERR("image size error(%d)", image_size);
359 info->ret = CONTACTS_ERROR_SYSTEM;
364 resized_width = image_size;
365 resized_height = height*image_size/width;
368 resized_height = image_size;
369 resized_width = width*image_size/height;
372 if (resized_height%8)
373 resized_height += 8 - (resized_height%8);
375 resized_width += 8 - (resized_width%8);
377 CTS_DBG("size(%d, %d) -> resize(%d,%d)", width, height, resized_width, resized_height);
379 image_util_calculate_buffer_size(resized_width, resized_height, colorspace , &size_decode);
381 img_target = malloc( size_decode );
384 ret = image_util_resize( img_target, &resized_width, &resized_height,
385 img_source, width, height, colorspace );
386 if (ret!=IMAGE_UTIL_ERROR_NONE) {
387 CTS_ERR("image_util_resize failed(%d)", ret);
390 info->ret = CONTACTS_ERROR_SYSTEM;
396 resized_width = width;
397 resized_height = height;
398 img_target = img_source;
402 if (IMAGE_UTIL_ROTATION_NONE != rotation) {
403 int rotated_width, rotated_height;
404 unsigned char *img_rotate = 0;
405 img_rotate = malloc( size_decode );
406 ret= image_util_rotate(img_rotate, &rotated_width, &rotated_height,
407 rotation, img_target, resized_width, resized_height, colorspace);
409 if (IMAGE_UTIL_ERROR_NONE != ret) {
410 CTS_ERR("image_util_rotate failed(%d)", ret);
411 info->ret = CONTACTS_ERROR_SYSTEM;
415 resized_width = rotated_width;
416 resized_height = rotated_height;
417 img_target = img_rotate;
421 ret = image_util_encode_jpeg(img_target, resized_width, resized_height, colorspace, CTS_IMAGE_ENCODE_QUALITY, info->dest );
423 if(ret != IMAGE_UTIL_ERROR_NONE) {
424 CTS_ERR("image_util_encode_jpeg failed(%d)", ret);
425 info->ret = CONTACTS_ERROR_SYSTEM;
429 dest_fd = open(info->dest, O_RDONLY);
431 CTS_ERR("System : Open Failed(%d)", errno);
432 info->ret = CONTACTS_ERROR_SYSTEM;
436 ret = fchown(dest_fd, getuid(), CTS_SECURITY_FILE_GROUP);
438 CTS_ERR("fchown Failed(%d)", errno);
439 info->ret = CONTACTS_ERROR_SYSTEM;
444 ret = fchmod(dest_fd, CTS_SECURITY_IMAGE_PERMISSION);
446 CTS_ERR("fchmod Failed(%d)", errno);
447 info->ret = CONTACTS_ERROR_SYSTEM;
453 info->ret = CONTACTS_ERROR_NONE;
457 static int __ctsvc_resize_and_copy_image(const char *src, const char *dest)
460 image_info info = {.src = src, .dest = dest, ret = CONTACTS_ERROR_SYSTEM};
462 ret = image_util_foreach_supported_jpeg_colorspace(__ctsvc_image_util_supported_jpeg_colorspace_cb, &info);
464 if (ret != IMAGE_UTIL_ERROR_NONE)
465 return CONTACTS_ERROR_SYSTEM;
470 #define CTSVC_COPY_SIZE_MAX 4096
471 int ctsvc_utils_copy_image(const char *dir, const char *src, const char *file)
476 char buf[CTSVC_COPY_SIZE_MAX] = {0};
478 if (NULL == file || *file == '\0')
479 return CONTACTS_ERROR_INVALID_PARAMETER;
481 char dest[strlen(dir) + strlen(file) + 2];
482 snprintf(dest, sizeof(dest), "%s/%s", dir, file);
484 if (!ctsvc_check_available_image_space())
485 return CONTACTS_ERROR_FILE_NO_SPACE;
487 ret = __ctsvc_resize_and_copy_image(src, dest);
488 if (CONTACTS_ERROR_NONE == ret) {
492 CTS_ERR("__ctsvc_resize_and_copy_image Failed(%d)", ret);
494 src_fd = open(src, O_RDONLY);
495 RETVM_IF(src_fd < 0, CONTACTS_ERROR_SYSTEM, "System : Open(src:%s) Failed(%d)", src, errno);
496 dest_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660);
498 CTS_ERR("Open Failed(%d)", errno);
500 return CONTACTS_ERROR_SYSTEM;
503 while ((size = read(src_fd, buf, CTSVC_COPY_SIZE_MAX)) > 0) {
504 ret = write(dest_fd, buf, size);
509 CTS_ERR("write() Failed(%d)", errno);
511 ret = CONTACTS_ERROR_FILE_NO_SPACE; // No space
513 ret = CONTACTS_ERROR_SYSTEM; // IO error
522 ret = fchown(dest_fd, getuid(), CTS_SECURITY_FILE_GROUP);
524 CTS_ERR("fchown() Failed(%d)", ret);
526 ret = fchmod(dest_fd, CTS_SECURITY_IMAGE_PERMISSION);
528 CTS_ERR("fchmod() Failed(%d)", ret);
533 return CONTACTS_ERROR_NONE;
536 int ctsvc_get_next_ver(void)
542 if (0 < transaction_count) {
544 return transaction_ver + 1;
547 query = "SELECT ver FROM "CTS_TABLE_VERSION;
548 ret = ctsvc_query_get_first_int_result(query, &version);
550 // In this case, contacts-service already works abnormally.
551 if (CONTACTS_ERROR_NONE != ret)
552 CTS_ERR("ctsvc_query_get_first_int_result : get version error(%d)", ret);
554 return (1 + version);
557 int ctsvc_get_current_version( int* out_current_version ){
558 if (transaction_count <= 0) {
561 const char *query = "SELECT ver FROM "CTS_TABLE_VERSION;
562 ret = ctsvc_query_get_first_int_result(query, &version);
563 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_query_get_first_int_result() Failed(%d)", ret);
564 *out_current_version = version;
567 *out_current_version = transaction_ver;
568 return CONTACTS_ERROR_NONE;
571 int ctsvc_get_transaction_ver(void)
573 return transaction_ver;
576 int SAFE_SNPRINTF(char **buf, int *buf_size, int len, const char *src)
584 remain = *buf_size - len;
585 if (remain > strlen(src) + 1) {
586 temp_len = snprintf((*buf)+len, remain, "%s", src);
592 temp = realloc(*buf, *buf_size*2);
596 *buf_size = *buf_size * 2;
597 remain = *buf_size - len;
598 if (remain > strlen(src) + 1)
601 temp_len = snprintf((*buf)+len, remain, "%s", src);