[SVACE Issue Fixes]
[platform/core/pim/contacts-service.git] / server / db / ctsvc_db_utils.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19 #include <ctype.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <errno.h>
23 #include <dirent.h>
24 #include <sys/stat.h>
25 #include <sys/vfs.h>
26 #include <image_util.h>
27 #include <unicode/ulocdata.h>
28 #include <unicode/uset.h>
29 #include <unicode/ustring.h>
30 #include <libexif/exif-data.h>
31
32 #include "contacts.h"
33 #include "ctsvc_internal.h"
34 #include "ctsvc_db_utils.h"
35 #include "ctsvc_mutex.h"
36 #include "ctsvc_db_sqlite.h"
37 #include "ctsvc_db_schema.h"
38 #include "ctsvc_notification.h"
39 #include "ctsvc_struct.h"
40 #include "ctsvc_normalize.h"
41 #include "ctsvc_localize.h"
42 #include "ctsvc_localize_utils.h"
43 #include "ctsvc_server_setting.h"
44 #include "ctsvc_notify.h"
45 #include "ctsvc_image_util.h"
46
47 #ifdef _CONTACTS_IPC_SERVER
48 #include "ctsvc_server_change_subject.h"
49 #endif
50
51 static __thread int transaction_count = 0;
52 static __thread int transaction_ver = 0;
53 static __thread bool version_up = false;
54
55 #define CTS_SECURITY_IMAGE_PERMISSION 0440
56 #define CTS_COMMIT_TRY_MAX 500000 /* For 3second */
57
58 int ctsvc_begin_trans(void)
59 {
60         int ret = -1, progress;
61
62         if (transaction_count <= 0) {
63                 ret = ctsvc_query_exec("BEGIN IMMEDIATE TRANSACTION");
64                 progress = 100000;
65                 while (CONTACTS_ERROR_DB == ret && progress < CTS_COMMIT_TRY_MAX) {
66                         usleep(progress);
67                         ret = ctsvc_query_exec("BEGIN IMMEDIATE TRANSACTION");
68                         progress *= 2;
69                 }
70                 if (CONTACTS_ERROR_NONE != ret) {
71                         /* LCOV_EXCL_START */
72                         ERR("ctsvc_query_exec() Fail(%d)", ret);
73                         return ret;
74                         /* LCOV_EXCL_STOP */
75                 }
76
77                 transaction_count = 0;
78
79                 const char *query = "SELECT ver FROM "CTS_TABLE_VERSION;
80                 ret = ctsvc_query_get_first_int_result(query, &transaction_ver);
81                 version_up = false;
82         }
83         transaction_count++;
84         INFO("transaction_count : %d.", transaction_count);
85         return CONTACTS_ERROR_NONE;
86 }
87
88 int ctsvc_end_trans(bool is_success)
89 {
90         int ret = -1, progress;
91         char query[CTS_SQL_MIN_LEN] = {0};
92
93         transaction_count--;
94         INFO("%s, transaction_count : %d", is_success ? "True" : "False",  transaction_count);
95
96         if (0 != transaction_count) {
97                 DBG("contact transaction_count : %d.", transaction_count);
98                 return CONTACTS_ERROR_NONE;
99         }
100
101         if (false == is_success) {
102                 ctsvc_nofitication_cancel();
103                 ctsvc_change_subject_clear_changed_info();
104                 ret = ctsvc_query_exec("ROLLBACK TRANSACTION");
105
106                 return CONTACTS_ERROR_NONE;
107         }
108
109         if (version_up) {
110                 transaction_ver++;
111                 snprintf(query, sizeof(query), "UPDATE %s SET ver = %d",
112                                 CTS_TABLE_VERSION, transaction_ver);
113                 ret = ctsvc_query_exec(query);
114                 if (CONTACTS_ERROR_NONE != ret)
115                         /* LCOV_EXCL_START */
116                         ERR("ctsvc_query_exec(version up) Fail(%d)", ret);
117                 /* LCOV_EXCL_STOP */
118         }
119
120         INFO("start commit");
121         progress = 100000;
122         ret = ctsvc_query_exec("COMMIT TRANSACTION");
123         while (CONTACTS_ERROR_DB == ret && progress < CTS_COMMIT_TRY_MAX) {
124                 usleep(progress);
125                 ret = ctsvc_query_exec("COMMIT TRANSACTION");
126                 progress *= 2;
127         }
128         INFO("%s", (CONTACTS_ERROR_NONE == ret) ? "commit" : "rollback");
129
130         if (CONTACTS_ERROR_NONE != ret) {
131                 /* LCOV_EXCL_START */
132                 int tmp_ret;
133                 ERR("ctsvc_query_exec() Fail(%d)", ret);
134                 ctsvc_nofitication_cancel();
135                 ctsvc_change_subject_clear_changed_info();
136
137                 tmp_ret = ctsvc_query_exec("ROLLBACK TRANSACTION");
138                 if (CONTACTS_ERROR_NONE != tmp_ret)
139                         ERR("ctsvc_query_exec(ROLLBACK) Fail(%d)", tmp_ret);
140
141                 return ret;
142                 /* LCOV_EXCL_STOP */
143         }
144
145         ctsvc_notification_send();
146         ctsvc_change_subject_publish_changed_info();
147
148         DBG("Transaction shut down! : (%d)\n", transaction_ver);
149
150         return CONTACTS_ERROR_NONE;
151 }
152
153 const char* ctsvc_get_display_column(void)
154 {
155         contacts_name_display_order_e order;
156
157         ctsvc_setting_get_name_display_order(&order);
158         if (CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST == order)
159                 return "display_name";
160         else
161                 return "reverse_display_name";
162 }
163
164 const char* ctsvc_get_sort_name_column(void)
165 {
166         contacts_name_sorting_order_e order;
167
168         ctsvc_setting_get_name_sorting_order(&order);
169         if (CONTACTS_NAME_SORTING_ORDER_FIRSTLAST == order)
170                 return "sort_name, display_name_language";
171         else
172                 return "reverse_sort_name, reverse_display_name_language";
173 }
174
175 const char* ctsvc_get_sort_column(void)
176 {
177         contacts_name_sorting_order_e order;
178
179         ctsvc_setting_get_name_sorting_order(&order);
180         if (CONTACTS_NAME_SORTING_ORDER_FIRSTLAST == order)
181                 return "display_name_language, sortkey";
182         else
183                 return "reverse_display_name_language, reverse_sortkey";
184 }
185
186 void ctsvc_utils_make_image_file_name(int parent_id, int id, char *src_img, char *dest,
187                 int dest_size)
188 {
189         char *ext;
190         char *temp;
191         char *lower_ext;
192
193         ext = strrchr(src_img, '.');
194         if (NULL == ext || strchr(ext, '/'))
195                 ext = "";
196
197         lower_ext = strdup(ext);
198         if (NULL == lower_ext) {
199                 /* LCOV_EXCL_START */
200                 ERR("strdup() Fail");
201                 return;
202                 /* LCOV_EXCL_STOP */
203         }
204         temp = lower_ext;
205         while (*temp) {
206                 *temp = tolower(*temp);
207                 temp++;
208         }
209
210         if (0 < parent_id)
211                 snprintf(dest, dest_size, "%d_%d%s", parent_id, id, lower_ext);
212         else
213                 snprintf(dest, dest_size, "%d%s", id, ext);
214         free(lower_ext);
215 }
216
217 static inline bool _ctsvc_check_available_image_space(int need_size)
218 {
219         int ret;
220         struct statfs buf;
221         long long size;
222
223         ret = statfs(CTSVC_IMG_REPERTORY, &buf);
224         RETVM_IF(ret != 0, false, "statfs() Fail(%d)", ret);
225
226         size = (long long)buf.f_bavail * (buf.f_bsize);
227
228         if (need_size < size)  /* if available space to copy a image is larger than need_size */
229                 return true;
230         return false;
231 }
232
233 static image_util_rotation_e _ctsvc_image_get_rotation_info(const char *path)
234 {
235         ExifData *ed = NULL;
236         ExifEntry *entry;
237         image_util_rotation_e rotation = IMAGE_UTIL_ROTATION_NONE;
238         int orientation = 0;
239
240         ed = exif_data_new_from_file(path);
241         if (NULL == ed) {
242                 /* LCOV_EXCL_START */
243                 ERR("exif_data_new_from_file() Fail");
244                 return IMAGE_UTIL_ROTATION_NONE;
245                 /* LCOV_EXCL_STOP */
246         }
247
248         entry = exif_data_get_entry(ed, EXIF_TAG_ORIENTATION);
249         if (entry) {
250                 ExifByteOrder mByteOrder = exif_data_get_byte_order(ed);
251                 orientation = (int)exif_get_short(entry->data, mByteOrder);
252                 if (orientation < 0 || 8 < orientation)
253                         orientation = 0;
254         }
255
256         if (ed)
257                 exif_data_unref(ed);
258
259         switch (orientation) {
260         case 1: /* Top-left */
261                 rotation = IMAGE_UTIL_ROTATION_NONE;
262                 break;
263         case 2: /* Top-right */
264                 rotation = IMAGE_UTIL_ROTATION_FLIP_HORZ;
265                 break;
266         case 3: /* Bottom-right */
267                 rotation = IMAGE_UTIL_ROTATION_180;
268                 break;
269         case 4: /* Bottom-left */
270                 rotation = IMAGE_UTIL_ROTATION_FLIP_VERT;
271                 break;
272         case 6: /* Right-top */
273                 rotation = IMAGE_UTIL_ROTATION_90;
274                 break;
275         case 8: /* Left-bottom */
276                 rotation = IMAGE_UTIL_ROTATION_270;
277                 break;
278         case 5: /* Left-top */
279         case 7: /* Right-bottom */
280         case 0:
281         default:
282                 break;
283         };
284
285         return rotation;
286 }
287
288
289 typedef struct {
290         const char *src;
291         const char *dest;
292         int max_size;
293         int ret;
294 } image_info;
295
296 static bool _ctsvc_image_util_supported_jpeg_colorspace_cb(
297                 image_util_colorspace_e colorspace, void *user_data)
298 {
299         int width = 0;
300         int height = 0;
301         int dest_fd = 0;
302         int mimetype = 0;
303         uint64_t size = 0;
304         unsigned int size_decode = 0;
305         void *buffer = NULL;
306         void *buffer_temp = NULL;
307         int ret;
308         image_util_rotation_e rotation;
309         image_info *info = user_data;
310
311         ret = ctsvc_image_util_get_mimetype(colorspace, &mimetype);
312         if (CONTACTS_ERROR_NONE != ret) {
313                 info->ret = CONTACTS_ERROR_SYSTEM;
314                 return true;
315         }
316
317         image_util_decode_h dh = NULL;
318         do {
319                 unsigned long l_width = 0;
320                 unsigned long l_height = 0;
321                 unsigned long long ll_size_decode = 0;
322
323                 ret = image_util_decode_create(&dh);
324                 if (IMAGE_UTIL_ERROR_NONE != ret)
325                         break;
326                 ret = image_util_decode_set_input_path(dh, info->src);
327                 if (IMAGE_UTIL_ERROR_NONE != ret)
328                         break;
329                 ret = image_util_decode_set_colorspace(dh, colorspace);
330                 if (IMAGE_UTIL_ERROR_NONE != ret)
331                         break;
332                 ret = image_util_decode_set_output_buffer(dh, (unsigned char **)&buffer);
333                 if (IMAGE_UTIL_ERROR_NONE != ret)
334                         break;
335                 ret = image_util_decode_run(dh, &l_width, &l_height, &ll_size_decode);
336                 if (IMAGE_UTIL_ERROR_NONE != ret)
337                         break;
338
339                 width = (int)l_width;
340                 height = (int)l_height;
341                 size_decode = (unsigned int)ll_size_decode;
342         } while (0);
343         if (dh)
344                 ret = image_util_decode_destroy(dh);
345         if (IMAGE_UTIL_ERROR_NONE != ret || 0 == width || 0 == height) {
346                 /* LCOV_EXCL_START */
347                 info->ret = CONTACTS_ERROR_SYSTEM;
348                 return true;
349                 /* LCOV_EXCL_STOP */
350         }
351         size = (uint64_t)size_decode;
352
353         rotation = _ctsvc_image_get_rotation_info(info->src);
354         if (IMAGE_UTIL_ROTATION_NONE != rotation) { /* need rotate */
355                 media_format_h fmt;
356                 media_packet_h packet;
357
358                 fmt = ctsvc_image_util_create_media_format(mimetype, width, height);
359                 if (NULL == fmt) {
360                         /* LCOV_EXCL_START */
361                         ERR("ctsvc_image_util_create_media_format() Fail");
362                         info->ret = CONTACTS_ERROR_SYSTEM;
363                         free(buffer);
364                         return false;
365                         /* LCOV_EXCL_STOP */
366                 }
367
368                 packet = ctsvc_image_util_create_media_packet(fmt, buffer, (unsigned int)size);
369                 free(buffer);
370
371                 if (NULL == packet) {
372                         /* LCOV_EXCL_START */
373                         ERR("ctsvc_image_util_create_media_packet() Fail");
374                         media_format_unref(fmt);
375                         info->ret = CONTACTS_ERROR_SYSTEM;
376                         return false;
377                         /* LCOV_EXCL_STOP */
378                 }
379
380                 ret = ctsvc_image_util_rotate(packet, rotation, &buffer_temp, &size);
381
382                 media_packet_destroy(packet);
383                 media_format_unref(fmt);
384
385                 if (CONTACTS_ERROR_NONE != ret) {
386                         /* LCOV_EXCL_START */
387                         info->ret = CONTACTS_ERROR_SYSTEM;
388                         return false;
389                         /* LCOV_EXCL_STOP */
390                 }
391
392                 if (rotation == IMAGE_UTIL_ROTATION_90 || rotation == IMAGE_UTIL_ROTATION_270) {
393                         int temp = width;
394                         width = height;
395                         height = temp;
396                 }
397                 buffer = buffer_temp;
398         }
399
400         if (info->max_size < width || info->max_size < height) { /* need resize */
401                 int resized_width;
402                 int resized_height;
403                 media_format_h fmt;
404                 media_packet_h packet;
405
406                 /* set resize */
407                 if (width > height) {
408                         resized_width = info->max_size;
409                         resized_height = height * info->max_size / width;
410                 } else {
411                         resized_height = info->max_size;
412                         resized_width = width * info->max_size / height;
413                 }
414
415                 if (resized_height % 8)
416                         resized_height += (8 - (resized_height % 8));
417
418                 if (resized_width % 8)
419                         resized_width += (8 - (resized_width % 8));
420
421                 fmt = ctsvc_image_util_create_media_format(mimetype, width, height);
422                 if (NULL == fmt) {
423                         /* LCOV_EXCL_START */
424                         ERR("ctsvc_image_util_create_media_format() Fail");
425                         info->ret = CONTACTS_ERROR_SYSTEM;
426                         free(buffer);
427                         return false;
428                         /* LCOV_EXCL_STOP */
429                 }
430
431                 packet = ctsvc_image_util_create_media_packet(fmt, buffer, (unsigned int)size);
432                 free(buffer);
433
434                 if (NULL == packet) {
435                         /* LCOV_EXCL_START */
436                         ERR("ctsvc_image_util_create_media_packet() Fail");
437                         media_format_unref(fmt);
438                         info->ret = CONTACTS_ERROR_SYSTEM;
439                         return false;
440                         /* LCOV_EXCL_STOP */
441                 }
442
443                 ret = ctsvc_image_util_resize(packet, resized_width, resized_height, &buffer_temp,
444                                 &size);
445
446                 media_packet_destroy(packet);
447                 media_format_unref(fmt);
448
449                 if (CONTACTS_ERROR_NONE != ret) {
450                         info->ret = -1;
451                         return false;
452                 }
453                 buffer = buffer_temp;
454
455                 width = resized_width;
456                 height = resized_height;
457         }
458
459         image_util_encode_h eh = NULL;
460         do {
461                 unsigned long long ll_size_encode = 0;
462
463                 ret = image_util_encode_create(IMAGE_UTIL_JPEG, &eh);
464                 if (IMAGE_UTIL_ERROR_NONE != ret)
465                         break;
466                 ret = image_util_encode_set_input_buffer(eh, buffer);
467                 if (IMAGE_UTIL_ERROR_NONE != ret)
468                         break;
469                 ret = image_util_encode_set_resolution(eh, width, height);
470                 if (IMAGE_UTIL_ERROR_NONE != ret)
471                         break;
472                 ret = image_util_encode_set_colorspace(eh, colorspace);
473                 if (IMAGE_UTIL_ERROR_NONE != ret)
474                         break;
475                 ret = image_util_encode_set_quality(eh, CTSVC_IMAGE_ENCODE_QUALITY);
476                 if (IMAGE_UTIL_ERROR_NONE != ret)
477                         break;
478                 ret = image_util_encode_set_output_path(eh, info->dest);
479                 if (IMAGE_UTIL_ERROR_NONE != ret)
480                         break;
481                 ret = image_util_encode_run(eh, &ll_size_encode);
482         } while (0);
483         if (eh)
484                 ret = image_util_encode_destroy(eh);
485         free(buffer);
486         if (IMAGE_UTIL_ERROR_NONE != ret) {
487                 /* LCOV_EXCL_START */
488                 ERR("image_util_encode_jpeg Fail(%d)", ret);
489                 info->ret = CONTACTS_ERROR_SYSTEM;
490                 return false;
491                 /* LCOV_EXCL_STOP */
492         }
493
494         dest_fd = open(info->dest, O_RDONLY);
495         if (dest_fd < 0) {
496                 /* LCOV_EXCL_START */
497                 ERR("System : Open Fail(%d)", errno);
498                 info->ret = CONTACTS_ERROR_SYSTEM;
499                 return false;
500                 /* LCOV_EXCL_STOP */
501         }
502
503         ret = fchmod(dest_fd, CTS_SECURITY_IMAGE_PERMISSION);
504         if (0 != ret) {
505                 /* LCOV_EXCL_START */
506                 ERR("fchmod Fail(%d)", errno);
507                 info->ret = CONTACTS_ERROR_SYSTEM;
508                 close(dest_fd);
509                 return false;
510                 /* LCOV_EXCL_STOP */
511         }
512         close(dest_fd);
513
514         info->ret = CONTACTS_ERROR_NONE;
515         return false;
516 }
517
518 static int _ctsvc_image_encode(const char *src, const char *dest, int max_size)
519 {
520         int ret;
521         image_info info = {src, dest, max_size, CONTACTS_ERROR_SYSTEM};
522
523         ret = image_util_foreach_supported_colorspace(IMAGE_UTIL_JPEG,
524                         _ctsvc_image_util_supported_jpeg_colorspace_cb, &info);
525
526         if (IMAGE_UTIL_ERROR_NONE != ret)
527                 return CONTACTS_ERROR_SYSTEM;
528
529         return info.ret;
530 }
531
532 #define CTSVC_COPY_SIZE_MAX 4096
533 int ctsvc_utils_copy_image(const char *dir, const char *src, const char *file)
534 {
535         int ret;
536         int size;
537         int src_fd, dest_fd;
538         char buf[CTSVC_COPY_SIZE_MAX] = {0};
539
540         if (NULL == file || *file == '\0')
541                 return CONTACTS_ERROR_INVALID_PARAMETER;
542
543         char dest[strlen(dir) + strlen(file) + 2];
544         snprintf(dest, sizeof(dest), "%s/%s", dir, file);
545
546         if (false == _ctsvc_check_available_image_space(1204 * 1204)) /*need larger than 1M*/
547                 return CONTACTS_ERROR_FILE_NO_SPACE;
548
549         ret = _ctsvc_image_encode(src, dest, CTSVC_IMAGE_MAX_SIZE);
550         if (CONTACTS_ERROR_NONE == ret)
551                 return ret;
552         else
553                 /* LCOV_EXCL_START */
554                 ERR("_ctsvc_image_encode Fail(%d)", ret);
555         /* LCOV_EXCL_STOP */
556
557         src_fd = open(src, O_RDONLY);
558         if (src_fd < 0) {
559                 /* LCOV_EXCL_START */
560                 ERR("System : Open(%s) Fail(%d)", src, errno);
561                 return CONTACTS_ERROR_SYSTEM;
562                 /* LCOV_EXCL_STOP */
563         }
564
565         dest_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660);
566         if (dest_fd < 0) {
567                 /* LCOV_EXCL_START */
568                 ERR("Open Fail(%d)", errno);
569                 close(src_fd);
570                 return CONTACTS_ERROR_SYSTEM;
571                 /* LCOV_EXCL_STOP */
572         }
573
574         while (0 < (size = read(src_fd, buf, CTSVC_COPY_SIZE_MAX))) {
575                 ret = write(dest_fd, buf, size);
576                 if (ret <= 0) {
577                         if (EINTR == errno) {
578                                 continue;
579                         } else {
580                                 /* LCOV_EXCL_START */
581                                 ERR("write() Fail(%d)", errno);
582                                 if (ENOSPC == errno)
583                                         ret = CONTACTS_ERROR_FILE_NO_SPACE; /* No space */
584                                 else
585                                         ret = CONTACTS_ERROR_SYSTEM; /* IO error */
586                                 close(src_fd);
587                                 close(dest_fd);
588                                 unlink(dest);
589                                 return ret;
590                                 /* LCOV_EXCL_STOP */
591                         }
592                 }
593         }
594
595         ret = fchmod(dest_fd, CTS_SECURITY_IMAGE_PERMISSION);
596         if (0 != ret)
597                 /* LCOV_EXCL_START */
598                 ERR("fchmod() Fail(%d)", ret);
599         /* LCOV_EXCL_STOP */
600
601         close(src_fd);
602         close(dest_fd);
603
604         return CONTACTS_ERROR_NONE;
605 }
606
607 char* ctsvc_utils_get_thumbnail_path(const char *image_path, bool check_file)
608 {
609         int name_len = 0;
610         int full_len = 0;
611         char *thumbnail_path = NULL;
612         char *ext = NULL;
613
614         RETV_IF(NULL == image_path, NULL);
615         RETV_IF(NULL != strstr(image_path, CTSVC_IMAGE_THUMBNAIL_SUFFIX), NULL);
616
617         full_len = strlen(image_path) + strlen(CTSVC_IMAGE_THUMBNAIL_SUFFIX) + 1;
618         thumbnail_path = calloc(1, full_len);
619         if (NULL == thumbnail_path) {
620                 /* LCOV_EXCL_START */
621                 ERR("calloc() Fail");
622                 return NULL;
623                 /* LCOV_EXCL_STOP */
624         }
625
626         ext = strrchr(image_path, '.');
627         if (ext) {
628                 name_len = ext -image_path;
629                 strncpy(thumbnail_path, image_path, name_len);
630                 snprintf(thumbnail_path+name_len, full_len-name_len, "%s%s", CTSVC_IMAGE_THUMBNAIL_SUFFIX, ext);
631         } else {
632                 snprintf(thumbnail_path, full_len, "%s%s", image_path, CTSVC_IMAGE_THUMBNAIL_SUFFIX);
633         }
634
635         if (check_file) {
636                 char full_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
637                 if (NULL != strstr(thumbnail_path, CTSVC_CONTACT_IMG_FULL_LOCATION))
638                         snprintf(full_path, sizeof(full_path), "%s", thumbnail_path);
639                 else
640                         snprintf(full_path, sizeof(full_path), "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, thumbnail_path);
641
642                 if (0 != access(full_path, F_OK)) {
643                         free(thumbnail_path);
644                         /* The original image is used as a thumbnail when the thumbnail is not made */
645                         return strdup(image_path);
646                 }
647         }
648
649         return thumbnail_path;
650 }
651
652 char* ctsvc_utils_get_image_path(const char *thumbnail_path)
653 {
654         int name_len = 0;
655         int full_len = 0;
656         char *image_path = NULL;
657         char *ext = NULL;
658
659         RETV_IF(NULL == thumbnail_path, NULL);
660
661         if (NULL == strstr(thumbnail_path, CTSVC_IMAGE_THUMBNAIL_SUFFIX)) {
662                 /* The original image is used as a thumbnail when the thumbnail is not made */
663                 return strdup(thumbnail_path);
664
665         }
666
667         full_len = strlen(thumbnail_path) - strlen(CTSVC_IMAGE_THUMBNAIL_SUFFIX) + 1;
668         image_path = calloc(1, full_len);
669         if (NULL == image_path) {
670                 /* LCOV_EXCL_START */
671                 ERR("calloc() Fail");
672                 return NULL;
673                 /* LCOV_EXCL_STOP */
674         }
675
676         ext = strrchr(thumbnail_path, '.');
677         if (ext) {
678                 name_len = ext -thumbnail_path - strlen(CTSVC_IMAGE_THUMBNAIL_SUFFIX);
679                 strncpy(image_path, thumbnail_path, name_len);
680                 snprintf(image_path + name_len, full_len -name_len, "%s", ext);
681         } else {
682                 name_len = strlen(thumbnail_path) - strlen(CTSVC_IMAGE_THUMBNAIL_SUFFIX);
683                 strncpy(image_path, thumbnail_path, name_len);
684         }
685         return image_path;
686 }
687
688 char* ctsvc_utils_make_thumbnail(const char *image_path)
689 {
690         int ret;
691         char src[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
692         char dest[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
693         char *thumbnail_path = NULL;
694
695         RETV_IF(NULL == image_path, NULL);
696         RETV_IF(NULL != strstr(image_path, CTSVC_IMAGE_THUMBNAIL_SUFFIX), NULL);
697
698         if (false == _ctsvc_check_available_image_space(
699                                 CTSVC_IMAGE_THUMBNAIL_SIZE * CTSVC_IMAGE_THUMBNAIL_SIZE)) {
700                 /* LCOV_EXCL_START */
701                 ERR("No space to make thumbnail");
702                 return NULL;
703                 /* LCOV_EXCL_STOP */
704         }
705
706         thumbnail_path = ctsvc_utils_get_thumbnail_path(image_path, FALSE);
707         if (NULL == thumbnail_path) {
708                 /* LCOV_EXCL_START */
709                 ERR("ctsvc_image_util_get_thumbnail_path() Fail");
710                 return NULL;
711                 /* LCOV_EXCL_STOP */
712         }
713
714         snprintf(src, sizeof(src), "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, image_path);
715         snprintf(dest, sizeof(dest), "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, thumbnail_path);
716
717         if (0 == access(dest, F_OK)) {
718                 DBG("already exist");
719                 return thumbnail_path;
720         }
721
722         ret = _ctsvc_image_encode(src, dest, CTSVC_IMAGE_THUMBNAIL_SIZE);
723         if (CONTACTS_ERROR_NONE != ret) {
724                 /* LCOV_EXCL_START */
725                 ERR("_ctsvc_image_encode() Fail(%d)", ret);
726                 free(thumbnail_path);
727                 /* The original image is used as a thumbnail when the thumbnail is not made */
728                 return strdup(image_path);
729                 /* LCOV_EXCL_STOP */
730         }
731
732         return thumbnail_path;
733 }
734
735 int ctsvc_get_next_ver(void)
736 {
737         const char *query;
738         int version;
739         int ret;
740
741         if (0 < transaction_count) {
742                 version_up = true;
743                 return transaction_ver + 1;
744         }
745
746         query = "SELECT ver FROM "CTS_TABLE_VERSION;
747         ret = ctsvc_query_get_first_int_result(query, &version);
748
749         /* In this case, contacts-service already works abnormally. */
750         if (CONTACTS_ERROR_NONE != ret)
751                 /* LCOV_EXCL_START */
752                 ERR("ctsvc_query_get_first_int_result : get version error(%d)", ret);
753         /* LCOV_EXCL_STOP */
754
755         return (1 + version);
756 }
757
758 int ctsvc_get_current_version(int *out_current_version)
759 {
760         if (transaction_count <= 0) {
761                 int ret;
762                 int version = 0;
763                 const char *query = "SELECT ver FROM "CTS_TABLE_VERSION;
764
765                 ret = ctsvc_query_get_first_int_result(query, &version);
766                 if (CONTACTS_ERROR_NONE != ret) {
767                         /* LCOV_EXCL_START */
768                         ERR("ctsvc_query_get_first_int_result() Fail(%d)", ret);
769                         return ret;
770                         /* LCOV_EXCL_STOP */
771                 }
772
773                 *out_current_version = version;
774         } else {
775                 *out_current_version = transaction_ver;
776         }
777         return CONTACTS_ERROR_NONE;
778 }
779
780 int ctsvc_get_transaction_ver(void)
781 {
782         return transaction_ver;
783 }
784
785 int SAFE_SNPRINTF(char **buf, int *buf_size, int len, const char *src)
786 {
787         int remain;
788         int temp_len;
789
790         if (len < 0)
791                 return -1;
792
793         remain = *buf_size - len;
794         if (strlen(src) + 1 < remain) {
795                 temp_len = snprintf((*buf)+len, remain, "%s", src);
796                 return temp_len;
797         } else {
798                 char *temp;
799                 while (1) {
800                         temp = realloc(*buf, *buf_size*2);
801                         if (NULL == temp)
802                                 return -1;
803                         *buf = temp;
804                         *buf_size = *buf_size * 2;
805                         remain = *buf_size - len;
806                         if (strlen(src) + 1 < remain)
807                                 break;
808                 }
809                 temp_len = snprintf((*buf)+len, remain, "%s", src);
810                 return temp_len;
811         }
812 }
813