summaryrefslogtreecommitdiff
path: root/src/cts-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cts-utils.c')
-rwxr-xr-xsrc/cts-utils.c929
1 files changed, 929 insertions, 0 deletions
diff --git a/src/cts-utils.c b/src/cts-utils.c
new file mode 100755
index 0000000..8bec57c
--- /dev/null
+++ b/src/cts-utils.c
@@ -0,0 +1,929 @@
+/*
+ * Contacts Service
+ *
+ * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Youngjae Shin <yj99.shin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <sys/time.h>
+#include <vconf.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+
+#include "cts-internal.h"
+#include "cts-utils.h"
+#include "cts-schema.h"
+#include "cts-sqlite.h"
+#include "cts-socket.h"
+#include "cts-normalize.h"
+#include "cts-inotify.h"
+#include "cts-vcard.h"
+#include "cts-pthread.h"
+#include "cts-types.h"
+
+static const char *CTS_NOTI_CONTACT_CHANGED=CTS_NOTI_CONTACT_CHANGED_DEF;
+static const char *CTS_NOTI_PLOG_CHANGED="/opt/data/contacts-svc/.CONTACTS_SVC_PLOG_CHANGED";
+static const char *CTS_NOTI_FAVORITE_CHANGED="/opt/data/contacts-svc/.CONTACTS_SVC_FAVOR_CHANGED";
+static const char *CTS_NOTI_SPEEDDIAL_CHANGED="/opt/data/contacts-svc/.CONTACTS_SVC_SPEED_CHANGED";
+static const char *CTS_NOTI_ADDRBOOK_CHANGED="/opt/data/contacts-svc/.CONTACTS_SVC_AB_CHANGED";
+static const char *CTS_NOTI_GROUP_CHANGED="/opt/data/contacts-svc/.CONTACTS_SVC_GROUP_CHANGED";
+static const char *CTS_NOTI_GROUP_RELATION_CHANGED="/opt/data/contacts-svc/.CONTACTS_SVC_GROUP_REL_CHANGED";
+static const char *CTS_NOTI_MISSED_CALL_CHANGED="/opt/data/contacts-svc/.CONTACTS_SVC_MISSED_CHANGED";
+
+static const char *CTS_VCONF_SORTING_ORDER="db/service/contacts/name_sorting_order";
+static const char *CTS_VCONF_DISPLAY_ORDER=CTS_VCONF_DISPLAY_ORDER_DEF;
+
+static int transaction_count = 0;
+static int transaction_ver = 0;
+static bool version_up=false;
+
+static bool contact_change=false;
+static bool plog_change=false;
+static bool missed_change=false;
+static bool favor_change=false;
+static bool speed_change=false;
+static bool addrbook_change=false;
+static bool group_change=false;
+static bool group_rel_change=false;
+
+static int name_sorting_order = -1;
+static int name_display_order = -1;
+static int default_lang = -1;
+
+static void cts_vconf_callback(keynode_t *key, void *data)
+{
+ //if(!strcmp(vconf_keynode_get_name(key), CTS_VCONF_SORTING_ORDER));
+ if (CTS_ORDER_OF_SORTING == (int)data)
+ name_sorting_order = vconf_keynode_get_int(key);
+ else if (CTS_ORDER_OF_DISPLAY == (int)data)
+ name_display_order = vconf_keynode_get_int(key);
+ else if (CTS_ORDER_OF_DISPLAY + 1 == (int)data)
+ default_lang = vconf_keynode_get_int(key);
+}
+
+int cts_get_default_language(void)
+{
+ if (default_lang < 0) {
+ int ret;
+ ret = vconf_get_int(CTS_VCONF_DEFAULT_LANGUAGE, &default_lang);
+ warn_if(ret < 0, "vconf_get_int() Failed(%d)", ret);
+ }
+ return default_lang;
+}
+
+void cts_set_contact_noti(void)
+{
+ contact_change = true;
+}
+void cts_set_plog_noti(void)
+{
+ plog_change = true;
+}
+void cts_set_missed_call_noti(void)
+{
+ missed_change = true;
+}
+void cts_set_favor_noti(void)
+{
+ favor_change = true;
+}
+void cts_set_speed_noti(void)
+{
+ speed_change = true;
+}
+void cts_set_addrbook_noti(void)
+{
+ addrbook_change = true;
+}
+void cts_set_group_noti(void)
+{
+ group_change = true;
+}
+void cts_set_group_rel_noti(void)
+{
+ group_rel_change = true;
+}
+
+static inline void cts_noti_publish_contact_change(void)
+{
+ int fd = open(CTS_NOTI_CONTACT_CHANGED, O_TRUNC | O_RDWR);
+ if (0 <= fd) {
+ close(fd);
+ contact_change = false;
+ }
+}
+
+static inline void cts_noti_publish_plog_change(void)
+{
+ int fd = open(CTS_NOTI_PLOG_CHANGED, O_TRUNC | O_RDWR);
+ if (0 <= fd) {
+ close(fd);
+ plog_change = false;
+ }
+}
+
+static inline void cts_noti_publish_missed_call_change(void)
+{
+ int fd = open(CTS_NOTI_MISSED_CALL_CHANGED, O_TRUNC | O_RDWR);
+ if (0 <= fd) {
+ close(fd);
+ missed_change = false;
+ }
+}
+
+static inline void cts_noti_publish_favor_change(void)
+{
+ int fd = open(CTS_NOTI_FAVORITE_CHANGED, O_TRUNC | O_RDWR);
+ if (0 <= fd) {
+ close(fd);
+ favor_change = false;
+ }
+}
+
+static inline void cts_noti_publish_speed_change(void)
+{
+ int fd = open(CTS_NOTI_SPEEDDIAL_CHANGED, O_TRUNC | O_RDWR);
+ if (0 <= fd) {
+ close(fd);
+ speed_change = false;
+ }
+}
+
+static inline void cts_noti_publish_addrbook_change(void)
+{
+ int fd = open(CTS_NOTI_ADDRBOOK_CHANGED, O_TRUNC | O_RDWR);
+ if (0 <= fd) {
+ close(fd);
+ addrbook_change = false;
+ }
+}
+
+static inline void cts_noti_publish_group_change(void)
+{
+ int fd = open(CTS_NOTI_GROUP_CHANGED, O_TRUNC | O_RDWR);
+ if (0 <= fd) {
+ close(fd);
+ group_change = false;
+ }
+}
+
+static inline void cts_noti_publish_group_rel_change(void)
+{
+ int fd = open(CTS_NOTI_GROUP_RELATION_CHANGED, O_TRUNC | O_RDWR);
+ if (0 <= fd) {
+ close(fd);
+ group_rel_change = false;
+ }
+}
+
+#define CTS_COMMIT_TRY_MAX 500000 // For 3second
+API int contacts_svc_begin_trans(void)
+{
+ int ret = -1, progress;
+
+ if (transaction_count <= 0)
+ {
+ ret = cts_query_exec("BEGIN IMMEDIATE TRANSACTION"); //taken 600ms
+ progress = 100000;
+ while (CTS_ERR_DB_LOCK == ret && progress<CTS_COMMIT_TRY_MAX) {
+ usleep(progress);
+ ret = cts_query_exec("BEGIN IMMEDIATE TRANSACTION");
+ progress *= 2;
+ }
+ retvm_if(CTS_SUCCESS != ret, ret, "cts_query_exec() Failed(%d)", ret);
+
+ transaction_count = 0;
+
+ const char *query = "SELECT ver FROM "CTS_TABLE_VERSION;
+ transaction_ver = cts_query_get_first_int_result(query);
+ version_up = false;
+ }
+ transaction_count++;
+ CTS_DBG("transaction_count : %d.", transaction_count);
+
+ return CTS_SUCCESS;
+}
+
+static inline void cts_cancel_changes(void)
+{
+ contact_change = false;
+ plog_change = false;
+ missed_change = false;
+ favor_change = false;
+ speed_change = false;
+ addrbook_change = false;
+ group_change = false;
+ group_rel_change = false;
+}
+
+API int contacts_svc_end_trans(bool is_success)
+{
+ int ret = -1, progress;
+ char query[CTS_SQL_MIN_LEN];
+
+ transaction_count--;
+
+ if (0 != transaction_count) {
+ CTS_DBG("contact transaction_count : %d.", transaction_count);
+ return CTS_SUCCESS;
+ }
+
+ if (false == is_success) {
+ cts_cancel_changes();
+ ret = cts_query_exec("ROLLBACK TRANSACTION");
+ return CTS_SUCCESS;
+ }
+
+ if (version_up) {
+ transaction_ver++;
+ snprintf(query, sizeof(query), "UPDATE %s SET ver = %d",
+ CTS_TABLE_VERSION, transaction_ver);
+ ret = cts_query_exec(query);
+ warn_if(CTS_SUCCESS != ret, "cts_query_exec(version up) Failed(%d)", ret);
+ }
+
+ progress = 400000;
+ ret = cts_query_exec("COMMIT TRANSACTION");
+ while (CTS_ERR_DB_LOCK == ret && progress<CTS_COMMIT_TRY_MAX) {
+ usleep(progress);
+ ret = cts_query_exec("COMMIT TRANSACTION");
+ progress *= 2;
+ }
+ if (CTS_SUCCESS != ret) {
+ int tmp_ret;
+ ERR("cts_query_exec() Failed(%d)", ret);
+ cts_cancel_changes();
+ tmp_ret = cts_query_exec("ROLLBACK TRANSACTION");
+ warn_if(CTS_SUCCESS != tmp_ret, "cts_query_exec(ROLLBACK) Failed(%d)", tmp_ret);
+ return ret;
+ }
+ if (contact_change) cts_noti_publish_contact_change();
+ if (plog_change) cts_noti_publish_plog_change();
+ if (missed_change) cts_noti_publish_missed_call_change();
+ if (favor_change) cts_noti_publish_favor_change();
+ if (speed_change) cts_noti_publish_speed_change();
+ if (addrbook_change) cts_noti_publish_addrbook_change();
+ if (group_change) cts_noti_publish_group_change();
+ if (group_rel_change) cts_noti_publish_group_rel_change();
+
+ return transaction_ver;
+}
+
+int cts_get_next_ver(void)
+{
+ const char *query;
+
+ if (0 < transaction_count) {
+ version_up = true;
+ return transaction_ver + 1;
+ }
+
+ query = "SELECT ver FROM "CTS_TABLE_VERSION;
+ return (1+cts_query_get_first_int_result(query));
+}
+
+void cts_deregister_noti(void)
+{
+ int ret;
+
+ cts_inotify_close();
+
+ ret = vconf_ignore_key_changed(CTS_VCONF_SORTING_ORDER, cts_vconf_callback);
+ retm_if(ret<0,"vconf_ignore_key_changed(%s) Failed(%d)",CTS_VCONF_SORTING_ORDER,ret);
+ ret = vconf_ignore_key_changed(CTS_VCONF_DISPLAY_ORDER, cts_vconf_callback);
+ retm_if(ret<0,"vconf_ignore_key_changed(%s) Failed(%d)",CTS_VCONF_DISPLAY_ORDER,ret);
+ ret = vconf_ignore_key_changed(CTS_VCONF_DEFAULT_LANGUAGE, cts_vconf_callback);
+ retm_if(ret<0,"vconf_ignore_key_changed(%s) Failed(%d)",CTS_VCONF_DEFAULT_LANGUAGE,ret);
+}
+
+static inline int cts_conf_init_name_info(void)
+{
+ int ret;
+
+ ret = vconf_get_int(CTS_VCONF_SORTING_ORDER, &name_sorting_order);
+ if (ret < 0) {
+ ERR("vconf_get_int() Failed(%d)", ret);
+ name_sorting_order = CTS_ORDER_NAME_FIRSTLAST;
+ }
+
+ ret = vconf_get_int(CTS_VCONF_DISPLAY_ORDER, &name_display_order);
+ if (ret < 0) {
+ ERR("vconf_get_int() Failed(%d)", ret);
+ name_display_order = CTS_ORDER_NAME_FIRSTLAST;
+ }
+
+ ret = vconf_get_int(CTS_VCONF_DEFAULT_LANGUAGE, &default_lang);
+ warn_if(ret < 0, "vconf_get_int() Failed(%d)", ret);
+
+ ret = vconf_notify_key_changed(CTS_VCONF_SORTING_ORDER,
+ cts_vconf_callback, (void *)CTS_ORDER_OF_SORTING);
+ retvm_if(ret<0, CTS_ERR_VCONF_FAILED, "vconf_notify_key_changed() Failed(%d)", ret);
+ ret = vconf_notify_key_changed(CTS_VCONF_DISPLAY_ORDER,
+ cts_vconf_callback, (void *)CTS_ORDER_OF_DISPLAY);
+ retvm_if(ret<0, CTS_ERR_VCONF_FAILED, "vconf_notify_key_changed() Failed(%d)", ret);
+ ret = vconf_notify_key_changed(CTS_VCONF_DEFAULT_LANGUAGE,
+ cts_vconf_callback, (void *)CTS_ORDER_OF_DISPLAY+1);
+ retvm_if(ret<0, CTS_ERR_VCONF_FAILED, "vconf_notify_key_changed() Failed(%d)", ret);
+
+ return CTS_SUCCESS;
+}
+
+void cts_register_noti(void)
+{
+ int ret;
+
+ ret = cts_inotify_init();
+ retm_if(CTS_SUCCESS != ret, "cts_inotify_init() Failed(%d)", ret);
+
+ ret = cts_conf_init_name_info();
+ retm_if(CTS_SUCCESS != ret, "cts_conf_init_name_info() Failed(%d)", ret);
+}
+
+API int contacts_svc_set_order(cts_order_op op_code, cts_order_type order)
+{
+ int ret;
+ const char *op;
+
+ retvm_if(CTS_ORDER_NAME_FIRSTLAST != order && CTS_ORDER_NAME_LASTFIRST != order,
+ CTS_ERR_ARG_INVALID, "The parameter(order:%d) is Invalid", order);
+
+ if (CTS_ORDER_OF_SORTING == op_code)
+ op = CTS_VCONF_SORTING_ORDER;
+ else
+ op = CTS_VCONF_DISPLAY_ORDER;
+
+ ret = vconf_set_int(op, order);
+ retvm_if(ret<0, CTS_ERR_VCONF_FAILED, "vconf_set_int(%s) Failed(%d)", op, ret);
+
+ if (CTS_ORDER_OF_SORTING == op_code)
+ name_sorting_order = order;
+ else
+ name_display_order = order;
+
+ return CTS_SUCCESS;
+}
+
+API cts_order_type contacts_svc_get_order(cts_order_op op_code)
+{
+ int ret;
+
+ if (CTS_ORDER_OF_SORTING == op_code) {
+ if (name_sorting_order < 0) {
+ ret = vconf_get_int(CTS_VCONF_SORTING_ORDER, &name_sorting_order);
+ retvm_if(ret<0, CTS_ERR_VCONF_FAILED, "vconf_get_int() Failed(%d)", ret);
+ }
+
+ return name_sorting_order;
+ }
+ else{
+ if (name_display_order < 0) {
+ ret = vconf_get_int(CTS_VCONF_DISPLAY_ORDER, &name_display_order);
+ retvm_if(ret<0, CTS_ERR_VCONF_FAILED, "vconf_get_int() Failed(%d)", ret);
+ }
+
+ return name_display_order;
+ }
+}
+
+static inline const char* cts_noti_get_file_path(int type)
+{
+ const char *noti;
+ switch (type)
+ {
+ case CTS_SUBSCRIBE_CONTACT_CHANGE:
+ noti = CTS_NOTI_CONTACT_CHANGED;
+ break;
+ case CTS_SUBSCRIBE_PLOG_CHANGE:
+ noti = CTS_NOTI_PLOG_CHANGED;
+ break;
+ case CTS_SUBSCRIBE_MISSED_CALL_CHANGE:
+ noti = CTS_NOTI_MISSED_CALL_CHANGED;
+ break;
+ case CTS_SUBSCRIBE_FAVORITE_CHANGE:
+ noti = CTS_NOTI_FAVORITE_CHANGED;
+ break;
+ case CTS_SUBSCRIBE_GROUP_CHANGE:
+ noti = CTS_NOTI_GROUP_CHANGED;
+ break;
+ case CTS_SUBSCRIBE_SPEEDDIAL_CHANGE:
+ noti = CTS_NOTI_SPEEDDIAL_CHANGED;
+ break;
+ case CTS_SUBSCRIBE_ADDRESSBOOK_CHANGE:
+ noti = CTS_NOTI_ADDRBOOK_CHANGED;
+ break;
+ default:
+ ERR("Invalid parameter : The type(%d) is not supported", type);
+ return NULL;
+ }
+
+ return noti;
+}
+
+API int contacts_svc_subscribe_change(cts_subscribe_type noti_type,
+ void (*cb)(void *), void *user_data)
+{
+ int ret;
+ const char *noti;
+
+ noti = cts_noti_get_file_path(noti_type);
+ retvm_if(NULL == noti, CTS_ERR_ARG_INVALID,
+ "cts_noti_get_file_path(%d) Failed", noti_type);
+
+ ret = cts_inotify_subscribe(noti, cb, user_data);
+ retvm_if(CTS_SUCCESS != ret, ret,
+ "cts_inotify_subscribe(%d) Failed(%d)", noti_type, ret);
+
+ return CTS_SUCCESS;
+}
+
+API int contacts_svc_unsubscribe_change(cts_subscribe_type noti_type,
+ void (*cb)(void *))
+{
+ int ret;
+ const char *noti;
+
+ noti = cts_noti_get_file_path(noti_type);
+ retvm_if(NULL == noti, CTS_ERR_ARG_INVALID,
+ "cts_noti_get_file_path(%d) Failed", noti_type);
+
+ ret = cts_inotify_unsubscribe(noti, cb);
+ retvm_if(CTS_SUCCESS != ret, ret,
+ "cts_inotify_unsubscribe(%d) Failed(%d)", noti_type, ret);
+
+ return CTS_SUCCESS;
+}
+
+API int contacts_svc_unsubscribe_change_with_data(cts_subscribe_type noti_type,
+ void (*cb)(void *), void *user_data)
+{
+ int ret;
+ const char *noti;
+
+ noti = cts_noti_get_file_path(noti_type);
+ retvm_if(NULL == noti, CTS_ERR_ARG_INVALID,
+ "cts_noti_get_file_path(%d) Failed", noti_type);
+
+ ret = cts_inotify_unsubscribe_with_data(noti, cb, user_data);
+ retvm_if(CTS_SUCCESS != ret, ret,
+ "cts_inotify_unsubscribe_with_data(%d) Failed(%d)", noti_type, ret);
+
+ return CTS_SUCCESS;
+}
+
+int cts_exist_file(char *path)
+{
+ int fd = open(path, O_RDONLY);
+ // errno == ENOENT
+ retvm_if(fd < 0, CTS_ERR_FAIL, "Open(%s) Failed(%d)", path, errno);
+ close(fd);
+ return CTS_SUCCESS;
+}
+
+#define CTS_COPY_SIZE_MAX 4096
+API int contacts_svc_get_image(cts_img_t img_type, int index, char **img_path)
+{
+ int ret;
+ cts_stmt stmt;
+ char *tmp_path;
+ char query[CTS_SQL_MIN_LEN] = {0};
+
+ retvm_if(CTS_IMG_FULL != img_type && CTS_IMG_NORMAL != img_type,
+ CTS_ERR_ARG_INVALID,
+ "You have to use CTS_IMG_FULL or CTS_IMG_NORMAL for img_type");
+ retvm_if(NULL == img_path, CTS_ERR_ARG_INVALID, "img_path is NULL");
+
+ snprintf(query, sizeof(query),
+ "SELECT image%d FROM %s WHERE contact_id = %d",
+ img_type, CTS_TABLE_CONTACTS, index);
+
+ stmt = cts_query_prepare(query);
+ retvm_if(NULL == stmt, CTS_ERR_DB_FAILED, "cts_query_prepare() Failed");
+
+ *img_path = NULL;
+ ret = cts_stmt_step(stmt);
+ if (CTS_TRUE != ret) {
+ ERR("cts_stmt_step() Failed(%d)", ret);
+ cts_stmt_finalize(stmt);
+ return CTS_ERR_DB_RECORD_NOT_FOUND;
+ }
+
+ tmp_path = cts_stmt_get_text(stmt, 0);
+ if (tmp_path) {
+ ret = cts_exist_file(tmp_path);
+ retvm_if(ret, ret, "cts_exist_file() Failed(%d)", ret);
+ *img_path = strdup(tmp_path);
+ if (NULL == *img_path) {
+ ERR("strdup() Failed");
+ cts_stmt_finalize(stmt);
+ return CTS_ERR_OUT_OF_MEMORY;
+ }
+ }
+ cts_stmt_finalize(stmt);
+ return CTS_SUCCESS;
+}
+
+int cts_delete_image_file(int img_type, int index)
+{
+ int ret;
+ cts_stmt stmt;
+ char *tmp_path;
+ char query[CTS_SQL_MIN_LEN];
+ snprintf(query, sizeof(query),
+ "SELECT image%d FROM %s WHERE contact_id = %d",
+ img_type, CTS_TABLE_CONTACTS, index);
+
+ stmt = cts_query_prepare(query);
+ if (NULL == stmt) {
+ ERR("cts_query_prepare() Failed");
+ return CTS_ERR_DB_FAILED;
+ }
+
+ ret = cts_stmt_step(stmt);
+ if (CTS_TRUE != ret) {
+ ERR("cts_stmt_step() Failed(%d)", ret);
+ cts_stmt_finalize(stmt);
+ return CTS_ERR_DB_RECORD_NOT_FOUND;
+ }
+
+ tmp_path = cts_stmt_get_text(stmt, 0);
+ if (tmp_path) {
+ ret = unlink(tmp_path);
+ warn_if (ret < 0, "unlink(%s) Failed(%d)", tmp_path, errno);
+ }
+ cts_stmt_finalize(stmt);
+ return CTS_SUCCESS;
+}
+
+int cts_add_image_file(int img_type, int index, char *src_img, char **dest_img)
+{
+ int src_fd;
+ int dest_fd;
+ int size;
+ int ret;
+ char *ext;
+ char buf[CTS_COPY_SIZE_MAX];
+ char dest[CTS_IMG_PATH_SIZE_MAX];
+
+ *dest_img = NULL;
+ retvm_if(NULL == src_img, CTS_ERR_ARG_INVALID, "img_path is NULL");
+
+ ext = strrchr(src_img, '.');
+ if (NULL == ext) ext = "";
+
+ size = snprintf(dest, sizeof(dest), "%s/%d-%d%s",
+ CTS_IMAGE_LOCATION, index, img_type, ext);
+ retvm_if(size<=0, CTS_ERR_FAIL, "Destination file name was not created");
+
+ src_fd = open(src_img, O_RDONLY);
+ retvm_if(src_fd < 0, CTS_ERR_IO_ERR, "Open(%s) Failed(%d)", src_img, errno);
+ dest_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660);
+ if (dest_fd < 0) {
+ ERR("Open(%s) Failed(%d)", dest, errno);
+ close(src_fd);
+ return CTS_ERR_FAIL;
+ }
+
+ while ((size = read(src_fd, buf, CTS_COPY_SIZE_MAX)) > 0) {
+ ret = write(dest_fd, buf, size);
+ if (ret <= 0) {
+ if (EINTR == errno)
+ continue;
+ else {
+ ERR("write() Failed(%d)", errno);
+ if (ENOSPC == errno)
+ ret = CTS_ERR_NO_SPACE;
+ else
+ ret = CTS_ERR_IO_ERR;
+ close(src_fd);
+ close(dest_fd);
+ unlink(dest);
+ return ret;
+ }
+ }
+ }
+
+ fchown(dest_fd, getuid(), CTS_SECURITY_FILE_GROUP);
+ fchmod(dest_fd, CTS_SECURITY_DEFAULT_PERMISSION);
+ close(src_fd);
+ close(dest_fd);
+ *dest_img = strdup(dest);
+ return CTS_SUCCESS;
+}
+
+int cts_update_image_file(int img_type, int index, char *src_img, char **dest_img)
+{
+ int ret;
+
+ *dest_img = NULL;
+ ret = cts_delete_image_file(img_type, index);
+ retvm_if(CTS_SUCCESS != ret && CTS_ERR_DB_RECORD_NOT_FOUND != ret,
+ ret, "cts_delete_image_file() Failed(%d)", ret);
+
+ if (src_img) {
+ ret = cts_add_image_file(img_type, index, src_img, &(*dest_img));
+ retvm_if(CTS_SUCCESS != ret, ret, "cts_add_image_file() Failed(%d)", ret);
+ }
+
+ return ret;
+}
+
+int cts_update_contact_changed_time(int contact_id)
+{
+ int ret;
+ char query[CTS_SQL_MIN_LEN];
+
+ snprintf(query, sizeof(query),
+ "UPDATE %s SET changed_ver=%d, changed_time=%d WHERE contact_id=%d",
+ CTS_TABLE_CONTACTS, cts_get_next_ver(), (int)time(NULL), contact_id);
+
+ ret = cts_query_exec(query);
+ retvm_if(CTS_SUCCESS != ret, ret, "cts_query_exec() Failed(%d)", ret);
+
+ cts_set_contact_noti();
+
+ return CTS_SUCCESS;
+}
+
+API int contacts_svc_save_image(cts_img_t img_type, int index, char *src_img)
+{
+ int ret;
+ char *dest_img;
+ char query[CTS_SQL_MIN_LEN];
+ cts_stmt stmt;
+
+ ret = contacts_svc_begin_trans();
+ retvm_if(ret, ret, "contacts_svc_begin_trans() Failed(%d)", ret);
+
+ ret = cts_update_image_file(img_type, index, src_img, &dest_img);
+ if (CTS_SUCCESS != ret) {
+ ERR("cts_update_image_file() Failed(%d)", ret);
+ contacts_svc_end_trans(false);
+ return ret;
+ }
+
+ snprintf(query, sizeof(query),
+ "UPDATE %s SET changed_ver=%d, changed_time=%d, image%d=? WHERE contact_id=%d",
+ CTS_TABLE_CONTACTS, cts_get_next_ver(), (int)time(NULL), img_type, index);
+ stmt = cts_query_prepare(query);
+ if (NULL == stmt) {
+ ERR("cts_query_prepare() Failed");
+ contacts_svc_end_trans(false);
+ return CTS_ERR_DB_FAILED;
+ }
+
+ if(dest_img)
+ cts_stmt_bind_text(stmt, 1, dest_img);
+ ret = cts_stmt_step(stmt);
+ warn_if(CTS_SUCCESS != ret, "cts_stmt_step() Failed(%d)", ret);
+ cts_stmt_finalize(stmt);
+
+ cts_set_contact_noti();
+
+ ret = contacts_svc_end_trans(true);
+ retvm_if(ret < CTS_SUCCESS, ret, "contacts_svc_end_trans() Failed(%d)", ret);
+
+ return CTS_SUCCESS;
+}
+
+API int contacts_svc_count_with_int(cts_count_int_op op_code, int search_value)
+{
+ int ret;
+ cts_stmt stmt;
+ char query[CTS_SQL_MIN_LEN] = {0};
+
+ switch (op_code)
+ {
+ case CTS_GET_COUNT_CONTACTS_IN_ADDRESSBOOK:
+ snprintf(query, sizeof(query),
+ "SELECT COUNT(contact_id) FROM %s "
+ "WHERE addrbook_id = ?", CTS_TABLE_CONTACTS);
+ break;
+ case CTS_GET_COUNT_CONTACTS_IN_GROUP:
+ snprintf(query, sizeof(query),
+ "SELECT COUNT(contact_id) FROM %s WHERE group_id = ?",
+ CTS_TABLE_GROUPING_INFO);
+ break;
+ case CTS_GET_COUNT_NO_GROUP_CONTACTS_IN_ADDRESSBOOK:
+ snprintf(query, sizeof(query),
+ "SELECT COUNT(contact_id) FROM %s A "
+ "WHERE addrbook_id = ? AND NOT EXISTS "
+ "(SELECT contact_id FROM %s WHERE contact_id=A.contact_id LIMIT 1)",
+ CTS_TABLE_CONTACTS, CTS_TABLE_GROUPING_INFO);
+ break;
+ default:
+ ERR("Invalid parameter : The op_code(%d) is not supported", op_code);
+ return CTS_ERR_ARG_INVALID;
+ }
+ stmt = cts_query_prepare(query);
+ retvm_if(NULL == stmt, CTS_ERR_DB_FAILED, "cts_query_prepare() Failed");
+
+ cts_stmt_bind_int(stmt, 1, search_value);
+ ret = cts_stmt_get_first_int_result(stmt);
+ if (CTS_ERR_DB_RECORD_NOT_FOUND == ret) return 0;
+ else return ret;
+}
+
+API int contacts_svc_count(cts_count_op op_code)
+{
+ int ret;
+ char query[CTS_SQL_MIN_LEN] = {0};
+
+ switch ((int)op_code)
+ {
+ case CTS_GET_ALL_CONTACT:
+ snprintf(query, sizeof(query),"SELECT COUNT(*) FROM %s",
+ CTS_TABLE_CONTACTS);
+ break;
+ case CTS_GET_COUNT_SDN:
+ snprintf(query, sizeof(query),"SELECT COUNT(*) FROM %s",
+ CTS_TABLE_SIM_SERVICES);
+ break;
+ case CTS_GET_ALL_PHONELOG:
+ snprintf(query, sizeof(query), "SELECT COUNT(*) FROM %s",
+ CTS_TABLE_PHONELOGS);
+ break;
+ case CTS_GET_UNSEEN_MISSED_CALL:
+ snprintf(query, sizeof(query),
+ "SELECT COUNT(*) FROM %s "
+ "WHERE log_type = %d OR log_type = %d",
+ CTS_TABLE_PHONELOGS,
+ CTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN, CTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN);
+ break;
+ default:
+ ERR("Invalid parameter : The op_code(%d) is not supported", op_code);
+ return CTS_ERR_ARG_INVALID;
+ }
+
+ ret = cts_query_get_first_int_result(query);
+ if (CTS_ERR_DB_RECORD_NOT_FOUND == ret) return 0;
+ else return ret;
+}
+
+int cts_convert_nicknames2textlist(GSList *src, char *dest, int dest_size)
+{
+ int len;
+ GSList *nick_repeat = src;
+ cts_nickname *nick_data;
+
+ retvm_if(dest_size <= 0 || NULL == dest, CTS_ERR_ARG_INVALID,
+ "The parameter is Invalid. dest = %p, dest_size = %d", dest, dest_size);
+
+ len = 0;
+ dest[0] = '\0';
+ while (nick_repeat) {
+ if (NULL != (nick_data = (cts_nickname *)nick_repeat->data) && nick_data->nick) {
+ if (!nick_data->deleted)
+ len += snprintf(dest+len, dest_size-len, "%s,", nick_data->nick);
+ }
+ nick_repeat = nick_repeat->next;
+ }
+
+ len = strlen(dest);
+ if (len)
+ dest[len - 1] = '\0';
+ else
+ return CTS_ERR_NO_DATA;
+ return CTS_SUCCESS;
+}
+
+GSList* cts_convert_textlist2nicknames(char *text_list)
+{
+ char temp[CTS_SQL_MAX_LEN], *text_start, *text_end;
+ GSList *ret_list = NULL;
+ cts_nickname *result;
+
+ snprintf(temp, sizeof(temp), "%s", text_list);
+
+ text_start = temp;
+ while (text_start)
+ {
+ text_end = strchr(text_start, ',');
+ if (text_end)
+ *text_end = '\0';
+
+ result = (cts_nickname *)contacts_svc_value_new(CTS_VALUE_NICKNAME);
+ if (result)
+ {
+ result->embedded = true;
+ result->nick = strdup(text_start);
+ }
+
+ ret_list = g_slist_append(ret_list, result);
+
+ if (text_end) {
+ *text_end = ',';
+ text_start = text_end+1;
+ }
+ else
+ text_start = NULL;
+ }
+ return ret_list;
+}
+
+API int contacts_svc_import_sim(void)
+{
+ int ret;
+
+ cts_mutex_lock(CTS_MUTEX_SOCKET_FD);
+ ret = cts_request_sim_import();
+ cts_mutex_unlock(CTS_MUTEX_SOCKET_FD);
+
+ return ret;
+}
+
+int cts_increase_outgoing_count(int contact_id)
+{
+ int ret;
+ char query[CTS_SQL_MIN_LEN];
+
+ ret = contacts_svc_begin_trans();
+ retvm_if(ret, ret, "contacts_svc_begin_trans() Failed(%d)", ret);
+
+ snprintf(query, sizeof(query),
+ "UPDATE %s SET outgoing_count = outgoing_count + 1 WHERE contact_id = %d",
+ CTS_TABLE_CONTACTS, contact_id);
+
+ ret = cts_query_exec(query);
+ if (CTS_SUCCESS != ret)
+ {
+ ERR("cts_query_exec() Failed(%d)", ret);
+ contacts_svc_end_trans(false);
+ return ret;
+ }
+
+ ret = contacts_svc_end_trans(true);
+ if (ret < CTS_SUCCESS)
+ return ret;
+ else
+ return CTS_SUCCESS;
+}
+
+API int contacts_svc_reset_outgoing_count(int contact_id)
+{
+ int ret ;
+ char query[CTS_SQL_MAX_LEN];
+
+ snprintf(query, sizeof(query),
+ "UPDATE %s SET outgoing_count = 0 WHERE contact_id = %d",
+ CTS_TABLE_CONTACTS, contact_id);
+
+ ret = contacts_svc_begin_trans();
+ retvm_if(ret, ret, "contacts_svc_begin_trans() Failed(%d)", ret);
+
+ ret = cts_query_exec(query);
+ if (CTS_SUCCESS != ret)
+ {
+ ERR("cts_query_exec() Failed(%d)", ret);
+ contacts_svc_end_trans(false);
+ return ret;
+ }
+
+ ret = contacts_svc_end_trans(true);
+ if (ret < CTS_SUCCESS)
+ return ret;
+ else
+ return CTS_SUCCESS;
+}
+
+#ifdef CTS_TIMECHECK
+double cts_set_start_time(void)
+{
+ struct timeval tv;
+ double curtime;
+
+ gettimeofday(&tv, NULL);
+ curtime = tv.tv_sec * 1000 + (double)tv.tv_usec/1000;
+ return curtime;
+}
+
+double cts_exec_time(double start)
+{
+ double end = cts_set_start_time();
+ return (end - start - correction);
+}
+
+int cts_init_time(void)
+{
+ double temp_t;
+ temp_t = cts_set_start_time();
+ correction = cts_exec_time(temp_t);
+
+ return 0;
+}
+#endif
+