3e48723d54c0eb6e9a1e0c6c0bb84d69b56fa9bf
[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         void *buffer = NULL;
305         void *buffer_temp = NULL;
306         int ret;
307         image_util_rotation_e rotation;
308         image_info *info = user_data;
309
310         ret = ctsvc_image_util_get_mimetype(colorspace, &mimetype);
311         if (CONTACTS_ERROR_NONE != ret) {
312                 info->ret = CONTACTS_ERROR_SYSTEM;
313                 return true;
314         }
315
316         ret = image_util_decode_jpeg(info->src, colorspace, (unsigned char **)&buffer,
317                         &width, &height, (unsigned int *)&size);
318         if (IMAGE_UTIL_ERROR_NONE != ret) {
319                 info->ret = CONTACTS_ERROR_SYSTEM;
320                 return true;
321         }
322
323         rotation = _ctsvc_image_get_rotation_info(info->src);
324         if (IMAGE_UTIL_ROTATION_NONE != rotation) { /* need rotate */
325                 media_format_h fmt;
326                 media_packet_h packet;
327
328                 fmt = ctsvc_image_util_create_media_format(mimetype, width, height);
329                 if (NULL == fmt) {
330                         /* LCOV_EXCL_START */
331                         ERR("ctsvc_image_util_create_media_format() Fail");
332                         info->ret = CONTACTS_ERROR_SYSTEM;
333                         free(buffer);
334                         return false;
335                         /* LCOV_EXCL_STOP */
336                 }
337
338                 packet = ctsvc_image_util_create_media_packet(fmt, buffer, (unsigned int)size);
339                 free(buffer);
340
341                 if (NULL == packet) {
342                         /* LCOV_EXCL_START */
343                         ERR("ctsvc_image_util_create_media_packet() Fail");
344                         media_format_unref(fmt);
345                         info->ret = CONTACTS_ERROR_SYSTEM;
346                         return false;
347                         /* LCOV_EXCL_STOP */
348                 }
349
350                 ret = ctsvc_image_util_rotate(packet, rotation, &buffer_temp, &size);
351
352                 media_packet_destroy(packet);
353                 media_format_unref(fmt);
354
355                 if (CONTACTS_ERROR_NONE != ret) {
356                         /* LCOV_EXCL_START */
357                         info->ret = CONTACTS_ERROR_SYSTEM;
358                         return false;
359                         /* LCOV_EXCL_STOP */
360                 }
361
362                 if (rotation == IMAGE_UTIL_ROTATION_90 || rotation == IMAGE_UTIL_ROTATION_270) {
363                         int temp = width;
364                         width = height;
365                         height = temp;
366                 }
367                 buffer = buffer_temp;
368         }
369
370         if (info->max_size < width || info->max_size < height) { /* need resize */
371                 int resized_width;
372                 int resized_height;
373                 media_format_h fmt;
374                 media_packet_h packet;
375
376                 /* set resize */
377                 if (width > height) {
378                         resized_width = info->max_size;
379                         resized_height = height * info->max_size / width;
380                 } else {
381                         resized_height = info->max_size;
382                         resized_width = width * info->max_size / height;
383                 }
384
385                 if (resized_height % 8)
386                         resized_height += (8 - (resized_height % 8));
387
388                 if (resized_width % 8)
389                         resized_width += (8 - (resized_width % 8));
390
391                 fmt = ctsvc_image_util_create_media_format(mimetype, width, height);
392                 if (NULL == fmt) {
393                         /* LCOV_EXCL_START */
394                         ERR("ctsvc_image_util_create_media_format() Fail");
395                         info->ret = CONTACTS_ERROR_SYSTEM;
396                         free(buffer);
397                         return false;
398                         /* LCOV_EXCL_STOP */
399                 }
400
401                 packet = ctsvc_image_util_create_media_packet(fmt, buffer, (unsigned int)size);
402                 free(buffer);
403
404                 if (NULL == packet) {
405                         /* LCOV_EXCL_START */
406                         ERR("ctsvc_image_util_create_media_packet() Fail");
407                         media_format_unref(fmt);
408                         info->ret = CONTACTS_ERROR_SYSTEM;
409                         return false;
410                         /* LCOV_EXCL_STOP */
411                 }
412
413                 ret = ctsvc_image_util_resize(packet, resized_width, resized_height, &buffer_temp,
414                                 &size);
415
416                 media_packet_destroy(packet);
417                 media_format_unref(fmt);
418
419                 if (CONTACTS_ERROR_NONE != ret) {
420                         info->ret = -1;
421                         return false;
422                 }
423                 buffer = buffer_temp;
424
425                 width = resized_width;
426                 height = resized_height;
427         }
428
429         ret = image_util_encode_jpeg(buffer, width, height, colorspace,
430                         CTSVC_IMAGE_ENCODE_QUALITY, info->dest);
431         free(buffer);
432         if (IMAGE_UTIL_ERROR_NONE != ret) {
433                 /* LCOV_EXCL_START */
434                 ERR("image_util_encode_jpeg Fail(%d)", ret);
435                 info->ret = CONTACTS_ERROR_SYSTEM;
436                 return false;
437                 /* LCOV_EXCL_STOP */
438         }
439
440         dest_fd = open(info->dest, O_RDONLY);
441         if (dest_fd < 0) {
442                 /* LCOV_EXCL_START */
443                 ERR("System : Open Fail(%d)", errno);
444                 info->ret = CONTACTS_ERROR_SYSTEM;
445                 return false;
446                 /* LCOV_EXCL_STOP */
447         }
448
449         ret = fchmod(dest_fd, CTS_SECURITY_IMAGE_PERMISSION);
450         if (0 != ret) {
451                 /* LCOV_EXCL_START */
452                 ERR("fchmod Fail(%d)", errno);
453                 info->ret = CONTACTS_ERROR_SYSTEM;
454                 close(dest_fd);
455                 return false;
456                 /* LCOV_EXCL_STOP */
457         }
458         close(dest_fd);
459
460         info->ret = CONTACTS_ERROR_NONE;
461         return false;
462 }
463
464 static int _ctsvc_image_encode(const char *src, const char *dest, int max_size)
465 {
466         int ret;
467         image_info info = {src, dest, max_size, CONTACTS_ERROR_SYSTEM};
468
469         ret = image_util_foreach_supported_jpeg_colorspace(
470                         _ctsvc_image_util_supported_jpeg_colorspace_cb, &info);
471
472         if (IMAGE_UTIL_ERROR_NONE != ret)
473                 return CONTACTS_ERROR_SYSTEM;
474
475         return info.ret;
476 }
477
478 #define CTSVC_COPY_SIZE_MAX 4096
479 int ctsvc_utils_copy_image(const char *dir, const char *src, const char *file)
480 {
481         int ret;
482         int size;
483         int src_fd, dest_fd;
484         char buf[CTSVC_COPY_SIZE_MAX] = {0};
485
486         if (NULL == file || *file == '\0')
487                 return CONTACTS_ERROR_INVALID_PARAMETER;
488
489         char dest[strlen(dir) + strlen(file) + 2];
490         snprintf(dest, sizeof(dest), "%s/%s", dir, file);
491
492         if (false == _ctsvc_check_available_image_space(1204 * 1204)) /*need larger than 1M*/
493                 return CONTACTS_ERROR_FILE_NO_SPACE;
494
495         ret = _ctsvc_image_encode(src, dest, CTSVC_IMAGE_MAX_SIZE);
496         if (CONTACTS_ERROR_NONE == ret)
497                 return ret;
498         else
499                 /* LCOV_EXCL_START */
500                 ERR("_ctsvc_image_encode Fail(%d)", ret);
501         /* LCOV_EXCL_STOP */
502
503         src_fd = open(src, O_RDONLY);
504         if (src_fd < 0) {
505                 /* LCOV_EXCL_START */
506                 ERR("System : Open(%s) Fail(%d)", src, errno);
507                 return CONTACTS_ERROR_SYSTEM;
508                 /* LCOV_EXCL_STOP */
509         }
510
511         dest_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660);
512         if (dest_fd < 0) {
513                 /* LCOV_EXCL_START */
514                 ERR("Open Fail(%d)", errno);
515                 close(src_fd);
516                 return CONTACTS_ERROR_SYSTEM;
517                 /* LCOV_EXCL_STOP */
518         }
519
520         while (0 < (size = read(src_fd, buf, CTSVC_COPY_SIZE_MAX))) {
521                 ret = write(dest_fd, buf, size);
522                 if (ret <= 0) {
523                         if (EINTR == errno) {
524                                 continue;
525                         } else {
526                                 /* LCOV_EXCL_START */
527                                 ERR("write() Fail(%d)", errno);
528                                 if (ENOSPC == errno)
529                                         ret = CONTACTS_ERROR_FILE_NO_SPACE; /* No space */
530                                 else
531                                         ret = CONTACTS_ERROR_SYSTEM; /* IO error */
532                                 close(src_fd);
533                                 close(dest_fd);
534                                 unlink(dest);
535                                 return ret;
536                                 /* LCOV_EXCL_STOP */
537                         }
538                 }
539         }
540
541         ret = fchmod(dest_fd, CTS_SECURITY_IMAGE_PERMISSION);
542         if (0 != ret)
543                 /* LCOV_EXCL_START */
544                 ERR("fchmod() Fail(%d)", ret);
545         /* LCOV_EXCL_STOP */
546
547         close(src_fd);
548         close(dest_fd);
549
550         return CONTACTS_ERROR_NONE;
551 }
552
553 char* ctsvc_utils_get_thumbnail_path(const char *image_path)
554 {
555         int name_len = 0;
556         int full_len = 0;
557         char *thumbnail_path = NULL;
558         char *ext = NULL;
559
560         RETV_IF(NULL == image_path, NULL);
561         RETV_IF(NULL != strstr(image_path, CTSVC_IMAGE_THUMBNAIL_SUFFIX), NULL);
562
563         full_len = strlen(image_path) + strlen(CTSVC_IMAGE_THUMBNAIL_SUFFIX) + 1;
564         thumbnail_path = calloc(1, full_len);
565         if (NULL == thumbnail_path) {
566                 /* LCOV_EXCL_START */
567                 ERR("calloc() Fail");
568                 return NULL;
569                 /* LCOV_EXCL_STOP */
570         }
571
572         ext = strrchr(image_path, '.');
573         if (ext) {
574                 name_len = ext -image_path;
575                 strncpy(thumbnail_path, image_path, name_len);
576                 snprintf(thumbnail_path+name_len, full_len-name_len, "%s%s", CTSVC_IMAGE_THUMBNAIL_SUFFIX, ext);
577         } else {
578                 snprintf(thumbnail_path, full_len, "%s%s", image_path, CTSVC_IMAGE_THUMBNAIL_SUFFIX);
579         }
580
581         return thumbnail_path;
582 }
583
584 char* ctsvc_utils_get_image_path(const char *thumbnail_path)
585 {
586         int name_len = 0;
587         int full_len = 0;
588         char *image_path = NULL;
589         char *ext = NULL;
590
591         RETV_IF(NULL == thumbnail_path, NULL);
592         RETV_IF(NULL == strstr(thumbnail_path, CTSVC_IMAGE_THUMBNAIL_SUFFIX), NULL);
593
594         full_len = strlen(thumbnail_path) - strlen(CTSVC_IMAGE_THUMBNAIL_SUFFIX) + 1;
595         image_path = calloc(1, full_len);
596         if (NULL == image_path) {
597                 /* LCOV_EXCL_START */
598                 ERR("calloc() Fail");
599                 return NULL;
600                 /* LCOV_EXCL_STOP */
601         }
602
603         ext = strrchr(thumbnail_path, '.');
604         if (ext) {
605                 name_len = ext -thumbnail_path - strlen(CTSVC_IMAGE_THUMBNAIL_SUFFIX);
606                 strncpy(image_path, thumbnail_path, name_len);
607                 snprintf(image_path + name_len, full_len -name_len, "%s", ext);
608         } else {
609                 name_len = strlen(thumbnail_path) - strlen(CTSVC_IMAGE_THUMBNAIL_SUFFIX);
610                 strncpy(image_path, thumbnail_path, name_len);
611         }
612         return image_path;
613 }
614
615 char* ctsvc_utils_make_thumbnail(const char *image_path)
616 {
617         int ret;
618         char src[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
619         char dest[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
620         char *thumbnail_path = NULL;
621
622         RETV_IF(NULL == image_path, NULL);
623         RETV_IF(NULL != strstr(image_path, CTSVC_IMAGE_THUMBNAIL_SUFFIX), NULL);
624
625         if (false == _ctsvc_check_available_image_space(
626                                 CTSVC_IMAGE_THUMBNAIL_SIZE * CTSVC_IMAGE_THUMBNAIL_SIZE)) {
627                 /* LCOV_EXCL_START */
628                 ERR("No space to make thumbnail");
629                 return NULL;
630                 /* LCOV_EXCL_STOP */
631         }
632
633         thumbnail_path = ctsvc_utils_get_thumbnail_path(image_path);
634         if (NULL == thumbnail_path) {
635                 /* LCOV_EXCL_START */
636                 ERR("ctsvc_image_util_get_thumbnail_path() Fail");
637                 return NULL;
638                 /* LCOV_EXCL_STOP */
639         }
640
641         snprintf(src, sizeof(src), "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, image_path);
642         snprintf(dest, sizeof(dest), "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, thumbnail_path);
643
644         if (0 == access(dest, F_OK)) {
645                 DBG("already exist");
646                 return thumbnail_path;
647         }
648
649         ret = _ctsvc_image_encode(src, dest, CTSVC_IMAGE_THUMBNAIL_SIZE);
650         if (CONTACTS_ERROR_NONE != ret) {
651                 /* LCOV_EXCL_START */
652                 ERR("_ctsvc_image_encode() Fail(%d)", ret);
653                 free(thumbnail_path);
654                 return NULL;
655                 /* LCOV_EXCL_STOP */
656         }
657
658         return strdup(thumbnail_path);
659 }
660
661 int ctsvc_get_next_ver(void)
662 {
663         const char *query;
664         int version;
665         int ret;
666
667         if (0 < transaction_count) {
668                 version_up = true;
669                 return transaction_ver + 1;
670         }
671
672         query = "SELECT ver FROM "CTS_TABLE_VERSION;
673         ret = ctsvc_query_get_first_int_result(query, &version);
674
675         /* In this case, contacts-service already works abnormally. */
676         if (CONTACTS_ERROR_NONE != ret)
677                 /* LCOV_EXCL_START */
678                 ERR("ctsvc_query_get_first_int_result : get version error(%d)", ret);
679         /* LCOV_EXCL_STOP */
680
681         return (1 + version);
682 }
683
684 int ctsvc_get_current_version(int *out_current_version)
685 {
686         if (transaction_count <= 0) {
687                 int ret;
688                 int version = 0;
689                 const char *query = "SELECT ver FROM "CTS_TABLE_VERSION;
690
691                 ret = ctsvc_query_get_first_int_result(query, &version);
692                 if (CONTACTS_ERROR_NONE != ret) {
693                         /* LCOV_EXCL_START */
694                         ERR("ctsvc_query_get_first_int_result() Fail(%d)", ret);
695                         return ret;
696                         /* LCOV_EXCL_STOP */
697                 }
698
699                 *out_current_version = version;
700         } else {
701                 *out_current_version = transaction_ver;
702         }
703         return CONTACTS_ERROR_NONE;
704 }
705
706 int ctsvc_get_transaction_ver(void)
707 {
708         return transaction_ver;
709 }
710
711 int SAFE_SNPRINTF(char **buf, int *buf_size, int len, const char *src)
712 {
713         int remain;
714         int temp_len;
715
716         if (len < 0)
717                 return -1;
718
719         remain = *buf_size - len;
720         if (strlen(src) + 1 < remain) {
721                 temp_len = snprintf((*buf)+len, remain, "%s", src);
722                 return temp_len;
723         } else {
724                 char *temp;
725                 while (1) {
726                         temp = realloc(*buf, *buf_size*2);
727                         if (NULL == temp)
728                                 return -1;
729                         *buf = temp;
730                         *buf_size = *buf_size * 2;
731                         remain = *buf_size - len;
732                         if (strlen(src) + 1 < remain)
733                                 break;
734                 }
735                 temp_len = snprintf((*buf)+len, remain, "%s", src);
736                 return temp_len;
737         }
738 }
739