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 if (transaction_count <= 0) {
66 ret = ctsvc_query_exec("BEGIN IMMEDIATE TRANSACTION");
68 while (CONTACTS_ERROR_DB == ret && progress < CTS_COMMIT_TRY_MAX) {
70 ret = ctsvc_query_exec("BEGIN IMMEDIATE TRANSACTION");
73 if(CONTACTS_ERROR_NONE != ret) {
74 CTS_ERR("ctsvc_query_exec() Failed(%d)", ret);
78 transaction_count = 0;
80 const char *query = "SELECT ver FROM "CTS_TABLE_VERSION;
81 ret = ctsvc_query_get_first_int_result(query, &transaction_ver);
85 INFO("transaction_count : %d.", transaction_count);
86 return CONTACTS_ERROR_NONE;
89 int ctsvc_end_trans(bool is_success)
91 int ret = -1, progress;
92 char query[CTS_SQL_MIN_LEN] = {0};
95 INFO("%s, transaction_count : %d", is_success?"True": "False", transaction_count);
97 if (0 != transaction_count) {
98 CTS_DBG("contact transaction_count : %d.", transaction_count);
99 return CONTACTS_ERROR_NONE;
102 if (false == is_success) {
103 ctsvc_nofitication_cancel();
104 #ifdef _CONTACTS_IPC_SERVER
105 ctsvc_change_subject_clear_changed_info();
107 ret = ctsvc_query_exec("ROLLBACK TRANSACTION");
109 return CONTACTS_ERROR_NONE;
114 snprintf(query, sizeof(query), "UPDATE %s SET ver = %d",
115 CTS_TABLE_VERSION, transaction_ver);
116 ret = ctsvc_query_exec(query);
117 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_query_exec(version up) Failed(%d)", ret);
120 INFO("start commit");
122 ret = ctsvc_query_exec("COMMIT TRANSACTION");
123 while (CONTACTS_ERROR_DB == ret && progress<CTS_COMMIT_TRY_MAX) {
125 ret = ctsvc_query_exec("COMMIT TRANSACTION");
128 INFO("%s", (CONTACTS_ERROR_NONE == ret)?"commit": "rollback");
130 if (CONTACTS_ERROR_NONE != ret) {
132 CTS_ERR("ctsvc_query_exec() Failed(%d)", ret);
133 ctsvc_nofitication_cancel();
134 #ifdef _CONTACTS_IPC_SERVER
135 ctsvc_change_subject_clear_changed_info();
137 tmp_ret = ctsvc_query_exec("ROLLBACK TRANSACTION");
138 WARN_IF(CONTACTS_ERROR_NONE != tmp_ret, "ctsvc_query_exec(ROLLBACK) Failed(%d)", tmp_ret);
142 ctsvc_notification_send();
143 #ifdef _CONTACTS_IPC_SERVER
144 ctsvc_change_subject_publish_changed_info();
147 CTS_DBG("Transaction shut down! : (%d)\n", transaction_ver);
149 return CONTACTS_ERROR_NONE;
152 const char* ctsvc_get_display_column(void)
154 contacts_name_display_order_e order;
156 contacts_setting_get_name_display_order(&order);
157 if (CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST == order)
158 return "display_name";
160 return "reverse_display_name";
163 const char* ctsvc_get_sort_name_column(void)
165 contacts_name_sorting_order_e order;
167 contacts_setting_get_name_sorting_order(&order);
168 if (CONTACTS_NAME_SORTING_ORDER_FIRSTLAST == order)
169 return "sort_name, display_name_language";
171 return "reverse_sort_name, reverse_display_name_language";
174 const char* ctsvc_get_sort_column(void)
176 contacts_name_sorting_order_e order;
178 contacts_setting_get_name_sorting_order(&order);
179 if (CONTACTS_NAME_SORTING_ORDER_FIRSTLAST == order)
180 return "display_name_language, sortkey";
182 return "reverse_display_name_language, reverse_sortkey";
185 void ctsvc_utils_make_image_file_name(int parent_id, int id, char *src_img, char *dest, int dest_size)
191 ext = strrchr(src_img, '.');
192 if (NULL == ext || strchr(ext, '/'))
195 lower_ext = strdup(ext);
198 *temp = tolower(*temp);
203 snprintf(dest, dest_size, "%d_%d%s", parent_id, id, lower_ext);
205 snprintf(dest, dest_size, "%d%s", id, ext);
209 static inline bool ctsvc_check_available_image_space(void){
213 ret = statfs(CTSVC_NOTI_IMG_REPERTORY, &buf);
215 RETVM_IF(ret!=0, false, "statfs Failed(%d)", ret);
217 size = (long long)buf.f_bavail * (buf.f_bsize);
219 if (size > 1024*1024) // if available space to copy a image is larger than 1M
224 static image_util_rotation_e __ctsvc_get_rotation_info(const char *path)
228 image_util_rotation_e rotation = IMAGE_UTIL_ROTATION_NONE;
231 ed = exif_data_new_from_file(path);
233 CTS_ERR("exif_data_new_from_file : ExifData is NULL");
234 return IMAGE_UTIL_ROTATION_NONE;
237 entry = exif_data_get_entry(ed, EXIF_TAG_ORIENTATION);
239 ExifByteOrder mByteOrder = exif_data_get_byte_order(ed);
240 orientation = (int)exif_get_short(entry->data, mByteOrder);
241 if (orientation < 0 || orientation > 8)
248 switch(orientation) {
250 rotation = IMAGE_UTIL_ROTATION_NONE;
253 rotation = IMAGE_UTIL_ROTATION_FLIP_HORZ;
255 case 3: // Bottom-right
256 rotation = IMAGE_UTIL_ROTATION_180;
258 case 4: // Bottom-left
259 rotation = IMAGE_UTIL_ROTATION_FLIP_VERT;
262 rotation = IMAGE_UTIL_ROTATION_90;
264 case 8: // Left-bottom
265 rotation = IMAGE_UTIL_ROTATION_270;
268 case 7: // Right-bottom
277 static int image_size = 480;
285 static bool __ctsvc_image_util_supported_jpeg_colorspace_cb(image_util_colorspace_e colorspace, void *user_data)
287 image_info *info = (image_info*)user_data;
288 image_util_error_e ret;
289 int width = 0, height = 0;
290 unsigned int size_decode = 0;
291 int resized_width, resized_height;
292 unsigned char * img_target = 0;
293 unsigned char * img_source = 0;
295 image_util_rotation_e rotation;
298 if (colorspace == IMAGE_UTIL_COLORSPACE_YV12 || colorspace == IMAGE_UTIL_COLORSPACE_I420) {
299 info->ret = CONTACTS_ERROR_SYSTEM;
303 rotation = __ctsvc_get_rotation_info(info->src);
305 // load jpeg sample file
306 CTS_DBG("colorspace %d src : %s, dest : %s", colorspace, info->src, info->dest);
307 ret = image_util_decode_jpeg( info->src, colorspace, &img_source, &width, &height, &size_decode );
308 if (ret!=IMAGE_UTIL_ERROR_NONE) {
309 info->ret = CONTACTS_ERROR_SYSTEM;
316 ecore_x_window_size_get(
317 ecore_x_window_root_get(ecore_x_window_focus_get())
328 if (width > image_size || height > image_size) {
330 if (image_size<=0 || width <=0 || height <= 0) {
332 CTS_ERR("image size error(%d)", image_size);
333 info->ret = CONTACTS_ERROR_SYSTEM;
338 resized_width = image_size;
339 resized_height = height*image_size/width;
342 resized_height = image_size;
343 resized_width = width*image_size/height;
346 if (resized_height%8)
347 resized_height += 8 - (resized_height%8);
349 resized_width += 8 - (resized_width%8);
351 CTS_DBG("size(%d, %d) -> resize(%d,%d)", width, height, resized_width, resized_height);
353 image_util_calculate_buffer_size(resized_width, resized_height, colorspace , &size_decode);
355 img_target = malloc( size_decode );
358 ret = image_util_resize( img_target, &resized_width, &resized_height,
359 img_source, width, height, colorspace );
360 if (ret!=IMAGE_UTIL_ERROR_NONE) {
361 CTS_ERR("image_util_resize failed(%d)", ret);
364 info->ret = CONTACTS_ERROR_SYSTEM;
370 resized_width = width;
371 resized_height = height;
372 img_target = img_source;
376 if (IMAGE_UTIL_ROTATION_NONE != rotation) {
377 int rotated_width, rotated_height;
378 unsigned char *img_rotate = 0;
379 img_rotate = malloc( size_decode );
380 ret= image_util_rotate(img_rotate, &rotated_width, &rotated_height,
381 rotation, img_target, resized_width, resized_height, colorspace);
383 if (IMAGE_UTIL_ERROR_NONE != ret) {
384 CTS_ERR("image_util_rotate failed(%d)", ret);
385 info->ret = CONTACTS_ERROR_SYSTEM;
389 resized_width = rotated_width;
390 resized_height = rotated_height;
391 img_target = img_rotate;
395 ret = image_util_encode_jpeg(img_target, resized_width, resized_height, colorspace, CTS_IMAGE_ENCODE_QUALITY, info->dest );
397 if(ret != IMAGE_UTIL_ERROR_NONE) {
398 CTS_ERR("image_util_encode_jpeg failed(%d)", ret);
399 info->ret = CONTACTS_ERROR_SYSTEM;
403 dest_fd = open(info->dest, O_RDONLY);
405 CTS_ERR("System : Open Failed(%d)", errno);
406 info->ret = CONTACTS_ERROR_SYSTEM;
410 ret = fchown(dest_fd, getuid(), CTS_SECURITY_FILE_GROUP);
412 CTS_ERR("fchown Failed(%d)", errno);
413 info->ret = CONTACTS_ERROR_SYSTEM;
418 ret = fchmod(dest_fd, CTS_SECURITY_IMAGE_PERMISSION);
420 CTS_ERR("fchmod Failed(%d)", errno);
421 info->ret = CONTACTS_ERROR_SYSTEM;
427 info->ret = CONTACTS_ERROR_NONE;
431 static int __ctsvc_resize_and_copy_image(const char *src, const char *dest)
434 image_info info = {.src = src, .dest = dest, ret = CONTACTS_ERROR_SYSTEM};
436 ret = image_util_foreach_supported_jpeg_colorspace(__ctsvc_image_util_supported_jpeg_colorspace_cb, &info);
438 if (ret != IMAGE_UTIL_ERROR_NONE)
439 return CONTACTS_ERROR_SYSTEM;
444 #define CTSVC_COPY_SIZE_MAX 4096
445 int ctsvc_utils_copy_image(const char *dir, const char *src, const char *file)
450 char buf[CTSVC_COPY_SIZE_MAX] = {0};
452 if (NULL == file || *file == '\0')
453 return CONTACTS_ERROR_INVALID_PARAMETER;
455 char dest[strlen(dir) + strlen(file) + 2];
456 snprintf(dest, sizeof(dest), "%s/%s", dir, file);
458 if (!ctsvc_check_available_image_space())
459 return CONTACTS_ERROR_FILE_NO_SPACE;
461 ret = __ctsvc_resize_and_copy_image(src, dest);
462 if (CONTACTS_ERROR_NONE == ret) {
466 CTS_ERR("__ctsvc_resize_and_copy_image Failed(%d)", ret);
468 src_fd = open(src, O_RDONLY);
469 RETVM_IF(src_fd < 0, CONTACTS_ERROR_SYSTEM, "System : Open(src:%s) Failed(%d)", src, errno);
470 dest_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660);
472 CTS_ERR("Open Failed(%d)", errno);
474 return CONTACTS_ERROR_SYSTEM;
477 while ((size = read(src_fd, buf, CTSVC_COPY_SIZE_MAX)) > 0) {
478 ret = write(dest_fd, buf, size);
483 CTS_ERR("write() Failed(%d)", errno);
485 ret = CONTACTS_ERROR_FILE_NO_SPACE; // No space
487 ret = CONTACTS_ERROR_SYSTEM; // IO error
496 ret = fchown(dest_fd, getuid(), CTS_SECURITY_FILE_GROUP);
498 CTS_ERR("fchown() Failed(%d)", ret);
500 ret = fchmod(dest_fd, CTS_SECURITY_IMAGE_PERMISSION);
502 CTS_ERR("fchmod() Failed(%d)", ret);
507 return CONTACTS_ERROR_NONE;
510 int ctsvc_get_next_ver(void)
516 if (0 < transaction_count) {
518 return transaction_ver + 1;
521 query = "SELECT ver FROM "CTS_TABLE_VERSION;
522 ret = ctsvc_query_get_first_int_result(query, &version);
524 // In this case, contacts-service already works abnormally.
525 if (CONTACTS_ERROR_NONE != ret)
526 CTS_ERR("ctsvc_query_get_first_int_result : get version error(%d)", ret);
528 return (1 + version);
531 int ctsvc_get_current_version( int* out_current_version ){
532 if (transaction_count <= 0) {
535 const char *query = "SELECT ver FROM "CTS_TABLE_VERSION;
536 ret = ctsvc_query_get_first_int_result(query, &version);
537 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_query_get_first_int_result() Failed(%d)", ret);
538 *out_current_version = version;
541 *out_current_version = transaction_ver;
542 return CONTACTS_ERROR_NONE;
545 int ctsvc_get_transaction_ver(void)
547 return transaction_ver;
550 int SAFE_SNPRINTF(char **buf, int *buf_size, int len, const char *src)
558 remain = *buf_size - len;
559 if (remain > strlen(src) + 1) {
560 temp_len = snprintf((*buf)+len, remain, "%s", src);
566 temp = realloc(*buf, *buf_size*2);
570 *buf_size = *buf_size * 2;
571 remain = *buf_size - len;
572 if (remain > strlen(src) + 1)
575 temp_len = snprintf((*buf)+len, remain, "%s", src);