--- /dev/null
+Jinmin Jung <jinmin@samsung.com>
+DoHyun Pyun <dh79.pyun@samsung.com>
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+ADD_SUBDIRECTORY(map-agent)
+
+ADD_SUBDIRECTORY(pb-agent)
+
+ADD_SUBDIRECTORY(hfp-agent)
--- /dev/null
+\r
+ Apache License\r
+ Version 2.0, January 2004\r
+ http://www.apache.org/licenses/\r
+\r
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r
+\r
+ 1. Definitions.\r
+\r
+ "License" shall mean the terms and conditions for use, reproduction,\r
+ and distribution as defined by Sections 1 through 9 of this document.\r
+\r
+ "Licensor" shall mean the copyright owner or entity authorized by\r
+ the copyright owner that is granting the License.\r
+\r
+ "Legal Entity" shall mean the union of the acting entity and all\r
+ other entities that control, are controlled by, or are under common\r
+ control with that entity. For the purposes of this definition,\r
+ "control" means (i) the power, direct or indirect, to cause the\r
+ direction or management of such entity, whether by contract or\r
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the\r
+ outstanding shares, or (iii) beneficial ownership of such entity.\r
+\r
+ "You" (or "Your") shall mean an individual or Legal Entity\r
+ exercising permissions granted by this License.\r
+\r
+ "Source" form shall mean the preferred form for making modifications,\r
+ including but not limited to software source code, documentation\r
+ source, and configuration files.\r
+\r
+ "Object" form shall mean any form resulting from mechanical\r
+ transformation or translation of a Source form, including but\r
+ not limited to compiled object code, generated documentation,\r
+ and conversions to other media types.\r
+\r
+ "Work" shall mean the work of authorship, whether in Source or\r
+ Object form, made available under the License, as indicated by a\r
+ copyright notice that is included in or attached to the work\r
+ (an example is provided in the Appendix below).\r
+\r
+ "Derivative Works" shall mean any work, whether in Source or Object\r
+ form, that is based on (or derived from) the Work and for which the\r
+ editorial revisions, annotations, elaborations, or other modifications\r
+ represent, as a whole, an original work of authorship. For the purposes\r
+ of this License, Derivative Works shall not include works that remain\r
+ separable from, or merely link (or bind by name) to the interfaces of,\r
+ the Work and Derivative Works thereof.\r
+\r
+ "Contribution" shall mean any work of authorship, including\r
+ the original version of the Work and any modifications or additions\r
+ to that Work or Derivative Works thereof, that is intentionally\r
+ submitted to Licensor for inclusion in the Work by the copyright owner\r
+ or by an individual or Legal Entity authorized to submit on behalf of\r
+ the copyright owner. For the purposes of this definition, "submitted"\r
+ means any form of electronic, verbal, or written communication sent\r
+ to the Licensor or its representatives, including but not limited to\r
+ communication on electronic mailing lists, source code control systems,\r
+ and issue tracking systems that are managed by, or on behalf of, the\r
+ Licensor for the purpose of discussing and improving the Work, but\r
+ excluding communication that is conspicuously marked or otherwise\r
+ designated in writing by the copyright owner as "Not a Contribution."\r
+\r
+ "Contributor" shall mean Licensor and any individual or Legal Entity\r
+ on behalf of whom a Contribution has been received by Licensor and\r
+ subsequently incorporated within the Work.\r
+\r
+ 2. Grant of Copyright License. Subject to the terms and conditions of\r
+ this License, each Contributor hereby grants to You a perpetual,\r
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+ copyright license to reproduce, prepare Derivative Works of,\r
+ publicly display, publicly perform, sublicense, and distribute the\r
+ Work and such Derivative Works in Source or Object form.\r
+\r
+ 3. Grant of Patent License. Subject to the terms and conditions of\r
+ this License, each Contributor hereby grants to You a perpetual,\r
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+ (except as stated in this section) patent license to make, have made,\r
+ use, offer to sell, sell, import, and otherwise transfer the Work,\r
+ where such license applies only to those patent claims licensable\r
+ by such Contributor that are necessarily infringed by their\r
+ Contribution(s) alone or by combination of their Contribution(s)\r
+ with the Work to which such Contribution(s) was submitted. If You\r
+ institute patent litigation against any entity (including a\r
+ cross-claim or counterclaim in a lawsuit) alleging that the Work\r
+ or a Contribution incorporated within the Work constitutes direct\r
+ or contributory patent infringement, then any patent licenses\r
+ granted to You under this License for that Work shall terminate\r
+ as of the date such litigation is filed.\r
+\r
+ 4. Redistribution. You may reproduce and distribute copies of the\r
+ Work or Derivative Works thereof in any medium, with or without\r
+ modifications, and in Source or Object form, provided that You\r
+ meet the following conditions:\r
+\r
+ (a) You must give any other recipients of the Work or\r
+ Derivative Works a copy of this License; and\r
+\r
+ (b) You must cause any modified files to carry prominent notices\r
+ stating that You changed the files; and\r
+\r
+ (c) You must retain, in the Source form of any Derivative Works\r
+ that You distribute, all copyright, patent, trademark, and\r
+ attribution notices from the Source form of the Work,\r
+ excluding those notices that do not pertain to any part of\r
+ the Derivative Works; and\r
+\r
+ (d) If the Work includes a "NOTICE" text file as part of its\r
+ distribution, then any Derivative Works that You distribute must\r
+ include a readable copy of the attribution notices contained\r
+ within such NOTICE file, excluding those notices that do not\r
+ pertain to any part of the Derivative Works, in at least one\r
+ of the following places: within a NOTICE text file distributed\r
+ as part of the Derivative Works; within the Source form or\r
+ documentation, if provided along with the Derivative Works; or,\r
+ within a display generated by the Derivative Works, if and\r
+ wherever such third-party notices normally appear. The contents\r
+ of the NOTICE file are for informational purposes only and\r
+ do not modify the License. You may add Your own attribution\r
+ notices within Derivative Works that You distribute, alongside\r
+ or as an addendum to the NOTICE text from the Work, provided\r
+ that such additional attribution notices cannot be construed\r
+ as modifying the License.\r
+\r
+ You may add Your own copyright statement to Your modifications and\r
+ may provide additional or different license terms and conditions\r
+ for use, reproduction, or distribution of Your modifications, or\r
+ for any such Derivative Works as a whole, provided Your use,\r
+ reproduction, and distribution of the Work otherwise complies with\r
+ the conditions stated in this License.\r
+\r
+ 5. Submission of Contributions. Unless You explicitly state otherwise,\r
+ any Contribution intentionally submitted for inclusion in the Work\r
+ by You to the Licensor shall be under the terms and conditions of\r
+ this License, without any additional terms or conditions.\r
+ Notwithstanding the above, nothing herein shall supersede or modify\r
+ the terms of any separate license agreement you may have executed\r
+ with Licensor regarding such Contributions.\r
+\r
+ 6. Trademarks. This License does not grant permission to use the trade\r
+ names, trademarks, service marks, or product names of the Licensor,\r
+ except as required for reasonable and customary use in describing the\r
+ origin of the Work and reproducing the content of the NOTICE file.\r
+\r
+ 7. Disclaimer of Warranty. Unless required by applicable law or\r
+ agreed to in writing, Licensor provides the Work (and each\r
+ Contributor provides its Contributions) on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
+ implied, including, without limitation, any warranties or conditions\r
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r
+ PARTICULAR PURPOSE. You are solely responsible for determining the\r
+ appropriateness of using or redistributing the Work and assume any\r
+ risks associated with Your exercise of permissions under this License.\r
+\r
+ 8. Limitation of Liability. In no event and under no legal theory,\r
+ whether in tort (including negligence), contract, or otherwise,\r
+ unless required by applicable law (such as deliberate and grossly\r
+ negligent acts) or agreed to in writing, shall any Contributor be\r
+ liable to You for damages, including any direct, indirect, special,\r
+ incidental, or consequential damages of any character arising as a\r
+ result of this License or out of the use or inability to use the\r
+ Work (including but not limited to damages for loss of goodwill,\r
+ work stoppage, computer failure or malfunction, or any and all\r
+ other commercial damages or losses), even if such Contributor\r
+ has been advised of the possibility of such damages.\r
+\r
+ 9. Accepting Warranty or Additional Liability. While redistributing\r
+ the Work or Derivative Works thereof, You may choose to offer,\r
+ and charge a fee for, acceptance of support, warranty, indemnity,\r
+ or other liability obligations and/or rights consistent with this\r
+ License. However, in accepting such obligations, You may act only\r
+ on Your own behalf and on Your sole responsibility, not on behalf\r
+ of any other Contributor, and only if You agree to indemnify,\r
+ defend, and hold each Contributor harmless for any liability\r
+ incurred by, or claims asserted against, such Contributor by reason\r
+ of your accepting any such warranty or additional liability.\r
+\r
+ END OF TERMS AND CONDITIONS\r
+\r
+ APPENDIX: How to apply the Apache License to your work.\r
+\r
+ To apply the Apache License to your work, attach the following\r
+ boilerplate notice, with the fields enclosed by brackets "[]"\r
+ replaced with your own identifying information. (Don't include\r
+ the brackets!) The text should be enclosed in the appropriate\r
+ comment syntax for the file format. We also recommend that a\r
+ file or class name and description of purpose be included on the\r
+ same "printed page" as the copyright notice for easier\r
+ identification within third-party archives.\r
+\r
+ Copyright [yyyy] [name of copyright owner]\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
--- /dev/null
+Copyright (c) Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE.APLv2 file for Apache License terms and conditions.
--- /dev/null
+<manifest>
+ <define>
+ <domain name="bt_agent"/>
+ <provide>
+ <label name="bt_agent::bt_hfp_agent"/>
+ <label name="bt_agent::bt_map_agent"/>
+ <label name="bt_agent::bt_pb_agent"/>
+ </provide>
+ </define>
+ <request>
+ <domain name="_"/>
+ </request>
+ <assign>
+ <filesystem path="/usr/bin/bluetooth-hfp-agent" label="bt_agent::bt_hfp_agent"/>
+ <filesystem path="/usr/bin/bluetooth-map-agent" label="bt_agent::bt_map_agent"/>
+ <filesystem path="/usr/bin/bluetooth-pb-agent" label="bt_agent::bt_pb_agent"/>
+ </assign>
+</manifest>
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(bluetooth-hfp-agent C)
+
+SET(SRCS bluetooth-hfp-agent.c)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs_hfp_agent
+ REQUIRED
+ dbus-glib-1 vconf appsvc contacts-service2 tapi)
+
+FOREACH(flag ${pkgs_hfp_agent_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+FIND_PROGRAM(DBUS_BINDING_TOOL NAMES dbus-binding-tool)
+EXEC_PROGRAM("${DBUS_BINDING_TOOL}"
+ ARGS "--prefix=bt_hfp_agent \\
+ ${CMAKE_CURRENT_SOURCE_DIR}/hfp_agent.xml \\
+ --mode=glib-server \\
+ --output=${CMAKE_CURRENT_SOURCE_DIR}/bluetooth_hfp_agent_glue.h")
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_hfp_agent_LDFLAGS})
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.bluez.hfp_agent.service
+ DESTINATION share/dbus-1/services)
--- /dev/null
+/*
+ * bluetooth-agent
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <signal.h>
+
+#include <TapiUtility.h>
+#include <ITapiSim.h>
+
+#include "vconf.h"
+#include "vconf-keys.h"
+#include "contacts.h"
+#include "appsvc.h"
+
+#include "bluetooth-hfp-agent.h"
+
+static GMainLoop *gmain_loop = NULL;
+static DBusGConnection *g_connection = NULL;
+static DBusConnection *gconn = NULL;
+static gboolean nrec_status = FALSE;
+
+#define BT_ERROR_INTERNAL "InternalError"
+#define BT_ERROR_NOT_AVAILABLE "NotAvailable"
+#define BT_ERROR_NOT_CONNECTED "NotConnected"
+#define BT_ERROR_BUSY "InProgress"
+#define BT_ERROR_INVALID_PARAM "InvalidArguments"
+#define BT_ERROR_ALREADY_EXSIST "AlreadyExists"
+#define BT_ERROR_ALREADY_CONNECTED "Already Connected"
+#define BT_ERROR_NO_MEMORY "No memory"
+#define BT_ERROR_I_O_ERROR "I/O error"
+#define BT_ERROR_OPERATION_NOT_AVAILABLE "Operation currently not available"
+#define BT_ERROR_BATTERY "Battery error "
+#define BT_ERROR_SIGNAL "Signal error"
+#define BT_ERROR_NO_CALL_LOG "No Call log"
+#define BT_ERROR_INVLAID_DTMF "Invalid dtmf"
+
+#define BLUEZ_SERVICE_NAME "org.bluez"
+#define TELEPHONY_CSD_INTERFACE "org.tizen.telephony.csd"
+#define TELEPHONY_CSD_OBJECT_PATH "/org/tizen/csd"
+#define TELEPHONY_APP_INTERFACE "org.tizen.csd.Call.Instance"
+
+#define BT_HFP_AGENT_SET_PROPERTY "SetProperty"
+
+#define BT_HFP_AGENT_OBJECT "/org/bluez/agent/hfp_agent"
+#define BT_HFP_AGENT_INTERFACE "org.bluez.hfp_agent"
+
+#define BT_SIGNAL_ARRAY_MAX 2
+
+/* AT+CSQ : Returns received signal strength indication.
+ Command response: +CSQ: <rssi>,<ber>
+ <ber> is not supported and has a constant value of 99, included for compatibility reasons.
+*/
+#define BT_SIGNAL_QUALITY_BER 99
+
+/*Length of the string used to send telephone number to app-svc
+ format: tel:<number>
+*/
+#define BT_MAX_TEL_NUM_STRING 20
+
+typedef struct {
+ GObject parent;
+} BtHfpAgent;
+
+typedef struct {
+ GObjectClass parent;
+} BtHfpAgentClass;
+
+GType bt_hfp_agent_get_type(void);
+
+#define BT_HFP_TYPE_AGENT (bt_hfp_agent_get_type())
+
+#define BT_HFP_AGENT(object)(G_TYPE_CHECK_INSTANCE_CAST((object), \
+ BT_HFP_TYPE_AGENT , BtHfpAgent))
+
+#define BT_HFP_AGENT_CLASS(klass)(G_TYPE_CHECK_CLASS_CAST((klass), \
+ BT_HFP_TYPE_AGENT , BtHfpAgentClass))
+
+#define BT_IS_HFP_AGENT(object)(G_TYPE_CHECK_INSTANCE_TYPE((object), \
+ BT_HFP_TYPE_AGENT))
+
+#define BT_IS_HFP_AGENT_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE((klass), \
+ BT_HFP_TYPE_AGENT))
+
+#define BT_HFP_AGENT_GET_CLASS(obj)(G_TYPE_INSTANCE_GET_CLASS((obj), \
+ BT_HFP_TYPE_AGENT , BtHfpAgentClass))
+
+G_DEFINE_TYPE(BtHfpAgent, bt_hfp_agent, G_TYPE_OBJECT)
+
+static gboolean bt_hfp_agent_register_application(BtHfpAgent *agent,
+ const gchar *path, DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_unregister_application(BtHfpAgent *agent,
+ const gchar *path, DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_incoming_call(BtHfpAgent *agent, const gchar *path,
+ const gchar *number, gint call_id,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_outgoing_call(BtHfpAgent *agent, const gchar *path,
+ const gchar *number, gint call_id,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_change_call_status(BtHfpAgent *agent,
+ const gchar *path, gint status, gint call_id,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_answer_call(BtHfpAgent *agent, unsigned int call_id,
+ const gchar *path, const gchar *sender,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_release_call(BtHfpAgent *agent, unsigned int call_id,
+ const gchar *path, const gchar *sender,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_reject_call(BtHfpAgent *agent, unsigned int call_id,
+ const gchar *path, const gchar *sender,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_threeway_call(BtHfpAgent *agent, gint call_id,
+ const gchar *path, const gchar *sender,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_dial_last_num(BtHfpAgent *agent,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_dial_num(BtHfpAgent *agent,
+ const gchar *number, guint flags,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_dial_memory(BtHfpAgent *agent, gint location,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_send_dtmf(BtHfpAgent *agent, const gchar *dtmf,
+ const gchar *path, const gchar *sender,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_voice_dial(BtHfpAgent *agent, gboolean activate,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_get_battery_status(BtHfpAgent *object,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_get_signal_quality(BtHfpAgent *object,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_get_properties(BtHfpAgent *agent,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_get_operator_name(BtHfpAgent *object,
+ DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_nrec_status(BtHfpAgent *agent, gboolean status,
+ DBusGMethodInvocation *context);
+
+#include "bluetooth_hfp_agent_glue.h"
+
+static void bt_hfp_agent_init(BtHfpAgent *obj)
+{
+ DBG("+\n");
+
+ g_assert(obj != NULL);
+}
+
+static void bt_hfp_agent_finalize(GObject *obj)
+{
+ DBG("+\n");
+
+ G_OBJECT_CLASS(bt_hfp_agent_parent_class)->finalize(obj);
+}
+
+static void bt_hfp_agent_class_init(BtHfpAgentClass *klass)
+{
+ DBG("+\n");
+
+ GObjectClass *object_class = (GObjectClass *)klass;
+
+ g_assert(klass != NULL);
+
+ object_class->finalize = bt_hfp_agent_finalize;
+
+ dbus_g_object_type_install_info(BT_HFP_TYPE_AGENT,
+ &dbus_glib_bt_hfp_agent_object_info);
+}
+
+static GQuark __bt_hfp_agent_error_quark(void)
+{
+ DBG("+\n");
+
+ static GQuark quark = 0;
+ if (!quark)
+ quark = g_quark_from_static_string("agent");
+
+ return quark;
+}
+
+static GError *__bt_hfp_agent_set_error(bt_hfp_agent_error_t error)
+{
+ DBG("+\n");
+
+ switch (error) {
+ case BT_HFP_AGENT_ERROR_NOT_AVAILABLE:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_NOT_AVAILABLE);
+ case BT_HFP_AGENT_ERROR_NOT_CONNECTED:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_NOT_CONNECTED);
+ case BT_HFP_AGENT_ERROR_BUSY:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_BUSY);
+ case BT_HFP_AGENT_ERROR_INVALID_PARAM:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_INVALID_PARAM);
+ case BT_HFP_AGENT_ERROR_ALREADY_EXSIST:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_ALREADY_EXSIST);
+ case BT_HFP_AGENT_ERROR_ALREADY_CONNECTED:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_ALREADY_CONNECTED);
+ case BT_HFP_AGENT_ERROR_NO_MEMORY:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_NO_MEMORY);
+ case BT_HFP_AGENT_ERROR_I_O_ERROR:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_I_O_ERROR);
+ case BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_OPERATION_NOT_AVAILABLE);
+ case BT_HFP_AGENT_ERROR_BATTERY_STATUS:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_BATTERY);
+ case BT_HFP_AGENT_ERROR_SIGNAL_STATUS:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_SIGNAL);
+ case BT_HFP_AGENT_ERROR_NO_CALL_LOGS:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_NO_CALL_LOG);
+ case BT_HFP_AGENT_ERROR_INTERNAL:
+ default:
+ return g_error_new(BT_HFP_AGENT_ERROR, error,
+ BT_ERROR_INTERNAL);
+ }
+}
+
+static int __bt_hfp_agent_get_error(const char *error_message)
+{
+ if (error_message == NULL) {
+ DBG("Error message NULL\n");
+ return BT_HFP_AGENT_ERROR_INTERNAL;
+ }
+
+ DBG("Error message = %s \n", error_message);
+
+ if (g_strcmp0(error_message, BT_ERROR_NOT_AVAILABLE) == 0)
+ return BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
+ else if (g_strcmp0(error_message, BT_ERROR_NOT_CONNECTED) == 0)
+ return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
+ else if (g_strcmp0(error_message, BT_ERROR_BUSY) == 0)
+ return BT_HFP_AGENT_ERROR_BUSY;
+ else if (g_strcmp0(error_message, BT_ERROR_INVALID_PARAM) == 0)
+ return BT_HFP_AGENT_ERROR_INVALID_PARAM;
+ else if (g_strcmp0(error_message, BT_ERROR_ALREADY_EXSIST) == 0)
+ return BT_HFP_AGENT_ERROR_ALREADY_EXSIST;
+ else if (g_strcmp0(error_message, BT_ERROR_ALREADY_CONNECTED) == 0)
+ return BT_HFP_AGENT_ERROR_ALREADY_CONNECTED;
+ else if (g_strcmp0(error_message, BT_ERROR_NO_MEMORY) == 0)
+ return BT_HFP_AGENT_ERROR_NO_MEMORY;
+ else if (g_strcmp0(error_message, BT_ERROR_I_O_ERROR) == 0)
+ return BT_HFP_AGENT_ERROR_I_O_ERROR;
+ else if (g_strcmp0(error_message,
+ BT_ERROR_OPERATION_NOT_AVAILABLE) == 0)
+ return BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE;
+ else if (g_strcmp0(error_message, BT_ERROR_INVLAID_DTMF) == 0)
+ return BT_HFP_AGENT_ERROR_INVALID_DTMF;
+ else
+ return BT_HFP_AGENT_ERROR_INTERNAL;
+}
+
+static int __bt_hfp_agent_dbus_method_send(const char *service,
+ const char *path, const char *interface,
+ const char *method, gboolean response,
+ int type, ...)
+{
+ DBusMessage *msg;
+ DBusMessage *reply;
+ DBusError err;
+ va_list args;
+ int error;
+
+ DBG("__bt_hfp_agent_dbus_method_send +\n");
+
+ msg = dbus_message_new_method_call(service, path, interface,
+ method);
+ if (!msg) {
+ DBG("Unable to allocate new D-Bus %s message \n", method);
+ return BT_HFP_AGENT_ERROR_INTERNAL;
+ }
+
+ va_start(args, type);
+
+ if (!dbus_message_append_args_valist(msg, type, args)) {
+ dbus_message_unref(msg);
+ va_end(args);
+ return BT_HFP_AGENT_ERROR_INTERNAL;
+ }
+
+ va_end(args);
+
+ dbus_error_init(&err);
+
+ if (response) {
+ reply = dbus_connection_send_with_reply_and_block(gconn,
+ msg, -1, &err);
+ dbus_message_unref(msg);
+
+ if (!reply) {
+ DBG("Error returned in method call\n");
+ if (dbus_error_is_set(&err)) {
+ error = __bt_hfp_agent_get_error(err.message);
+ dbus_error_free(&err);
+ return error;
+ } else {
+ DBG("Error is not set\n");
+ return BT_HFP_AGENT_ERROR_INTERNAL;
+ }
+ }
+ dbus_message_unref(reply);
+ } else {
+ dbus_connection_send(gconn, msg, NULL);
+ dbus_message_unref(msg);
+ }
+
+ DBG("__bt_hfp_agent_dbus_method_send -\n");
+
+ return BT_HFP_AGENT_ERROR_NONE;
+}
+
+static gboolean bt_hfp_agent_register_application(BtHfpAgent *agent,
+ const gchar *path, DBusGMethodInvocation *context)
+{
+ gboolean flag = TRUE;
+ char *sender;
+ GError *error;
+ int ret;
+
+ DBG("bt_hfp_agent_register_application + \n");
+
+ if (path == NULL) {
+ DBG("Invalid Argument path\n");
+ error = __bt_hfp_agent_set_error(
+ BT_HFP_AGENT_ERROR_INVALID_PARAM);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ DBG("Application path = %s\n", path);
+
+ sender = dbus_g_method_get_sender(context);
+
+ DBG("Sender = %s\n", sender);
+
+ ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
+ TELEPHONY_CSD_OBJECT_PATH,
+ TELEPHONY_CSD_INTERFACE,
+ "RegisterTelephonyAgent", TRUE,
+ DBUS_TYPE_BOOLEAN, &flag,
+ DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_STRING, &sender, DBUS_TYPE_INVALID);
+ g_free(sender);
+
+ if (ret != BT_HFP_AGENT_ERROR_NONE) {
+ error = __bt_hfp_agent_set_error(ret);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ dbus_g_method_return(context);
+
+ DBG("bt_hfp_agent_register_application - \n");
+ return TRUE;
+}
+
+static gboolean bt_hfp_agent_unregister_application(BtHfpAgent *agent,
+ const gchar *path, DBusGMethodInvocation *context)
+{
+ gboolean flag = FALSE;
+ char *sender;
+ GError *error;
+ int ret;
+
+ DBG("bt_hfp_agent_unregister_application + \n");
+
+ if (path == NULL) {
+ DBG("Invalid Argument path\n");
+ error = __bt_hfp_agent_set_error(
+ BT_HFP_AGENT_ERROR_INVALID_PARAM);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ DBG("Application path = %s \n", path);
+
+ sender = dbus_g_method_get_sender(context);
+
+ DBG("Sender = %s\n", sender);
+
+ ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
+ TELEPHONY_CSD_OBJECT_PATH,
+ TELEPHONY_CSD_INTERFACE,
+ "RegisterTelephonyAgent", TRUE,
+ DBUS_TYPE_BOOLEAN, &flag,
+ DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_STRING, &sender, DBUS_TYPE_INVALID);
+ g_free(sender);
+
+ if (ret != BT_HFP_AGENT_ERROR_NONE) {
+ error = __bt_hfp_agent_set_error(ret);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ dbus_g_method_return(context);
+
+ DBG("bt_hfp_agent_unregister_application - \n");
+ return TRUE;
+}
+
+static gboolean bt_hfp_agent_incoming_call(BtHfpAgent *agent, const gchar *path,
+ const gchar *number, gint call_id,
+ DBusGMethodInvocation *context)
+{
+ GError *error;
+ char *sender;
+ int ret;
+
+ DBG("bt_hfp_agent_incoming_call + \n");
+
+ if (path == NULL || number == NULL) {
+ DBG("Invalid Arguments\n");
+ error = __bt_hfp_agent_set_error(
+ BT_HFP_AGENT_ERROR_INVALID_PARAM);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ DBG("Application path = %s\n", path);
+ DBG("Phone number = %s\n", number);
+ DBG("Call id = %d\n", call_id);
+
+ sender = dbus_g_method_get_sender(context);
+
+ DBG("Sender = %s\n", sender);
+
+ ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
+ TELEPHONY_CSD_OBJECT_PATH,
+ TELEPHONY_CSD_INTERFACE,
+ "Incoming", TRUE,
+ DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_STRING, &number,
+ DBUS_TYPE_UINT32, &call_id,
+ DBUS_TYPE_STRING, &sender,
+ DBUS_TYPE_INVALID);
+ g_free(sender);
+
+ if (ret != BT_HFP_AGENT_ERROR_NONE) {
+ error = __bt_hfp_agent_set_error(ret);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ dbus_g_method_return(context);
+
+ DBG("bt_hfp_agent_incoming_call - \n");
+ return TRUE;
+}
+
+static gboolean bt_hfp_agent_outgoing_call(BtHfpAgent *agent, const gchar *path,
+ const gchar *number, gint call_id,
+ DBusGMethodInvocation *context)
+{
+ GError *error;
+ char *sender;
+ int ret;
+
+ DBG("bt_hfp_agent_outgoing_call + \n");
+
+ if (path == NULL || number == NULL) {
+ DBG("Invalid Arguments\n");
+ error = __bt_hfp_agent_set_error(
+ BT_HFP_AGENT_ERROR_INVALID_PARAM);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ DBG("Application path = %s\n", path);
+ DBG("Phone number = %s\n", number);
+ DBG("Call id = %d\n", call_id);
+
+ sender = dbus_g_method_get_sender(context);
+
+ DBG("Sender = %s\n", sender);
+
+ ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
+ TELEPHONY_CSD_OBJECT_PATH,
+ TELEPHONY_CSD_INTERFACE,
+ "Outgoing", TRUE,
+ DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_STRING, &number,
+ DBUS_TYPE_UINT32, &call_id,
+ DBUS_TYPE_STRING, &sender,
+ DBUS_TYPE_INVALID);
+ g_free(sender);
+
+ if (ret != BT_HFP_AGENT_ERROR_NONE) {
+ error = __bt_hfp_agent_set_error(ret);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ dbus_g_method_return(context);
+
+ DBG("bt_hfp_agent_outgoing_call - \n");
+ return TRUE;
+}
+
+static gboolean bt_hfp_agent_change_call_status(BtHfpAgent *agent,
+ const gchar *path, gint status, gint call_id,
+ DBusGMethodInvocation *context)
+{
+ GError *error;
+ char *sender;
+ int ret;
+
+ DBG("bt_hfp_agent_change_call_status + \n");
+
+ if (path == NULL) {
+ DBG("Invalid Argument path\n");
+ error = __bt_hfp_agent_set_error(
+ BT_HFP_AGENT_ERROR_INVALID_PARAM);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ DBG("Application path = %s\n", path);
+ DBG("Status = %d\n", status);
+ DBG("Call id = %d\n", call_id);
+
+ sender = dbus_g_method_get_sender(context);
+
+ DBG("Sender = %s\n", sender);
+
+ ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
+ TELEPHONY_CSD_OBJECT_PATH,
+ TELEPHONY_CSD_INTERFACE,
+ "SetCallStatus", TRUE,
+ DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_UINT32, &status,
+ DBUS_TYPE_UINT32, &call_id,
+ DBUS_TYPE_STRING, &sender,
+ DBUS_TYPE_INVALID);
+ g_free(sender);
+
+ if (ret != BT_HFP_AGENT_ERROR_NONE) {
+ error = __bt_hfp_agent_set_error(ret);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ dbus_g_method_return(context);
+
+ DBG("bt_hfp_agent_change_call_status - \n");
+ return TRUE;
+}
+
+static gboolean bt_hfp_agent_answer_call(BtHfpAgent *agent, unsigned int call_id,
+ const gchar *path, const gchar *sender,
+ DBusGMethodInvocation *context)
+{
+ int ret;
+ GError *error;
+ DBG("+\n");
+
+ if (path == NULL || sender == NULL) {
+ DBG("Invalid Arguments\n");
+ error = __bt_hfp_agent_set_error(
+ BT_HFP_AGENT_ERROR_INVALID_PARAM);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ DBG("Application path = %s \n", path);
+ DBG("Call Id = %d", call_id);
+ DBG("Sender = %s\n", sender);
+
+ ret = __bt_hfp_agent_dbus_method_send(sender,
+ path, TELEPHONY_APP_INTERFACE,
+ "Answer", FALSE,
+ DBUS_TYPE_UINT32, &call_id,
+ DBUS_TYPE_INVALID);
+
+ if (ret != BT_HFP_AGENT_ERROR_NONE) {
+ error = __bt_hfp_agent_set_error(ret);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ dbus_g_method_return(context);
+
+ DBG("-\n");
+ return TRUE;
+}
+
+static gboolean bt_hfp_agent_release_call(BtHfpAgent *agent, unsigned int call_id,
+ const gchar *path, const gchar *sender,
+ DBusGMethodInvocation *context)
+{
+ int ret;
+ GError *error;
+ DBG("+\n");
+
+ if (path == NULL || sender == NULL) {
+ DBG("Invalid Arguments\n");
+ error = __bt_hfp_agent_set_error(
+ BT_HFP_AGENT_ERROR_INVALID_PARAM);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ DBG("Application path = %s \n", path);
+ DBG("Call Id = %d", call_id);
+ DBG("Sender = %s\n", sender);
+
+ ret = __bt_hfp_agent_dbus_method_send(sender,
+ path, TELEPHONY_APP_INTERFACE,
+ "Release", FALSE,
+ DBUS_TYPE_UINT32, &call_id,
+ DBUS_TYPE_INVALID);
+
+ if (ret != BT_HFP_AGENT_ERROR_NONE) {
+ error = __bt_hfp_agent_set_error(ret);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ dbus_g_method_return(context);
+ DBG("-\n");
+ return TRUE;
+}
+
+static gboolean bt_hfp_agent_reject_call(BtHfpAgent *agent, unsigned int call_id,
+ const gchar *path, const gchar *sender,
+ DBusGMethodInvocation *context)
+{
+ int ret;
+ GError *error;
+ DBG("+\n");
+
+ if (path == NULL || sender == NULL) {
+ DBG("Invalid Arguments\n");
+ error = __bt_hfp_agent_set_error(
+ BT_HFP_AGENT_ERROR_INVALID_PARAM);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ DBG("Application path = %s \n", path);
+ DBG("Call Id = %d", call_id);
+ DBG("Sender = %s\n", sender);
+
+ ret = __bt_hfp_agent_dbus_method_send(sender,
+ path, TELEPHONY_APP_INTERFACE,
+ "Reject", FALSE,
+ DBUS_TYPE_UINT32, &call_id,
+ DBUS_TYPE_INVALID);
+
+ if (ret != BT_HFP_AGENT_ERROR_NONE) {
+ error = __bt_hfp_agent_set_error(ret);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ dbus_g_method_return(context);
+ DBG("-\n");
+ return TRUE;
+}
+
+static gboolean bt_hfp_agent_threeway_call(BtHfpAgent *agent, gint value,
+ const gchar *path, const gchar *sender,
+ DBusGMethodInvocation *context)
+{
+ int ret;
+ GError *error;
+ DBG("+\n");
+
+ if (path == NULL || sender == NULL) {
+ DBG("Invalid Arguments\n");
+ error = __bt_hfp_agent_set_error(
+ BT_HFP_AGENT_ERROR_INVALID_PARAM);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ DBG("Application path = %s \n", path);
+ DBG("Value = %d", value);
+ DBG("Sender = %s\n", sender);
+
+ ret = __bt_hfp_agent_dbus_method_send(sender,
+ path, TELEPHONY_APP_INTERFACE,
+ "Threeway", TRUE,
+ DBUS_TYPE_UINT32, &value,
+ DBUS_TYPE_INVALID);
+
+ if (ret != BT_HFP_AGENT_ERROR_NONE) {
+ error = __bt_hfp_agent_set_error(ret);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ dbus_g_method_return(context);
+ DBG("-\n");
+ return TRUE;
+}
+
+void __bt_append_entry(DBusMessageIter *iter,
+ const char *key, int type, void *val)
+{
+ DBusMessageIter entry;
+ DBusMessageIter value;
+ const char *str;
+ char signal[BT_SIGNAL_ARRAY_MAX] = { type, '\0' };
+
+ if (type == DBUS_TYPE_STRING) {
+ str = *((const char **) val);
+ if (str == NULL) {
+ return;
+ }
+ }
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+ signal, &value);
+
+ dbus_message_iter_append_basic(&value, type, val);
+
+ dbus_message_iter_close_container(&entry, &value);
+
+ dbus_message_iter_close_container(iter, &entry);
+}
+
+static gboolean bt_hfp_agent_get_properties(BtHfpAgent *agent,
+ DBusGMethodInvocation *context)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusMessageIter dict;
+ GError *error;
+
+ DBG("bt_hfp_agent_get_properties + \n");
+
+ reply = dbus_g_method_get_reply(context);
+ if (!reply) {
+ error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_INTERNAL);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+ __bt_append_entry(&dict, "nrec", DBUS_TYPE_BOOLEAN, &nrec_status);
+ dbus_message_iter_close_container(&iter, &dict);
+ dbus_g_method_send_reply(context, reply);
+ DBG("bt_hfp_agent_get_properties - \n");
+ return TRUE;
+}
+
+static gboolean __bt_hfp_agent_make_call(const char *number)
+{
+ bundle *b;
+ char telnum[BT_MAX_TEL_NUM_STRING];
+
+ b = bundle_create();
+ if (NULL == b)
+ return FALSE;
+
+ appsvc_set_operation(b, APPSVC_OPERATION_CALL);
+ snprintf(telnum, sizeof(telnum), "tel:%s", number);
+ appsvc_set_uri(b, telnum);
+ appsvc_add_data(b, "ctindex", "-1");
+ appsvc_run_service(b, 0, NULL, NULL);
+ bundle_free(b);
+
+ return TRUE;
+}
+
+static gboolean bt_hfp_agent_dial_last_num(BtHfpAgent *agent,
+ DBusGMethodInvocation *context)
+{
+ GError *error;
+ int error_code = BT_HFP_AGENT_ERROR_NONE;
+ char *last_number = NULL;
+ contacts_list_h list = NULL;
+ contacts_query_h query = NULL;
+ contacts_filter_h filter = NULL;
+ contacts_record_h record = NULL;
+ unsigned int projections[] = {
+ _contacts_phone_log.address,
+ };
+
+ DBG("+ \n");
+
+ if (contacts_connect2() != CONTACTS_ERROR_NONE) {
+ ERR(" contacts_connect2 failed \n");
+ error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_INTERNAL);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ contacts_filter_create(_contacts_phone_log._uri, &filter);
+
+ if (filter == NULL)
+ goto done;
+
+ if (contacts_filter_add_int(filter, _contacts_phone_log.log_type,
+ CONTACTS_MATCH_EQUAL,
+ CONTACTS_PLOG_TYPE_VOICE_OUTGOING) !=
+ CONTACTS_ERROR_NONE) {
+ ERR(" contacts_filter_add_int failed \n");
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ if (contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_OR) !=
+ CONTACTS_ERROR_NONE) {
+ ERR(" contacts_filter_add_operator failed \n");
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ if (contacts_filter_add_int(filter, _contacts_phone_log.log_type,
+ CONTACTS_MATCH_EQUAL,
+ CONTACTS_PLOG_TYPE_VIDEO_OUTGOING) !=
+ CONTACTS_ERROR_NONE) {
+ ERR(" contacts_filter_add_int failed \n");
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ contacts_query_create(_contacts_phone_log._uri, &query);
+
+ if (query == NULL)
+ goto done;
+
+ contacts_query_set_filter(query, filter);
+
+ if (contacts_query_set_projection(query, projections,
+ sizeof(projections)/sizeof(unsigned int)) !=
+ CONTACTS_ERROR_NONE) {
+ ERR(" contacts_query_set_projection failed \n");
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ if (contacts_query_set_sort(query, _contacts_phone_log.log_time, false) !=
+ CONTACTS_ERROR_NONE) {
+ ERR(" contacts_query_set_sort failed \n");
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ if (contacts_db_get_records_with_query(query, 0, 1, &list) !=
+ CONTACTS_ERROR_NONE) {
+ ERR(" contacts_db_get_records_with_query failed \n");
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ if (contacts_list_first(list) != CONTACTS_ERROR_NONE) {
+ ERR(" contacts_list_first failed \n");
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ if (contacts_list_get_current_record_p(list, &record) !=
+ CONTACTS_ERROR_NONE) {
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ if (record == NULL)
+ goto done;
+
+ contacts_record_get_str(record, _contacts_phone_log.address,
+ &last_number);
+
+ if (last_number == NULL) {
+ ERR("No last number \n");
+ error_code = BT_HFP_AGENT_ERROR_NO_CALL_LOGS;
+ goto done;
+ }
+
+ /*Make Voice call*/
+ if (!__bt_hfp_agent_make_call(last_number)) {
+ ERR("Problem launching application \n");
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ }
+
+ g_free(last_number);
+
+done:
+ if (list != NULL)
+ contacts_list_destroy(list, TRUE);
+
+ if (filter != NULL)
+ contacts_filter_destroy(filter);
+
+ if (query != NULL)
+ contacts_query_destroy(query);
+
+ contacts_disconnect2();
+
+ DBG("-\n");
+
+ if (error_code == BT_HFP_AGENT_ERROR_NONE) {
+ dbus_g_method_return(context);
+ return TRUE;
+ } else {
+ error = __bt_hfp_agent_set_error(error_code);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+}
+
+static gboolean bt_hfp_agent_dial_num(BtHfpAgent *agent,
+ const gchar *number, guint flags,
+ DBusGMethodInvocation *context)
+{
+ GError *error;
+ int error_code;
+
+ DBG("+\n");
+
+ if (number == NULL) {
+ ERR("Invalid Argument\n");
+ error_code = BT_HFP_AGENT_ERROR_INVALID_PARAM;
+ goto fail;
+ }
+
+ DBG("Number = %s \n", number);
+ DBG("flags = %d", flags);
+
+ /*TODO: Make use of flags*/
+
+ /*Make Voice call*/
+ if (!__bt_hfp_agent_make_call(number)) {
+ ERR("Problem launching application \n");
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto fail;
+ }
+
+ dbus_g_method_return(context);
+
+ DBG("-\n");
+ return TRUE;
+fail:
+ error = __bt_hfp_agent_set_error(error_code);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ DBG("-\n");
+ return FALSE;
+}
+
+static gboolean bt_hfp_agent_dial_memory(BtHfpAgent *agent, gint location,
+ DBusGMethodInvocation *context)
+{
+ GError *error;
+ int error_code = BT_HFP_AGENT_ERROR_NONE;
+ char *number = NULL;
+ contacts_filter_h filter = NULL;
+ contacts_query_h query = NULL;
+ contacts_list_h list = NULL;
+ contacts_record_h record = NULL;
+ unsigned int projections[] = {
+ _contacts_speeddial.number,
+ };
+
+ DBG("+\n");
+
+ DBG("location = %d \n", location);
+
+ /*Get number from contacts location*/
+ if (contacts_connect2() != CONTACTS_ERROR_NONE) {
+ ERR(" contacts_connect2 failed \n");
+ error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_INTERNAL);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ contacts_filter_create(_contacts_speeddial._uri, &filter);
+
+ if (filter == NULL)
+ goto done;
+
+ if (contacts_filter_add_int(filter, _contacts_speeddial.speeddial_number,
+ CONTACTS_MATCH_EQUAL, location) !=
+ CONTACTS_ERROR_NONE) {
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ contacts_query_create(_contacts_speeddial._uri, &query);
+
+ if (query == NULL)
+ goto done;
+
+ contacts_query_set_filter(query, filter);
+
+ if (contacts_query_set_projection(query, projections,
+ sizeof(projections)/sizeof(unsigned int)) !=
+ CONTACTS_ERROR_NONE) {
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ if (contacts_db_get_records_with_query(query, 0, 1, &list) !=
+ CONTACTS_ERROR_NONE) {
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ if (contacts_list_first(list) != CONTACTS_ERROR_NONE) {
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ if (contacts_list_get_current_record_p(list, &record) !=
+ CONTACTS_ERROR_NONE) {
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto done;
+ }
+
+ if (record == NULL)
+ goto done;
+
+ contacts_record_get_str(record, _contacts_speeddial.number,
+ &number);
+
+ if (number == NULL) {
+ ERR("No number at the location \n");
+ error_code = BT_HFP_AGENT_ERROR_INVALID_MEMORY_INDEX;
+ goto done;
+ }
+
+ DBG("number %s\n", number);
+
+ /*Make Voice call*/
+ if (!__bt_hfp_agent_make_call(number)) {
+ ERR("Problem launching application \n");
+ error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+ }
+
+ g_free(number);
+done:
+ if (list != NULL)
+ contacts_list_destroy(list, TRUE);
+
+ if (filter != NULL)
+ contacts_filter_destroy(filter);
+
+ if (query != NULL)
+ contacts_query_destroy(query);
+
+ contacts_disconnect2();
+
+ DBG("-\n");
+
+ if (error_code == BT_HFP_AGENT_ERROR_NONE) {
+ dbus_g_method_return(context);
+ return TRUE;
+ } else {
+ error = __bt_hfp_agent_set_error(error_code);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+}
+
+static gboolean bt_hfp_agent_send_dtmf(BtHfpAgent *agent, const gchar *dtmf,
+ const gchar *path, const gchar *sender,
+ DBusGMethodInvocation *context)
+{
+ GError *error;
+ int ret;
+
+ DBG("+\n");
+
+ if (dtmf == NULL || path == NULL || sender == NULL) {
+ ERR("Invalid Argument\n");
+ error = __bt_hfp_agent_set_error(
+ BT_HFP_AGENT_ERROR_INVALID_PARAM);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ DBG("Dtmf = %s \n", dtmf);
+ DBG("Application path = %s \n", path);
+ DBG("Sender = %s\n", sender);
+
+ ret = __bt_hfp_agent_dbus_method_send(sender,
+ path, TELEPHONY_APP_INTERFACE,
+ "SendDtmf", FALSE,
+ DBUS_TYPE_STRING, &dtmf,
+ DBUS_TYPE_INVALID);
+
+ if (ret != BT_HFP_AGENT_ERROR_NONE) {
+ error = __bt_hfp_agent_set_error(ret);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ /*App Selector code here needed*/
+ dbus_g_method_return(context);
+
+ DBG("-\n");
+ return TRUE;
+}
+
+static gboolean bt_hfp_agent_voice_dial(BtHfpAgent *agent, gboolean activate,
+ DBusGMethodInvocation *context)
+{
+ DBG("+\n");
+
+ DBG("Activate = %d \n", activate);
+
+ /*App Selector code here needed*/
+ dbus_g_method_return(context);
+
+ DBG("-\n");
+ return TRUE;
+}
+
+static gboolean bt_hfp_agent_get_battery_status(BtHfpAgent *object,
+ DBusGMethodInvocation *context)
+{
+ gint battery_chrg_status;
+ gint battery_capacity;
+ GError *error;
+
+ DBG("+\n");
+
+ if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
+ &battery_chrg_status)) {
+ DBG("VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW failed\n");
+ goto fail;
+ }
+
+ DBG("Status : %d\n", battery_chrg_status);
+
+ if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
+ &battery_capacity)) {
+ DBG("VCONFKEY_SYSMAN_BATTERY_CAPACITY failed\n");
+ goto fail;
+ }
+
+ DBG("Capacity : %d\n", battery_capacity);
+
+ dbus_g_method_return(context, battery_chrg_status, battery_capacity);
+ DBG("-\n");
+ return TRUE;
+
+fail:
+ error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_BATTERY_STATUS);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ DBG("-\n");
+ return FALSE;
+}
+
+static gboolean bt_hfp_agent_get_signal_quality(BtHfpAgent *object,
+ DBusGMethodInvocation *context)
+{
+ gint rssi;
+ GError *error;
+
+ DBG("+\n");
+
+ if (vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &rssi)) {
+ DBG("VCONFKEY_TELEPHONY_RSSI failed\n");
+ goto fail;
+ }
+
+ DBG("RSSI : %d \n", rssi);
+
+ dbus_g_method_return(context, rssi, BT_SIGNAL_QUALITY_BER);
+ DBG("-\n");
+ return TRUE;
+fail:
+ error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_SIGNAL_STATUS);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ DBG("-\n");
+ return FALSE;
+}
+
+static gboolean bt_hfp_agent_get_operator_name(BtHfpAgent *object,
+ DBusGMethodInvocation *context)
+{
+ char *operator_name;
+ GError *error;
+
+ DBG(" +\n");
+
+ operator_name = vconf_get_str(VCONFKEY_TELEPHONY_NWNAME);
+ if (NULL == operator_name) {
+ DBG("vconf_get_str failed \n");
+ error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_INTERNAL);
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ DBG("operator_name = [%s] \n", operator_name);
+
+ dbus_g_method_return(context, operator_name);
+ free(operator_name);
+
+ DBG(" -\n");
+ return TRUE;
+}
+
+static gboolean bt_hfp_agent_nrec_status(BtHfpAgent *agent, gboolean status,
+ DBusGMethodInvocation *context)
+{
+ DBusMessage *signal;
+
+ DBG("+\n");
+
+ DBG("NREC status = %d \n", status);
+ nrec_status = status;
+ dbus_g_method_return(context);
+
+ /*Emit NREC Status change signal with value*/
+ signal = dbus_message_new_signal(BT_HFP_AGENT_OBJECT,
+ BT_HFP_AGENT_INTERFACE,
+ "NrecStatusChanged");
+ if (!signal)
+ return FALSE;
+
+ if (!dbus_message_append_args(signal,
+ DBUS_TYPE_BOOLEAN, &status,
+ DBUS_TYPE_INVALID)) {
+ DBG("Signal appending failed\n");
+ dbus_message_unref(signal);
+ return FALSE;
+ }
+
+ dbus_connection_send(gconn, signal, NULL);
+ dbus_message_unref(signal);
+ DBG("-\n");
+ return TRUE;
+}
+
+static void __bt_hfp_agent_append_variant(DBusMessageIter *iter,
+ int type, void *val)
+{
+ DBusMessageIter value_iter;
+ const char *variant;
+
+ switch (type) {
+ case DBUS_TYPE_BOOLEAN:
+ variant = DBUS_TYPE_BOOLEAN_AS_STRING;
+ break;
+ case DBUS_TYPE_STRING:
+ variant = DBUS_TYPE_STRING_AS_STRING;
+ break;
+ case DBUS_TYPE_BYTE:
+ variant = DBUS_TYPE_BYTE_AS_STRING;
+ break;
+ case DBUS_TYPE_UINT16:
+ variant = DBUS_TYPE_UINT16_AS_STRING;
+ break;
+ case DBUS_TYPE_UINT32:
+ variant = DBUS_TYPE_UINT32_AS_STRING;
+ break;
+ case DBUS_TYPE_INT16:
+ variant = DBUS_TYPE_INT16_AS_STRING;
+ break;
+ case DBUS_TYPE_INT32:
+ variant = DBUS_TYPE_INT32_AS_STRING;
+ break;
+ case DBUS_TYPE_OBJECT_PATH:
+ variant = DBUS_TYPE_OBJECT_PATH_AS_STRING;
+ break;
+ default:
+ variant = DBUS_TYPE_VARIANT_AS_STRING;
+ break;
+ }
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, variant,
+ &value_iter);
+ dbus_message_iter_append_basic(&value_iter, type, val);
+ dbus_message_iter_close_container(iter, &value_iter);
+}
+
+static gboolean __bt_hfp_agent_dbus_method_variant_send(const char *path,
+ const char *interface, const char *method, const char *name,
+ int type, void *value)
+{
+ DBusMessage *msg;
+ DBusMessage *reply;
+ DBusError err;
+ DBusMessageIter iter;
+
+ DBG(" +\n");
+
+ msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME,
+ path, interface, method);
+
+ if (!msg) {
+ DBG("Unable to allocate new D-Bus %s message", method);
+ return FALSE;
+ }
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
+
+ __bt_hfp_agent_append_variant(&iter, type, value);
+
+ dbus_error_init(&err);
+
+ reply = dbus_connection_send_with_reply_and_block(gconn,
+ msg, -1, &err);
+
+ dbus_message_unref(msg);
+
+ if (!reply) {
+ DBG("Error returned in method call\n");
+ if (dbus_error_is_set(&err)) {
+ if (err.message != NULL) {
+ DBG("Error message = %s\n", err.message);
+ }
+ dbus_error_free(&err);
+ }
+ return FALSE;
+ }
+
+ dbus_message_unref(reply);
+
+ DBG(" -\n");
+ return TRUE;
+}
+
+static gboolean __bt_hfp_agent_send_registration_status_changed(
+ bt_hfp_agent_network_registration_status_t status)
+{
+ const char *property = g_strdup("RegistrationChanged");
+
+ DBG(" +\n");
+
+ if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
+ TELEPHONY_CSD_INTERFACE,
+ BT_HFP_AGENT_SET_PROPERTY,
+ property, DBUS_TYPE_BYTE, &status)) {
+ DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
+ g_free((void *)property);
+ return FALSE;
+ }
+ DBG(" -\n");
+
+ g_free((void *)property);
+ return TRUE;
+}
+
+static gboolean __bt_hfp_agent_send_subscriber_number_changed(
+ const char *number)
+{
+ const char *property = g_strdup("SubscriberNumberChanged");
+
+ DBG(" +\n");
+
+ if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
+ TELEPHONY_CSD_INTERFACE,
+ BT_HFP_AGENT_SET_PROPERTY,
+ property,
+ DBUS_TYPE_STRING, &number)) {
+ DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
+ g_free((void *)property);
+ return FALSE;
+ }
+
+ DBG(" -\n");
+ g_free((void *)property);
+ return TRUE;
+}
+
+static gboolean __bt_hfp_agent_send_signal_bar_changed(int signal_bar)
+{
+ const char *property = g_strdup("SignalBarsChanged");
+
+ DBG(" +\n");
+
+ if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
+ TELEPHONY_CSD_INTERFACE,
+ BT_HFP_AGENT_SET_PROPERTY,
+ property, DBUS_TYPE_INT32, &signal_bar)) {
+ DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
+ g_free((void *)property);
+ return FALSE;
+ }
+
+ g_free((void *)property);
+ DBG(" -\n");
+ return TRUE;
+}
+
+static gboolean __bt_hfp_agent_send_battery_level_changed(int battery_level)
+{
+ const char *property = g_strdup("BatteryBarsChanged");
+ int battery_status;
+
+ DBG(" +\n");
+
+ /* We need to send battery status ranging from 0-5 */
+ if (battery_level < 5)
+ battery_status = 0;
+ else if (battery_level >= 100)
+ battery_status = 5;
+ else
+ battery_status = battery_level / 20 + 1;
+
+ if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
+ TELEPHONY_CSD_INTERFACE,
+ BT_HFP_AGENT_SET_PROPERTY,
+ property,
+ DBUS_TYPE_INT32, &battery_status)) {
+ DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
+ g_free((void *)property);
+ return FALSE;
+ }
+
+ DBG(" -\n");
+ g_free((void *)property);
+ return TRUE;
+}
+
+static void __bt_hfp_agent_send_battery_level(void)
+{
+ int ret;
+ int batt;
+
+ DBG(" +\n");
+
+ ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, &batt);
+ if (ret != 0) {
+ DBG("vconf_get_int failed err = %d \n", ret);
+ return;
+ }
+
+ DBG("Current battery Level = [%d] \n", batt);
+
+ __bt_hfp_agent_send_battery_level_changed(batt);
+
+ DBG(" -\n");
+}
+
+static void __bt_hfp_agent_send_signal_status(void)
+{
+ int ret;
+ int signal_level;
+
+ DBG(" +\n");
+
+ ret = vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &signal_level);
+ if (ret != 0) {
+ DBG("vconf_get_int failed err = %d \n", ret);
+ return;
+ }
+
+ DBG("Current Signal Level = [%d] \n", signal_level);
+
+ __bt_hfp_agent_send_signal_bar_changed(signal_level);
+
+ DBG(" -\n");
+}
+
+static void __bt_hfp_agent_network_send( int service, int roam_status)
+{
+ int ret;
+ bt_hfp_agent_network_registration_status_t network_service;
+
+ DBG(" +\n");
+
+ switch (service) {
+ case VCONFKEY_TELEPHONY_SVCTYPE_NONE:
+ case VCONFKEY_TELEPHONY_SVCTYPE_NOSVC:
+ case VCONFKEY_TELEPHONY_SVCTYPE_SEARCH:
+ service = 0;
+ break;
+ default:
+ service = 1;
+ break;
+ }
+
+ ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
+ if (ret != 0) {
+ DBG("Get roaming status failed err = %d\n", ret);
+ return;
+ }
+
+ if (roam_status == 0 && service == 1)
+ network_service = BT_HFP_AGENT_NETWORK_REG_STATUS_HOME;
+ else if (roam_status == 1 && service == 1)
+ network_service = BT_HFP_AGENT_NETWORK_REG_STATUS_ROAMING;
+ else
+ network_service = BT_HFP_AGENT_NETWORK_REG_STATUS_UNKOWN;
+
+ DBG("Network service = %d\n", network_service);
+
+ __bt_hfp_agent_send_registration_status_changed(network_service);
+
+ DBG(" -\n");
+}
+
+static void __bt_hfp_agent_send_network_status(void)
+{
+ int ret;
+ int roam_status;
+ int service;
+
+
+ DBG(" +\n");
+
+ ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
+ if (ret != 0) {
+ DBG("vconf_get_int failed for \n");
+ return;
+ }
+
+ DBG("roam_status = [%d] \n", roam_status);
+
+ ret = vconf_get_int(VCONFKEY_TELEPHONY_SVCTYPE, &service);
+ if (ret != 0) {
+ DBG("vconf_get_int failed\n");
+ return;
+ }
+
+ DBG("service = [%d] \n", service);
+
+ __bt_hfp_agent_network_send(service, roam_status);
+
+ DBG(" -\n");
+}
+
+static void __bt_hfp_agent_send_vconf_values(void)
+{
+ __bt_hfp_agent_send_battery_level();
+ __bt_hfp_agent_send_signal_status();
+ __bt_hfp_agent_send_network_status();
+}
+
+static void __bt_hfp_agent_battery_status_cb(keynode_t *node)
+{
+ int batt = vconf_keynode_get_int(node);
+
+ DBG(" +\n");
+
+ DBG("Current Battery Level = [%d] \n", batt);
+
+ __bt_hfp_agent_send_battery_level_changed(batt);
+
+ DBG(" -\n");
+}
+
+static void __bt_hfp_agent_network_signal_status_cb(keynode_t *node)
+{
+ int signal_bar = vconf_keynode_get_int(node);
+
+ DBG(" +\n");
+
+ DBG("Current Signal Level = [%d] \n", signal_bar);
+
+ __bt_hfp_agent_send_signal_bar_changed(signal_bar);
+
+ DBG(" -\n");
+}
+
+static void __bt_hfp_agent_network_register_status_cb(keynode_t *node)
+{
+ int service = vconf_keynode_get_int(node);
+ int roam_status;
+ int ret;
+
+ DBG(" +\n");
+
+ DBG("Current Signal Level = [%d] \n", service);
+
+ ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
+ if (ret != 0) {
+ DBG("Get roaming status failed err = %d\n", ret);
+ return;
+ }
+
+ __bt_hfp_agent_network_send(service, roam_status);
+
+ DBG(" -\n");
+}
+
+static void __bt_hfp_agent_subscribe_vconf_updates(void)
+{
+ int ret;
+
+ DBG(" +\n");
+
+ ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
+ (void *)__bt_hfp_agent_battery_status_cb, NULL);
+ if (0 != ret) {
+ DBG("Subsrciption to battery status failed err = [%d]\n", ret);
+ }
+
+ ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_RSSI,
+ (void *)__bt_hfp_agent_network_signal_status_cb, NULL);
+ if (0 != ret) {
+ DBG("Subsrciption to netowrk signal failed err = [%d]\n", ret);
+ }
+
+ ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
+ (void *)__bt_hfp_agent_network_register_status_cb, NULL);
+ if (0 != ret) {
+ DBG("Subsrciption to network failed err = [%d]\n", ret);
+ }
+
+ DBG(" -\n");
+}
+
+static void __bt_hfp_agent_release_vconf_updates(void)
+{
+ int ret;
+
+ DBG(" +\n");
+
+ ret = vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
+ (vconf_callback_fn)__bt_hfp_agent_battery_status_cb);
+ if (0 != ret) {
+ DBG("vconf_ignore_key_changed failed\n");
+ }
+
+ ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_RSSI,
+ (vconf_callback_fn)__bt_hfp_agent_network_signal_status_cb);
+ if (0 != ret) {
+ DBG("vconf_ignore_key_changed failed\n");
+ }
+
+ ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
+ (vconf_callback_fn)__bt_hfp_agent_network_register_status_cb);
+ if (0 != ret) {
+ DBG("vconf_ignore_key_changed failed\n");
+ }
+
+ DBG(" -\n");
+}
+
+static void __bt_hfp_agent_dbus_init(BtHfpAgent *agent)
+{
+ GError *error = NULL;
+ DBusGProxy *bus_proxy = NULL;
+ guint result;
+
+ g_connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
+ if (error != NULL) {
+ ERR("Failed connection to system bus[%s] \n", error->message);
+ g_error_free(error);
+ return;
+ }
+
+ bus_proxy = dbus_g_proxy_new_for_name(g_connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
+ if (bus_proxy == NULL) {
+ ERR("Failed to get a proxy for D-Bus\n");
+ return;
+ }
+
+ if (!dbus_g_proxy_call(bus_proxy, "RequestName", &error, G_TYPE_STRING,
+ BT_HFP_SERVICE, G_TYPE_UINT, 0, G_TYPE_INVALID,
+ G_TYPE_UINT, &result, G_TYPE_INVALID)) {
+ if (error != NULL) {
+ ERR("RequestName RPC failed[%s]\n", error->message);
+ g_error_free(error);
+ }
+
+ g_object_unref(bus_proxy);
+ return;
+ }
+
+ DBG("result : %d %d\n", result, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ ERR("Failed to get the primary well-known name.\n");
+ g_object_unref(bus_proxy);
+ return;
+ }
+
+ g_object_unref(bus_proxy);
+
+ dbus_g_connection_register_g_object(g_connection,
+ BT_HFP_SERVICE_OBJECT_PATH, G_OBJECT(agent));
+
+ gconn = dbus_g_connection_get_connection(g_connection);
+ if (gconn == NULL) {
+ ERR("Failed to get connection \n");
+ return;
+ }
+
+ __bt_hfp_agent_send_vconf_values();
+ __bt_hfp_agent_subscribe_vconf_updates();
+}
+
+static void __bt_hfp_agent_tel_cb(TapiHandle *handle,
+ int result,
+ void *data,
+ void *user_data)
+{
+ TelSimMsisdnList_t *number;
+ gchar *subscriber_number;
+
+ if (data == NULL)
+ return;
+
+ number = (TelSimMsisdnList_t *)data;
+ subscriber_number = g_strdup(number->list[0].num);
+ __bt_hfp_agent_send_subscriber_number_changed(subscriber_number);
+ g_free(subscriber_number);
+}
+
+static void __bt_hfp_agent_sigterm_handler(int signo)
+{
+ DBG("+\n");
+
+ if (gmain_loop)
+ g_main_loop_quit(gmain_loop);
+ else
+ exit(0);
+
+ DBG("-\n");
+}
+
+int main(void)
+{
+ TapiHandle *handle;
+ BtHfpAgent *bt_hfp_obj = NULL;
+ struct sigaction sa;
+ int tapi_result;
+
+ g_type_init();
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = __bt_hfp_agent_sigterm_handler;
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+
+ gmain_loop = g_main_loop_new(NULL, FALSE);
+
+ if (gmain_loop == NULL) {
+ ERR("GMainLoop create failed \n");
+ return EXIT_FAILURE;
+ }
+
+ bt_hfp_obj = g_object_new(BT_HFP_TYPE_AGENT, NULL);
+ if (bt_hfp_obj == NULL) {
+ ERR("Failed to create BtHfpAgent instance \n");
+ if (gmain_loop)
+ g_main_loop_unref(gmain_loop);
+
+ return EXIT_FAILURE;
+ }
+
+ handle = tel_init(NULL);
+ tapi_result = tel_get_sim_msisdn(handle, __bt_hfp_agent_tel_cb,
+ bt_hfp_obj);
+
+ if(tapi_result != TAPI_API_SUCCESS)
+ ERR("Fail to get sim info: %d", tapi_result);
+
+ __bt_hfp_agent_dbus_init(bt_hfp_obj);
+
+ g_main_loop_run(gmain_loop);
+
+ tel_deinit(handle);
+
+ __bt_hfp_agent_release_vconf_updates();
+
+ if (bt_hfp_obj) {
+ dbus_g_connection_unregister_g_object(g_connection,
+ G_OBJECT(bt_hfp_obj));
+ g_object_unref(bt_hfp_obj);
+ }
+
+ if (g_connection)
+ dbus_g_connection_unref(g_connection);
+
+ if (gmain_loop)
+ g_main_loop_unref(gmain_loop);
+
+ return 0;
+}
--- /dev/null
+/*
+ * bluetooth-agent
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DEF_BT_HFP_AGENT_H_
+#define __DEF_BT_HFP_AGENT_H_
+
+#include <unistd.h>
+#include <dlog.h>
+#include <stdio.h>
+
+#define BT_HFP_AGENT_ERROR (__bt_hfp_agent_error_quark())
+
+typedef enum {
+ BT_HFP_AGENT_NETWORK_REG_STATUS_HOME,
+ BT_HFP_AGENT_NETWORK_REG_STATUS_ROAMING,
+ BT_HFP_AGENT_NETWORK_REG_STATUS_OFFLINE,
+ BT_HFP_AGENT_NETWORK_REG_STATUS_SEARCHING,
+ BT_HFP_AGENT_NETWORK_REG_STATUS_NO_SIM,
+ BT_HFP_AGENT_NETWORK_REG_STATUS_POWEROFF,
+ BT_HFP_AGENT_NETWORK_REG_STATUS_POWERSAFE,
+ BT_HFP_AGENT_NETWORK_REG_STATUS_NO_COVERAGE,
+ BT_HFP_AGENT_NETWORK_REG_STATUS_REJECTED,
+ BT_HFP_AGENT_NETWORK_REG_STATUS_UNKOWN,
+} bt_hfp_agent_network_registration_status_t;
+
+typedef enum {
+ BT_HFP_AGENT_ERROR_INTERNAL,
+ BT_HFP_AGENT_ERROR_NOT_AVAILABLE,
+ BT_HFP_AGENT_ERROR_NOT_CONNECTED,
+ BT_HFP_AGENT_ERROR_BUSY,
+ BT_HFP_AGENT_ERROR_INVALID_PARAM,
+ BT_HFP_AGENT_ERROR_ALREADY_EXSIST,
+ BT_HFP_AGENT_ERROR_ALREADY_CONNECTED,
+ BT_HFP_AGENT_ERROR_NO_MEMORY,
+ BT_HFP_AGENT_ERROR_I_O_ERROR,
+ BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE,
+ BT_HFP_AGENT_ERROR_NO_CALL_LOGS,
+ BT_HFP_AGENT_ERROR_INVALID_MEMORY_INDEX,
+ BT_HFP_AGENT_ERROR_INVALID_CHLD_INDEX,
+ BT_HFP_AGENT_ERROR_BATTERY_STATUS,
+ BT_HFP_AGENT_ERROR_SIGNAL_STATUS,
+ BT_HFP_AGENT_ERROR_NOT_SUPPORTED,
+ BT_HFP_AGENT_ERROR_INVALID_NUMBER,
+ BT_HFP_AGENT_ERROR_APPLICATION,
+ BT_HFP_AGENT_ERROR_INVALID_DTMF,
+ BT_HFP_AGENT_ERROR_NONE,
+} bt_hfp_agent_error_t;
+
+#define BT_HFP_SERVICE_OBJECT_PATH "/org/bluez/hfp_agent"
+#define BT_HFP_SERVICE "org.bluez.hfp_agent"
+
+#undef LOG_TAG
+#define LOG_TAG "BLUETOOTH_AGENT_HFP"
+
+#define DBG(fmt, args...) SLOGD(fmt, ##args)
+#define ERR(fmt, args...) SLOGE(fmt, ##args)
+#endif /* __DEF_BT_HFP_AGENT_H_ */
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+ <interface name="Org.Hfp.App.Interface">
+
+ <method name="RegisterApplication">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="path"/>
+ </method>
+
+ <method name="UnregisterApplication">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="path"/>
+ </method>
+
+ <method name="IncomingCall">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="path"/>
+ <arg type="s" name="number"/>
+ <arg type="i" name="id"/>
+ </method>
+
+ <method name="OutgoingCall">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="path"/>
+ <arg type="s" name="number"/>
+ <arg type="i" name="id"/>
+ </method>
+
+ <method name="ChangeCallStatus">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="path"/>
+ <arg type="i" name="status"/>
+ <arg type="i" name="id"/>
+ </method>
+
+ <method name="GetProperties">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ </method>
+
+ </interface>
+
+ <interface name="Org.Hfp.Bluez.Interface">
+
+ <method name="AnswerCall">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="u" name="callid"/>
+ <arg type="s" name="path"/>
+ <arg type="s" name="sender"/>
+ </method>
+
+ <method name="ReleaseCall">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="u" name="callid"/>
+ <arg type="s" name="path"/>
+ <arg type="s" name="sender"/>
+ </method>
+
+ <method name="RejectCall">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="u" name="callid"/>
+ <arg type="s" name="path"/>
+ <arg type="s" name="sender"/>
+ </method>
+
+ <method name="ThreewayCall">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="u" name="value"/>
+ <arg type="s" name="path"/>
+ <arg type="s" name="sender"/>
+ </method>
+
+ <method name="DialLastNum">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ </method>
+
+ <method name="DialNum">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="Number"/>
+ <arg type="u" name="flags"/>
+ </method>
+
+ <method name="DialMemory">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="i" name="location"/>
+ </method>
+
+ <method name="SendDtmf">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="dtmf"/>
+ <arg type="s" name="path"/>
+ <arg type="s" name="sender"/>
+ </method>
+
+ <method name="VoiceDial">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="b" name="activate"/>
+ </method>
+
+ <method name="GetBatteryStatus">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="i" name="bcl" direction="out"/>
+ <arg type="i" name="bcs" direction="out"/>
+ </method>
+
+ <method name="GetSignalQuality">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="i" name="rssi" direction="out"/>
+ <arg type="i" name="ber" direction="out"/>
+ </method>
+
+ <method name="GetOperatorName">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="operator" direction="out"/>
+ </method>
+
+ <method name="NrecStatus">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="b" name="status"/>
+ </method>
+
+ </interface>
+</node>
--- /dev/null
+[D-BUS Service]
+Name=org.bluez.hfp_agent
+Exec=/usr/bin/bluetooth-hfp-agent
+User=root
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(bluetooth-map-agent C)
+
+SET(SRCS bluetooth_map_agent.c map_bmessage.c)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs_map_agent
+ REQUIRED
+ dbus-glib-1 dlog msg-service email-service vconf)
+
+FOREACH(flag ${pkgs_map_agent_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+FIND_PROGRAM(DBUS_BINDING_TOOL NAMES dbus-binding-tool)
+EXEC_PROGRAM("${DBUS_BINDING_TOOL}"
+ ARGS "--prefix=bluetooth_map \\
+ ${CMAKE_CURRENT_SOURCE_DIR}/bluetooth_map_agent.xml \\
+ --mode=glib-server \\
+ --output=${CMAKE_CURRENT_SOURCE_DIR}/bluetooth_map_agent_glue.h")
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_map_agent_LDFLAGS})
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.bluez.map_agent.service
+ DESTINATION share/dbus-1/services)
--- /dev/null
+/*
+ * bluetooth-agent
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus.h>
+#include <time.h>
+#include "vconf.h"
+#include "vconf-keys.h"
+
+#include <sys/types.h>
+#include <fcntl.h>
+
+/*Messaging Header Files*/
+#include "msg.h"
+#include "msg_storage.h"
+#include "msg_storage_types.h"
+#include "msg_transport.h"
+#include "msg_transport_types.h"
+#include "msg_types.h"
+
+#ifdef SUPPORT_EMAIL
+/*Email Header Files*/
+#include "email-types.h"
+#include "email-api-init.h"
+#include "email-api-account.h"
+#include "email-api-mailbox.h"
+#include "email-api-mail.h"
+#include "email-api-network.h"
+#endif
+
+#include <bluetooth_map_agent.h>
+
+#include <map_bmessage.h>
+
+#define OBEX_CLIENT_SERVICE "org.openobex.client"
+#define OBEX_CLIENT_INTERFACE "org.openobex.Client"
+#define OBEX_CLIENT_PATH "/"
+#define MNS_CLIENT_INTERFACE "org.openobex.MessageNotification"
+
+#define DBUS_STRUCT_STRING_STRING_UINT (dbus_g_type_get_struct("GValueArray", \
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID))
+
+#define DBUS_STRUCT_MESSAGE_LIST (dbus_g_type_get_struct("GValueArray", \
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, \
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, \
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_STRING, \
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, \
+ G_TYPE_BOOLEAN, G_TYPE_STRING, \
+ G_TYPE_INVALID))
+
+static msg_handle_t g_msg_handle = NULL;
+
+#define BT_MAP_NEW_MESSAGE "NewMessage"
+#define BT_MAP_STATUS_CB "sent status callback"
+#define BT_MAP_MSG_CB "sms message callback"
+#define BT_MAP_EMAIL_DEFAULTACCOUNT "db/email/defaultaccount"
+#define BT_MNS_OBJECT_PATH "/org/bluez/mns"
+#define BT_MNS_INTERFACE "org.bluez.mns"
+#define BT_MAIL_TEMP_BODY "/tmp/bt_mail.txt"
+#define BT_MAP_SENT_FOLDER_NAME "SENT"
+#define BT_MAP_MSG_INFO_MAX 256
+#define BT_MAP_MSG_HANDLE_MAX 21
+#define BT_MAP_TIMESTAMP_MAX_LEN 16
+#define BT_MAP_SUBJECT_MAX_LEN 20
+#define BT_MAP_MSG_BODY_MAX 1024
+#define BT_MSG_UPDATE 0
+#define BT_MSG_DELETE 1
+#define BT_SMS 0
+#define BT_EMAIL 1
+#define BT_EMAIL_HANDLE_BASE (G_MAXUINT64 / 2)
+#define BT_MAIL_ID_MAX_LENGTH 50
+
+#define BEGIN_BMSEG "BEGIN:BMSG\r\n"
+#define END_BMSEG "END:BMSG\r\n"
+#define BMSEG_VERSION "VERSION:1.0\r\n"
+#define MSEG_STATUS "STATUS:%s\r\n"
+#define MSEG_TYPE "TYPE:%s\r\n"
+#define FOLDER_PATH "FOLDER:%s\r\n"
+#define VCARD "BEGIN:VCARD\r\nVERSION:2.1\r\nN:%s\r\nTEL:%s\r\nEND:VCARD\r\n"
+#define BEGIN_BENV "BEGIN:BENV\r\n"
+#define END_BENV "END:BENV\r\n"
+#define BEGIN_BBODY "BEGIN:BBODY\r\n"
+#define END_BBODY "END:BBODY\r\n"
+#define ENCODING "ENCODING:%s\r\n"
+#define CHARSET "CHARSET:%s\r\n"
+#define LANGUAGE "LANGUAGE:%s\r\n"
+#define LENGTH "LENGTH:%d\r\n"
+#define MSG_BODY "BEGIN:MSG\r\n%s\r\nEND:MSG\r\n"
+
+/* This has been added for testing purpose, will be removed when SMS APIs
+ are available. */
+#define TEST_PDU "06810000000000040681567777000021017101750261A05"\
+ "376BA0D8297E5F3B73BCC4ED3F3A030FB1ECECF41613A"\
+ "5D1E1ED3E7A0B2BD2CCF8362AEA4195407C941ECF77C9"\
+ "E769F41753968FC769BD3E4B27B5C0691EB6510FD0D7AD"\
+ "BCBF27B397D46D343A163990E42BFDB6590BCDC4E93D3"\
+ "E539889E86CF41F437485E26D7C765D0DB5E96DFCBE933"\
+ "9A1E9A36A72063900AA2BF41B5DBED760385E920E9DC357B35A9"
+
+GSList* id_list = NULL;
+guint64 current_push_map_id;
+
+struct id_info {
+ guint64 map_id;
+ int uid;
+};
+
+struct msg_send_option {
+ bool save_copy;
+ bool retry_send;
+ bool native;
+};
+
+struct message_info {
+ char *handle;
+ char *subject;
+ char *datetime;
+ char *sender_name;
+ char *sender_addressing;
+ char *recipient_name;
+ char *recipient_addressing;
+ char *type;
+ char *size;
+ char *reception_status;
+ char *attachment_size;
+ char *replyto_addressing;
+ gboolean text;
+ gboolean priority;
+ gboolean read;
+ gboolean sent;
+ gboolean protect;
+};
+
+typedef struct {
+ GObject parent;
+} BluetoothMapAgent;
+
+typedef struct {
+ GObjectClass parent;
+} BluetoothMapAgentClass;
+
+GType bluetooth_map_agent_get_type(void);
+
+#define BLUETOOTH_MAP_TYPE_AGENT (bluetooth_map_agent_get_type())
+
+#define BLUETOOTH_MAP_AGENT(object) \
+ (G_TYPE_CHECK_INSTANCE_CAST((object), \
+ BLUETOOTH_MAP_TYPE_AGENT , BluetoothMapAgent))
+#define BLUETOOTH_MAP_AGENT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), \
+ BLUETOOTH_MAP_TYPE_AGENT , BluetoothMapAgentClass))
+#define BLUETOOTH_MAP_IS_AGENT(object) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((object), \
+ BLUETOOTH_MAP_TYPE_AGENT))
+#define BLUETOOTH_MAP_IS_AGENT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), \
+ BLUETOOTH_MAP_TYPE_AGENT))
+#define BLUETOOTH_MAP_AGENT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), \
+ BLUETOOTH_MAP_TYPE_AGENT , BluetoothMapAgentClass))
+
+G_DEFINE_TYPE(BluetoothMapAgent, bluetooth_map_agent, G_TYPE_OBJECT)
+
+GMainLoop *g_mainloop = NULL;
+static DBusGConnection *g_connection = NULL;
+static char *g_mns_path = NULL;
+static struct msg_send_option opt;
+
+static gboolean bluetooth_map_get_folder_tree(BluetoothMapAgent *agent,
+ DBusGMethodInvocation *context);
+static gboolean bluetooth_map_get_message_list(BluetoothMapAgent *agent,
+ gchar *folder_name, guint16 max,
+ DBusGMethodInvocation *context);
+static gboolean bluetooth_map_get_message(BluetoothMapAgent *agent,
+ gchar *message_name,
+ gboolean attach, gboolean transcode,
+ gboolean first_request,
+ DBusGMethodInvocation *context);
+static gboolean bluetooth_map_push_message(BluetoothMapAgent *agent,
+ gboolean save_copy,
+ gboolean retry_send,
+ gboolean native,
+ gchar *folder_name,
+ DBusGMethodInvocation *context);
+static gboolean bluetooth_map_push_message_data(BluetoothMapAgent *agent,
+ gchar *bmsg,
+ DBusGMethodInvocation *context);
+static gboolean bluetooth_map_update_message(BluetoothMapAgent *agent,
+ DBusGMethodInvocation *context);
+static gboolean bluetooth_map_set_read_status(BluetoothMapAgent *agent,
+ gchar *handle, gboolean read_status,
+ DBusGMethodInvocation *context);
+static gboolean bluetooth_map_set_delete_status(BluetoothMapAgent *agent,
+ gchar *handle, gboolean delete_status,
+ DBusGMethodInvocation *context);
+static gboolean bluetooth_map_noti_registration(BluetoothMapAgent *agent,
+ gchar *remote_addr,
+ gboolean status,
+ DBusGMethodInvocation *context);
+
+
+#include "bluetooth_map_agent_glue.h"
+
+static void bluetooth_map_agent_init(BluetoothMapAgent *obj)
+{
+ DBG("+\n");
+
+ g_assert(obj != NULL);
+}
+
+static void bluetooth_map_agent_finalize(GObject *obj)
+{
+ DBG("+\n");
+
+ G_OBJECT_CLASS(bluetooth_map_agent_parent_class)->finalize(obj);
+}
+
+static void bluetooth_map_agent_class_init(BluetoothMapAgentClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+
+ g_assert(klass != NULL);
+
+ object_class->finalize = bluetooth_map_agent_finalize;
+
+ dbus_g_object_type_install_info(BLUETOOTH_MAP_TYPE_AGENT,
+ &dbus_glib_bluetooth_map_object_info);
+}
+
+static GQuark __bt_map_agent_error_quark(void)
+{
+ static GQuark quark = 0;
+ if (!quark)
+ quark = g_quark_from_static_string("agent");
+
+ return quark;
+}
+
+static GError *__bt_map_agent_error(bt_map_agent_error_t error,
+ const char *err_msg)
+{
+ return g_error_new(BT_MAP_AGENT_ERROR, error, err_msg, NULL);
+}
+
+static guint64 _bt_validate_uid(int uid)
+{
+ DBG("Validate uid");
+ struct id_info *info;
+ int count;
+ int i;
+
+ count = g_slist_length(id_list);
+ for (i = 0; i < count; i++) {
+ info = (struct id_info *)g_slist_nth_data(id_list, i);
+ if (!info)
+ break;
+
+ if (info->uid == uid) {
+ printf("uid = %d\n", uid);
+ return info->map_id;
+ }
+ }
+
+ return 0;
+}
+
+static guint64 __bt_add_id(int uid)
+{
+ DBG("Add id: %d\n", uid);
+ static guint64 map_id;
+ struct id_info *info;
+ guint64 test;
+
+ test = _bt_validate_uid(uid);
+ DBG("test: %llx\n", test);
+ if (test)
+ return test;
+
+ info = g_new0(struct id_info, 1);
+
+ map_id++;
+
+ info->map_id = map_id;
+ info->uid = uid;
+ DBG("map_id = %llx, uid = %d \n", info->map_id, info->uid);
+
+ id_list = g_slist_append(id_list, info);
+
+ return map_id;
+}
+
+static int __bt_get_id(guint64 map_id)
+{
+ DBG("get id\n");
+ struct id_info *info;
+ int count;
+ int i;
+
+ count = g_slist_length(id_list);
+
+ for (i = 0; i < count; i++) {
+ info = (struct id_info *)g_slist_nth_data(id_list, i);
+
+ if (info->map_id == map_id)
+ return info->uid;
+ }
+
+ return -1;
+}
+
+static int __bt_get_uid(gchar *handle)
+{
+ guint64 map_id;
+ int uid;
+
+ if (NULL == handle)
+ return -1;
+
+ map_id = g_ascii_strtoull(handle, NULL, 16);
+ if (!map_id)
+ return -1;
+
+ uid = __bt_get_id(map_id);
+
+ return uid;
+}
+
+static int __bt_update_id(guint64 map_id, int new_uid)
+{
+ DBG("update id\n");
+ struct id_info *info;
+ int i;
+ int count;
+
+ count = g_slist_length(id_list);
+
+ for (i = 0; i < count; i++) {
+ info = g_slist_nth_data(id_list, i);
+
+ if (info->map_id == map_id) {
+ info->uid = new_uid;
+ return map_id;
+ }
+ }
+
+ return -1;
+}
+
+static void __bt_remove_list(GSList *id_list)
+{
+ if (!id_list)
+ return;
+
+ DBG("Removing id list\n");
+ g_slist_free_full(id_list, g_free);
+}
+
+
+static gchar *__bt_get_folder_name(int id)
+{
+ int ret;
+ char folder_name[BT_MAP_MSG_INFO_MAX] = {0,};
+
+ msg_struct_list_s g_folderList;
+ msg_struct_t p_folder;
+
+ ret = msg_get_folder_list(g_msg_handle, &g_folderList);
+ if (ret != MSG_SUCCESS)
+ goto done;
+
+ p_folder = g_folderList.msg_struct_info[id];
+
+ ret = msg_get_str_value(p_folder, MSG_FOLDER_INFO_NAME_STR,
+ folder_name, BT_MAP_MSG_INFO_MAX);
+ if (ret != MSG_SUCCESS)
+ goto done;
+
+ return g_strdup_printf("TELECOM/MSG/%s", folder_name);
+
+done:
+ return g_strdup("TELECOM/MSG");
+}
+
+static void __get_msg_timestamp(time_t *ltime, char *timestamp)
+{
+ struct tm local_time;
+ int year;
+ int month;
+
+ if (!localtime_r(ltime, &local_time))
+ return;
+
+ year = local_time.tm_year + 1900; /* years since 1900 */
+ month = local_time.tm_mon + 1; /* months since January */
+ snprintf(timestamp, 16, "%04d%02d%02dT%02d%02d%02d", year, month,
+ local_time.tm_mday, local_time.tm_hour,
+ local_time.tm_min, local_time.tm_sec);
+
+ return;
+}
+
+static char *__bt_prepare_msg_bmseg(msg_struct_t msg_info, gboolean attach,
+ gboolean transcode)
+{
+ int ret;
+ int m_type = MSG_TYPE_SMS;
+ int folder_id;
+ int count;
+ bool read_status = false;
+ char msg_body[BT_MAP_MSG_BODY_MAX] = {0,};
+ char addr_value[MAX_ADDRESS_VAL_LEN] = {0,};
+ char name_value[MAX_ADDRESS_VAL_LEN] = {0,};
+ gchar *folder_path;
+
+ msg_struct_list_s *addr_list = NULL;
+ GString *msg;
+
+ msg = g_string_new(BEGIN_BMSEG);
+ g_string_append(msg, BMSEG_VERSION);
+
+ ret = msg_get_bool_value(msg_info, MSG_MESSAGE_READ_BOOL, &read_status);
+ if (ret == MSG_SUCCESS) {
+ DBG("read_status %d\n", read_status);
+ }
+
+ if (read_status)
+ g_string_append_printf(msg, MSEG_STATUS, "READ");
+ else
+ g_string_append_printf(msg, MSEG_STATUS, "UNREAD");
+
+ ret = msg_get_int_value(msg_info, MSG_MESSAGE_TYPE_INT, &m_type);
+ if (ret == MSG_SUCCESS) {
+ DBG("m_type %d\n", m_type);
+ }
+
+ switch (m_type) {
+ case MSG_TYPE_MMS:
+ case MSG_TYPE_MMS_JAVA:
+ case MSG_TYPE_MMS_NOTI:
+ g_string_append_printf(msg, MSEG_TYPE, "MMS");
+ break;
+
+ default:
+ g_string_append_printf(msg, MSEG_TYPE, "SMS_GSM");
+ break;
+ }
+
+ ret = msg_get_int_value(msg_info, MSG_MESSAGE_FOLDER_ID_INT,
+ &folder_id);
+ if (ret == MSG_SUCCESS) {
+ DBG("folder_id %d\n", folder_id);
+ }
+
+ folder_path = __bt_get_folder_name(folder_id);
+ g_string_append_printf(msg, FOLDER_PATH, folder_path);
+
+
+ ret = msg_get_list_handle(msg_info, MSG_MESSAGE_ADDR_LIST_STRUCT,
+ (void **)&addr_list);
+ if (ret == MSG_SUCCESS) {
+ count = addr_list->nCount;
+ DBG("count %d \n", count);
+ while (count > 0) {
+ msg_struct_t addr_info = NULL;
+ addr_info = addr_list->msg_struct_info[count - 1];
+
+ msg_get_str_value(addr_info,
+ MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+ addr_value, MAX_ADDRESS_VAL_LEN);
+ DBG("addr_value %s\n", addr_value);
+ msg_get_str_value(addr_info,
+ MSG_ADDRESS_INFO_DISPLAYNAME_STR,
+ name_value, MAX_ADDRESS_VAL_LEN);
+ if (!strlen(name_value))
+ g_stpcpy(name_value, addr_value);
+
+ DBG("name_value %s\n", name_value);
+
+ g_string_append_printf(msg, VCARD, name_value,
+ addr_value);
+ count--;
+ }
+ }
+
+ g_string_append(msg, BEGIN_BENV);
+ g_string_append(msg, BEGIN_BBODY);
+
+ if (transcode) {
+ g_string_append_printf(msg, CHARSET, "UTF-8");
+
+ if (m_type == MSG_TYPE_MMS)
+ ret = msg_get_str_value(msg_info,
+ MSG_MESSAGE_MMS_TEXT_STR,
+ msg_body, BT_MAP_SUBJECT_MAX_LEN);
+ else
+ ret = msg_get_str_value(msg_info,
+ MSG_MESSAGE_SMS_DATA_STR,
+ msg_body, BT_MAP_MSG_BODY_MAX);
+
+ if (ret == MSG_SUCCESS) {
+ g_string_append_printf(msg, LENGTH, strlen(msg_body));
+ g_string_append_printf(msg, MSG_BODY, msg_body);
+ }
+ } else {
+ gchar *msg_pdu;
+ g_string_append_printf(msg, ENCODING, "G-7BIT");
+ g_string_append_printf(msg, CHARSET, "native");
+ /* The below line has been added for testing purpose,
+ will be removed when SMS APIs are available. */
+ msg_pdu = g_strdup(TEST_PDU);
+ g_string_append_printf(msg, LENGTH, strlen(msg_pdu));
+ g_string_append_printf(msg, MSG_BODY, msg_pdu);
+ g_free(msg_pdu);
+ }
+
+ g_string_append(msg, END_BBODY);
+ g_string_append(msg, END_BENV);
+ g_string_append(msg, END_BMSEG);
+
+ return g_string_free(msg, FALSE);
+}
+
+static void __bt_message_info_free(struct message_info msg_info)
+{
+ g_free(msg_info.handle);
+ g_free(msg_info.subject);
+ g_free(msg_info.datetime);
+ g_free(msg_info.sender_name);
+ g_free(msg_info.sender_addressing);
+ g_free(msg_info.replyto_addressing);
+ g_free(msg_info.recipient_name);
+ g_free(msg_info.recipient_addressing);
+ g_free(msg_info.type);
+ g_free(msg_info.reception_status);
+ g_free(msg_info.size);
+ g_free(msg_info.attachment_size);
+}
+
+static struct message_info __bt_message_info_get(msg_struct_t msg_struct_handle)
+{
+ struct message_info msg_info = {0,};
+ int ret;
+ int msg_id;
+ guint64 uid;
+ int dptime;
+ int m_type = 0;
+ int data_size;
+ int priority;
+ int direction_type;
+ bool protect_status = 0;
+ bool read_status = 0;
+
+ char msg_handle[BT_MAP_MSG_HANDLE_MAX] = {0,};
+ char msg_subject[BT_MAP_SUBJECT_MAX_LEN] = {0,};
+ char msg_datetime[BT_MAP_TIMESTAMP_MAX_LEN] = {0,};
+ char msg_size[5] = {0,};
+ char msg_body[BT_MAP_MSG_BODY_MAX] = {0,};
+ char addr_value[MAX_ADDRESS_VAL_LEN] = {0,};
+ char name_value[MAX_ADDRESS_VAL_LEN] = {0,};
+
+ msg_info.text = FALSE;
+ msg_info.protect = FALSE;
+ msg_info.read = FALSE;
+ msg_info.priority = FALSE;
+
+ msg_struct_t msg = NULL;
+ msg_struct_t send_opt = NULL;
+ msg_struct_list_s *addr_list = NULL;
+ msg_struct_t addr_info = NULL;
+
+ ret = msg_get_int_value(msg_struct_handle, MSG_MESSAGE_ID_INT, &msg_id);
+ if (ret == MSG_SUCCESS) {
+ uid = __bt_add_id(msg_id);
+ snprintf(msg_handle, sizeof(msg_handle), "%llx", uid);
+ }
+ msg_info.handle = g_strdup(msg_handle);
+
+ msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+ send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
+
+ ret = msg_get_message(g_msg_handle,
+ (msg_message_id_t)msg_id,
+ msg, send_opt);
+ if (ret != MSG_SUCCESS) {
+ DBG("ret = %d\n", ret);
+ goto next;
+ }
+
+ ret = msg_get_list_handle(msg, MSG_MESSAGE_ADDR_LIST_STRUCT,
+ (void **)&addr_list);
+ if (ret != MSG_SUCCESS) {
+ DBG("ret = %d\n", ret);
+ goto next;
+ }
+
+ addr_info = addr_list->msg_struct_info[0];
+
+ ret = msg_get_str_value(addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+ addr_value, MAX_ADDRESS_VAL_LEN);
+ if (ret == MSG_SUCCESS)
+ DBG("addr_value %s\n", addr_value);
+
+ ret = msg_get_str_value(addr_info, MSG_ADDRESS_INFO_DISPLAYNAME_STR,
+ name_value, MAX_ADDRESS_VAL_LEN);
+ if (ret == MSG_SUCCESS)
+ DBG("name_value %s\n", name_value);
+
+ if (!strlen(name_value))
+ g_stpcpy(name_value, addr_value);
+
+ DBG("name_value %s\n", name_value);
+
+ ret = msg_get_int_value(msg, MSG_MESSAGE_DIRECTION_INT, &direction_type);
+ if (ret != MSG_SUCCESS)
+ goto next;
+
+ if (direction_type == MSG_DIRECTION_TYPE_MT) {
+ msg_info.sender_name = g_strdup(name_value);
+ msg_info.sender_addressing = g_strdup(addr_value);
+ msg_info.recipient_name = g_strdup("Unknown");
+ msg_info.recipient_addressing = g_strdup("0000");
+ } else {
+ msg_info.sender_name = g_strdup("Unknown");
+ msg_info.sender_addressing = g_strdup("0000");
+ msg_info.recipient_name = g_strdup(name_value);
+ msg_info.recipient_addressing = g_strdup(addr_value);
+ }
+
+next:
+ msg_release_struct(&msg);
+ msg_release_struct(&send_opt);
+
+ ret = msg_get_int_value(msg_struct_handle, MSG_MESSAGE_DISPLAY_TIME_INT, &dptime);
+ if (ret == MSG_SUCCESS) {
+ __get_msg_timestamp((time_t *)&dptime, msg_datetime);
+ }
+ msg_info.datetime = g_strdup(msg_datetime);
+
+ ret = msg_get_int_value(msg_struct_handle, MSG_MESSAGE_TYPE_INT,
+ &m_type);
+ if (ret == MSG_SUCCESS) {
+ DBG("m_type %d\n", m_type);
+ }
+
+ switch (m_type) {
+ case MSG_TYPE_MMS:
+ case MSG_TYPE_MMS_JAVA:
+ case MSG_TYPE_MMS_NOTI:
+ msg_info.type = g_strdup("MMS");
+ break;
+
+ default:
+ msg_info.type = g_strdup("SMS_GSM");
+ break;
+ }
+
+ if (m_type == MSG_TYPE_MMS) {
+ ret = msg_get_str_value(msg_struct_handle,
+ MSG_MESSAGE_SUBJECT_STR, msg_subject,
+ BT_MAP_SUBJECT_MAX_LEN);
+ if (ret == MSG_SUCCESS) {
+ DBG("MMS subject %s", msg_subject);
+ }
+
+ msg_info.subject = g_strdup(msg_subject);
+
+ ret = msg_get_str_value(msg_struct_handle,
+ MSG_MESSAGE_MMS_TEXT_STR, msg_body,
+ BT_MAP_MSG_BODY_MAX);
+ if (ret == MSG_SUCCESS) {
+ DBG("msg_body %s", msg_body);
+ if (strlen(msg_body))
+ msg_info.text = TRUE ;
+ }
+
+ } else if (m_type == MSG_TYPE_SMS) {
+ ret = msg_get_str_value(msg_struct_handle,
+ MSG_MESSAGE_SMS_DATA_STR, msg_body,
+ BT_MAP_MSG_BODY_MAX);
+ if (ret == MSG_SUCCESS) {
+ DBG("SMS subject %s", msg_body);
+ if (strlen(msg_body)) {
+ msg_info.text = TRUE ;
+ msg_info.subject = g_strndup(msg_body,
+ BT_MAP_SUBJECT_MAX_LEN);
+ }
+ }
+ }
+
+ ret = msg_get_int_value(msg_struct_handle, MSG_MESSAGE_DATA_SIZE_INT,
+ &data_size);
+ if (ret == MSG_SUCCESS)
+ snprintf(msg_size, sizeof(msg_size), "%d", data_size);
+
+ msg_info.size = g_strdup(msg_size);
+
+ msg_info.reception_status = g_strdup("complete");
+ msg_info.attachment_size = g_strdup("0");
+
+ ret = msg_get_bool_value(msg_struct_handle, MSG_MESSAGE_PROTECTED_BOOL,
+ &protect_status);
+ if (ret == MSG_SUCCESS) {
+ if (protect_status)
+ msg_info.protect = TRUE;
+ }
+
+ ret = msg_get_bool_value(msg_struct_handle, MSG_MESSAGE_READ_BOOL,
+ &read_status);
+ if (ret == MSG_SUCCESS) {
+ if (read_status)
+ msg_info.read = TRUE;
+ }
+
+ ret = msg_get_int_value(msg_struct_handle, MSG_MESSAGE_PRIORITY_INT,
+ &priority);
+ if (ret == MSG_SUCCESS) {
+ if (priority == MSG_MESSAGE_PRIORITY_HIGH)
+ msg_info.priority = TRUE;
+ }
+
+ return msg_info;
+}
+
+static void __bluetooth_map_msg_incoming_status_cb(msg_handle_t handle,
+ msg_struct_t msg,
+ void *user_param)
+{
+ DBusGProxy *mns_proxy;
+ GError *error = NULL;
+
+ int msg_id = 0;
+ int msg_type = 0;
+ int ret = MSG_SUCCESS;
+
+ char *message_type = NULL;
+
+ guint64 uid;
+
+ DBG("+\n");
+
+ ret = msg_get_int_value(msg, MSG_MESSAGE_ID_INT, &msg_id);
+ if (ret != MSG_SUCCESS)
+ return;;
+
+ uid = __bt_add_id(msg_id);
+
+ ret = msg_get_int_value(msg, MSG_MESSAGE_TYPE_INT, &msg_type);
+ if (ret != MSG_SUCCESS)
+ return;
+
+ switch (msg_type) {
+ case MSG_TYPE_SMS:
+ message_type = g_strdup("SMS_GSM");
+ break;
+ case MSG_TYPE_MMS:
+ message_type = g_strdup("MMS");
+ break;
+ default:
+ return;
+ }
+
+ mns_proxy = dbus_g_proxy_new_for_name(g_connection, OBEX_CLIENT_SERVICE,
+ g_mns_path,
+ MNS_CLIENT_INTERFACE);
+ if (mns_proxy == NULL) {
+ ERR("Failed to get a proxy for D-Bus\n");
+ g_free(message_type);
+ return;
+ }
+
+ dbus_g_proxy_call(mns_proxy, "SendEvent", &error,
+ G_TYPE_STRING, "NewMessage",
+ G_TYPE_UINT64, uid,
+ G_TYPE_STRING, "TELECOM/MSG/INBOX",
+ G_TYPE_STRING, "",
+ G_TYPE_STRING, message_type,
+ G_TYPE_INVALID, G_TYPE_INVALID);
+ if (error) {
+ DBG("Error [%s]", error->message);
+ g_error_free(error);
+ }
+
+ DBG("-\n");
+ g_free(message_type);
+ g_object_unref(mns_proxy);
+ return;
+}
+
+static gboolean __bluetooth_map_start_service()
+{
+ msg_error_t err = MSG_SUCCESS;
+ gboolean msg_ret = TRUE;
+#ifdef SUPPORT_EMAIL
+ int email_err = EMAIL_ERROR_NONE;
+ gboolean email_ret = TRUE;
+#endif
+
+ err = msg_open_msg_handle(&g_msg_handle);
+ if (err != MSG_SUCCESS) {
+ ERR("msg_open_msg_handle error = %d\n", err);
+ msg_ret = FALSE;
+ goto done;
+ }
+
+ err = msg_reg_sms_message_callback(g_msg_handle,
+ __bluetooth_map_msg_incoming_status_cb,
+ 0, (void *)BT_MAP_MSG_CB);
+ if (err != MSG_SUCCESS) {
+ ERR("msg_reg_sms_message_callback error = %d\n", err);
+ msg_ret = FALSE;
+ }
+
+done:
+
+#ifdef SUPPORT_EMAIL
+
+ email_err = email_service_begin();
+ if (email_err != EMAIL_ERROR_NONE) {
+ ERR("email_service_begin fail error = %d\n", email_err);
+ email_ret = FALSE;
+ }
+
+ if (msg_ret || email_ret)
+ return TRUE;
+ else
+ return FALSE;
+
+#else
+
+ return msg_ret;
+
+#endif
+}
+
+static void __bluetooth_map_stop_service()
+{
+ if (NULL != g_msg_handle)
+ msg_close_msg_handle(&g_msg_handle);
+
+ g_msg_handle = NULL;
+
+#ifdef SUPPORT_EMAIL
+ if (EMAIL_ERROR_NONE != email_service_end())
+ ERR("email_service_end fail \n");
+#endif
+ return;
+}
+
+#ifdef SUPPORT_EMAIL
+static int __bt_store_mail(email_mailbox_type_e type, char *subject,
+ char *body, char *recepients)
+{
+ int account_id;
+ int mail_id;
+ int err;
+ char from_address[BT_MAIL_ID_MAX_LENGTH] = { 0, };
+ FILE *body_file;
+ struct stat st_buf;
+
+ email_account_t *account_data = NULL;
+ email_mailbox_t *mailbox_data = NULL;
+ email_mail_data_t *mail_data = NULL;
+
+ err = email_load_default_account_id(&account_id);
+ if (EMAIL_ERROR_NONE != err)
+ goto fail;
+
+ err = email_get_account(account_id, GET_FULL_DATA_WITHOUT_PASSWORD,
+ &account_data);
+ if (EMAIL_ERROR_NONE != err)
+ goto fail;
+
+ err = email_get_mailbox_by_mailbox_type(account_id, type,
+ &mailbox_data);
+ if (EMAIL_ERROR_NONE != err)
+ goto fail;
+
+ snprintf(from_address, BT_MAIL_ID_MAX_LENGTH, "<%s>",
+ account_data->user_email_address);
+ email_free_account(&account_data, 1);
+
+ mail_data = calloc(1, sizeof(email_mail_data_t));
+ if (NULL == mail_data) {
+ email_free_mailbox(&mailbox_data, 1);
+ goto fail;
+ }
+
+ DBG("\n account_id %d\n", account_id);
+ mail_data->account_id = account_id;
+ mail_data->save_status = 1;
+ mail_data->body_download_status = 1;
+ /* mail_data->flags_draft_field = 1; */
+ mail_data->flags_seen_field = 1;
+ mail_data->file_path_plain = g_strdup(BT_MAIL_TEMP_BODY);
+
+ mail_data->mailbox_id = mailbox_data->mailbox_id;
+ mail_data->mailbox_type = mailbox_data->mailbox_type;
+ email_free_mailbox(&mailbox_data, 1);
+
+ mail_data->full_address_from = g_strdup(from_address);
+ mail_data->full_address_to = g_strdup(recepients);
+ mail_data->subject = g_strdup(subject);
+ mail_data->report_status = EMAIL_MAIL_REQUEST_DSN |
+ EMAIL_MAIL_REQUEST_MDN;
+
+ body_file = fopen(BT_MAIL_TEMP_BODY, "w");
+ if (body_file == NULL) {
+ DBG("\n fopen [%s]failed\n", BT_MAIL_TEMP_BODY);
+ email_free_mail_data(&mail_data, 1);
+ goto fail;
+ }
+
+ fprintf(body_file, body);
+ fflush(body_file);
+ fclose(body_file);
+
+ err = email_add_mail(mail_data, NULL, 0, NULL, 0);
+ if (err != EMAIL_ERROR_NONE) {
+ DBG("email_add_mail failed. [%d]\n", err);
+ if (!stat(mail_data->file_path_plain, &st_buf))
+ remove(mail_data->file_path_plain);
+
+ email_free_mail_data(&mail_data, 1);
+ goto fail;
+ }
+
+ DBG("saved mail id = [%d]\n", mail_data->mail_id);
+
+ mail_id = mail_data->mail_id;
+
+ email_free_mail_data(&mail_data, 1);
+
+ return mail_id;
+
+fail:
+ return 0;
+}
+
+static int __bt_email_send(char *subject, char *body, char* recepients)
+{
+ int err;
+ int mail_id;
+ int handle;
+
+ mail_id = __bt_store_mail(EMAIL_MAILBOX_TYPE_OUTBOX, subject,
+ body, recepients);
+ if (mail_id) {
+ DBG("mail_id = %d\n", mail_id);
+ err = email_send_mail(mail_id, &handle);
+ if (err != EMAIL_ERROR_NONE)
+ DBG("Sending failed[%d]\n", err);
+ }
+
+ return mail_id;
+}
+#endif
+
+static int __bt_get_folder_id(char *folder_path)
+{
+ int folder_id = -1;
+ int i;
+ char *folder;
+ msg_struct_list_s folder_list;
+ msg_error_t err;
+ msg_struct_t p_folder;
+ DBG("__bt_get_folder_id\n");
+
+ folder = strrchr(folder_path, '/');
+ if (NULL == folder)
+ return -1;
+
+ folder++;
+
+ DBG("folderName %s\n", folder);
+
+ err = msg_get_folder_list(g_msg_handle, &folder_list);
+ if (err != MSG_SUCCESS)
+ return -1;
+
+ for (i = 0; i < folder_list.nCount; i++) {
+ p_folder = folder_list.msg_struct_info[i];
+ char folder_name[BT_MAP_MSG_INFO_MAX] = {0, };
+
+ err = msg_get_str_value(p_folder, MSG_FOLDER_INFO_NAME_STR,
+ folder_name, BT_MAP_MSG_INFO_MAX);
+ if (err != MSG_SUCCESS)
+ continue;
+
+ DBG("folderName %s\n", folder_name);
+ if (!g_ascii_strncasecmp(folder_name, folder, strlen(folder))) {
+ err = msg_get_int_value(p_folder, MSG_FOLDER_INFO_ID_INT,
+ &folder_id);
+ if (err != MSG_SUCCESS)
+ return -1;
+
+ break;
+ }
+ }
+
+ return folder_id;
+
+}
+
+msg_error_t __bt_send_sms(int msg_id, msg_struct_t pMsg, msg_struct_t pSendOpt)
+{
+ msg_error_t err;
+ msg_struct_t pReq;
+
+ pReq = msg_create_struct(MSG_STRUCT_REQUEST_INFO);
+
+ msg_set_int_value(pMsg, MSG_MESSAGE_ID_INT, msg_id);
+ msg_set_struct_handle(pReq, MSG_REQUEST_MESSAGE_HND, pMsg);
+ msg_set_struct_handle(pReq, MSG_REQUEST_SENDOPT_HND, pSendOpt);
+
+ err = msg_sms_send_message(g_msg_handle, pReq);
+ if (err == MSG_SUCCESS)
+ DBG("Sending Message is successful!!!");
+ else
+ DBG("Sending Message is failed!!! %d", err);
+
+ msg_release_struct(&pReq);
+ return err;
+}
+
+static int __bt_push_sms(gboolean send, int folder_id, char *body,
+ GSList *recepients)
+{
+ DBG("+ \n");
+ msg_struct_t msg_info = NULL;
+ msg_struct_t send_opt = NULL;
+ msg_struct_list_s *addr_list;
+ msg_error_t err;
+
+ int count = 0;
+ int i = 0;
+ int msg_id;
+ guint64 uid = -1;
+
+ msg_info = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+ if (msg_info == NULL)
+ goto fail;
+
+ err = msg_set_int_value(msg_info, MSG_MESSAGE_TYPE_INT, MSG_TYPE_SMS);
+ if (err != MSG_SUCCESS)
+ goto fail;
+
+ if (body) {
+ err = msg_set_str_value(msg_info, MSG_MESSAGE_SMS_DATA_STR, body,
+ strlen(body));
+ if (err != MSG_SUCCESS)
+ goto fail;
+ } else {
+ err = msg_set_str_value(msg_info, MSG_MESSAGE_SMS_DATA_STR,
+ NULL, 0);
+ if (err != MSG_SUCCESS)
+ goto fail;
+ }
+
+ DBG("folder_id %d\n", folder_id);
+ err = msg_set_int_value(msg_info, MSG_MESSAGE_FOLDER_ID_INT,
+ folder_id);
+ if (err != MSG_SUCCESS)
+ goto fail;
+
+ if (recepients) {
+ count = g_slist_length(recepients);
+ DBG("Count = %d\n", count);
+ msg_get_list_handle(msg_info, MSG_MESSAGE_ADDR_LIST_STRUCT,
+ (void**)&addr_list);
+
+ addr_list->nCount = count;
+ for (i = 0; i < count; i++) {
+ char *address = (char *)g_slist_nth_data(recepients, i);
+ if (address == NULL) {
+ DBG("[ERROR] address is value NULL, skip");
+ continue;
+ }
+ msg_set_int_value(addr_list->msg_struct_info[i],
+ MSG_ADDRESS_INFO_ADDRESS_TYPE_INT,
+ MSG_ADDRESS_TYPE_PLMN);
+
+ msg_set_int_value(addr_list->msg_struct_info[i],
+ MSG_ADDRESS_INFO_RECIPIENT_TYPE_INT,
+ MSG_RECIPIENTS_TYPE_TO);
+
+ msg_set_str_value(addr_list->msg_struct_info[i],
+ MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+ address, strlen(address));
+ }
+ }
+
+ send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
+
+ err = msg_set_bool_value(send_opt, MSG_SEND_OPT_SETTING_BOOL, true);
+ if (err != MSG_SUCCESS)
+ goto fail;
+
+ /* Do not keep a copy */
+ err = msg_set_bool_value(send_opt, MSG_SEND_OPT_KEEPCOPY_BOOL,
+ opt.save_copy);
+ if (err != MSG_SUCCESS)
+ goto fail;
+
+ msg_id = msg_add_message(g_msg_handle, msg_info, send_opt);
+ DBG("msg_id = %d\n", msg_id);
+ uid = __bt_add_id(msg_id);
+
+ if (send == TRUE) {
+ err = __bt_send_sms(msg_id, msg_info, send_opt);
+ if (err != MSG_SUCCESS) {
+ uid = -1;
+ goto fail;
+ }
+ }
+
+fail:
+ msg_release_struct(&msg_info);
+ msg_release_struct(&send_opt);
+ DBG("-\n");
+ return uid;
+}
+
+static gboolean __bt_msg_is_mms(int msg_type)
+{
+ gboolean result = FALSE;
+
+ switch (msg_type) {
+ case MSG_TYPE_MMS_NOTI:
+ case MSG_TYPE_MMS_JAVA:
+ case MSG_TYPE_MMS:
+ result = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static void __bt_mns_client_connect(char *address)
+{
+ DBusGProxy *mns_proxy;
+ GHashTable *hash;
+ GValue *addr_value;
+ GValue *tgt_value;
+ GError *error = NULL;
+ const char *session_path = NULL;
+
+ DBG("+ address %s\n", address);
+
+ mns_proxy = dbus_g_proxy_new_for_name(g_connection, OBEX_CLIENT_SERVICE,
+ OBEX_CLIENT_PATH,
+ OBEX_CLIENT_INTERFACE);
+ if (mns_proxy == NULL) {
+ ERR("Failed to get a proxy for D-Bus\n");
+ return;
+ }
+
+ hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify)g_free);
+
+ addr_value = g_new0(GValue, 1);
+ g_value_init(addr_value, G_TYPE_STRING);
+ g_value_set_string(addr_value, address);
+ g_hash_table_insert(hash, "Destination", addr_value);
+
+ tgt_value = g_new0(GValue, 1);
+ g_value_init(tgt_value, G_TYPE_STRING);
+ g_value_set_string(tgt_value, "MNS");
+ g_hash_table_insert(hash, "Target", tgt_value);
+
+ dbus_g_proxy_call(mns_proxy, "CreateSession", &error,
+ dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+ hash, G_TYPE_INVALID,
+ DBUS_TYPE_G_OBJECT_PATH, &session_path,
+ G_TYPE_INVALID);
+ if (error) {
+ DBG("Error [%s]", error->message);
+ g_error_free(error);
+ g_hash_table_destroy(hash);
+ g_object_unref(mns_proxy);
+ return;
+ }
+
+ g_mns_path = g_strdup(session_path);
+ DBG("g_mns_path = %s\n", g_mns_path);
+
+ g_hash_table_destroy(hash);
+ g_object_unref(mns_proxy);
+
+ DBG("-\n");
+ return;
+}
+
+static void __bt_mns_client_disconnect()
+{
+ DBusGProxy *mns_proxy;
+ GError *error = NULL;
+
+ if (!g_mns_path)
+ return;
+
+ mns_proxy = dbus_g_proxy_new_for_name(g_connection, OBEX_CLIENT_SERVICE,
+ OBEX_CLIENT_PATH,
+ OBEX_CLIENT_INTERFACE);
+ if (mns_proxy == NULL) {
+ DBG("Failed to get a proxy for D-Bus\n");
+ return;
+ }
+
+ dbus_g_proxy_call(mns_proxy, "RemoveSession", &error,
+ DBUS_TYPE_G_OBJECT_PATH, g_mns_path,
+ G_TYPE_INVALID, G_TYPE_INVALID);
+ if (error) {
+ DBG("Error [%s]", error->message);
+ g_error_free(error);
+ g_object_unref(mns_proxy);
+ return;
+ }
+
+ g_free(g_mns_path);
+ g_mns_path = NULL;
+
+ g_object_unref(mns_proxy);
+
+ DBG("-\n");
+ return;
+}
+
+static gboolean bluetooth_map_get_folder_tree(BluetoothMapAgent *agent,
+ DBusGMethodInvocation *context)
+{
+ GPtrArray *array = g_ptr_array_new();
+ GValue value;
+ GError *error = NULL;
+
+ char name[BT_MAP_MSG_INFO_MAX] = {0,};
+ char folder_name[BT_MAP_MSG_INFO_MAX] = {0,};
+ int i;
+ int ret;
+ gboolean msg_ret = TRUE;
+
+ msg_struct_list_s g_folderList;
+ msg_struct_t p_folder;
+
+#ifdef SUPPORT_EMAIL
+ int j;
+ int account_id = 0;
+ int mailbox_count = 0;
+ gboolean flag = FALSE;
+ email_mailbox_t *mailbox_list = NULL;
+#endif
+
+ if (g_msg_handle == NULL) {
+ msg_ret = FALSE;
+ goto done;
+ }
+
+ if (msg_get_folder_list(g_msg_handle, &g_folderList) != MSG_SUCCESS) {
+ msg_ret = FALSE;
+ goto done;
+ }
+
+ for (i = 0; i < g_folderList.nCount; i++) {
+ p_folder = g_folderList.msg_struct_info[i];
+ memset(folder_name, 0x00, BT_MAP_MSG_INFO_MAX);
+
+ ret = msg_get_str_value(p_folder, MSG_FOLDER_INFO_NAME_STR,
+ folder_name, BT_MAP_MSG_INFO_MAX);
+ if (ret != MSG_SUCCESS)
+ continue;
+
+ if (!g_ascii_strncasecmp(folder_name, BT_MAP_SENT_FOLDER_NAME,
+ strlen(BT_MAP_SENT_FOLDER_NAME))) {
+ memset(folder_name, 0, sizeof(folder_name));
+ g_strlcpy(folder_name, BT_MAP_SENT_FOLDER_NAME,
+ sizeof(folder_name));
+ }
+
+ g_strlcpy(name, folder_name, sizeof(name));
+ memset(&value, 0, sizeof(GValue));
+ g_value_init(&value, DBUS_STRUCT_STRING_STRING_UINT);
+ g_value_take_boxed(&value, dbus_g_type_specialized_construct(
+ DBUS_STRUCT_STRING_STRING_UINT));
+ dbus_g_type_struct_set(&value, 0, name, G_MAXUINT);
+ g_ptr_array_add(array, g_value_get_boxed(&value));
+ }
+
+#ifdef SUPPORT_EMAIL
+email:
+ if (EMAIL_ERROR_NONE != email_load_default_account_id(&account_id))
+ goto done;
+
+ if (EMAIL_ERROR_NONE != email_get_mailbox_list(account_id,
+ EMAIL_MAILBOX_ALL,
+ &mailbox_list,
+ &mailbox_count)) {
+ goto done;
+ }
+
+ msg_ret = TRUE;
+
+ for (i = 0; i < mailbox_count; i++) {
+ flag = FALSE;
+ for (j = 0; j < g_folderList.nCount; j++) {
+
+ p_folder = g_folderList.msg_struct_info[j];
+ memset(folder_name, 0x00, BT_MAP_MSG_INFO_MAX);
+
+ ret = msg_get_str_value(p_folder,
+ MSG_FOLDER_INFO_NAME_STR,
+ folder_name,
+ BT_MAP_MSG_INFO_MAX);
+ if (ret != MSG_SUCCESS)
+ continue;
+
+ if (!g_ascii_strncasecmp(mailbox_list[i].alias,
+ folder_name, strlen(mailbox_list[i].alias))) {
+ flag = TRUE;
+ break;
+ }
+ }
+
+ if (!flag) {
+ g_strlcpy(name, mailbox_list[i].alias, sizeof(name));
+
+ if (!g_ascii_strncasecmp(name, BT_MAP_SENT_FOLDER_NAME,
+ strlen(BT_MAP_SENT_FOLDER_NAME)))
+ continue;
+
+ memset(&value, 0, sizeof(GValue));
+ g_value_init(&value, DBUS_STRUCT_STRING_STRING_UINT);
+ g_value_take_boxed(&value,
+ dbus_g_type_specialized_construct(
+ DBUS_STRUCT_STRING_STRING_UINT));
+ dbus_g_type_struct_set(&value, 0, name, G_MAXUINT);
+ g_ptr_array_add(array, g_value_get_boxed(&value));
+ }
+ }
+
+ if (mailbox_list != NULL)
+ email_free_mailbox(&mailbox_list, mailbox_count);
+#endif
+
+done:
+
+ if (msg_ret == FALSE) {
+ g_ptr_array_free(array, TRUE);
+
+ error = __bt_map_agent_error(BT_MAP_AGENT_ERROR_INTERNAL,
+ "InternalError");
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ } else {
+ dbus_g_method_return(context, array);
+ g_ptr_array_free(array, TRUE);
+ return TRUE;
+ }
+}
+
+static gboolean bluetooth_map_get_message_list(BluetoothMapAgent *agent,
+ gchar *folder_name, guint16 max,
+ DBusGMethodInvocation *context)
+{
+ GPtrArray *array = g_ptr_array_new();
+ GValue value;
+ GError *error = NULL;
+
+ char *folder = NULL;
+ int i = 0;
+ int ret = 0;
+ int folder_id = 0;
+ int unread_cnt;
+ guint64 count;
+ gboolean newmsg;
+
+ msg_struct_list_s g_folderList;
+ msg_struct_list_s msg_list;
+ msg_struct_t count_info;
+
+#ifdef SUPPORT_EMAIL
+ int total = 0;
+ int account_id = 0;
+ int mailbox_count = 0;
+ int mail_count = 0;
+ char *type = NULL;
+ char msg_datetime[BT_MAP_TIMESTAMP_MAX_LEN] = {0,};
+ email_mailbox_t *mailbox_list = NULL;
+ email_mail_list_item_t *mail_list = NULL;
+ email_list_filter_t *filter_list = NULL;
+ email_list_sorting_rule_t *sorting_rule_list = NULL;
+#endif
+
+ if (g_msg_handle == NULL)
+ goto fail;
+
+ folder = strrchr(folder_name, '/');
+ if (NULL == folder)
+ folder = folder_name;
+ else
+ folder++;
+
+ ret = msg_get_folder_list(g_msg_handle, &g_folderList);
+ if (ret != MSG_SUCCESS)
+ goto fail;
+
+ for (i = 0; i < g_folderList.nCount; i++) {
+ msg_struct_t pFolder = g_folderList.msg_struct_info[i];
+ char folderName[BT_MAP_MSG_INFO_MAX] = {0, };
+
+ ret = msg_get_str_value(pFolder, MSG_FOLDER_INFO_NAME_STR,
+ folderName, BT_MAP_MSG_INFO_MAX);
+ if (ret != MSG_SUCCESS)
+ continue;
+
+ if (!g_ascii_strncasecmp(folderName, folder, strlen(folder))) {
+ ret = msg_get_int_value(pFolder, MSG_FOLDER_INFO_ID_INT,
+ &folder_id);
+ if (ret != MSG_SUCCESS)
+ goto fail;
+ else
+ DBG("folder_id %d \n", folder_id);
+
+ break;
+ }
+ }
+
+ ret = msg_get_folder_view_list(g_msg_handle, folder_id,
+ NULL, &msg_list);
+ if (ret != MSG_SUCCESS)
+ goto fail;
+
+ count = msg_list.nCount;
+
+ count_info = msg_create_struct(MSG_STRUCT_COUNT_INFO);
+ ret = msg_count_message(g_msg_handle, folder_id, count_info);
+ if (ret != MSG_SUCCESS) {
+ msg_release_struct(&count_info);
+ goto fail;
+ }
+
+ ret = msg_get_int_value(count_info, MSG_COUNT_INFO_UNREAD_INT,
+ &unread_cnt);
+ if (ret != MSG_SUCCESS) {
+ msg_release_struct(&count_info);
+ goto fail;
+ }
+
+ if (unread_cnt != 0)
+ newmsg = TRUE;
+ else
+ newmsg = FALSE;
+
+ msg_release_struct(&count_info);
+
+ DBG("MaxlistCount %d \n", max);
+ if (max == 0)
+ goto done;
+
+ for (i = 0; i < msg_list.nCount; i++) {
+
+ struct message_info msg_info;
+
+ memset(&value, 0, sizeof(GValue));
+ g_value_init(&value, DBUS_STRUCT_MESSAGE_LIST);
+ g_value_take_boxed(&value, dbus_g_type_specialized_construct(
+ DBUS_STRUCT_MESSAGE_LIST));
+
+ msg_info = __bt_message_info_get(msg_list.msg_struct_info[i]);
+
+/* Keeping the bleow debug till stabilization is done. */
+
+/*
+ DBG("msg_info.handle = %s\n", msg_info.handle);
+ DBG("msg_info.subject = %s\n", msg_info.subject);
+ DBG("msg_info.datetime = %s\n", msg_info.datetime);
+ DBG("msg_info.sender_name = %s\n", msg_info.sender_name);
+ DBG("msg_info.sender_addressing = %s\n", msg_info.sender_addressing);
+ DBG("msg_info.replyto_addressing = %s\n", msg_info.replyto_addressing);
+ DBG("msg_info.recipient_name = %s\n", msg_info.recipient_name);
+ DBG("msg_info.recipient_addressing = %s\n",
+ msg_info.recipient_addressing);
+ DBG("msg_info.type = %s\n", msg_info.type);
+ DBG("msg_info.reception_status = %s\n", msg_info.reception_status);
+ DBG("msg_info.size = %s\n", msg_info.size);
+ DBG("msg_info.attachment_size = %s\n", msg_info.attachment_size);
+ DBG("msg_info.text = %d\n", msg_info.text);
+ DBG("msg_info.read = %d\n", msg_info.read);
+ DBG("msg_info.sent = %d\n", msg_info.sent);
+ DBG("msg_info.protect = %d\n", msg_info.protect);
+ DBG("msg_info.priority = %d\n", msg_info.priority);
+*/
+
+ dbus_g_type_struct_set(&value, 0, msg_info.handle,
+ 1, msg_info.subject,
+ 2, msg_info.datetime,
+ 3, msg_info.sender_name,
+ 4, msg_info.sender_addressing,
+ 5, msg_info.recipient_name,
+ 6, msg_info.recipient_addressing,
+ 7, msg_info.type,
+ 8, msg_info.size,
+ 9, msg_info.reception_status,
+ 10, msg_info.text,
+ 11, msg_info.attachment_size,
+ 12, msg_info.priority,
+ 13, msg_info.read,
+ 14, msg_info.sent,
+ 15, msg_info.protect,
+ 16, msg_info.replyto_addressing, G_MAXUINT);
+ g_ptr_array_add(array, g_value_get_boxed(&value));
+
+ __bt_message_info_free(msg_info);
+ }
+
+#ifdef SUPPORT_EMAIL
+email:
+ if (EMAIL_ERROR_NONE != email_load_default_account_id(&account_id)) {
+ if (!msg_ret)
+ goto fail;
+ }
+
+ if (EMAIL_ERROR_NONE != email_get_mailbox_list(account_id,
+ EMAIL_MAILBOX_ALL,
+ &mailbox_list,
+ &mailbox_count)) {
+ if (!msg_ret)
+ goto fail;
+ }
+
+ if (mailbox_list == NULL)
+ goto fail;
+
+ for (i = 0; i < mailbox_count; i++) {
+ DBG("mailbox alias = %s \n", mailbox_list[i].alias);
+ if (!g_ascii_strncasecmp(mailbox_list[i].alias, folder,
+ strlen(folder))) {
+ total = mailbox_list[i].total_mail_count_on_server;
+ DBG("Total mail on sever:%d\n", total);
+ DBG("mailbox name:%s\n", mailbox_list[i].mailbox_name);
+
+ break;
+ }
+
+ if (!msg_ret)
+ goto fail;
+ else
+ goto done;
+ }
+
+ /* Need to modify the filter code, have to make it dynamic
+ based on remote device request Also to check whether it needs
+ to be done in agent or in obexd */
+
+ filter_list = g_new0(email_list_filter_t, 3);
+ filter_list[0].list_filter_item_type = EMAIL_LIST_FILTER_ITEM_RULE;
+ filter_list[0].list_filter_item.rule.target_attribute =
+ EMAIL_MAIL_ATTRIBUTE_ACCOUNT_ID;
+ filter_list[0].list_filter_item.rule.rule_type =
+ EMAIL_LIST_FILTER_RULE_EQUAL;
+ filter_list[0].list_filter_item.rule.key_value.integer_type_value =
+ account_id;
+
+ filter_list[1].list_filter_item_type = EMAIL_LIST_FILTER_ITEM_OPERATOR;
+ filter_list[1].list_filter_item.operator_type =
+ EMAIL_LIST_FILTER_OPERATOR_AND;
+
+ filter_list[2].list_filter_item_type = EMAIL_LIST_FILTER_ITEM_RULE;
+ filter_list[2].list_filter_item.rule.target_attribute =
+ EMAIL_MAIL_ATTRIBUTE_MAILBOX_NAME;
+ filter_list[2].list_filter_item.rule.rule_type =
+ EMAIL_LIST_FILTER_RULE_EQUAL;
+ type = g_strdup(mailbox_list[i].mailbox_name);
+ filter_list[2].list_filter_item.rule.key_value.string_type_value = type;
+ filter_list[2].list_filter_item.rule.case_sensitivity = true;
+
+ sorting_rule_list = g_new0(email_list_sorting_rule_t, 1);
+ sorting_rule_list->target_attribute = EMAIL_MAIL_ATTRIBUTE_DATE_TIME;
+ sorting_rule_list->sort_order = EMAIL_SORT_ORDER_ASCEND;
+
+ ret = email_get_mail_list_ex(filter_list, 3,
+ sorting_rule_list, 1, 0, total - 1,
+ &mail_list, &mail_count);
+
+ DBG("email API ret %d \n", ret);
+ if (ret != EMAIL_ERROR_NONE) {
+ if (!msg_ret) {
+ g_free(type);
+ g_free(filter_list);
+ g_free(sorting_rule_list);
+ goto fail;
+ } else
+ goto done;
+ }
+
+ for (i = 0; i < mail_count; ++i) {
+ time_t time = {0,};
+ memset(&value, 0, sizeof(GValue));
+ g_value_init(&value, DBUS_STRUCT_MESSAGE_LIST);
+ g_value_take_boxed(&value, dbus_g_type_specialized_construct(
+ DBUS_STRUCT_MESSAGE_LIST));
+
+ uid = __bt_add_id(mail_list[i].mail_id);
+ snprintf(msg_handle, sizeof(msg_handle), "%llx", uid);
+
+ g_strlcpy(msg_type, "EMAIL", sizeof(msg_type));
+
+ time = mail_list[i].date_time;
+ __get_msg_timestamp(&time, msg_datetime);
+
+ dbus_g_type_struct_set(&value, 0, msg_handle, 1, msg_type,
+ 2, msg_datetime, G_MAXUINT);
+ g_ptr_array_add(array, g_value_get_boxed(&value));
+ }
+
+ if (mailbox_list != NULL)
+ email_free_mailbox(&mailbox_list, mailbox_count);
+ if (mail_list != NULL)
+ g_free(mail_list);
+
+ g_free(filter_list);
+ g_free(sorting_rule_list);
+ g_free(type);
+#endif
+
+done:
+ DBG("Request completed \n");
+ dbus_g_method_return(context, newmsg, count, array);
+ g_ptr_array_free(array, TRUE);
+ DBG("Request completed successfully \n");
+ return TRUE;
+
+fail:
+ g_ptr_array_free(array, TRUE);
+ error = __bt_map_agent_error(BT_MAP_AGENT_ERROR_INTERNAL,
+ "InternalError");
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+}
+
+static gboolean bluetooth_map_get_message(BluetoothMapAgent *agent,
+ gchar *message_name,
+ gboolean attach,
+ gboolean transcode,
+ gboolean first_request,
+ DBusGMethodInvocation *context)
+{
+ DBG("+ \n");
+ char *buf = NULL;
+ int message_id = 0;
+ int msg_type = BT_SMS;
+
+ GError *error = NULL;
+
+ msg_struct_t msg = NULL;
+ msg_struct_t send_opt = NULL;
+#ifdef SUPPORT_EMAIL
+ email_mail_data_t *mail_data = NULL;
+#endif
+ message_id = __bt_get_uid(message_name);
+ if (message_id == -1)
+ goto fail;
+
+ DBG("message_id %d \n", message_id);
+ DBG("msg_type %d \n", msg_type);
+ DBG("attach %d \n", attach);
+ DBG("transcode %d \n", transcode);
+ DBG("first_request %d \n", first_request);
+
+ if (msg_type == BT_SMS) {
+ if (g_msg_handle == NULL)
+ goto fail;
+
+ msg_error_t msg_err;
+
+ msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+ send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
+
+ msg_err = msg_get_message(g_msg_handle,
+ (msg_message_id_t)message_id,
+ msg, send_opt);
+ if (msg_err != MSG_SUCCESS)
+ goto fail;
+
+ buf = __bt_prepare_msg_bmseg(msg, attach, transcode);
+
+ msg_release_struct(&msg);
+ msg_release_struct(&send_opt);
+#ifdef SUPPORT_EMAIL
+ } else if (msg_type == BT_EMAIL) {
+
+ FILE *body_file;
+ int account_id;
+ long read_size;
+ long email_size;
+
+ if (EMAIL_ERROR_NONE !=
+ email_load_default_account_id(&account_id))
+ goto fail;
+
+ if (EMAIL_ERROR_NONE !=
+ email_get_mail_data(message_id, &mail_data))
+ goto fail;
+
+ body_file = fopen(mail_data->file_path_plain, "r");
+ if (body_file == NULL)
+ body_file = fopen(mail_data->file_path_html, "rb");
+
+ if (body_file != NULL) {
+ fseek(body_file , 0, SEEK_END);
+ email_size = ftell(body_file);
+ rewind(body_file);
+
+ buf = (char *)g_malloc0(sizeof(char) * email_size);
+
+ read_size = fread(buf, 1, email_size, body_file);
+
+ fclose(body_file);
+
+ if (read_size != email_size)
+ goto fail;
+ } else
+ buf = (char *)g_strdup("");
+
+ email_free_mail_data(&mail_data, 1);
+#endif
+ } else {
+ DBG("msg_type not supported %d \n", msg_type);
+ goto fail;
+ }
+
+ dbus_g_method_return(context, FALSE, buf);
+ g_free(buf);
+
+ DBG("- \n");
+ return TRUE;
+
+fail:
+ g_free(buf);
+
+ if (msg)
+ msg_release_struct(&msg);
+
+ if (send_opt)
+ msg_release_struct(&send_opt);
+
+#ifdef SUPPORT_EMAIL
+ if (mail_data)
+ email_free_mail_data(&mail_data, 1);
+#endif
+
+ error = __bt_map_agent_error(BT_MAP_AGENT_ERROR_INTERNAL,
+ "InternalError");
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+}
+
+static gboolean bluetooth_map_push_message(BluetoothMapAgent *agent,
+ gboolean save_copy,
+ gboolean retry_send,
+ gboolean native,
+ gchar *folder_name,
+ DBusGMethodInvocation *context)
+{
+ DBG("+\n");
+ GError *error = NULL;
+ guint64 handle = 0;
+ int folder_id;
+
+ DBG("folder_name = %s\n", folder_name);
+
+ folder_id = __bt_get_folder_id(folder_name);
+ if (folder_id == -1)
+ goto fail;
+
+ handle = __bt_add_id(-1);
+ current_push_map_id = handle;
+
+ /* FALSE : Keep messages in Sent folder */
+ /* TRUE : don't keep messages in sent folder */
+ opt.save_copy = save_copy;
+ DBG("opt.save_copy = %d\n", opt.save_copy);
+
+ /* FALSE : don't retry */
+ /* TRUE : retry */
+ opt.retry_send = retry_send;
+ DBG("opt.retry_send = %d\n", opt.retry_send);
+
+ /* FALSE : native */
+ /* TRUE : UTF-8 */
+ opt.native = native;
+ DBG("opt.native = %d\n", opt.native);
+
+ dbus_g_method_return(context, handle);
+ DBG("-\n");
+ return TRUE;
+fail:
+ error = __bt_map_agent_error(BT_MAP_AGENT_ERROR_INTERNAL,
+ "InternalError");
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+
+ return FALSE;
+}
+
+static gboolean bluetooth_map_push_message_data(BluetoothMapAgent *agent,
+ gchar *bmsg,
+ DBusGMethodInvocation *context)
+{
+ DBG("+\n");
+ int id = -1;
+ int folder_id;
+ char *folder = NULL;
+ char *body = NULL;
+ GSList *recepients = NULL;
+ gboolean send = FALSE;
+
+ GError *error = NULL;
+
+ DBG("BMSG is \n %s", bmsg);
+
+ struct bmsg_data *bmsg_info = NULL;
+
+ bmsg_info = bmsg_parse(bmsg);
+ if (!bmsg_info)
+ goto done;
+
+ folder = bmsg_get_msg_folder(bmsg_info);
+ if (folder == NULL)
+ goto done;
+
+ folder_id = __bt_get_folder_id(bmsg_info->folder);
+ if (folder_id == -1)
+ goto done;
+
+ if (MSG_OUTBOX_ID == folder_id)
+ send = TRUE;
+
+ body = bmsg_get_msg_body(bmsg_info);
+ if (body == NULL)
+ goto done;
+
+ recepients = bmsg_get_msg_recepients(bmsg_info);
+
+ id = __bt_push_sms(send, folder_id, body, recepients);
+ if (id == -1)
+ goto done;
+
+ __bt_update_id(current_push_map_id, id);
+
+done:
+ g_free(folder);
+ g_free(body);
+ g_slist_free(recepients);
+ g_free(bmsg_info);
+
+ if (id == -1) {
+ error = __bt_map_agent_error(BT_MAP_AGENT_ERROR_INTERNAL,
+ "InternalError");
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ DBG("-\n");
+ return FALSE;
+ }
+
+ dbus_g_method_return(context);
+ DBG("-\n");
+ return TRUE;
+}
+
+static gboolean bluetooth_map_update_message(BluetoothMapAgent *agent,
+ DBusGMethodInvocation *context)
+{
+ int err = TRUE;
+#ifdef SUPPORT_EMAIL
+ int handle;
+ err = email_sync_header_for_all_account(&handle);
+
+ if (err == EMAIL_ERROR_NONE) {
+ DBG("Handle to stop download = %d \n", handle);
+ } else {
+ ERR("Message Update failed \n");
+ }
+
+ dbus_g_method_return(context, err);
+ return (err == EMAIL_ERROR_NONE) ? TRUE : FALSE;
+#else
+ dbus_g_method_return(context, err);
+ return TRUE;
+#endif
+}
+
+static gboolean bluetooth_map_set_read_status(BluetoothMapAgent *agent,
+ gchar *handle,
+ gboolean read_status,
+ DBusGMethodInvocation *context)
+{
+ int message_id = 0;
+ int msg_type = BT_SMS;
+#ifdef SUPPORT_EMAIL
+ email_mail_data_t *mail_data = NULL;
+#endif
+ GError *error = NULL;
+
+ DBG("+\n");
+
+ message_id = __bt_get_uid(handle);
+ if (message_id == -1)
+ goto fail;
+
+ DBG("message_id = %d, read_status = %d\n", message_id, read_status);
+
+ if (msg_type == BT_SMS) {
+ msg_error_t msg_err;
+ msg_struct_t msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+ msg_struct_t send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
+ int msg_type = 0;
+
+ msg_err = msg_get_message(g_msg_handle,
+ (msg_message_id_t)message_id,
+ msg, send_opt);
+ if (msg_err != MSG_SUCCESS) {
+ msg_release_struct(&msg);
+ msg_release_struct(&send_opt);
+ goto fail;
+ }
+
+ msg_err = msg_get_int_value(msg, MSG_MESSAGE_TYPE_INT,
+ &msg_type);
+ if (msg_err != MSG_SUCCESS) {
+ msg_release_struct(&msg);
+ msg_release_struct(&send_opt);
+ goto fail;
+ }
+
+ msg_err = msg_update_read_status(g_msg_handle, message_id,
+ read_status);
+ if (msg_err != MSG_SUCCESS) {
+ msg_release_struct(&msg);
+ msg_release_struct(&send_opt);
+ goto fail;
+ }
+
+ if (__bt_msg_is_mms(msg_type)) {
+ if (read_status == TRUE)
+ msg_err = msg_mms_send_read_report(g_msg_handle,
+ message_id,
+ MSG_READ_REPORT_IS_READ);
+ else
+ msg_err = msg_mms_send_read_report(g_msg_handle,
+ message_id,
+ MSG_READ_REPORT_NONE);
+ }
+
+ msg_release_struct(&msg);
+ msg_release_struct(&send_opt);
+
+ if (msg_err != MSG_SUCCESS)
+ goto fail;
+#ifdef SUPPORT_EMAIL
+ } else if (msg_type == BT_EMAIL) {
+
+ if (email_get_mail_data(message_id, &mail_data) !=
+ EMAIL_ERROR_NONE) {
+ ERR("email_get_mail_data failed\n");
+ goto fail;
+ }
+
+ if (email_set_flags_field(mail_data->account_id, &message_id, 1,
+ EMAIL_FLAGS_SEEN_FIELD, read_status, 0) !=
+ EMAIL_ERROR_NONE) {
+ email_free_mail_data(&mail_data, 1);
+ goto fail;
+ }
+
+ email_free_mail_data(&mail_data, 1);
+#endif
+ } else
+ goto fail;
+
+ dbus_g_method_return(context);
+ DBG("-\n");
+ return TRUE;
+
+fail:
+ error = __bt_map_agent_error(BT_MAP_AGENT_ERROR_INTERNAL,
+ "InternalError");
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+
+ return FALSE;
+}
+
+static gboolean bluetooth_map_set_delete_status(BluetoothMapAgent *agent,
+ gchar *handle,
+ gboolean delete_status,
+ DBusGMethodInvocation *context)
+{
+ int message_id = 0;
+ int msg_type = BT_SMS;
+#ifdef SUPPORT_EMAIL
+ email_mail_data_t *mail_data = NULL;
+#endif
+ GError *error = NULL;
+
+ DBG("+\n");
+
+ message_id = __bt_get_uid(handle);
+ if (message_id == -1)
+ goto fail;
+
+ DBG("message_id = %d, delete_status = %d\n", message_id, delete_status);
+
+ if (msg_type == BT_SMS) {
+ if (msg_delete_message(g_msg_handle, message_id) !=
+ MSG_SUCCESS) {
+ goto fail;
+ }
+#ifdef SUPPORT_EMAIL
+ } else if (msg_type == BT_EMAIL) {
+
+ if (email_get_mail_data(message_id, &mail_data) !=
+ EMAIL_ERROR_NONE)
+ goto fail;
+
+ if (email_delete_mail(mail_data->mailbox_id, &message_id,
+ 1, 1) != EMAIL_ERROR_NONE) {
+ email_free_mail_data(&mail_data, 1);
+ goto fail;
+ }
+
+ email_free_mail_data(&mail_data, 1);
+#endif
+ } else
+ goto fail;
+
+ dbus_g_method_return(context);
+ DBG("-\n");
+ return TRUE;
+
+fail:
+ error = __bt_map_agent_error(BT_MAP_AGENT_ERROR_INTERNAL,
+ "InternalError");
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+}
+
+static gboolean bluetooth_map_noti_registration(BluetoothMapAgent *agent,
+ gchar *remote_addr,
+ gboolean status,
+ DBusGMethodInvocation *context)
+{
+ DBG("remote_addr = %s \n", remote_addr);
+
+ if (status == TRUE)
+ __bt_mns_client_connect(remote_addr);
+ else
+ __bt_mns_client_disconnect();
+
+ return TRUE;
+}
+
+int main(int argc, char **argv)
+{
+ BluetoothMapAgent *bluetooth_map_obj = NULL;
+ DBusGProxy *bus_proxy = NULL;
+ guint result = 0;
+ GError *error = NULL;
+
+ g_type_init();
+
+ g_mainloop = g_main_loop_new(NULL, FALSE);
+
+ if (g_mainloop == NULL) {
+ ERR("Couldn't create GMainLoop\n");
+ return EXIT_FAILURE;
+ }
+
+ g_connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+
+ if (error != NULL) {
+ ERR("Couldn't connect to system bus[%s]\n", error->message);
+ g_error_free(error);
+ return EXIT_FAILURE;
+ }
+
+ bus_proxy = dbus_g_proxy_new_for_name(g_connection, DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+ if (bus_proxy == NULL) {
+ ERR("Failed to get a proxy for D-Bus\n");
+ goto failure;
+ }
+
+ if (!dbus_g_proxy_call(bus_proxy, "RequestName", &error, G_TYPE_STRING,
+ BT_MAP_SERVICE_NAME, G_TYPE_UINT, 0,
+ G_TYPE_INVALID, G_TYPE_UINT, &result,
+ G_TYPE_INVALID)) {
+ if (error != NULL) {
+ ERR("RequestName RPC failed[%s]\n", error->message);
+ g_error_free(error);
+ }
+ goto failure;
+ }
+ DBG("result : %d %d\n", result, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ ERR("Failed to get the primary well-known name.\n");
+ goto failure;
+ }
+
+ g_object_unref(bus_proxy);
+ bus_proxy = NULL;
+
+ bluetooth_map_obj = g_object_new(BLUETOOTH_MAP_TYPE_AGENT, NULL);
+ if (bluetooth_map_obj == NULL) {
+ ERR("Failed to create one BluetoothMapAgent instance.\n");
+ goto failure;
+ }
+
+ /* Registering it on the D-Bus */
+ dbus_g_connection_register_g_object(g_connection,
+ BT_MAP_SERVICE_OBJECT_PATH,
+ G_OBJECT(bluetooth_map_obj));
+
+ if (__bluetooth_map_start_service() == FALSE)
+ goto failure;
+
+ g_main_loop_run(g_mainloop);
+
+ failure:
+ DBG("Terminate the bluetooth-map-agent\n");
+
+ __bt_remove_list(id_list);
+
+ if (g_mns_path)
+ __bt_mns_client_disconnect();
+ if (bus_proxy)
+ g_object_unref(bus_proxy);
+ if (bluetooth_map_obj)
+ g_object_unref(bluetooth_map_obj);
+ if (g_connection)
+ dbus_g_connection_unref(g_connection);
+
+
+ __bluetooth_map_stop_service();
+ return EXIT_FAILURE;
+}
--- /dev/null
+/*
+ * bluetooth-agent
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DEF_BT_PB_AGENT_H_
+#define __DEF_BT_PB_AGENT_H_
+
+#include <unistd.h>
+#include <dlog.h>
+
+#include <stdio.h>
+
+#include <dbus/dbus-glib.h>
+
+#define BT_MAP_AGENT_ERROR (__bt_map_agent_error_quark())
+
+typedef enum {
+ BT_MAP_AGENT_ERROR_INTERNAL,
+ BT_MAP_AGENT_ERROR_CANCEL,
+} bt_map_agent_error_t;
+
+#define BT_MAP_SERVICE_OBJECT_PATH "/org/bluez/map_agent"
+#define BT_MAP_SERVICE_NAME "org.bluez.map_agent"
+#define BT_MAP_SERVICE_INTERFACE "org.bluez.MapAgent"
+
+#undef LOG_TAG
+#define LOG_TAG "BLUETOOTH_AGENT_MESSAGE"
+
+#define DBG(fmt, args...) SLOGD(fmt, ##args)
+#define ERR(fmt, args...) SLOGE(fmt, ##args)
+
+#endif /* __DEF_BT_AGENT_H_ */
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<node name="/">
+ <interface name="org.bluez.MapAgent">
+ <method name="GetFolderTree">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="a(s)" name="folder_list" direction="out"/>
+ </method>
+ <method name="GetMessageList">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="folder_name"/>
+ <arg type="q" name="max"/>
+ <arg type="b" name="newmessage" direction="out"/>
+ <arg type="t" name="count" direction="out"/>
+ <arg type="a(ssssssssssbsbbbbs)" name="msg_list" direction="out"/>
+ </method>
+ <method name="GetMessage">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="messgae_name"/>
+ <arg type="b" name="attach"/>
+ <arg type="b" name="transcode"/>
+ <arg type="b" name="first_request"/>
+ <arg type="b" name="fraction_deliver" direction="out"/>
+ <arg type="s" name="msg_body" direction="out"/>
+ </method>
+ <method name="PushMessage">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="b" name="save_copy"/>
+ <arg type="b" name="retry_send"/>
+ <arg type="b" name="native"/>
+ <arg type="s" name="folder_name"/>
+ <arg type="t" name="handle" direction="out"/>
+ </method>
+ <method name="PushMessageData">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="bmsg"/>
+ </method>
+ <method name="UpdateMessage">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="u" name="update_err" direction="out"/>
+ </method>
+ <method name="SetReadStatus">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="handle"/>
+ <arg type="b" name="read_status"/>
+ <arg type="u" name="update_err" direction="out"/>
+ </method>
+ <method name="SetDeleteStatus">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="handle"/>
+ <arg type="b" name="delete_status"/>
+ <arg type="u" name="update_err" direction="out"/>
+ </method>
+ <method name="NotiRegistration">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="remote_addr"/>
+ <arg type="b" name="status"/>
+ <arg type="u" name="update_err" direction="out"/>
+ </method>
+ </interface>
+</node>
--- /dev/null
+/*
+ * bluetooth-agent
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include <map_bmessage.h>
+
+#include <bluetooth_map_agent.h>
+
+#define CRLF_LEN 2
+
+#define BMSG_TAG "BEGIN:BMSG\r\n"
+#define VER_TAG "VERSION:"
+#define STATUS_TAG "STATUS:"
+#define TYPE_TAG "TYPE:"
+#define FOLDER_TAG "FOLDER:"
+#define VCARD_BEGIN_TAG "BEGIN:VCARD\r\n"
+#define VCARD_END_TAG "END:VCARD\r\n"
+#define VCARD_N_TAG "N:"
+#define VCARD_FN_TAG "FN:"
+#define VCARD_TEL_TAG "TEL:"
+#define VCARD_EMAIL_TAG "EMAIL:"
+#define BENV_TAG "BEGIN:BENV\r\n"
+#define BBODY_TAG "BEGIN:BBODY\r\n"
+#define MSG_TAG "BEGIN:MSG\r\n"
+#define PARTID_TAG "PARTID:"
+#define ENCODING_TAG "ENCODING:"
+#define CHARSET_TAG "CHARSET:"
+#define LANGUAGE_TAG "LANGUAGE:"
+#define LENGTH_TAG "LENGTH:"
+
+
+void print_bmsg(struct bmsg_data *bmsg)
+{
+ if (bmsg == NULL)
+ return;
+
+ struct benv_data *env_data = NULL;
+
+ DBG("bmsg->version = %s", bmsg->version);
+ DBG("bmsg->status = %s", bmsg->status);
+ DBG("bmsg->type = %s", bmsg->type);
+ DBG("bmsg->folder = %s", bmsg->folder);
+ DBG("bmsg->originator_vcard_data->version = %s",
+ bmsg->originator_vcard_data->version);
+ DBG("bmsg->originator_vcard_data->n = %s",
+ bmsg->originator_vcard_data->n);
+
+ int i = 0;
+ env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
+ while (env_data != NULL) {
+
+ DBG("env_data = %d", env_data->encapsulation_level);
+ int k = 0;
+ struct bmsg_vcard *rvcard;
+
+ rvcard = g_slist_nth_data(env_data->recipient_vcard, k);
+
+ while (rvcard != NULL) {
+ k++;
+
+ if (rvcard->version != NULL)
+ DBG("vcard->version = %s\n", rvcard->version);
+ if (rvcard->n != NULL)
+ DBG("vcard->n = %s\n", rvcard->n);
+ if (rvcard->fn != NULL)
+ DBG("vcard->fn = %s\n", rvcard->fn);
+ if (rvcard->tel != NULL)
+ DBG("vcard->tel = %s\n", rvcard->tel);
+ if (rvcard->email != NULL)
+ DBG("vcard->email = %s\n", rvcard->email);
+
+ rvcard = g_slist_nth_data(env_data->recipient_vcard, k);
+ }
+
+ if (env_data->body_content != NULL) {
+ DBG("env_data->body_content->length = %"
+ G_GUINT64_FORMAT "\n",
+ env_data->body_content->length);
+ DBG("env_data->body_content->msg = %s\n",
+ env_data->body_content->msg);
+ }
+
+ i++;
+
+ if (i > 2)
+ break;
+
+ env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
+ }
+}
+
+char *bmsg_get_msg_folder(struct bmsg_data *bmsg)
+{
+ return g_strdup(bmsg->folder);
+}
+
+char *bmsg_get_msg_body(struct bmsg_data *bmsg)
+{
+ struct benv_data *env_data;
+ int i = 0;
+
+ env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
+
+ while (env_data != NULL) {
+ if (env_data->body_content != NULL) {
+ DBG("env_data->body_content->msg = %s\n",
+ env_data->body_content->msg);
+ DBG("env_data->body_content->length = %"
+ G_GUINT64_FORMAT "\n",
+ env_data->body_content->length);
+ return g_strndup(env_data->body_content->msg,
+ env_data->body_content->length);
+ }
+
+ i++;
+ if (i > 2)
+ break;
+
+ env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
+ }
+
+ return NULL;
+}
+
+GSList *bmsg_get_msg_recepients(struct bmsg_data *bmsg)
+{
+ struct benv_data *env_data;
+ GSList *receiver = NULL;
+ int i = 0;
+
+ env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
+
+ while (env_data != NULL) {
+
+ DBG("env_data = %d", env_data->encapsulation_level);
+ int k = 0;
+ struct bmsg_vcard *rvcard;
+
+ rvcard = g_slist_nth_data(env_data->recipient_vcard, k);
+ while (rvcard != NULL) {
+ k++;
+
+ if (rvcard->tel != NULL) {
+ DBG("vcard->tel = %s\n", rvcard->tel);
+ receiver = g_slist_append(receiver, rvcard->tel);
+ }
+
+ rvcard = g_slist_nth_data(env_data->recipient_vcard, k);
+ }
+
+ i++;
+ if (i > 2)
+ break;
+
+ env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
+ }
+
+ return receiver;
+}
+
+void bmsg_free_vcard_data(struct bmsg_vcard *vcard_data)
+{
+ if (vcard_data == NULL)
+ return;
+
+ g_free(vcard_data->version);
+ g_free(vcard_data->n);
+ g_free(vcard_data->fn);
+ g_free(vcard_data->tel);
+ g_free(vcard_data->email);
+ g_free(vcard_data);
+
+ return;
+}
+
+void bmsg_free_bmsg(struct bmsg_data *bmsg)
+{
+ struct benv_data *env_data;
+ int i = 0;
+
+ if (bmsg == NULL)
+ return;
+
+ g_free(bmsg->version);
+ g_free(bmsg->status);
+ g_free(bmsg->type);
+ g_free(bmsg->folder);
+ bmsg_free_vcard_data(bmsg->originator_vcard_data);
+
+ if (bmsg->envelope_data == NULL)
+ goto done;
+
+ if (bmsg->envelope_data->env_data == NULL)
+ goto done;
+
+ env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
+ while (env_data != NULL) {
+
+ DBG("env_data = %d", env_data->encapsulation_level);
+ int k = 0;
+ struct bmsg_vcard *rvcard;
+
+ rvcard = g_slist_nth_data(env_data->recipient_vcard, k);
+
+ while (rvcard != NULL) {
+ k++;
+ bmsg_free_vcard_data(rvcard);
+ rvcard = g_slist_nth_data(env_data->recipient_vcard, k);
+ }
+
+ if (env_data->body_content != NULL) {
+ g_free(env_data->body_content->encoding);
+ g_free(env_data->body_content->charset);
+ g_free(env_data->body_content->language);
+ g_free(env_data->body_content->msg);
+ g_free(env_data->body_content);
+ }
+
+ g_free(env_data);
+ i++;
+
+ env_data = g_slist_nth_data(bmsg->envelope_data->env_data, i);
+ }
+
+done:
+ g_free(bmsg);
+}
+
+gchar *bmsg_get_parse_sub_block(char **sub_block_data, char *element)
+{
+ gchar *start;
+ gchar *end;
+ gchar *block_start;
+ gchar *block_end;
+ gchar *sub_block = NULL;
+ size_t offset;
+ size_t len;
+
+ DBG("");
+
+ start = g_strdup_printf("BEGIN:%s\r\n", element);
+ end = g_strdup_printf("END:%s\r\n", element);
+ offset = strlen(start);
+
+ block_start = g_strstr_len(*sub_block_data, offset, start);
+ if (block_start == NULL)
+ goto done;
+
+ if (!g_strcmp0(start, VCARD_BEGIN_TAG))
+ block_end = g_strstr_len(*sub_block_data, -1, end);
+ else
+ block_end = g_strrstr(*sub_block_data, end);
+
+ if (block_end == NULL)
+ goto done;
+
+ len = block_end - block_start - offset;
+ sub_block = g_strndup(block_start + offset, len);
+ *sub_block_data = *sub_block_data + strlen(sub_block) + strlen(start) +
+ strlen(end);
+done:
+ g_free(start);
+ g_free(end);
+ return sub_block;
+}
+
+gchar *bmsg_get_tag_data(char **block_data, char *element)
+{
+ gchar *end = "\r\n";
+ gchar *block_start;
+ gchar *block_end;
+ gchar *sub_block;
+ size_t offset;
+ size_t len;
+
+ DBG("");
+
+ if (*block_data == NULL || element == NULL)
+ return NULL;
+
+ block_start = g_strstr_len(*block_data, -1, element);
+ if (block_start == NULL)
+ return NULL;
+
+ offset = strlen(element);
+
+ block_end = g_strstr_len(block_start+offset, -1, end);
+ if (block_end == NULL)
+ return NULL;
+
+ len = block_end - block_start - offset;
+ sub_block = g_strndup(block_start + offset, len);
+ *block_data = *block_data + offset + len + CRLF_LEN;
+
+ return sub_block;
+}
+
+struct bmsg_bbody *bmsg_get_bbody_data(gchar *block_data)
+{
+ gchar *bbody_block_data_start;
+ gchar *temp;
+ struct bmsg_bbody *bbody;
+ DBG("");
+
+ bbody_block_data_start = block_data;
+
+ bbody = g_new0(struct bmsg_bbody, 1);
+
+ temp = bmsg_get_tag_data(&block_data, PARTID_TAG);
+ if (temp != NULL) {
+ bbody->part_id = (guint16)g_ascii_strtoull(temp, NULL, 10);
+ g_free(temp);
+ }
+
+ bbody->encoding = bmsg_get_tag_data(&block_data, ENCODING_TAG);
+ bbody->charset = bmsg_get_tag_data(&block_data, CHARSET_TAG);
+ bbody->language = bmsg_get_tag_data(&block_data, LANGUAGE_TAG);
+
+ temp = bmsg_get_tag_data(&block_data, LENGTH_TAG);
+
+ if (temp != NULL) {
+ bbody->length = g_ascii_strtoull(temp, NULL, 10);
+ g_free(temp);
+ }
+
+ bbody->msg = bmsg_get_parse_sub_block(&block_data, "MSG");
+
+ g_free(bbody_block_data_start);
+
+ return bbody;
+}
+
+struct bmsg_vcard *bmsg_get_vcard_data(gchar *sub_block_data)
+{
+ gchar *vcard_block_data_start;
+ struct bmsg_vcard *vcard;
+ DBG("");
+
+ vcard_block_data_start = sub_block_data;
+
+ vcard = g_new0(struct bmsg_vcard, 1);
+
+ vcard->version = bmsg_get_tag_data(&sub_block_data, VER_TAG);
+ vcard->n = bmsg_get_tag_data(&sub_block_data, VCARD_N_TAG);
+ vcard->fn = bmsg_get_tag_data(&sub_block_data, VCARD_FN_TAG);
+ vcard->tel = bmsg_get_tag_data(&sub_block_data, VCARD_TEL_TAG);
+ vcard->email = bmsg_get_tag_data(&sub_block_data, VCARD_EMAIL_TAG);
+
+ g_free(vcard_block_data_start);
+
+ return vcard;
+}
+
+struct benv_data *bmsg_get_env_encapsulation_data(gchar **sub_block_data)
+{
+ gchar *is_valid;
+ gchar *bbody_data = NULL;
+ static guint8 lvl = 1;
+
+ is_valid = g_strstr_len(*sub_block_data, strlen(VCARD_BEGIN_TAG),
+ VCARD_BEGIN_TAG);
+ if (is_valid == NULL)
+ return NULL;
+
+ if (lvl > 3)
+ return NULL;
+
+ struct benv_data *rec_data = g_new0(struct benv_data, 1);
+
+ rec_data->encapsulation_level = lvl;
+ lvl++;
+
+ while (is_valid != NULL) {
+ gchar *vcard_data = NULL;
+ struct bmsg_vcard *vcard;
+
+ vcard_data = bmsg_get_parse_sub_block(sub_block_data, "VCARD");
+ if (vcard_data == NULL) {
+ DBG("parse error\n");
+ g_free(rec_data);
+ return NULL;
+ }
+ vcard = bmsg_get_vcard_data(vcard_data);
+
+ rec_data->recipient_vcard = g_slist_append(
+ rec_data->recipient_vcard,
+ vcard);
+
+ is_valid = g_strstr_len(*sub_block_data,
+ strlen(VCARD_BEGIN_TAG),
+ VCARD_BEGIN_TAG);
+ }
+
+ is_valid = g_strstr_len(*sub_block_data, strlen(BBODY_TAG), BBODY_TAG);
+
+ if (!is_valid)
+ return rec_data;
+
+ bbody_data = bmsg_get_parse_sub_block(sub_block_data, "BBODY");
+ if (bbody_data == NULL) {
+ DBG("parse error\n");
+ return rec_data;
+ }
+
+ rec_data->body_content = bmsg_get_bbody_data(bbody_data);
+
+ return rec_data;
+}
+
+struct bmsg_envelope *bmsg_get_envelope_data(gchar **block_data)
+{
+ gchar *env_block_data_start;
+ gchar *sub_block_data;
+ struct bmsg_envelope *envelope_data;
+ struct benv_data *rec_data;
+
+ env_block_data_start = *block_data;
+
+ envelope_data = g_new0(struct bmsg_envelope, 1);
+
+ sub_block_data = bmsg_get_parse_sub_block(block_data, "BENV");
+
+ while (sub_block_data) {
+
+ rec_data = bmsg_get_env_encapsulation_data(&sub_block_data);
+
+ while (rec_data) {
+ envelope_data->env_data = g_slist_append(
+ envelope_data->env_data,
+ rec_data);
+
+ rec_data = bmsg_get_env_encapsulation_data(
+ &sub_block_data);
+ }
+ sub_block_data = bmsg_get_parse_sub_block(&sub_block_data,
+ "BENV");
+ }
+ g_free(sub_block_data);
+
+ return envelope_data;
+}
+
+struct bmsg_data * bmsg_parse(gchar *buf)
+{
+ gchar *block_data;
+ gchar *sub_block_data;
+ gchar *block_data_start;
+ struct bmsg_data *bmsg;
+
+ DBG("");
+
+ block_data = bmsg_get_parse_sub_block(&buf, "BMSG");
+ if (block_data == NULL)
+ return NULL;
+
+ block_data_start = block_data;
+
+ bmsg = g_new0(struct bmsg_data, 1);
+
+ bmsg->version = bmsg_get_tag_data(&block_data, VER_TAG);
+ if (bmsg->version == NULL)
+ goto parse_fail;
+
+ bmsg->status = bmsg_get_tag_data(&block_data, STATUS_TAG);
+ if (bmsg->status == NULL)
+ goto parse_fail;
+
+ bmsg->type = bmsg_get_tag_data(&block_data, TYPE_TAG);
+ if (bmsg->type == NULL)
+ goto parse_fail;
+
+ bmsg->folder = bmsg_get_tag_data(&block_data, FOLDER_TAG);
+ if (bmsg->folder == NULL)
+ goto parse_fail;
+
+ sub_block_data = bmsg_get_parse_sub_block(&block_data, "VCARD");
+ if (sub_block_data == NULL)
+ goto parse_fail;
+
+ bmsg->originator_vcard_data = bmsg_get_vcard_data(sub_block_data);
+ if (bmsg->originator_vcard_data == NULL)
+ goto parse_fail;
+
+ bmsg->envelope_data = bmsg_get_envelope_data(&block_data);
+ if (bmsg->envelope_data == NULL)
+ goto parse_fail;
+
+ g_free(block_data_start);
+
+ DBG("Parse done");
+ print_bmsg(bmsg);
+
+ return bmsg;
+
+parse_fail:
+ DBG("Parse fail");
+ bmsg_free_bmsg(bmsg);
+
+ return NULL;
+}
+
--- /dev/null
+/*
+ * bluetooth-agent
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+ #ifndef __BMSG_H
+#define __BMSG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bmsg_vcard {
+ gchar *version;
+ gchar *n;
+ gchar *fn;
+ gchar *tel;
+ gchar *email;
+};
+
+struct bmsg_bbody {
+ guint16 part_id;
+ gchar *encoding;
+ gchar *charset;
+ gchar *language;
+ guint64 length;
+ gchar *msg;
+};
+
+struct benv_data {
+ guint8 encapsulation_level;
+ GSList *recipient_vcard;
+ struct bmsg_bbody *body_content;
+};
+
+struct bmsg_envelope {
+ GSList *env_data; /* Add benv_data here*/
+};
+
+struct bmsg_data {
+ gchar *version;
+ gchar *status;
+ gchar *type;
+ gchar *folder;
+ struct bmsg_vcard *originator_vcard_data;
+ struct bmsg_envelope *envelope_data;
+};
+
+struct bmsg_data * bmsg_parse(gchar *buf);
+char *bmsg_get_msg_folder(struct bmsg_data *bmsg);
+char *bmsg_get_msg_body(struct bmsg_data *bmsg);
+GSList *bmsg_get_msg_recepients(struct bmsg_data *bmsg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BMSG_H */
--- /dev/null
+[D-BUS Service]
+Name=org.bluez.map_agent
+Exec=/usr/bin/bluetooth-map-agent
+User=root
--- /dev/null
+Name: bluetooth-agent
+Summary: Bluetooth agent packages that support various external profiles
+Version: 0.0.8
+Release: 2
+Group: TO_BE/FILLED_IN
+License: TO BE FILLED IN
+Source0: %{name}-%{version}.tar.gz
+
+BuildRequires: pkgconfig(contacts-service2)
+BuildRequires: pkgconfig(dbus-glib-1)
+BuildRequires: pkgconfig(msg-service)
+BuildRequires: pkgconfig(email-service)
+BuildRequires: pkgconfig(tapi)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(vconf)
+BuildRequires: pkgconfig(appsvc)
+BuildRequires: cmake
+
+%description
+Bluetooth agent packages that support various external profiles
+
+%prep
+%setup -q
+
+%build
+cmake . -DCMAKE_INSTALL_PREFIX=/usr
+
+make VERBOSE=1
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%files
+%manifest bluetooth-agent.manifest
+%defattr(-, root, root)
+%{_bindir}/bluetooth-map-agent
+%{_bindir}/bluetooth-pb-agent
+%{_bindir}/bluetooth-hfp-agent
+%{_datadir}/dbus-1/services/org.bluez.pb_agent.service
+%{_datadir}/dbus-1/services/org.bluez.map_agent.service
+%{_datadir}/dbus-1/services/org.bluez.hfp_agent.service
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(bluetooth-pb-agent C)
+
+SET(SRCS bluetooth_pb_agent.c bluetooth_pb_vcard.c)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs_pb_agent
+ REQUIRED
+ dbus-glib-1 dlog contacts-service2 tapi vconf)
+
+FOREACH(flag ${pkgs_pb_agent_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+FIND_PROGRAM(DBUS_BINDING_TOOL NAMES dbus-binding-tool)
+EXEC_PROGRAM("${DBUS_BINDING_TOOL}"
+ ARGS "--prefix=bluetooth_pb \\
+ ${CMAKE_CURRENT_SOURCE_DIR}/bluetooth_pb_agent.xml \\
+ --mode=glib-server \\
+ --output=${CMAKE_CURRENT_SOURCE_DIR}/bluetooth_pb_agent_glue.h")
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_pb_agent_LDFLAGS})
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.bluez.pb_agent.service
+ DESTINATION share/dbus-1/services)
--- /dev/null
+/*
+ * bluetooth-agent
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <contacts.h>
+
+#include <TapiUtility.h>
+#include <ITapiSim.h>
+
+#include "bluetooth_pb_agent.h"
+#include "bluetooth_pb_vcard.h"
+
+#define BLUETOOTH_PB_AGENT_TIMEOUT 600
+
+static gchar *bluetooth_pb_agent_folder_list[] = {
+ "/telecom/pb",
+ "/telecom/ich",
+ "/telecom/och",
+ "/telecom/mch",
+ "/telecom/cch",
+ NULL
+};
+
+typedef enum {
+ TELECOM_PB = 0,
+ TELECOM_ICH,
+ TELECOM_OCH,
+ TELECOM_MCH,
+ TELECOM_CCH,
+ TELECOM_NONE
+} PhoneBookType;
+
+typedef struct {
+ GObject parent;
+
+ DBusGConnection *bus;
+ DBusGProxy *proxy;
+
+ TapiHandle *tapi_handle;
+ gchar *tel_number;
+
+ GHashTable *contact_list;
+
+ guint timeout_id;
+
+ PhoneBookType pb_type;
+} BluetoothPbAgent;
+
+typedef struct {
+ GObjectClass parent;
+
+ void (*clear) (BluetoothPbAgent *agent);
+} BluetoothPbAgentClass;
+
+enum {
+ CLEAR,
+ LAST_SIGNAL
+};
+
+GType bluetooth_pb_agent_get_type(void);
+
+#define BLUETOOTH_PB_TYPE_AGENT (bluetooth_pb_agent_get_type())
+
+#define BLUETOOTH_PB_AGENT(object) \
+ (G_TYPE_CHECK_INSTANCE_CAST((object), \
+ BLUETOOTH_PB_TYPE_AGENT , BluetoothPbAgent))
+#define BLUETOOTH_PB_AGENT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), \
+ BLUETOOTH_PB_TYPE_AGENT , BluetoothPbAgentClass))
+#define BLUETOOTH_IS_PB_AGENT(object) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((object), \
+ BLUETOOTH_PB_TYPE_AGENT))
+#define BLUETOOTH_IS_PB_AGENT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), \
+ BLUETOOTH_PB_TYPE_AGENT))
+#define BLUETOOTH_PB_AGENT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), \
+ BLUETOOTH_PB_TYPE_AGENT , BluetoothPbAgentClass))
+
+G_DEFINE_TYPE(BluetoothPbAgent, bluetooth_pb_agent, G_TYPE_OBJECT)
+
+#define DBUS_STRUCT_STRING_STRING_UINT (dbus_g_type_get_struct("GValueArray", G_TYPE_STRING, \
+ G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INVALID))
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static GMainLoop *mainloop = NULL;
+
+static void bluetooth_pb_agent_finalize(GObject *obj);
+
+static void bluetooth_pb_agent_clear(BluetoothPbAgent *agent);
+
+/* Dbus messages */
+static gboolean bluetooth_pb_get_phonebook_folder_list(BluetoothPbAgent *agent,
+ const gchar ***folder_list,
+ GError **error);
+
+static gboolean bluetooth_pb_get_phonebook(BluetoothPbAgent *agent,
+ const char *name,
+ guint64 filter,
+ guint8 format,
+ guint16 max_list_count,
+ guint16 list_start_offset,
+ DBusGMethodInvocation *context);
+
+static gboolean bluetooth_pb_get_phonebook_size(BluetoothPbAgent *agent,
+ const char *name,
+ DBusGMethodInvocation *context);
+
+static gboolean bluetooth_pb_get_phonebook_list(BluetoothPbAgent *agent,
+ const char *name,
+ DBusGMethodInvocation *context);
+
+static gboolean bluetooth_pb_get_phonebook_entry(BluetoothPbAgent *agent,
+ const gchar *folder,
+ const gchar *id,
+ guint64 filter,
+ guint8 format,
+ DBusGMethodInvocation *context);
+
+static gboolean bluetooth_pb_get_phonebook_size_at(BluetoothPbAgent *agent,
+ const gchar *command,
+ DBusGMethodInvocation *context);
+
+static gboolean bluetooth_pb_get_phonebook_entries_at(BluetoothPbAgent *agent,
+ const gchar *command,
+ gint32 start_index,
+ gint32 end_index,
+ DBusGMethodInvocation *context);
+
+static gboolean bluetooth_pb_get_phonebook_entries_find_at(BluetoothPbAgent *agent,
+ const gchar *command,
+ const gchar *find_text,
+ DBusGMethodInvocation *context);
+
+static gboolean bluetooth_pb_get_total_object_count(BluetoothPbAgent *agent,
+ gchar *path,
+ DBusGMethodInvocation *context);
+
+static gboolean bluetooth_pb_add_contact (BluetoothPbAgent *agent,
+ const char *filename,
+ GError **error);
+
+static void __bluetooth_pb_dbus_return_error(DBusGMethodInvocation *context,
+ gint code,
+ const gchar *message);
+
+static PhoneBookType __bluetooth_pb_get_pb_type(const char *name);
+
+static PhoneBookType __bluetooth_pb_get_storage_pb_type(const char *name);
+
+static gint __bluetooth_pb_phone_log_filter_append(contacts_filter_h filter,
+ gint *match,
+ gint size);
+
+static contacts_query_h __bluetooth_pb_query_phone_log(gint *match,
+ gint size);
+
+static contacts_query_h __bluetooth_pb_query_person(void);
+
+static contacts_query_h __bluetooth_pb_query_person_number(void);
+
+static contacts_query_h __bluetooth_pb_query_phone_log_incoming(void);
+
+static contacts_query_h __bluetooth_pb_query_phone_log_outgoing(void);
+
+static contacts_query_h __bluetooth_pb_query_phone_log_missed(void);
+
+static contacts_query_h __bluetooth_pb_query_phone_log_combined(void);
+
+static gboolean __bluetooth_pb_get_count(PhoneBookType pb_type,
+ guint *count);
+
+static gboolean __bluetooth_pb_get_count_new_missed_call(guint *count);
+
+static const char *__bluetooth_pb_phone_log_get_log_type(contacts_record_h record);
+
+static void __bluetooth_pb_get_vcards(BluetoothPbAgent *agent,
+ PhoneBookType pb_type,
+ guint64 filter,
+ guint8 format,
+ guint16 max_list_count,
+ guint16 list_start_offset,
+ GPtrArray *vcards);
+
+static void __bluetooth_pb_get_contact_list(BluetoothPbAgent *agent,
+ contacts_query_h query,
+ GPtrArray *ptr_array);
+
+static void __bluetooth_pb_get_phone_log_list(BluetoothPbAgent *agent,
+ contacts_query_h query,
+ GPtrArray *ptr_array);
+
+static void __bluetooth_pb_get_list(BluetoothPbAgent *agent,
+ PhoneBookType pb_type,
+ GPtrArray *ptr_array);
+
+static void __bluetooth_pb_get_contact_list_number(BluetoothPbAgent *agent,
+ contacts_query_h query,
+ gint start_index,
+ gint end_index,
+ GPtrArray *ptr_array);
+
+static void __bluetooth_pb_get_phone_log_list_number(BluetoothPbAgent *agent,
+ contacts_query_h query,
+ gint start_index,
+ gint end_index,
+ GPtrArray *ptr_array);
+
+static void __bluetooth_pb_get_list_number(BluetoothPbAgent *agent,
+ PhoneBookType pb_type,
+ gint start_index,
+ gint end_index,
+ GPtrArray *ptr_array);
+
+static void __bluetooth_pb_get_contact_list_name(BluetoothPbAgent *agent,
+ contacts_query_h query,
+ const gchar *find_text,
+ GPtrArray *ptr_array);
+
+static void __bluetooth_pb_get_phone_log_list_name(BluetoothPbAgent *agent,
+ contacts_query_h query,
+ const gchar *find_text,
+ GPtrArray *ptr_array);
+
+static void __bluetooth_pb_get_list_name(BluetoothPbAgent *agent,
+ PhoneBookType pb_type,
+ const gchar *find_text,
+ GPtrArray *ptr_array);
+
+static void __bluetooth_pb_list_hash_reset(BluetoothPbAgent *agent);
+
+static gboolean __bluetooth_pb_list_hash_insert(BluetoothPbAgent *agent,
+ gint handle,
+ gint id);
+
+static gint __bluetooth_pb_list_hash_lookup_id(BluetoothPbAgent *agent,
+ gint handle);
+
+static void __bluetooth_pb_list_ptr_array_add(GPtrArray *ptr_array,
+ const gchar *name,
+ const gchar *number,
+ gint handle);
+
+static void __bluetooth_pb_list_ptr_array_free(gpointer data);
+
+static void __bluetooth_pb_agent_signal_handler(int signum);
+
+static void __bluetooth_pb_contact_changed(const gchar *view_uri,
+ void *user_data);
+
+static void __bluetooth_pb_agent_timeout_add_seconds(BluetoothPbAgent *agent);
+
+static gboolean __bluetooth_pb_agent_timeout_calback(gpointer user_data);
+
+static void __bluetooth_pb_tel_callback(TapiHandle *handle,
+ int result,
+ void *data,
+ void *user_data);
+
+static void __bluetooth_pb_agent_dbus_init(BluetoothPbAgent *agent);
+
+#include "bluetooth_pb_agent_glue.h"
+
+static void bluetooth_pb_agent_init(BluetoothPbAgent *agent)
+{
+ agent->bus = NULL;
+ agent->proxy = NULL;
+
+ agent->tapi_handle = NULL;
+ agent->tel_number = NULL;
+
+ agent->contact_list = NULL;
+ agent->timeout_id = 0;
+
+ agent->pb_type = TELECOM_NONE;
+}
+
+static void bluetooth_pb_agent_class_init(BluetoothPbAgentClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+
+ klass->clear = bluetooth_pb_agent_clear;
+
+ object_class->finalize = bluetooth_pb_agent_finalize;
+
+ signals[CLEAR] = g_signal_new("clear",
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(BluetoothPbAgentClass, clear),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ dbus_g_object_type_install_info(BLUETOOTH_PB_TYPE_AGENT,
+ &dbus_glib_bluetooth_pb_object_info);
+}
+
+static void bluetooth_pb_agent_finalize(GObject *obj)
+{
+ BluetoothPbAgent *agent = BLUETOOTH_PB_AGENT(obj);
+
+ DBG("+\n");
+
+ if (agent->tapi_handle) {
+ tel_deinit(agent->tapi_handle);
+ agent->tapi_handle = NULL;
+ }
+
+ if (agent->tel_number) {
+ g_free(agent->tel_number);
+ agent->tel_number = NULL;
+ }
+
+ if(agent->timeout_id) {
+ g_source_remove(agent->timeout_id);
+ agent->timeout_id = 0;
+ }
+
+ if (agent->contact_list) {
+ g_hash_table_destroy(agent->contact_list);
+ agent->contact_list = NULL;
+ }
+
+ if (agent->proxy) {
+ g_object_unref(agent->proxy);
+ agent->proxy = NULL;
+ }
+
+ if (agent->bus) {
+ dbus_g_connection_unref(agent->bus);
+ agent->bus = NULL;
+ }
+
+
+ G_OBJECT_CLASS(bluetooth_pb_agent_parent_class)->finalize(obj);
+}
+
+static void bluetooth_pb_agent_clear(BluetoothPbAgent *agent)
+{
+ DBG("+\n");
+
+ if (agent->contact_list) {
+ g_hash_table_destroy(agent->contact_list);
+ agent->contact_list = NULL;
+ }
+
+ agent->pb_type = TELECOM_NONE;
+}
+
+static gboolean bluetooth_pb_get_phonebook_folder_list(BluetoothPbAgent *agent,
+ const gchar ***folder_list,
+ GError **error)
+{
+ gint size;
+ gint i;
+ gchar **folder;
+
+ size = G_N_ELEMENTS(bluetooth_pb_agent_folder_list);
+ folder = g_new0(gchar *, size);
+
+ for (i = 0; i < size; i++)
+ folder[i] = g_strdup(bluetooth_pb_agent_folder_list[i]);
+
+ *folder_list = (const gchar **)folder;
+
+ return TRUE;
+}
+
+static gboolean bluetooth_pb_get_phonebook(BluetoothPbAgent *agent,
+ const char *name,
+ guint64 filter,
+ guint8 format,
+ guint16 max_list_count,
+ guint16 list_start_offset,
+ DBusGMethodInvocation *context)
+{
+ PhoneBookType pb_type = TELECOM_NONE;
+ GPtrArray *vcards = NULL;
+ gchar **vcards_str = NULL;
+
+ guint new_missed_call = 0;
+
+ DBG("name: %s filter: %lld format: %d max_list_count: %d list_start_offset: %d\n",
+ name, filter, format, max_list_count, list_start_offset);
+
+ __bluetooth_pb_agent_timeout_add_seconds(agent);
+
+ pb_type = __bluetooth_pb_get_pb_type(name);
+
+ if (pb_type == TELECOM_NONE) {
+ __bluetooth_pb_dbus_return_error(context,
+ G_FILE_ERROR_INVAL,
+ "unsupported name defined");
+ return FALSE;
+ }
+
+ vcards = g_ptr_array_new();
+
+ if (max_list_count > 0) {
+ __bluetooth_pb_get_vcards(agent, pb_type,
+ filter, format,
+ max_list_count, list_start_offset,
+ vcards);
+
+ }
+
+ g_ptr_array_add(vcards, NULL);
+
+ vcards_str = (gchar **) g_ptr_array_free(vcards, FALSE);
+
+ dbus_g_method_return(context, vcards_str, new_missed_call);
+
+ g_strfreev(vcards_str);
+
+ return TRUE;
+}
+
+static gboolean bluetooth_pb_get_phonebook_size(BluetoothPbAgent *agent,
+ const char *name,
+ DBusGMethodInvocation *context)
+{
+ PhoneBookType pb_type = TELECOM_NONE;
+
+ guint new_missed_call = 0;
+ guint count = 0;
+
+ DBG("name: %s\n", name);
+
+ __bluetooth_pb_agent_timeout_add_seconds(agent);
+
+ pb_type = __bluetooth_pb_get_pb_type(name);
+
+ if (__bluetooth_pb_get_count(pb_type, &count) == FALSE) {
+ __bluetooth_pb_dbus_return_error(context,
+ G_FILE_ERROR_INVAL,
+ "unsupported name defined");
+ return FALSE;
+ }
+
+ /* for owner */
+ if (pb_type == TELECOM_PB)
+ count++;
+
+ __bluetooth_pb_get_count_new_missed_call(&new_missed_call);
+
+ dbus_g_method_return(context, count, new_missed_call);
+
+ return TRUE;
+}
+
+
+static gboolean bluetooth_pb_get_phonebook_list(BluetoothPbAgent *agent,
+ const char *name,
+ DBusGMethodInvocation *context)
+{
+ PhoneBookType pb_type = TELECOM_NONE;
+
+ GPtrArray *ptr_array;
+
+ DBG("name: %s\n", name);
+
+ __bluetooth_pb_agent_timeout_add_seconds(agent);
+
+ pb_type = __bluetooth_pb_get_pb_type(name);
+
+ if (pb_type == TELECOM_NONE) {
+ __bluetooth_pb_dbus_return_error(context,
+ G_FILE_ERROR_INVAL,
+ "unsupported name defined");
+ return FALSE;
+ }
+
+ ptr_array = g_ptr_array_new_with_free_func(__bluetooth_pb_list_ptr_array_free);
+
+ __bluetooth_pb_get_list(agent, pb_type, ptr_array);
+
+ dbus_g_method_return(context, ptr_array);
+
+ if (ptr_array)
+ g_ptr_array_free(ptr_array, TRUE);
+
+ return TRUE;
+}
+
+
+static gboolean bluetooth_pb_get_phonebook_entry(BluetoothPbAgent *agent,
+ const gchar *folder,
+ const gchar *id,
+ guint64 filter,
+ guint8 format,
+ DBusGMethodInvocation *context)
+{
+ PhoneBookType pb_type = TELECOM_NONE;
+
+ gint handle = 0;
+ gint cid = -1;
+ gchar *str = NULL;
+
+ const gchar *attr = NULL;
+
+ DBG("folder: %s id: %s filter: %ld format: %d\n",
+ folder, id, filter, format);
+
+ __bluetooth_pb_agent_timeout_add_seconds(agent);
+
+ if (!g_str_has_suffix(id, ".vcf")) {
+ __bluetooth_pb_dbus_return_error(context,
+ G_FILE_ERROR_INVAL,
+ "invalid vcf file");
+ return FALSE;
+ }
+
+ handle = (gint)g_ascii_strtoll(id, NULL, 10);
+
+ pb_type = __bluetooth_pb_get_pb_type(folder);
+
+ if (pb_type == TELECOM_NONE) {
+ __bluetooth_pb_dbus_return_error(context,
+ G_FILE_ERROR_INVAL,
+ "unsupported name defined");
+ return FALSE;
+ }
+
+ /* create index cache */
+ __bluetooth_pb_get_list(agent, pb_type, NULL);
+
+ cid = __bluetooth_pb_list_hash_lookup_id(agent, handle);
+
+ switch(pb_type) {
+ case TELECOM_PB:
+ if (handle == 0) {
+ str = _bluetooth_pb_vcard_contact_owner(agent->tel_number,
+ filter, format);
+ } else {
+ str = _bluetooth_pb_vcard_contact(cid, filter, format);
+ }
+ break;
+ case TELECOM_ICH:
+ str = _bluetooth_pb_vcard_call(cid, filter, format, "RECEIVED");
+ break;
+ case TELECOM_OCH:
+ str = _bluetooth_pb_vcard_call(cid, filter, format, "DIALED");
+ break;
+ case TELECOM_MCH:
+ str = _bluetooth_pb_vcard_call(cid, filter, format, "MISSED");
+ break;
+ case TELECOM_CCH: {
+ contacts_record_h record = NULL;
+
+ gint status;
+
+ status = contacts_db_get_record(_contacts_phone_log._uri,
+ cid, &record);
+
+ if (status != CONTACTS_ERROR_NONE)
+ break;
+
+ attr = __bluetooth_pb_phone_log_get_log_type(record);
+ str = _bluetooth_pb_vcard_call(cid, filter, format, attr);
+
+ contacts_record_destroy(record, TRUE);
+ break;
+ }
+ default:
+ __bluetooth_pb_dbus_return_error(context,
+ G_FILE_ERROR_INVAL,
+ "unsupported name defined");
+ return FALSE;
+ }
+
+ dbus_g_method_return(context, str);
+ g_free(str);
+
+ return TRUE;
+}
+
+static gboolean bluetooth_pb_get_phonebook_size_at(BluetoothPbAgent *agent,
+ const gchar *command,
+ DBusGMethodInvocation *context)
+{
+ PhoneBookType pb_type = TELECOM_NONE;
+ guint count = 0;
+
+ DBG("command: %s\n", command);
+
+ __bluetooth_pb_agent_timeout_add_seconds(agent);
+
+ pb_type = __bluetooth_pb_get_storage_pb_type(command);
+
+ if (__bluetooth_pb_get_count(pb_type, &count) == FALSE) {
+ __bluetooth_pb_dbus_return_error(context,
+ G_FILE_ERROR_INVAL,
+ "unsupported name defined");
+ return FALSE;
+ }
+
+ dbus_g_method_return(context, count);
+
+ return TRUE;
+}
+
+static gboolean bluetooth_pb_get_phonebook_entries_at(BluetoothPbAgent *agent,
+ const gchar *command,
+ gint start_index,
+ gint end_index,
+ DBusGMethodInvocation *context)
+{
+ PhoneBookType pb_type = TELECOM_NONE;
+
+ GPtrArray *ptr_array = NULL;
+
+ DBG("command: %s, start_index: %d, end_index: %d\n",
+ command, start_index, end_index);
+
+ __bluetooth_pb_agent_timeout_add_seconds(agent);
+
+ pb_type = __bluetooth_pb_get_storage_pb_type(command);
+
+ if (pb_type == TELECOM_NONE || pb_type == TELECOM_CCH) {
+ __bluetooth_pb_dbus_return_error(context,
+ G_FILE_ERROR_INVAL,
+ "unsupported name defined");
+ return FALSE;
+ }
+
+ ptr_array = g_ptr_array_new_with_free_func(__bluetooth_pb_list_ptr_array_free);
+
+ __bluetooth_pb_get_list_number(agent, pb_type,
+ start_index, end_index,
+ ptr_array);
+
+ dbus_g_method_return(context, ptr_array);
+
+ if (ptr_array)
+ g_ptr_array_free(ptr_array, TRUE);
+
+ return TRUE;
+}
+
+static gboolean bluetooth_pb_get_phonebook_entries_find_at(BluetoothPbAgent *agent,
+ const gchar *command,
+ const gchar *find_text,
+ DBusGMethodInvocation *context)
+{
+ PhoneBookType pb_type = TELECOM_NONE;
+
+ GPtrArray *ptr_array = NULL;
+
+ DBG("command: %s, find text: %s\n", command, find_text);
+
+ __bluetooth_pb_agent_timeout_add_seconds(agent);
+
+ pb_type = __bluetooth_pb_get_storage_pb_type(command);
+
+ if (pb_type == TELECOM_NONE || pb_type == TELECOM_CCH) {
+ __bluetooth_pb_dbus_return_error(context,
+ G_FILE_ERROR_INVAL,
+ "unsupported name defined");
+ return FALSE;
+ }
+
+ ptr_array = g_ptr_array_new_with_free_func(__bluetooth_pb_list_ptr_array_free);
+
+ __bluetooth_pb_get_list_name(agent, pb_type,
+ find_text, ptr_array);
+
+ dbus_g_method_return(context, ptr_array);
+
+ if (ptr_array)
+ g_ptr_array_free(ptr_array, TRUE);
+
+ return TRUE;
+}
+
+static gboolean bluetooth_pb_get_total_object_count(BluetoothPbAgent *agent,
+ gchar *path, DBusGMethodInvocation *context)
+{
+ guint count = 0;
+ PhoneBookType pb_type = TELECOM_NONE;
+
+ DBG("%s() %d\n", __FUNCTION__, __LINE__);
+
+ __bluetooth_pb_agent_timeout_add_seconds(agent);
+
+ pb_type = __bluetooth_pb_get_storage_pb_type(path);
+
+ if (__bluetooth_pb_get_count(pb_type, &count) == FALSE) {
+ __bluetooth_pb_dbus_return_error(context,
+ G_FILE_ERROR_INVAL,
+ "unsupported name defined");
+ return FALSE;
+ }
+
+ dbus_g_method_return(context, count);
+
+ DBG("%s() %d\n", __FUNCTION__, __LINE__);
+
+ return TRUE;
+}
+
+
+#if 0
+static int __bluetooth_pb_agent_read_file(const char *file_path, char **stream)
+{
+ FILE *fp = NULL;
+ int read_len = -1;
+ int received_file_size = 0;
+ struct stat file_attr;
+
+ if (file_path == NULL || stream == NULL) {
+ DBG("Invalid data \n");
+ return -1;
+ }
+
+ DBG("file_path = %s\n", file_path);
+
+ if ((fp = fopen(file_path, "r+")) == NULL) {
+ DBG("Cannot open %s\n", file_path);
+ return -1;
+ }
+
+ if (fstat(fileno(fp), &file_attr) == 0) {
+ received_file_size = file_attr.st_size;
+ DBG("file_attr.st_size = %d, size = %d\n", file_attr.st_size, received_file_size);
+
+ if (received_file_size <= 0) {
+ DBG("Some problem in the file size [%s] \n", file_path);
+ fclose(fp);
+ fp = NULL;
+ return -1;
+ }
+
+ *stream = (char *)malloc(sizeof(char) * received_file_size);
+ if (NULL == *stream) {
+ fclose(fp);
+ fp = NULL;
+ return -1;
+ }
+ } else {
+ DBG("Some problem in the file [%s] \n", file_path);
+ fclose(fp);
+ fp = NULL;
+ return -1;
+ }
+
+ read_len = fread(*stream, 1, received_file_size, fp);
+
+ if (read_len == 0) {
+ if (fp != NULL) {
+ fclose(fp);
+ fp = NULL;
+ }
+ DBG("Cannot open %s\n", file_path);
+ return -1;
+ }
+
+ if (fp != NULL) {
+ fclose(fp);
+ fp = NULL;
+ }
+ return 0;
+}
+#endif
+
+static gboolean bluetooth_pb_add_contact(BluetoothPbAgent *agent, const char *filename,
+ GError **error)
+{
+ /* Contact API is changed, Temporary blocked */
+#if 0
+ CTSstruct *contact_record = NULL;
+ GSList *numbers_list = NULL, *cursor;
+ int is_success = 0;
+ int is_duplicated = 0;
+ int err = 0;
+ char *stream = NULL;
+
+ DBG("file_path = %s\n", filename);
+
+ err = contacts_svc_connect();
+ DBG("contact_db_service_connect fucntion call [error] = %d \n", err);
+
+ err = __bluetooth_pb_agent_read_file(filename, &stream);
+
+ if (err != 0) {
+ contacts_svc_disconnect();
+ DBG("contacts_svc_disconnect fucntion call [error] = %d \n", err);
+
+ if (NULL != stream) {
+ free(stream);
+ stream = NULL;
+ }
+ return FALSE;
+ }
+
+ is_success = contacts_svc_get_contact_from_vcard((const void *)stream, &contact_record);
+
+ DBG("contacts_svc_get_contact_from_vcard fucntion call [is_success] = %d \n", is_success);
+
+ if (0 == is_success) {
+ contacts_svc_struct_get_list(contact_record, CTS_CF_NUMBER_LIST, &numbers_list);
+ cursor = numbers_list;
+
+ for (; cursor; cursor = g_slist_next(cursor)) {
+ if (contacts_svc_find_contact_by(CTS_FIND_BY_NUMBER,
+ contacts_svc_value_get_str(cursor->data,
+ CTS_NUM_VAL_NUMBER_STR)) > 0) {
+ DBG("is_duplicated\n");
+ is_duplicated = TRUE;
+ }
+ }
+
+ if (is_duplicated == FALSE) {
+ contacts_svc_insert_contact(0, contact_record);
+ }
+ } else {
+ DBG("Fail \n");
+ }
+
+ err = contacts_svc_disconnect();
+ DBG("contacts_svc_disconnect fucntion call [error] = %d \n", err);
+
+ if (NULL != stream) {
+ free(stream);
+ stream = NULL;
+ }
+#endif
+
+ return TRUE;
+}
+
+static void __bluetooth_pb_dbus_return_error(DBusGMethodInvocation *context,
+ gint code,
+ const gchar *message)
+{
+ GQuark quark;
+ GError *error = NULL;
+
+ quark = g_type_qname(bluetooth_pb_agent_get_type());
+ error = g_error_new_literal(quark, code, message);
+
+ DBG("%s\n", message);
+
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+}
+
+static PhoneBookType __bluetooth_pb_get_pb_type(const char *name)
+{
+ gchar *suffix = ".vcf";
+ gint len;
+ gint size;
+ gint i;
+
+ if (name == NULL)
+ return TELECOM_NONE;
+
+ len = strlen(name);
+
+ if (g_str_has_suffix(name, suffix))
+ len -= strlen(suffix);
+
+ size = G_N_ELEMENTS(bluetooth_pb_agent_folder_list) - 1;
+ for (i = 0; i < size; i++) {
+ if (strncmp(name, bluetooth_pb_agent_folder_list[i], len) == 0)
+ return i;
+ }
+
+ return TELECOM_NONE;
+}
+
+static PhoneBookType __bluetooth_pb_get_storage_pb_type(const char *name)
+{
+ if (name == NULL)
+ return TELECOM_NONE;
+
+ if (g_strcmp0(name, "\"ME\"") == 0 )
+ return TELECOM_PB;
+
+ if (g_strcmp0(name, "\"RC\"") == 0)
+ return TELECOM_ICH;
+
+ if (g_strcmp0(name, "\"DC\"") == 0)
+ return TELECOM_OCH;
+
+ if (g_strcmp0(name, "\"MC\"") == 0)
+ return TELECOM_MCH;
+
+ return TELECOM_NONE;
+}
+
+static gint __bluetooth_pb_phone_log_filter_append(contacts_filter_h filter,
+ gint *match,
+ gint size)
+{
+ gint i;
+ gint status;
+
+ for (i = 0; i < size; i++) {
+
+ if ( i > 0) {
+ status = contacts_filter_add_operator(filter,
+ CONTACTS_FILTER_OPERATOR_OR);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return status;
+ }
+
+ status = contacts_filter_add_int(filter,
+ _contacts_phone_log.log_type,
+ CONTACTS_MATCH_EQUAL,
+ match[i]);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return status;
+ }
+
+ return CONTACTS_ERROR_NONE;
+}
+
+static contacts_query_h __bluetooth_pb_query_phone_log(gint *match,
+ gint size)
+{
+ contacts_query_h query = NULL;
+ contacts_filter_h filter = NULL;
+
+ gint status;
+
+ status = contacts_query_create(_contacts_phone_log._uri,
+ &query);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ status = contacts_filter_create(_contacts_phone_log._uri, &filter);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_query_destroy(query);
+ return NULL;
+ }
+
+ status = __bluetooth_pb_phone_log_filter_append(filter, match, size);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_filter_destroy(filter);
+ contacts_query_destroy(query);
+ return NULL;
+ }
+
+ status = contacts_query_set_filter(query, filter);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_filter_destroy(filter);
+ contacts_query_destroy(query);
+ return NULL;
+ }
+
+ status = contacts_query_set_sort(query,
+ _contacts_phone_log.log_time,
+ false);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_filter_destroy(filter);
+ contacts_query_destroy(query);
+ return NULL;
+ }
+
+ contacts_filter_destroy(filter);
+
+ return query;
+}
+
+static contacts_query_h __bluetooth_pb_query_person(void)
+{
+ contacts_query_h query = NULL;
+
+ gint status;
+
+ status = contacts_query_create(_contacts_person._uri,
+ &query);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ return query;
+}
+
+static contacts_query_h __bluetooth_pb_query_person_number(void)
+{
+ contacts_query_h query = NULL;
+
+ gint status;
+
+ status = contacts_query_create(_contacts_person_number._uri,
+ &query);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ return query;
+}
+
+static contacts_query_h __bluetooth_pb_query_phone_log_incoming(void)
+{
+ gint size = 2;
+ gint match[] = {
+ CONTACTS_PLOG_TYPE_VOICE_INCOMMING,
+ CONTACTS_PLOG_TYPE_VIDEO_INCOMMING
+ };
+
+ return __bluetooth_pb_query_phone_log(match, size);
+}
+
+static contacts_query_h __bluetooth_pb_query_phone_log_outgoing(void)
+{
+ gint size = 2;
+ gint match[] = {
+ CONTACTS_PLOG_TYPE_VOICE_OUTGOING,
+ CONTACTS_PLOG_TYPE_VIDEO_OUTGOING
+ };
+
+ return __bluetooth_pb_query_phone_log(match, size);
+
+}
+
+static contacts_query_h __bluetooth_pb_query_phone_log_missed(void)
+{
+ gint size = 4;
+ gint match[] = {
+ CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN,
+ CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN,
+ CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN,
+ CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN
+ };
+
+ return __bluetooth_pb_query_phone_log(match, size);
+}
+
+static contacts_query_h __bluetooth_pb_query_phone_log_combined(void)
+{
+ gint size = 8;
+ gint match[] = {
+ CONTACTS_PLOG_TYPE_VOICE_INCOMMING,
+ CONTACTS_PLOG_TYPE_VIDEO_INCOMMING,
+ CONTACTS_PLOG_TYPE_VOICE_OUTGOING,
+ CONTACTS_PLOG_TYPE_VIDEO_OUTGOING,
+ CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN,
+ CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN,
+ CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN,
+ CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN
+ };
+
+ return __bluetooth_pb_query_phone_log(match, size);
+}
+
+static gboolean __bluetooth_pb_get_count(PhoneBookType pb_type,
+ guint *count)
+{
+ contacts_query_h query = NULL;
+
+ gint status;
+ gint signed_count;
+
+ switch (pb_type) {
+ case TELECOM_PB:
+ query = __bluetooth_pb_query_person();
+ break;
+ case TELECOM_ICH:
+ query = __bluetooth_pb_query_phone_log_incoming();
+ break;
+ case TELECOM_OCH:
+ query = __bluetooth_pb_query_phone_log_outgoing();
+ break;
+ case TELECOM_MCH:
+ query = __bluetooth_pb_query_phone_log_missed();
+ break;
+ case TELECOM_CCH:
+ query = __bluetooth_pb_query_phone_log_combined();
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (query == NULL)
+ return FALSE;
+
+ status = contacts_db_get_count_with_query(query, &signed_count);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_query_destroy(query);
+ return FALSE;
+ }
+
+ contacts_query_destroy(query);
+
+ if (signed_count < 0)
+ signed_count = 0;
+
+ *count = (gint) signed_count;
+
+ return TRUE;
+}
+
+static gboolean __bluetooth_pb_get_count_new_missed_call(guint *count)
+{
+ contacts_query_h query = NULL;
+
+ gint status;
+ gint signed_count;
+
+ gint size = 2;
+ gint match[] = {
+ CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN,
+ CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN
+ };
+
+ query = __bluetooth_pb_query_phone_log(match, size);
+
+ if (query == NULL)
+ return FALSE;
+
+ status = contacts_db_get_count_with_query(query, &signed_count);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_query_destroy(query);
+ return FALSE;
+ }
+
+ contacts_query_destroy(query);
+
+ if (signed_count < 0)
+ signed_count = 0;
+
+ *count = (guint)signed_count;
+
+ return TRUE;
+}
+
+static const char *__bluetooth_pb_phone_log_get_log_type(contacts_record_h record)
+{
+ gint status;
+ gint log_type;
+
+ status = contacts_record_get_int(record,
+ _contacts_phone_log.log_type,
+ &log_type);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ switch (log_type) {
+ case CONTACTS_PLOG_TYPE_VOICE_INCOMMING:
+ case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING:
+ return "RECEIVED";
+ case CONTACTS_PLOG_TYPE_VOICE_OUTGOING:
+ case CONTACTS_PLOG_TYPE_VIDEO_OUTGOING:
+ return "DIALED";
+ case CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN:
+ case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN:
+ case CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN:
+ case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN:
+ return "MISSED";
+ default:
+ return NULL;
+ }
+}
+
+static void __bluetooth_pb_get_vcards(BluetoothPbAgent *agent,
+ PhoneBookType pb_type,
+ guint64 filter,
+ guint8 format,
+ guint16 max_list_count,
+ guint16 list_start_offset,
+ GPtrArray *vcards)
+{
+ contacts_list_h record_list = NULL;
+ contacts_query_h query = NULL;
+
+ gint status;
+
+ gint limit;
+ gint offset;
+
+ guint property_id = 0;
+
+ const char *attr = NULL;
+
+ gboolean get_log = FALSE;
+
+ /* contact offset is n - 1 of PBAP */
+ offset = (gint)list_start_offset - 1;
+
+ if ( max_list_count >= 65535)
+ limit = -1; /* contact limit -1 means unrestricted */
+ else
+ limit = (gint)max_list_count;
+
+ switch (pb_type) {
+ case TELECOM_PB:
+ /* for owner */
+ if (list_start_offset == 0) {
+ char *vcard;
+
+ vcard = _bluetooth_pb_vcard_contact_owner(agent->tel_number,
+ filter, format);
+ if (vcard)
+ g_ptr_array_add(vcards, vcard);
+
+ offset = 0;
+
+ if (limit > 0)
+ limit--;
+ }
+
+ query = __bluetooth_pb_query_person();
+ property_id = _contacts_person.id;
+ break;
+ case TELECOM_ICH:
+ query = __bluetooth_pb_query_phone_log_incoming();
+ property_id = _contacts_phone_log.id;
+ attr = "RECEIVED";
+ break;
+ case TELECOM_OCH:
+ query = __bluetooth_pb_query_phone_log_outgoing();
+ property_id = _contacts_phone_log.id;
+ attr = "DIALED";
+ break;
+ case TELECOM_MCH:
+ query = __bluetooth_pb_query_phone_log_missed();
+ property_id = _contacts_phone_log.id;
+ attr = "MISSED";
+ break;
+ case TELECOM_CCH:
+ query = __bluetooth_pb_query_phone_log_combined();
+ property_id = _contacts_phone_log.id;
+ get_log = TRUE;
+ break;
+ default:
+ return;
+ }
+
+ status = contacts_db_get_records_with_query(query, offset, limit, &record_list);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_query_destroy(query);
+ return;
+ }
+
+ status = contacts_list_first(record_list);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_list_destroy(record_list, TRUE);
+ contacts_query_destroy(query);
+ return;
+ }
+
+ do {
+ contacts_record_h record;
+
+ gint id;
+
+ gchar *vcard = NULL;
+
+ record = NULL;
+ status = contacts_list_get_current_record_p(record_list, &record);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+ id = 0;
+ status = contacts_record_get_int(record, property_id, &id);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ if (property_id == _contacts_person.id)
+ vcard = _bluetooth_pb_vcard_contact(id, filter, format);
+ else {
+ if (get_log)
+ attr = __bluetooth_pb_phone_log_get_log_type(record);
+
+ vcard = _bluetooth_pb_vcard_call(id, filter, format, attr);
+ }
+
+ if (vcard)
+ g_ptr_array_add(vcards, vcard);
+
+ } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
+
+ contacts_list_destroy(record_list, TRUE);
+ contacts_query_destroy(query);
+}
+
+static void __bluetooth_pb_get_contact_list(BluetoothPbAgent *agent,
+ contacts_query_h query,
+ GPtrArray *ptr_array)
+{
+ contacts_list_h record_list = NULL;
+
+ gint status;
+ int i = 1;
+
+ /* Add owner */
+ if (ptr_array) {
+ gchar *tmp;
+ gchar *name;
+
+ tmp = _bluetooth_pb_owner_name();
+ name = g_strdup_printf("%s;;;;", tmp);
+ g_free(tmp);
+
+ __bluetooth_pb_list_ptr_array_add(ptr_array,
+ name, agent->tel_number, 0);
+
+ g_free(name);
+ }
+
+ status = contacts_db_get_records_with_query(query,
+ -1, -1, &record_list);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ status = contacts_list_first(record_list);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_list_destroy(record_list, TRUE);
+ contacts_query_destroy(query);
+ return;
+ }
+
+ __bluetooth_pb_list_hash_reset(agent);
+
+ do {
+ contacts_record_h record;
+
+ gint id;
+
+ record = NULL;
+ status = contacts_list_get_current_record_p(record_list,
+ &record);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ id = 0;
+ status = contacts_record_get_int(record,
+ _contacts_person.id,
+ &id);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ __bluetooth_pb_list_hash_insert(agent, i, id);
+
+ /* create list */
+ if (ptr_array) {
+ gchar *name;
+ gchar *number;
+
+ name = _bluetooth_pb_name_from_person_id(id);
+ number = _bluetooth_pb_number_from_person_id(id);
+
+ __bluetooth_pb_list_ptr_array_add(ptr_array,
+ name, number, i);
+
+ g_free(name);
+ g_free(number);
+ }
+
+ i++;
+
+ } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
+
+ contacts_list_destroy(record_list, TRUE);
+}
+
+static void __bluetooth_pb_get_phone_log_list(BluetoothPbAgent *agent,
+ contacts_query_h query,
+ GPtrArray *ptr_array)
+{
+ contacts_list_h record_list = NULL;
+
+ gint status;
+ int i = 1;
+
+ status = contacts_db_get_records_with_query(query,
+ -1, -1, &record_list);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ status = contacts_list_first(record_list);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_list_destroy(record_list, TRUE);
+ contacts_query_destroy(query);
+ return;
+ }
+
+ __bluetooth_pb_list_hash_reset(agent);
+
+ do {
+ contacts_record_h record;
+
+ gint id;
+
+ record = NULL;
+ status = contacts_list_get_current_record_p(record_list,
+ &record);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ id = 0;
+ status = contacts_record_get_int(record,
+ _contacts_phone_log.id,
+ &id);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ __bluetooth_pb_list_hash_insert(agent, i, id);
+
+ /* create list */
+ if (ptr_array) {
+ gchar *name;
+ gchar *number;
+
+ name = _bluetooth_pb_name_from_phonelog_id(id);
+
+ number = NULL;
+ contacts_record_get_str_p(record,
+ _contacts_phone_log.address,
+ &number);
+
+ __bluetooth_pb_list_ptr_array_add(ptr_array,
+ name, number, i);
+
+ g_free(name);
+ }
+
+ i++;
+
+ } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
+
+ contacts_list_destroy(record_list, TRUE);
+}
+
+
+static void __bluetooth_pb_get_list(BluetoothPbAgent *agent,
+ PhoneBookType pb_type,
+ GPtrArray *ptr_array)
+{
+ contacts_query_h query;
+
+ /* no requires refresh cache */
+ if (ptr_array == NULL && agent->pb_type == pb_type)
+ return;
+
+ switch (pb_type) {
+ case TELECOM_PB:
+ query = __bluetooth_pb_query_person();
+ __bluetooth_pb_get_contact_list(agent, query, ptr_array);
+ break;
+ case TELECOM_ICH:
+ query = __bluetooth_pb_query_phone_log_incoming();
+ __bluetooth_pb_get_phone_log_list(agent, query, ptr_array);
+ break;
+ case TELECOM_OCH:
+ query = __bluetooth_pb_query_phone_log_outgoing();
+ __bluetooth_pb_get_phone_log_list(agent, query, ptr_array);
+ break;
+ case TELECOM_MCH:
+ query = __bluetooth_pb_query_phone_log_missed();
+ __bluetooth_pb_get_phone_log_list(agent, query, ptr_array);
+ break;
+ case TELECOM_CCH:
+ query = __bluetooth_pb_query_phone_log_combined();
+ __bluetooth_pb_get_phone_log_list(agent, query, ptr_array);
+ break;
+ default:
+ return;
+ }
+
+ agent->pb_type = pb_type;
+
+ if (query)
+ contacts_query_destroy(query);
+}
+
+static void __bluetooth_pb_get_contact_list_number(BluetoothPbAgent *agent,
+ contacts_query_h query,
+ gint start_index,
+ gint end_index,
+ GPtrArray *ptr_array)
+{
+ contacts_list_h record_list = NULL;
+
+ gint status;
+
+ gint i;
+
+ gint from;
+ gint to;
+ gint offset;
+
+ from = start_index;
+ to = end_index;
+
+ if (from < 1)
+ from = 1;
+
+ if (to < 1)
+ to = 1;
+
+ offset = to - from + 1;
+ if (offset <= 0)
+ return;
+
+ i = from;
+
+ status = contacts_db_get_records_with_query(query,
+ from - 1 , offset,
+ &record_list);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ status = contacts_list_first(record_list);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_list_destroy(record_list, TRUE);
+ return;
+ }
+
+ do {
+ contacts_record_h record;
+
+ gchar *display_name;
+ gchar *number;
+
+ record = NULL;
+ status = contacts_list_get_current_record_p(record_list,
+ &record);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ display_name = NULL;
+ number = NULL;
+
+ contacts_record_get_str_p(record,
+ _contacts_person_number.display_name,
+ &display_name);
+ contacts_record_get_str_p(record,
+ _contacts_person_number.number,
+ &number);
+
+ __bluetooth_pb_list_ptr_array_add(ptr_array,
+ display_name, number, i);
+
+ i++;
+ } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
+
+ contacts_list_destroy(record_list, TRUE);
+}
+
+static void __bluetooth_pb_get_phone_log_list_number(BluetoothPbAgent *agent,
+ contacts_query_h query,
+ gint start_index,
+ gint end_index,
+ GPtrArray *ptr_array)
+{
+ contacts_list_h record_list = NULL;
+
+ gint status;
+
+ gint i;
+
+ gint from;
+ gint to;
+ gint offset;
+
+ from = start_index;
+ to = end_index;
+
+ if (from < 1)
+ from = 1;
+
+ if (to < 1)
+ to = 1;
+
+ offset = to - from + 1;
+ if (offset <= 0)
+ return;
+
+ i = from;
+
+ status = contacts_db_get_records_with_query(query,
+ from - 1 , offset,
+ &record_list);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ status = contacts_list_first(record_list);
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_list_destroy(record_list, TRUE);
+ return;
+ }
+
+ do {
+ contacts_record_h record = NULL;
+
+ gint id;
+
+ gchar *display_name;
+ gchar *number;
+
+ record = NULL;
+ status = contacts_list_get_current_record_p(record_list,
+ &record);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ id = 0;
+ status = contacts_record_get_int(record,
+ _contacts_phone_log.id,
+ &id);
+
+ display_name = _bluetooth_pb_fn_from_phonelog_id(id);
+
+ number = NULL;
+ contacts_record_get_str_p(record,
+ _contacts_phone_log.address,
+ &number);
+
+
+ __bluetooth_pb_list_ptr_array_add(ptr_array,
+ display_name, number, i);
+
+ i++;
+
+ g_free(display_name);
+
+ } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
+
+ contacts_list_destroy(record_list, TRUE);
+}
+
+static void __bluetooth_pb_get_list_number(BluetoothPbAgent *agent,
+ PhoneBookType pb_type,
+ gint start_index,
+ gint end_index,
+ GPtrArray *ptr_array)
+{
+ contacts_query_h query;
+
+ switch (pb_type) {
+ case TELECOM_PB:
+ query = __bluetooth_pb_query_person_number();
+ __bluetooth_pb_get_contact_list_number(agent, query,
+ start_index, end_index, ptr_array);
+ break;
+ case TELECOM_ICH:
+ query = __bluetooth_pb_query_phone_log_incoming();
+ __bluetooth_pb_get_phone_log_list_number(agent, query,
+ start_index, end_index, ptr_array);
+ break;
+ case TELECOM_OCH:
+ query = __bluetooth_pb_query_phone_log_outgoing();
+ __bluetooth_pb_get_phone_log_list_number(agent, query,
+ start_index, end_index, ptr_array);
+ break;
+ case TELECOM_MCH:
+ query = __bluetooth_pb_query_phone_log_missed();
+ __bluetooth_pb_get_phone_log_list_number(agent, query,
+ start_index, end_index, ptr_array);
+ break;
+ case TELECOM_CCH:
+ query = __bluetooth_pb_query_phone_log_combined();
+ __bluetooth_pb_get_phone_log_list_number(agent, query,
+ start_index, end_index, ptr_array);
+ break;
+ default:
+ return;
+ }
+
+ if (query)
+ contacts_query_destroy(query);
+}
+
+static void __bluetooth_pb_get_contact_list_name(BluetoothPbAgent *agent,
+ contacts_query_h query,
+ const gchar *find_text,
+ GPtrArray *ptr_array)
+{
+ contacts_list_h record_list = NULL;
+
+ gint status;
+ gint i = 1;
+
+ status = contacts_db_get_records_with_query(query,
+ -1, -1, &record_list);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ status = contacts_list_first(record_list);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_list_destroy(record_list, TRUE);
+ return;
+ }
+
+ do {
+ contacts_record_h record;
+
+ gchar *display_name;
+
+ record = NULL;
+ status = contacts_list_get_current_record_p(record_list,
+ &record);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ display_name = NULL;
+ contacts_record_get_str_p(record,
+ _contacts_person_number.display_name,
+ &display_name);
+
+ if (g_str_has_prefix(display_name, find_text)) {
+ gchar *number;
+
+ number = NULL;
+ contacts_record_get_str_p(record,
+ _contacts_person_number.number,
+ &number);
+
+ __bluetooth_pb_list_ptr_array_add(ptr_array,
+ display_name, number, i);
+ }
+
+ i++;
+ } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
+}
+
+static void __bluetooth_pb_get_phone_log_list_name(BluetoothPbAgent *agent,
+ contacts_query_h query,
+ const gchar *find_text,
+ GPtrArray *ptr_array)
+{
+ contacts_list_h record_list = NULL;
+
+ gint status;
+
+ gint i = 1;
+
+ status = contacts_db_get_records_with_query(query,
+ -1, -1,
+ &record_list);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ status = contacts_list_first(record_list);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_list_destroy(record_list, TRUE);
+ return;
+ }
+
+ do {
+ contacts_record_h record = NULL;
+
+ gint id;
+
+ gchar *display_name;
+
+ record = NULL;
+ status = contacts_list_get_current_record_p(record_list,
+ &record);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ id = 0;
+ status = contacts_record_get_int(record,
+ _contacts_phone_log.id,
+ &id);
+
+ display_name = _bluetooth_pb_fn_from_phonelog_id(id);
+
+ if (g_str_has_prefix(display_name, find_text)) {
+ gchar *number = NULL;
+
+ number = NULL;
+ contacts_record_get_str_p(record,
+ _contacts_phone_log.address,
+ &number);
+
+ __bluetooth_pb_list_ptr_array_add(ptr_array,
+ display_name, number, i);
+ }
+
+ i++;
+
+ g_free(display_name);
+
+ } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
+
+ contacts_list_destroy(record_list, TRUE);
+}
+
+static void __bluetooth_pb_get_list_name(BluetoothPbAgent *agent,
+ PhoneBookType pb_type,
+ const gchar *find_text,
+ GPtrArray *ptr_array)
+{
+ contacts_query_h query;
+
+ switch (pb_type) {
+ case TELECOM_PB:
+ query = __bluetooth_pb_query_person_number();
+ __bluetooth_pb_get_contact_list_name(agent, query,
+ find_text, ptr_array);
+ break;
+ case TELECOM_ICH:
+ query = __bluetooth_pb_query_phone_log_incoming();
+ __bluetooth_pb_get_phone_log_list_name(agent, query,
+ find_text, ptr_array);
+ break;
+ case TELECOM_OCH:
+ query = __bluetooth_pb_query_phone_log_outgoing();
+ __bluetooth_pb_get_phone_log_list_name(agent, query,
+ find_text, ptr_array);
+ break;
+ case TELECOM_MCH:
+ query = __bluetooth_pb_query_phone_log_missed();
+ __bluetooth_pb_get_phone_log_list_name(agent, query,
+ find_text, ptr_array);
+ break;
+ case TELECOM_CCH:
+ query = __bluetooth_pb_query_phone_log_combined();
+ __bluetooth_pb_get_phone_log_list_name(agent, query,
+ find_text, ptr_array);
+ break;
+ default:
+ return;
+ }
+
+ if (query)
+ contacts_query_destroy(query);
+}
+
+static void __bluetooth_pb_list_hash_reset(BluetoothPbAgent *agent)
+{
+ if(agent->contact_list)
+ g_hash_table_destroy(agent->contact_list);
+
+ agent->contact_list = g_hash_table_new(g_direct_hash, g_direct_equal);
+}
+
+static gboolean __bluetooth_pb_list_hash_insert(BluetoothPbAgent *agent,
+ gint handle,
+ gint id)
+{
+ if (agent->contact_list == NULL)
+ return FALSE;
+
+ g_hash_table_insert(agent->contact_list,
+ GINT_TO_POINTER(handle), GINT_TO_POINTER(id));
+
+ return TRUE;
+}
+
+static gint __bluetooth_pb_list_hash_lookup_id(BluetoothPbAgent *agent,
+ gint handle)
+{
+ gint id;
+
+ if (agent->contact_list == NULL)
+ return 0;
+
+ id = GPOINTER_TO_INT(g_hash_table_lookup(agent->contact_list,
+ GINT_TO_POINTER(handle)));
+
+ return id;
+}
+
+static void __bluetooth_pb_list_ptr_array_add(GPtrArray *ptr_array,
+ const gchar *name,
+ const gchar *number,
+ gint handle)
+{
+ GValue value = { 0, };
+
+ g_value_init(&value, DBUS_STRUCT_STRING_STRING_UINT);
+ g_value_take_boxed(&value,
+ dbus_g_type_specialized_construct(DBUS_STRUCT_STRING_STRING_UINT));
+
+ dbus_g_type_struct_set(&value,
+ 0, g_strdup(name),
+ 1, g_strdup(number),
+ 2, handle,
+ G_MAXUINT);
+
+ g_ptr_array_add(ptr_array, g_value_get_boxed(&value));
+}
+
+static void __bluetooth_pb_list_ptr_array_free(gpointer data)
+{
+ GValue value = { 0, };
+
+ gchar *name = NULL;
+ gchar *number = NULL;
+
+ if(data == NULL)
+ return;
+
+ g_value_init(&value, DBUS_STRUCT_STRING_STRING_UINT);
+ g_value_set_boxed(&value, data);
+
+ dbus_g_type_struct_get(&value,
+ 0, &name,
+ 1, &number,
+ G_MAXUINT);
+
+ g_free(name);
+ g_free(number);
+}
+
+static void __bluetooth_pb_agent_signal_handler(int signum)
+{
+ if (mainloop)
+ g_main_loop_quit(mainloop);
+ else
+ exit(0);
+}
+
+
+static void __bluetooth_pb_contact_changed(const gchar *view_uri,
+ void *user_data)
+{
+ BluetoothPbAgent *agent;
+
+ g_return_if_fail(BLUETOOTH_IS_PB_AGENT(user_data));
+ agent = BLUETOOTH_PB_AGENT(user_data);
+
+ g_signal_emit(agent, signals[CLEAR], 0);
+ g_object_unref(agent);
+}
+
+static void __bluetooth_pb_agent_timeout_add_seconds(BluetoothPbAgent *agent)
+{
+ g_return_if_fail(BLUETOOTH_IS_PB_AGENT(agent));
+
+ if(agent->timeout_id)
+ g_source_remove(agent->timeout_id);
+
+ agent->timeout_id = g_timeout_add_seconds(BLUETOOTH_PB_AGENT_TIMEOUT,
+ __bluetooth_pb_agent_timeout_calback,
+ agent);
+}
+
+static gboolean __bluetooth_pb_agent_timeout_calback(gpointer user_data)
+{
+ BluetoothPbAgent *agent;
+
+ g_return_val_if_fail(BLUETOOTH_IS_PB_AGENT(user_data), FALSE);
+
+ agent = BLUETOOTH_PB_AGENT(user_data);
+ agent->timeout_id = 0;
+
+ if (mainloop)
+ g_main_loop_quit(mainloop);
+
+ return FALSE;
+}
+
+static void __bluetooth_pb_tel_callback(TapiHandle *handle,
+ int result,
+ void *data,
+ void *user_data)
+{
+ BluetoothPbAgent *agent;
+ TelSimMsisdnList_t *number;
+
+ g_return_if_fail(BLUETOOTH_IS_PB_AGENT(user_data));
+
+ agent = BLUETOOTH_PB_AGENT(user_data);
+
+ __bluetooth_pb_agent_dbus_init(agent);
+
+ number = (TelSimMsisdnList_t *)data;
+ agent->tel_number = g_strdup(number->list[0].num);
+
+ tel_deinit(agent->tapi_handle);
+ agent->tapi_handle = NULL;
+}
+
+static void __bluetooth_pb_agent_dbus_init(BluetoothPbAgent *agent)
+{
+ guint result = 0;
+ GError *error = NULL;
+
+ agent->bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
+
+ if (error != NULL) {
+ DBG("Couldn't connect to system bus[%s]\n", error->message);
+ g_error_free(error);
+ return;
+ }
+
+ agent->proxy = dbus_g_proxy_new_for_name(agent->bus,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ if (agent->proxy == NULL) {
+ DBG("Failed to get a proxy for D-Bus\n");
+ return;
+ }
+
+ if (!dbus_g_proxy_call(agent->proxy,
+ "RequestName", &error,
+ G_TYPE_STRING, BT_PB_SERVICE_NAME,
+ G_TYPE_UINT, 0,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &result,
+ G_TYPE_INVALID)) {
+ if (error != NULL) {
+ DBG("RequestName RPC failed[%s]\n", error->message);
+ g_error_free(error);
+ }
+
+ g_object_unref(agent->proxy);
+ agent->proxy = NULL;
+
+ return;
+ }
+ DBG("result : %d %d\n", result, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ DBG("Failed to get the primary well-known name.\n");
+
+ g_object_unref(agent->proxy);
+ agent->proxy = NULL;
+
+ return;
+ }
+
+ g_object_unref(agent->proxy);
+ agent->proxy = NULL;
+
+ dbus_g_connection_register_g_object(agent->bus,
+ BT_PB_SERVICE_OBJECT_PATH,
+ G_OBJECT(agent));
+}
+
+int main(int argc, char **argv)
+{
+ BluetoothPbAgent *agent;
+
+ gint ret = EXIT_SUCCESS;
+ gint tapi_result;
+
+ struct sigaction sa;
+
+ g_type_init();
+
+ mainloop = g_main_loop_new(NULL, FALSE);
+ if (mainloop == NULL) {
+ DBG("Couldn't create GMainLoop\n");
+ return EXIT_FAILURE;
+ }
+
+ agent = g_object_new(BLUETOOTH_PB_TYPE_AGENT, NULL);
+
+ /* connect contact */
+ if (contacts_connect2() != CONTACTS_ERROR_NONE) {
+ DBG("Can not connect contacts server\n");
+ g_object_unref(agent);
+ return EXIT_FAILURE;
+ }
+
+ if (contacts_db_add_changed_cb(_contacts_event._uri,
+ __bluetooth_pb_contact_changed,
+ g_object_ref(agent)) != CONTACTS_ERROR_NONE) {
+ DBG("Can not add changed callback");
+ }
+
+ /* set signal */
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = __bluetooth_pb_agent_signal_handler;
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+
+ /* init tapi */
+ agent->tapi_handle = tel_init(NULL);
+ tapi_result = tel_get_sim_msisdn(agent->tapi_handle,
+ __bluetooth_pb_tel_callback, agent);
+
+ if (tapi_result != TAPI_API_SUCCESS) {
+ __bluetooth_pb_agent_dbus_init(agent);
+ }
+
+
+ __bluetooth_pb_agent_timeout_add_seconds(agent);
+
+ g_main_loop_run(mainloop);
+
+ DBG("Terminate the bluetooth-pb-agent\n");
+
+ if (agent) {
+ contacts_db_remove_changed_cb(_contacts_event._uri,
+ __bluetooth_pb_contact_changed,
+ g_object_ref(agent));
+
+ g_object_unref(agent);
+ }
+
+
+ contacts_disconnect2();
+
+ g_signal_emit(agent, signals[CLEAR], 0);
+
+ if (agent)
+ g_object_unref(agent);
+
+ return ret;
+}
--- /dev/null
+/*
+ * bluetooth-agent
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DEF_BT_PB_AGENT_H_
+#define __DEF_BT_PB_AGENT_H_
+
+#include <unistd.h>
+#include <dlog.h>
+
+#include <stdio.h>
+
+#include <dbus/dbus-glib.h>
+
+#define BT_PB_SERVICE_OBJECT_PATH "/org/bluez/pb_agent"
+#define BT_PB_SERVICE_NAME "org.bluez.pb_agent"
+#define BT_PB_SERVICE_INTERFACE "org.bluez.PbAgent"
+
+#undef LOG_TAG
+#define LOG_TAG "BLUETOOTH_AGENT_PHONEBOOK"
+
+#define DBG(fmt, args...) SLOGD(fmt, ##args)
+#define ERR(fmt, args...) SLOGE(fmt, ##args)
+
+#endif /* __DEF_BT_AGENT_H_ */
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+ <interface name="org.bluez.PbAgent">
+ <method name="GetPhonebookFolderList">
+ <arg type="as" name="folder_list" direction="out"/>
+ </method>
+
+ <method name="GetPhonebook">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="name"/>
+ <arg type="t" name="filter"/>
+ <arg type="y" name="format"/>
+ <arg type="q" name="max_list_count"/>
+ <arg type="q" name="list_start_offset"/>
+ <arg type="as" name="phonebook" direction="out"/>
+ <arg type="u" name="new_missed_call" direction="out"/>
+ </method>
+
+ <method name="GetPhonebookSize">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="name"/>
+ <arg type="u" name="phonebook_size" direction="out"/>
+ <arg type="u" name="new_missed_call" direction="out"/>
+ </method>
+
+ <method name="GetPhonebookList">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="name"/>
+ <arg type="a(ssu)" name="phonebook_list" direction="out"/>
+ </method>
+
+ <method name="GetPhonebookEntry">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="folder"/>
+ <arg type="s" name="id"/>
+ <arg type="t" name="filter"/>
+ <arg type="y" name="format"/>
+ <arg type="s" name="phonebook_entry" direction="out"/>
+ </method>
+
+ <method name="GetTotalObjectCount">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="path"/>
+ <arg type="u" name="phonebook_size" direction="out"/>
+ </method>
+
+ <method name="AddContact">
+ <arg type="s" name="filename"/>
+ </method>
+
+ <signal name="clear"/>
+
+ </interface>
+
+ <interface name="org.bluez.PbAgent.At">
+ <method name="GetPhonebookSizeAt">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="command"/>
+ <arg type="u" name="phonebook_size" direction="out"/>
+ </method>
+
+ <method name="GetPhonebookEntriesAt">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="command"/>
+ <arg type="i" name="start_index"/>
+ <arg type="i" name="end_index"/>
+ <arg type="a(ssu)" name="phonebook_entries" direction="out"/>
+ </method>
+
+ <method name="GetPhonebookEntriesFindAt">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg type="s" name="command"/>
+ <arg type="s" name="find_text" />
+ <arg type="a(ssu)" name="phonebook_entries" direction="out"/>
+ </method>
+ </interface>
+</node>
--- /dev/null
+/*
+ * bluetooth-agent
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * 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 <time.h>
+#include <string.h>
+#include <stdarg.h>
+
+
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+
+#include <vconf.h>
+#include <dlog.h>
+#include <contacts.h>
+
+#include "bluetooth_pb_vcard.h"
+
+#define BT_PB_AGENT "BT_PB_AGENT"
+#define DBG(fmt, args...) SLOG(LOG_DEBUG, BT_PB_AGENT, "%s():%d "fmt, __func__, __LINE__, ##args)
+#define ERR(fmt, args...) SLOG(LOG_ERROR, BT_PB_AGENT, "%s():%d "fmt, __func__, __LINE__, ##args)
+
+#define VCARD_FORMAT_2_1 0x0
+#define VCARD_FORMAT_3_0 0x1
+
+#define VCARD_VERSION (0x1)
+#define VCARD_FN (0x1 << 1)
+#define VCARD_N (0x1 << 2)
+#define VCARD_PHOTO (0x1 << 3)
+#define VCARD_BDAY (0x1 << 4)
+#define VCARD_ADR (0x1 << 5)
+#define VCARD_LABEL (0x1 << 6) /* not supported */
+#define VCARD_TEL (0x1 << 7)
+#define VCARD_EMAIL (0x1 << 8)
+#define VCARD_MAILER (0x1 << 9) /* not supported */
+#define VCARD_TZ (0x1 << 10) /* not supported */
+#define VCARD_GEO (0x1 << 11) /* not supported */
+#define VCARD_TITLE (0x1 << 12)
+#define VCARD_ROLE (0x1 << 13)
+#define VCARD_LOGO (0x1 << 14) /* not supported */
+#define VCARD_AGENT (0x1 << 15) /* not supported */
+#define VCARD_ORG (0x1 << 16)
+#define VCARD_NOTE (0x1 << 17)
+#define VCARD_REV (0x1 << 18)
+#define VCARD_SOUND (0x1 << 19) /* not supported */
+#define VCARD_URL (0x1 << 20)
+#define VCARD_UID (0x1 << 21)
+#define VCARD_KEY (0x1 << 22) /* not supported */
+#define VCARD_NICKNAME (0x1 << 23)
+#define VCARD_CATEGORIES (0x1 << 24) /* not supported */
+#define VCARD_PROID (0x1 << 25) /* not supported */
+#define VCARD_CLASS (0x1 << 26) /* not supported */
+#define VCARD_SORT_STRING (0x1 << 27) /* not supported */
+
+#define VCARD_X_IRMC_CALL_DATETIME (0x1 << 28)
+
+#define QP_ENC_LEN 3
+#define LINEBREAK_LEN 75
+
+static gchar *__bluetooth_pb_vcard_escape(const gchar *str);
+
+static gchar *__bluetooth_pb_vcard_strv_concat(gchar **strv,
+ const gchar *delimeter);
+
+static gboolean __bluetooth_pb_vcard_qp_encode_check(const gchar *str);
+
+static gint __bluetooth_pb_vcard_qp_encode_strlen(const gchar *str,
+ gint len);
+
+static void __bluetooth_pb_vcard_qp_encode_append_to_hex(GString *string,
+ const gchar *str,
+ gint len,
+ gint *line_pos);
+
+static void __bluetooth_pb_vcard_qp_encode_append_printable_c(GString *string,
+ gchar ch,
+ gint *line_pos);
+
+static void __bluetooth_pb_vcard_qp_encode_append(GString *string,
+ const gchar *str,
+ gint len,
+ gint *line_pos);
+
+static gchar *__bluetooth_pb_vcard_qp_encode(const gchar *str);
+
+static void __bluetooth_pb_vcard_append_param_v21(GString *string,
+ const gchar *param);
+
+static void __bluetooth_pb_vcard_append_qp_encode_v21(GString *string,
+ const gchar *name,
+ const gchar *param,
+ const gchar *value);
+
+static void __bluetooth_pb_vcard_append_base64_encode_v21(GString *string,
+ const gchar *name,
+ const gchar *param,
+ const gchar *value,
+ gsize len,
+ gboolean folding);
+
+static void __bluetooth_pb_vcard_append_n_v21(GString *string,
+ contacts_record_h contact);
+
+static void __bluetooth_pb_vcard_append_tel_v21(GString *string,
+ contacts_record_h conatct);
+
+static void __bluetooth_pb_vcard_append_fn_v21(GString *string,
+ contacts_record_h person);
+
+static void __bluetooth_pb_vcard_append_photo_v21(GString *string,
+ contacts_record_h person);
+
+static void __bluetooth_pb_vcard_append_bday_v21(GString *string,
+ contacts_record_h contact);
+
+static void __bluetooth_pb_vcard_append_adr_v21(GString *string,
+ contacts_record_h contact);
+
+static void __bluetooth_pb_vcard_append_email_v21(GString *string,
+ contacts_record_h contact);
+
+static void __bluetooth_pb_vcard_append_title_v21(GString *string,
+ contacts_record_h contact);
+
+static void __bluetooth_pb_vcard_append_role_v21(GString *string,
+ contacts_record_h contact);
+
+static void __bluetooth_pb_vcard_append_org_v21(GString *string,
+ contacts_record_h contact);
+
+static void __bluetooth_pb_vcard_append_note_v21(GString *string,
+ contacts_record_h contact);
+
+static void __bluetooth_pb_vcard_append_rev_v21(GString *string,
+ contacts_record_h contact);
+
+static void __bluetooth_pb_vcard_append_url_v21(GString *string,
+ contacts_record_h contact);
+
+static void __bluetooth_pb_vcard_append_uid_v21(GString *string,
+ contacts_record_h contact);
+
+static void __bluetooth_pb_vcard_append_v30(GString *string,
+ const gchar *name,
+ const gchar *param,
+ const gchar *value);
+
+static void __bluetooth_pb_vcard_remove_v30(GString *string,
+ const gchar *property_name);
+
+static gchar *__bluetooth_pb_vcard_filter_v30(const gchar *vcard,
+ guint64 filter);
+
+static gchar *__bluetooth_pb_vcard_real_contact_valist_v21(gint person_id,
+ gint phonelog_id,
+ guint64 filter,
+ const gchar *first_name,
+ va_list args);
+
+static gchar *__bluetooth_pb_vcard_real_contact_valist_v30(gint person_id,
+ gint phonelog_id,
+ guint64 filter,
+ const gchar *first_name,
+ va_list args);
+
+static gchar *__bluetooth_pb_vcard_real_contact_with_properties(gint person_id,
+ gint phonelog_id,
+ guint64 filter,
+ guint8 format,
+ const gchar *first_name,
+ ...);
+
+static gchar *__bluetooth_pb_vcard_real_call_v21(gint phonelog_id,
+ guint filter,
+ const gchar *attr);
+
+static gchar *__bluetooth_pb_vcard_real_call_v30(gint phonelog_id,
+ guint filter,
+ const gchar *attr);
+
+static gchar *__bluetooth_pb_vcard_real_call(gint phonelog_id,
+ guint filter,
+ guint8 format,
+ const gchar *attr);
+
+static gchar **__bluetooth_pb_contact_add_field_str(contacts_record_h record,
+ int *field,
+ gint field_size);
+
+static gchar **__bluetooth_pb_contact_tel_param(contacts_record_h number);
+
+static gchar *__bluetooth_pb_contact_photo_type(const gchar *filename);
+
+static gchar **__bluetooth_pb_contact_addr(contacts_record_h address);
+
+static gchar **__bluetooth_pb_contact_addr_param(contacts_record_h address);
+
+static gchar *__bluetooth_pb_phonelog_datetime(gint phonelog_id);
+
+static gchar *__bluetooth_pb_name_from_contact(contacts_record_h contact);
+
+static gchar *__bluetooth_pb_number_from_contact(contacts_record_h contact);
+
+static gint __bluetooth_pb_person_id_from_phonelog_id(gint phonelog_id);
+
+
+static gchar *__bluetooth_pb_vcard_escape(const gchar *str)
+{
+ GString *escaped;
+
+ gchar *st = NULL;
+ gchar *pos = NULL;
+
+ if (str == NULL)
+ return NULL;
+
+ escaped = g_string_new(NULL);
+
+ st = (gchar *)str;
+ pos = st;
+
+ while (*pos != '\0') {
+ if (*pos == ';') {
+ g_string_append_len(escaped, st, (pos - st));
+ g_string_append(escaped, "\\;");
+
+ pos++;
+ st = pos;
+ }
+ else {
+ pos++;
+ }
+ }
+
+ g_string_append_len(escaped, st, (pos - st));
+ return g_string_free(escaped, FALSE);
+}
+
+static gchar *__bluetooth_pb_vcard_strv_concat(gchar **strv,
+ const gchar *separator)
+{
+ GString *string = g_string_new(NULL);
+ gint i;
+
+ for (i = 0; strv[i] != NULL; i++) {
+ if (i > 0)
+ g_string_append(string, ";");
+
+ g_string_append(string, strv[i]);
+ }
+
+ return g_string_free(string, FALSE);
+}
+
+static gboolean __bluetooth_pb_vcard_qp_encode_check(const gchar *str)
+{
+ gchar *pos = NULL;
+
+ if (str == NULL)
+ return FALSE;
+
+ pos = (gchar *)str;
+ while (*pos != '\0') {
+ /* ascii code ' ' : 32, '~' : 126 */
+ if ((guchar)*pos < ' ' || (guchar)*pos > '~')
+ return TRUE;
+
+ pos++;
+ }
+ return FALSE;
+}
+
+/* get string length, which convert to quoted-printable encoding */
+static gint __bluetooth_pb_vcard_qp_encode_strlen(const gchar *str,
+ gint len)
+{
+ gchar *pos;
+
+ gint count = 0;
+ gint length = len;
+
+ if (str == NULL)
+ return 0;
+
+ if (strlen(str) < len )
+ length = -1;
+
+ pos = (gchar *)str;
+
+ while (*pos != '\0' && (((pos - str) < length) || length < 0)) {
+ if ((guchar)*pos == '\t') {
+ count++;
+ pos++;
+ continue;
+ }
+
+ if ((guchar)*pos < ' ' || (guchar)*pos == '=') {
+ count += QP_ENC_LEN;
+ pos++;
+ continue;
+ }
+
+ /* check no-ascii utf-8 character */
+ if ((guchar)*pos > '~') {
+
+ gchar *next;
+
+ next = g_utf8_next_char(pos);
+
+ count += QP_ENC_LEN * (next - pos);
+ pos = next;
+ continue;
+ }
+
+ pos++;
+ count++;
+ }
+
+ return count;
+}
+
+/* convert to quoted printable code */
+static void __bluetooth_pb_vcard_qp_encode_append_to_hex(GString *string,
+ const gchar *str,
+ gint len,
+ gint *line_pos)
+{
+ int i;
+
+ if (str == NULL || len == 0)
+ return;
+
+ /* add soft linebreak when it exceed */
+ if ((*line_pos + (QP_ENC_LEN * len) > LINEBREAK_LEN)) {
+ g_string_append(string, "=\r\n");
+ *line_pos = 0;
+ }
+
+ for (i = 0; i < len; i++) {
+ g_string_append_printf(string, "=%02X", (guchar)*(str+i));
+ *line_pos += QP_ENC_LEN;
+ }
+}
+
+/* append plain visiable ascii character */
+static void __bluetooth_pb_vcard_qp_encode_append_printable_c(GString *string,
+ gchar ch,
+ gint *line_pos)
+{
+ /* add soft linebreak when it exceed */
+ if (*line_pos + 1 > LINEBREAK_LEN) {
+ g_string_append(string, "=\r\n");
+ *line_pos = 0;
+ }
+ g_string_append_c(string, ch);
+ (*line_pos)++;
+}
+
+static void __bluetooth_pb_vcard_qp_encode_append(GString *string,
+ const gchar *str,
+ gint len,
+ gint *line_pos)
+{
+ gint length;
+ gint encode_len;
+
+ gint i = 0;
+
+ if (string == NULL)
+ return;
+
+ encode_len = __bluetooth_pb_vcard_qp_encode_strlen(str, len);
+
+ /* add soft linebreak when it exceed */
+ if (((*line_pos + encode_len) > LINEBREAK_LEN) && (*line_pos > 1)) {
+ g_string_append(string, "=\r\n");
+ *line_pos = 0;
+ }
+
+ length = strlen(str);
+ if (length > len)
+ length = len;
+
+ while (i < len) {
+ gchar *pos;
+
+ pos = ((gchar *)str) + i;
+
+ /* converts invisiable character and escape character '=' to quoted-printable */
+ if ((guchar)*pos != '\t' &&
+ ((guchar)*pos < ' ' || (guchar)*pos == '=')) {
+ __bluetooth_pb_vcard_qp_encode_append_to_hex(string, pos,
+ 1, line_pos);
+ i++;
+
+ continue;
+ }
+
+ /* converts non-ascii utf-8 character to quoted-printable */
+ if ((guchar)*pos > '~') {
+ gchar *next;
+ int ch_len;
+
+ next = g_utf8_next_char(pos);
+
+ ch_len = next - pos;
+ __bluetooth_pb_vcard_qp_encode_append_to_hex(string, pos,
+ ch_len, line_pos);
+ i += ch_len;
+
+ continue;
+ }
+
+ __bluetooth_pb_vcard_qp_encode_append_printable_c(string, *pos, line_pos);
+ i++;
+ }
+}
+
+static gchar* __bluetooth_pb_vcard_qp_encode(const gchar *str)
+{
+ GString *enc;
+
+ gchar *st_pos;
+ gchar *pos;
+
+ gint line_pos = 0;
+
+ if (str == NULL)
+ return NULL;
+
+ enc = g_string_new(NULL);
+
+ st_pos = (gchar *)str;
+ pos = (gchar *)str;
+
+ while (*pos != '\0') {
+ /* split string with given delimeter ' ' or '\t' */
+ if (*pos == ' ' || *pos == '\t') {
+ __bluetooth_pb_vcard_qp_encode_append(enc, st_pos,
+ (pos - st_pos), &line_pos);
+
+ st_pos = pos;
+ pos++;
+
+ continue;
+ }
+
+ /* split string with given delimeter '\r', '\n' or '\r\n' - newline */
+ if (*pos == '\r' || *pos == '\n' ) {
+ __bluetooth_pb_vcard_qp_encode_append(enc, st_pos,
+ (pos - st_pos), &line_pos);
+
+ /* converts newline to qp_encode with soft linebreak
+ for example, converts \r\n to =0D=0A=\r\n */
+ __bluetooth_pb_vcard_qp_encode_append_to_hex(enc, "\r\n",
+ 2, &line_pos);
+ g_string_append(enc, "=\r\n ");
+
+ line_pos = 1;
+
+ if (*pos == '\r' && *(pos + 1) == '\n')
+ pos += 2;
+ else
+ pos++;
+
+ st_pos = pos;
+
+ continue;
+ }
+
+ pos++;
+ }
+
+ __bluetooth_pb_vcard_qp_encode_append(enc, st_pos,
+ (pos - st_pos), &line_pos);
+
+ return g_string_free(enc, FALSE);
+}
+
+static void __bluetooth_pb_vcard_append_param_v21(GString *string,
+ const gchar *param)
+{
+ gchar *pos = NULL;
+
+ if (param == NULL)
+ return;
+
+ pos = (gchar *)param;
+
+ /* trim ';' on first */
+ while (*pos != '\0') {
+ if (*pos != ';')
+ break;
+
+ pos++;
+ }
+
+ if (*pos != '\0')
+ g_string_append_printf(string, ";%s", pos);
+}
+
+static void __bluetooth_pb_vcard_append_qp_encode_v21(GString *string,
+ const gchar *name,
+ const gchar *param,
+ const gchar *value)
+{
+ GString *property = NULL;
+
+ if (name == NULL)
+ return;
+
+ property = g_string_new(name);
+ __bluetooth_pb_vcard_append_param_v21(property, param);
+
+ if (__bluetooth_pb_vcard_qp_encode_check(value)) {
+ gchar *enc = NULL;
+
+ __bluetooth_pb_vcard_append_param_v21(property,
+ "CHARSET=UTF-8");
+ __bluetooth_pb_vcard_append_param_v21(property,
+ "ENCODING=QUOTED-PRINTABLE");
+ g_string_append(property, ":");
+
+ enc = __bluetooth_pb_vcard_qp_encode(value);
+
+ if (enc) {
+ g_string_append(property, enc);
+ g_free(enc);
+ }
+ } else {
+ g_string_append(property, ":");
+ if (value)
+ g_string_append(property , value);
+ }
+
+ g_string_append_printf(string, "%s\r\n", property->str);
+
+ g_string_free(property, TRUE);
+}
+
+
+static void __bluetooth_pb_vcard_append_base64_encode_v21(GString *string,
+ const gchar *name,
+ const gchar *param,
+ const gchar *value,
+ gsize len,
+ gboolean folding)
+{
+ gchar *enc = NULL;
+
+ if (name == NULL)
+ return;
+
+ g_string_append(string, name);
+
+ __bluetooth_pb_vcard_append_param_v21(string, param);
+ __bluetooth_pb_vcard_append_param_v21(string, "ENCODING=BASE64");
+
+ g_string_append(string, ":");
+
+ if (value == NULL)
+ return;
+
+ enc = g_base64_encode((const guchar *)value, len);
+
+
+ if (folding == FALSE) {
+ g_string_append(string, enc);
+ } else {
+ gint enc_len = strlen(enc);
+ gint i = 0;
+
+ /* count ' ' size for folding */
+ gint fline_len = LINEBREAK_LEN -1;
+
+ for (i = 0; (i * fline_len) < enc_len; i++) {
+ g_string_append(string, "\r\n ");
+ if ((i * fline_len) + fline_len > enc_len)
+ g_string_append(string, enc + (i * fline_len));
+ else
+ g_string_append_len(string, enc + (i * fline_len), fline_len);
+ }
+
+ /* some application requires more \r\n */
+ g_string_append(string, "\r\n");
+ }
+ g_string_append(string, "\r\n");
+
+ g_free(enc);
+}
+
+static void __bluetooth_pb_vcard_append_n_v21(GString *string,
+ contacts_record_h contact)
+{
+ gchar *str;
+
+ str = __bluetooth_pb_name_from_contact(contact);
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "N", NULL, str);
+
+ g_free(str);
+}
+
+static void __bluetooth_pb_vcard_append_tel_v21(GString *string,
+ contacts_record_h contact)
+{
+ guint count = 0;
+
+ gint i;
+ gint status;
+
+ status = contacts_record_get_child_record_count(contact,
+ _contacts_contact.number,
+ &count);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ for (i = 0; i < count; i++) {
+ contacts_record_h number = NULL;
+
+ gchar **paramv = NULL;
+ gchar *param = NULL;
+
+ gchar *tel = NULL;
+ gchar *escaped = NULL;
+
+ status = contacts_record_get_child_record_at_p(contact,
+ _contacts_contact.number, i, &number);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ status = contacts_record_get_str_p(number,
+ _contacts_number.number,
+ &tel);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ escaped = __bluetooth_pb_vcard_escape(tel);
+
+ paramv = __bluetooth_pb_contact_tel_param(number);
+ param = __bluetooth_pb_vcard_strv_concat(paramv, ";");
+
+ g_strfreev(paramv);
+
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "TEL", param, escaped);
+
+ g_free(escaped);
+ g_free(param);
+ }
+}
+
+static void __bluetooth_pb_vcard_append_fn_v21(GString *string,
+ contacts_record_h person)
+{
+ gint status;
+
+ gchar *fn = NULL;
+ gchar *tmp = NULL;
+
+ status = contacts_record_get_str_p(person,
+ _contacts_person.display_name,
+ &tmp);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ fn = __bluetooth_pb_vcard_escape(tmp);
+
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "FN", NULL, fn);
+
+ g_free(fn);
+}
+
+static void __bluetooth_pb_vcard_append_photo_v21(GString *string,
+ contacts_record_h person)
+{
+ gint status;
+
+ gsize len = 0;
+
+ gchar *filename = NULL;
+
+ gchar *type = NULL;
+ gchar *param = NULL;
+ gchar *contents = NULL;
+
+
+ status = contacts_record_get_str_p(person,
+ _contacts_person.image_thumbnail_path,
+ &filename);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ type = __bluetooth_pb_contact_photo_type(filename);
+
+ if (type) {
+ param = g_strdup_printf("TYPE=%s", type);
+ g_free(type);
+ }
+
+ if (g_file_get_contents(filename, &contents, &len, NULL) == FALSE) {
+ ERR("can not read file contents:%s\n", filename);
+ return;
+ }
+
+ __bluetooth_pb_vcard_append_base64_encode_v21(string,
+ "PHOTO", param, contents, len, TRUE);
+
+ g_free(param);
+ g_free(contents);
+}
+
+static void __bluetooth_pb_vcard_append_bday_v21(GString *string,
+ contacts_record_h contact)
+{
+ guint count = 0;
+
+ gint status;
+ gint i;
+
+ status = contacts_record_get_child_record_count(contact,
+ _contacts_contact.event, &count);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ for (i = 0; i < count; i++) {
+ contacts_record_h event = NULL;
+
+ gint date;
+
+ gchar *bday;
+
+ contacts_event_type_e type;
+
+ status = contacts_record_get_child_record_at_p(contact,
+ _contacts_contact.event, i, &event);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ status = contacts_record_get_int(event,
+ _contacts_event.type,
+ (gint *) &type);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ if (type != CONTACTS_EVENT_TYPE_BIRTH)
+ continue;
+
+ status = contacts_record_get_int(event,
+ _contacts_event.date,
+ &date);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ if (date <= 0)
+ continue;
+
+ bday = g_strdup_printf("%04d-%02d-%02d",
+ (date/10000), (date/100)%100, date%100);
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "BDAY",
+ NULL, bday);
+ g_free(bday);
+ }
+}
+
+static void __bluetooth_pb_vcard_append_adr_v21(GString *string,
+ contacts_record_h contact)
+{
+ guint count = 0;
+
+ gint status;
+ gint i;
+
+ status = contacts_record_get_child_record_count(contact,
+ _contacts_contact.address,
+ &count);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ for (i = 0; i < count; i++) {
+ contacts_record_h address = NULL;
+
+ gchar **addrv;
+ gchar **paramv;
+
+ gchar *addr;
+ gchar *param;
+
+ status = contacts_record_get_child_record_at_p(contact,
+ _contacts_contact.address, i, &address);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ addrv = __bluetooth_pb_contact_addr(address);
+
+ if (addrv == NULL)
+ continue;
+
+ addr = __bluetooth_pb_vcard_strv_concat(addrv, ";");
+ g_strfreev(addrv);
+
+ paramv = __bluetooth_pb_contact_addr_param(address);
+ param = __bluetooth_pb_vcard_strv_concat(paramv, ";");
+ g_strfreev(paramv);
+
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "ADR",
+ param, addr);
+
+ g_free(param);
+ g_free(addr);
+ }
+}
+
+static void __bluetooth_pb_vcard_append_email_v21(GString *string,
+ contacts_record_h contact)
+{
+ guint count = 0;
+
+ gint status;
+ gint i;
+
+ status = contacts_record_get_child_record_count(contact,
+ _contacts_contact.email,
+ &count);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ for (i = 0; i < count; i++) {
+ contacts_record_h email = NULL;
+
+ gchar *tmp = NULL;
+ gchar *escaped;
+
+ status = contacts_record_get_child_record_at_p(contact,
+ _contacts_contact.email, i, &email);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ status = contacts_record_get_str_p(email,
+ _contacts_email.email,
+ &tmp);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ escaped = __bluetooth_pb_vcard_escape(tmp);
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "EMAIL", NULL, escaped);
+
+ g_free(escaped);
+ }
+}
+
+static void __bluetooth_pb_vcard_append_title_v21(GString *string,
+ contacts_record_h contact)
+{
+ guint count = 0;
+
+ gint status;
+ gint i;
+
+ status = contacts_record_get_child_record_count(contact,
+ _contacts_contact.company,
+ &count);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ for (i = 0; i < count; i++) {
+ contacts_record_h company = NULL;
+
+ char *title = NULL;
+ gchar *escaped;
+
+ status = contacts_record_get_child_record_at_p(contact,
+ _contacts_contact.company,i, &company);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ status = contacts_record_get_str_p(company,
+ _contacts_company.job_title,
+ &title);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ escaped = __bluetooth_pb_vcard_escape(title);
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "TITLE", NULL, escaped);
+
+ g_free(escaped);
+ }
+}
+
+static void __bluetooth_pb_vcard_append_role_v21(GString *string,
+ contacts_record_h contact)
+{
+ guint count = 0;
+
+ gint status;
+ gint i;
+
+ status = contacts_record_get_child_record_count(contact,
+ _contacts_contact.company,
+ &count);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ for (i = 0; i < count; i++) {
+ contacts_record_h company = NULL;
+
+ char *role = NULL;
+ gchar *escaped;
+
+ status = contacts_record_get_child_record_at_p(contact,
+ _contacts_contact.company, i, &company);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ status = contacts_record_get_str_p(company,
+ _contacts_company.role,
+ &role);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ escaped = __bluetooth_pb_vcard_escape(role);
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "ROLE", NULL, escaped);
+
+ g_free(escaped);
+ }
+}
+
+static void __bluetooth_pb_vcard_append_org_v21(GString *string,
+ contacts_record_h contact)
+{
+ guint count = 0;
+
+ gint status;
+ gint i;
+
+ status = contacts_record_get_child_record_count(contact,
+ _contacts_contact.company,
+ &count);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ for (i = 0; i < count; i++) {
+ contacts_record_h company = NULL;
+
+ GString *str;
+
+ gchar *name = NULL;
+ gchar *department = NULL;
+
+ gint name_status;
+ gint department_status;
+
+ status = contacts_record_get_child_record_at_p(contact,
+ _contacts_contact.company, i, &company);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+
+ name_status = contacts_record_get_str_p(company,
+ _contacts_company.name,
+ &name);
+
+ department_status = contacts_record_get_str_p(company,
+ _contacts_company.department,
+ &department);
+
+ if ((name_status != CONTACTS_ERROR_NONE) &&
+ (department_status != CONTACTS_ERROR_NONE))
+ continue;
+
+ str = g_string_new(NULL);
+
+ if (name) {
+ gchar *escaped;
+
+ escaped = __bluetooth_pb_vcard_escape(name);
+ g_string_append(str, escaped);
+ g_free(escaped);
+ }
+
+ g_string_append(str, ";");
+
+ if (department) {
+ gchar *escaped;
+
+ escaped = __bluetooth_pb_vcard_escape(department);
+ g_string_append(str, escaped);
+ g_free(escaped);
+ }
+
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "ORG", NULL, str->str);
+
+ g_string_free(str, TRUE);
+
+ }
+}
+
+static void __bluetooth_pb_vcard_append_note_v21(GString *string,
+ contacts_record_h contact)
+{
+ guint count = 0;
+
+ gint status;
+ gint i;
+
+ status = contacts_record_get_child_record_count(contact,
+ _contacts_contact.note,
+ &count);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ for (i = 0; i < count; i++) {
+ contacts_record_h note = NULL;
+
+ char *tmp = NULL;
+ gchar *escaped;
+
+ status = contacts_record_get_child_record_at_p(contact,
+ _contacts_contact.note, i, ¬e);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ status = contacts_record_get_str_p(note,
+ _contacts_note.note,
+ &tmp);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ escaped = __bluetooth_pb_vcard_escape(tmp);
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "NOTE", NULL, escaped);
+
+ g_free(escaped);
+ }
+}
+
+static void __bluetooth_pb_vcard_append_rev_v21(GString *string,
+ contacts_record_h contact)
+{
+ gint time = 0;
+ gint status;
+
+ gchar *rev;
+ struct tm result;
+
+ status = contacts_record_get_int(contact,
+ _contacts_contact.changed_time,
+ &time);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ if (time <= 0)
+ return;
+
+ gmtime_r((const time_t*)(&time), &result);
+
+ rev = g_strdup_printf("%04d-%02d-%02dT%02d:%02d:%02dZ",
+ (1900 + result.tm_year), (1 + result.tm_mon), result.tm_mday,
+ result.tm_hour, result.tm_min, result.tm_sec);
+
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "REV", NULL, rev);
+
+ g_free(rev);
+}
+
+static void __bluetooth_pb_vcard_append_url_v21(GString *string,
+ contacts_record_h contact)
+{
+ guint count = 0;
+
+ gint i;
+ gint status;
+
+ status = contacts_record_get_child_record_count(contact,
+ _contacts_contact.url,
+ &count);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ for (i = 0; i < count; i++) {
+ contacts_record_h url = NULL;
+
+ gchar *tmp = NULL;
+ gchar *escaped;
+
+ status = contacts_record_get_child_record_at_p(contact,
+ _contacts_contact.url, i, &url);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ if (url == NULL)
+ continue;
+
+ status = contacts_record_get_str_p(url,
+ _contacts_url.url,
+ &tmp);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ escaped = __bluetooth_pb_vcard_escape(tmp);
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "URL", NULL, escaped);
+
+ g_free(escaped);
+ }
+}
+
+static void __bluetooth_pb_vcard_append_uid_v21(GString *string,
+ contacts_record_h contact)
+{
+ int status;
+
+ gchar *uid = NULL;
+ gchar *escaped;
+
+ status = contacts_record_get_str_p(contact,
+ _contacts_contact.uid,
+ &uid);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return;
+
+ escaped = __bluetooth_pb_vcard_escape(uid);
+ __bluetooth_pb_vcard_append_qp_encode_v21(string, "UID", NULL, escaped);
+
+ g_free(escaped);
+}
+
+static void __bluetooth_pb_vcard_append_v30(GString *string,
+ const gchar *name,
+ const gchar *param,
+ const gchar *value)
+{
+ if (string == NULL)
+ return;
+ if (name == NULL)
+ return;
+
+ g_string_append(string, name);
+
+ if (param)
+ g_string_append_printf(string, ";%s", param);
+
+ g_string_append(string, ":");
+
+ if (value)
+ g_string_append(string, value);
+
+ g_string_append(string, "\r\n");
+}
+
+static void __bluetooth_pb_vcard_remove_v30(GString *string,
+ const gchar *property_name)
+{
+ gchar *pos = NULL;
+ gchar *st_pos = NULL;
+
+ gboolean matched = FALSE;
+
+ if(string == NULL || property_name == NULL)
+ return;
+
+ pos = string->str;
+
+ while(*pos != '\0') {
+ if (matched == FALSE) {
+ if (g_ascii_strncasecmp(pos, "\r\n", 2) == 0) {
+ gint attrlen = 0;
+
+ st_pos = pos;
+ pos += 2;
+
+ attrlen = strlen(property_name);
+ if (g_ascii_strncasecmp(pos, property_name, attrlen) == 0) {
+ pos += attrlen;
+
+ if (*pos == ':' || *pos == ';') {
+ matched = TRUE;
+ pos++;
+ }
+ }
+ continue;
+ }
+ }
+ else {
+ if (g_ascii_strncasecmp(pos, "\r\n", 2) == 0) {
+ pos += 2;
+
+ if (*pos != ' ' && *pos != '\t') {
+ /* +2 means move over \r\n */
+ g_string_erase(string, (st_pos+2)-(string->str), pos-(st_pos +2));
+ pos = st_pos;
+ matched = FALSE;
+ }
+ continue;
+ }
+ }
+
+ pos++;
+ }
+}
+
+static gchar *__bluetooth_pb_vcard_filter_v30(const gchar *vcard,
+ guint64 filter)
+{
+ GString *string = NULL;
+
+ if (vcard == NULL)
+ return NULL;
+
+ string = g_string_new(vcard);
+
+ if ((filter & VCARD_PHOTO) == 0)
+ __bluetooth_pb_vcard_remove_v30(string, "PHOTO");
+
+ if ((filter & VCARD_BDAY) == 0)
+ __bluetooth_pb_vcard_remove_v30(string, "BDAY");
+
+ if ((filter & VCARD_ADR) == 0 )
+ __bluetooth_pb_vcard_remove_v30(string, "ADR");
+
+ if ((filter & VCARD_EMAIL) == 0 )
+ __bluetooth_pb_vcard_remove_v30(string, "EMAIL");
+
+ if ((filter & VCARD_TITLE) == 0 )
+ __bluetooth_pb_vcard_remove_v30(string, "TITLE");
+
+ if ((filter & VCARD_ROLE) == 0 )
+ __bluetooth_pb_vcard_remove_v30(string, "ROLE");
+
+ if ((filter & VCARD_ORG) == 0 )
+ __bluetooth_pb_vcard_remove_v30(string, "ORG");
+
+ if ((filter & VCARD_NOTE) == 0 )
+ __bluetooth_pb_vcard_remove_v30(string, "NOTE");
+
+ if ((filter & VCARD_REV) == 0 )
+ __bluetooth_pb_vcard_remove_v30(string, "REV");
+
+ if ((filter & VCARD_URL) == 0 )
+ __bluetooth_pb_vcard_remove_v30(string, "URL");
+
+ if ((filter & VCARD_UID) == 0 )
+ __bluetooth_pb_vcard_remove_v30(string, "UID");
+
+ if ((filter & VCARD_NICKNAME) == 0 )
+ __bluetooth_pb_vcard_remove_v30(string, "NICKNAME");
+
+ return g_string_free(string, FALSE);
+}
+
+static gchar *__bluetooth_pb_vcard_real_contact_valist_v21(gint person_id,
+ gint phonelog_id,
+ guint64 filter,
+ const gchar *first_name,
+ va_list args)
+{
+ contacts_record_h person = NULL;
+ contacts_record_h contact = NULL;
+
+ GString *str = NULL;
+
+ gint contact_id = 0;
+ gint status;
+
+ guint64 f = filter;
+
+ const gchar *name = first_name;
+
+ status = contacts_db_get_record(_contacts_person._uri,
+ person_id,
+ &person);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ status = contacts_record_get_int(person,
+ _contacts_person.display_contact_id,
+ &contact_id);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ status = contacts_db_get_record(_contacts_contact._uri,
+ contact_id,
+ &contact);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_record_destroy(person, TRUE);
+ return NULL;;
+ }
+
+ if (f == 0)
+ f = ~f;
+
+ str = g_string_new("BEGIN:VCARD\r\nVERSION:2.1\r\n");
+
+ /* N, TEL is default */
+ __bluetooth_pb_vcard_append_n_v21(str, contact);
+
+ if (phonelog_id > 0) {
+ gchar *number;
+
+ number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
+ __bluetooth_pb_vcard_append_qp_encode_v21(str, "TEL", "X-0", number);
+ g_free(number);
+
+
+ } else {
+ __bluetooth_pb_vcard_append_tel_v21(str, contact);
+ }
+
+ if (f & VCARD_FN)
+ __bluetooth_pb_vcard_append_fn_v21(str, person);
+ if (f & VCARD_PHOTO)
+ __bluetooth_pb_vcard_append_photo_v21(str, person);
+ if (f & VCARD_BDAY)
+ __bluetooth_pb_vcard_append_bday_v21(str, contact);
+ if (f & VCARD_ADR)
+ __bluetooth_pb_vcard_append_adr_v21(str, contact);
+ if (f & VCARD_EMAIL)
+ __bluetooth_pb_vcard_append_email_v21(str, contact);
+ if (f & VCARD_TITLE)
+ __bluetooth_pb_vcard_append_title_v21(str, contact);
+ if (f & VCARD_ROLE)
+ __bluetooth_pb_vcard_append_role_v21(str, contact);
+ if (f & VCARD_ORG)
+ __bluetooth_pb_vcard_append_org_v21(str, contact);
+ if (f & VCARD_NOTE)
+ __bluetooth_pb_vcard_append_note_v21(str, contact);
+ if (f & VCARD_REV)
+ __bluetooth_pb_vcard_append_rev_v21(str, contact);
+ if (f & VCARD_URL)
+ __bluetooth_pb_vcard_append_url_v21(str, contact);
+ if (f & VCARD_UID)
+ __bluetooth_pb_vcard_append_uid_v21(str, contact);
+
+ while (name) {
+ const gchar *param = va_arg(args, const gchar *);
+ const gchar *value = va_arg(args, const gchar *);
+
+ if (value) {
+ gchar *escaped = NULL;
+
+ escaped = __bluetooth_pb_vcard_escape(value);
+ __bluetooth_pb_vcard_append_qp_encode_v21(str, name, param, escaped);
+
+ g_free(escaped);
+ }
+
+ name = va_arg(args, const gchar *);
+ }
+
+ g_string_append(str, "END:VCARD\r\n");
+
+ contacts_record_destroy(contact, TRUE);
+ contacts_record_destroy(person, TRUE);
+
+ return g_string_free(str, FALSE);
+}
+
+
+static gchar *__bluetooth_pb_vcard_real_contact_valist_v30(gint person_id,
+ gint phonelog_id,
+ guint64 filter,
+ const gchar *first_name,
+ va_list args)
+{
+ contacts_record_h person = NULL;
+
+ GString *str = NULL;
+
+ gint status;
+
+ const gchar *name = first_name;
+ gchar *vcard = NULL;
+
+ status = contacts_db_get_record(_contacts_person._uri,
+ person_id,
+ &person);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ status = contacts_vcard_make_from_person(person, &vcard);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ status = contacts_record_destroy(person, TRUE);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ str = g_string_new(vcard);
+ g_free(vcard);
+
+ /* append contents on vcard */
+ while (name) {
+ const gchar *param = va_arg(args, const gchar *);
+ const gchar *value = va_arg(args, const gchar *);
+
+ __bluetooth_pb_vcard_append_v30(str, name, param, value);
+
+ name = va_arg(args, const gchar *);
+ }
+
+ /* if phonelog_id exist,
+ we shall show only the phone number, which was used for that phone log */
+ if (phonelog_id > 0) {
+ gchar *number;
+
+ __bluetooth_pb_vcard_remove_v30(str, "TEL");
+
+ number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
+ __bluetooth_pb_vcard_append_v30(str, "TEL", NULL, number);
+ g_free(number);
+ }
+
+ vcard = g_string_free(str, FALSE);
+
+ /* temporary fixed for some application crash */
+ if (filter == 0)
+ filter = ~VCARD_NOTE;
+
+ if (filter) {
+ gchar *new_vcard = NULL;
+
+ new_vcard = __bluetooth_pb_vcard_filter_v30(vcard, filter);
+
+ if (new_vcard) {
+ g_free(vcard);
+ vcard = new_vcard;
+ }
+ }
+
+ return vcard;
+}
+
+
+static gchar *__bluetooth_pb_vcard_real_contact_with_properties(gint person_id,
+ gint phonelog_id,
+ guint64 filter,
+ guint8 format,
+ const gchar *first_name,
+ ...)
+{
+ DBG("\n");
+ gchar *vcard = NULL;
+ va_list args;
+
+ va_start(args, first_name);
+
+ switch(format) {
+ case VCARD_FORMAT_3_0:
+ vcard = __bluetooth_pb_vcard_real_contact_valist_v30(person_id,
+ phonelog_id, filter,
+ first_name, args);
+ break;
+ case VCARD_FORMAT_2_1:
+ default:
+ vcard = __bluetooth_pb_vcard_real_contact_valist_v21(person_id,
+ phonelog_id, filter,
+ first_name, args);
+ break;
+ }
+
+ va_end(args);
+
+ return vcard;
+}
+
+static gchar *__bluetooth_pb_vcard_real_call_v21(gint phonelog_id,
+ guint filter,
+ const char *attr)
+{
+ GString *str;
+ gchar *number;
+
+ str = g_string_new("BEGIN:VCARD\r\nVERSION:2.1\r\n");
+
+ __bluetooth_pb_vcard_append_qp_encode_v21(str, "N", NULL, NULL);
+
+ number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
+ __bluetooth_pb_vcard_append_qp_encode_v21(str, "TEL", "X-0", number);
+ g_free(number);
+
+ if (((filter == 0) || (filter & VCARD_X_IRMC_CALL_DATETIME))
+ && attr) {
+ gchar *datetime = NULL;
+
+ datetime = __bluetooth_pb_phonelog_datetime(phonelog_id);
+ __bluetooth_pb_vcard_append_qp_encode_v21(str, "X-IRMC-CALL-DATETIME",
+ attr, datetime);
+ g_free(datetime);
+ }
+
+ g_string_append(str, "END:VCARD\r\n");
+
+ return g_string_free(str, FALSE);
+}
+
+static gchar *__bluetooth_pb_vcard_real_call_v30(gint phonelog_id,
+ guint filter,
+ const gchar *attr)
+{
+ GString *str;
+ gchar *number;
+
+ str = g_string_new("BEGIN:VCARD\r\nVERSION:3.0\r\n");
+
+ __bluetooth_pb_vcard_append_v30(str, "N", NULL, NULL);
+ __bluetooth_pb_vcard_append_v30(str, "FN", NULL, NULL);
+
+ number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
+ __bluetooth_pb_vcard_append_v30(str, "TEL", NULL, number);
+ g_free(number);
+
+ if (((filter == 0) || (filter & VCARD_X_IRMC_CALL_DATETIME))
+ && attr) {
+ gchar *datetime = NULL;
+
+ datetime = __bluetooth_pb_phonelog_datetime(phonelog_id);
+ __bluetooth_pb_vcard_append_v30(str,
+ "X-IRMC-CALL-DATETIME", attr, datetime);
+ g_free(datetime);
+ }
+
+ g_string_append(str, "END:VCARD\r\n");
+
+ return g_string_free(str, FALSE);
+}
+
+static gchar *__bluetooth_pb_vcard_real_call(gint phonelog_id,
+ guint filter,
+ guint8 format,
+ const gchar *attr)
+{
+ DBG("\n");
+ gchar *vcard = NULL;
+
+ switch(format) {
+ case VCARD_FORMAT_3_0:
+ vcard = __bluetooth_pb_vcard_real_call_v30(phonelog_id,
+ filter, attr);
+ break;
+ case VCARD_FORMAT_2_1:
+ default:
+ vcard = __bluetooth_pb_vcard_real_call_v21(phonelog_id,
+ filter, attr);
+ break;
+ }
+
+ return vcard;
+}
+
+static gchar **__bluetooth_pb_contact_add_field_str(contacts_record_h record,
+ int *field,
+ gint field_size)
+{
+ gchar **strv;
+
+ gint status;
+ gint i;
+
+ gboolean valid = FALSE;
+
+ /* check empty field */
+ for (i = 0; i < field_size; i++) {
+ gchar *tmp = NULL;
+
+ status = contacts_record_get_str_p(record, field[i], &tmp);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ if (tmp) {
+ valid = TRUE;
+ break;
+ }
+ }
+
+ if (valid == FALSE)
+ return NULL;
+
+ strv = g_new0(gchar *, field_size + 1);
+
+ for (i = 0; i < field_size; i++) {
+ gchar *tmp;
+
+ status = contacts_record_get_str_p(record, field[i], &tmp);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ if (tmp == NULL)
+ strv[i] = g_strdup("");
+ else
+ strv[i] = __bluetooth_pb_vcard_escape(tmp);
+ }
+
+ return strv;
+}
+
+static gchar **__bluetooth_pb_contact_tel_param(contacts_record_h number)
+{
+ gchar **strv = NULL;
+
+ const gint TEL_PARAM_LEN = 13;
+
+ gint status;
+ gint i = 0;
+
+ contacts_number_type_e type;
+
+ bool is_default = false;
+
+ strv = g_new0(char *, TEL_PARAM_LEN + 1); /* tel param max size is 13 */
+
+ status = contacts_record_get_bool(number, _contacts_number.is_default,
+ &is_default);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ if (is_default) {
+ strv[i] = g_strdup("PREF");
+ i++;
+ }
+
+ status = contacts_record_get_int(number,
+ _contacts_number.type,
+ (gint *)&type);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ if (type & CONTACTS_NUMBER_TYPE_HOME) {
+ strv[i] = g_strdup("HOME");
+ i++;
+ }
+
+ if (type & CONTACTS_NUMBER_TYPE_WORK) {
+ strv[i] = g_strdup("WORK");
+ i++;
+ }
+
+ if (type & CONTACTS_NUMBER_TYPE_VOICE) {
+ strv[i] = g_strdup("VOICE");
+ i++;
+ }
+
+ if (type & CONTACTS_NUMBER_TYPE_FAX) {
+ strv[i] = g_strdup("FAX");
+ i++;
+ }
+
+ if (type & CONTACTS_NUMBER_TYPE_MSG) {
+ strv[i] = g_strdup("MSG");
+ i++;
+ }
+
+ if (type & CONTACTS_NUMBER_TYPE_CELL) {
+ strv[i] = g_strdup("CELL");
+ i++;
+ }
+
+ if (type & CONTACTS_NUMBER_TYPE_PAGER) {
+ strv[i] = g_strdup("PAGER");
+ i++;
+ }
+
+ if (type & CONTACTS_NUMBER_TYPE_BBS) {
+ strv[i] = g_strdup("BBS");
+ i++;
+ }
+
+ if (type & CONTACTS_NUMBER_TYPE_MODEM) {
+ strv[i] = g_strdup("MODEM");
+ i++;
+ }
+
+ if (type & CONTACTS_NUMBER_TYPE_CAR) {
+ strv[i] = g_strdup("CAR");
+ i++;
+ }
+
+ if (type & CONTACTS_NUMBER_TYPE_ISDN) {
+ strv[i] = g_strdup("ISDN");
+ i++;
+ }
+
+ if (type & CONTACTS_NUMBER_TYPE_VIDEO) {
+ strv[i] = g_strdup("VIDEO");
+ i++;
+ }
+
+ /* CTS_NUM_TYPE_PCS is not part of vcard2.1 */
+ return strv;
+}
+
+
+static gchar *__bluetooth_pb_contact_photo_type(const gchar *filename)
+{
+ gchar *filetype = NULL;
+ gchar *ext = NULL;
+
+ if (g_file_test(filename, G_FILE_TEST_IS_REGULAR) == FALSE) {
+ ERR("file does not regular:%s\n", filename);
+ return NULL;
+ }
+
+ ext = strrchr(filename, '.');
+ if (ext == NULL) {
+ ERR("file doesn't have extension\n");
+ return NULL;
+ }
+
+ ext++;
+
+ if (g_ascii_strcasecmp(ext, "gif") == 0)
+ filetype = "GIF";
+ else if (g_ascii_strcasecmp(ext, "cgm") == 0)
+ filetype = "CGM";
+ else if (g_ascii_strcasecmp(ext, "wmf") == 0)
+ filetype = "WMF";
+ else if (g_ascii_strcasecmp(ext, "bmp") == 0)
+ filetype = "BMP";
+ else if (g_ascii_strcasecmp(ext, "met") == 0)
+ filetype = "MET";
+ else if (g_ascii_strcasecmp(ext, "dib") == 0)
+ filetype = "DIB";
+ else if (g_ascii_strcasecmp(ext, "pict") == 0 || g_ascii_strcasecmp(ext, "pct") == 0 ||
+ g_ascii_strcasecmp(ext, "pic") == 0)
+ filetype = "PICT";
+ else if (g_ascii_strcasecmp(ext, "tiff") == 0 || g_ascii_strcasecmp(ext, "tif") == 0)
+ filetype = "TIFF";
+ else if (g_ascii_strcasecmp(ext, "ps") == 0)
+ filetype = "PS";
+ else if (g_ascii_strcasecmp(ext, "pdf") == 0)
+ filetype = "PDF";
+ else if (g_ascii_strcasecmp(ext, "jpeg") == 0 || g_ascii_strcasecmp(ext, "jpg") == 0 ||
+ g_ascii_strcasecmp(ext, "jpe") == 0)
+ filetype = "JPEG";
+ else if (g_ascii_strcasecmp(ext, "mpeg") == 0 || g_ascii_strcasecmp(ext, "mpg") == 0)
+ filetype = "MPEG";
+ else if (g_ascii_strcasecmp(ext, "m2v") == 0)
+ filetype = "MPEG2";
+ else if (g_ascii_strcasecmp(ext, "avi") == 0)
+ filetype = "AVI";
+ else if (g_ascii_strcasecmp(ext, "mov") == 0)
+ filetype = "QTIME";
+ else if (g_ascii_strcasecmp(ext, "png") == 0)
+ filetype = "PNG";
+
+ return g_strdup(filetype);
+}
+
+static gchar **__bluetooth_pb_contact_addr(contacts_record_h address)
+{
+ const gint ADDR_LEN = 7;
+
+ gchar **strv = NULL;
+
+ gint addr[] = { _contacts_address.postbox,
+ _contacts_address.extended,
+ _contacts_address.street,
+ _contacts_address.locality,
+ _contacts_address.region,
+ _contacts_address.postal_code,
+ _contacts_address.country };
+
+ strv = __bluetooth_pb_contact_add_field_str(address,
+ addr, ADDR_LEN);
+ return strv;
+}
+
+static gchar **__bluetooth_pb_contact_addr_param(contacts_record_h address)
+{
+
+ contacts_address_type_e type;
+
+ gint status;
+ gint i = 0;
+
+ gchar **strv = NULL;
+
+ strv = g_new0(gchar *, 7); /* ADDR param max size is 6 */
+
+ status = contacts_record_get_int(address,
+ _contacts_address.type,
+ (gint *)&type);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ if (type & CONTACTS_ADDRESS_TYPE_HOME) {
+ strv[i] = g_strdup("HOME");
+ i++;
+ }
+ if (type & CONTACTS_ADDRESS_TYPE_WORK) {
+ strv[i] = g_strdup("WORK");
+ i++;
+ }
+ if (type & CONTACTS_ADDRESS_TYPE_DOM) {
+ strv[i] = g_strdup("DOM");
+ i++;
+ }
+ if (type & CONTACTS_ADDRESS_TYPE_INTL) {
+ strv[i] = g_strdup("INTL");
+ i++;
+ }
+ if (type & CONTACTS_ADDRESS_TYPE_POSTAL) {
+ strv[i] = g_strdup("POSTAL");
+ i++;
+ }
+ if (type & CONTACTS_ADDRESS_TYPE_PARCEL) {
+ strv[i] = g_strdup("PARCEL");
+ i++;
+ }
+ return strv;
+}
+
+static gchar *__bluetooth_pb_phonelog_datetime(gint phonelog_id)
+{
+ contacts_record_h phone_log;
+
+ char time_str[32] = {0,};
+
+ gint status;
+ gint time = 0;
+
+ struct tm time_info;
+
+ status = contacts_db_get_record(_contacts_phone_log._uri,
+ phonelog_id,
+ &phone_log);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ status = contacts_record_get_int(phone_log,
+ _contacts_phone_log.log_time,
+ &time);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ if (time <= 0)
+ return NULL;
+
+ localtime_r((time_t *)&time, &time_info);
+
+ strftime(time_str, sizeof(time_str),
+ "%Y%m%dT%H%M%S", &time_info);
+
+ contacts_record_destroy(phone_log, TRUE);
+
+ return g_strdup(time_str);
+}
+
+static gchar *__bluetooth_pb_name_from_contact(contacts_record_h contact)
+{
+ contacts_record_h name = NULL;
+
+ GString *str = g_string_new(NULL);
+
+ gint status;
+ gint i;
+
+ gint name_size = 5;
+ gint name_val[] = { _contacts_name.last,
+ _contacts_name.first,
+ _contacts_name.addition,
+ _contacts_name.prefix,
+ _contacts_name.suffix };
+
+
+ status = contacts_record_get_child_record_at_p(contact,
+ _contacts_contact.name, 0, &name);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ for (i = 0; i < name_size; i++) {
+ gchar *tmp = NULL;
+ gchar *escape = NULL;
+
+ if (i > 0)
+ g_string_append_c(str, ';');
+
+ status = contacts_record_get_str_p(name, name_val[i], &tmp);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ escape = __bluetooth_pb_vcard_escape(tmp);
+ g_string_append(str, escape);
+
+ g_free(escape);
+ }
+
+ return g_string_free(str, FALSE);
+}
+
+static gchar *__bluetooth_pb_number_from_contact(contacts_record_h contact)
+{
+ guint count = 0;
+
+ gint status;
+ gint i;
+
+ gchar *str = NULL;
+
+ status = contacts_record_get_child_record_count(contact,
+ _contacts_contact.number,
+ &count);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ for (i = 0; i < count; i++) {
+ contacts_record_h number = NULL;
+
+ gchar *tmp = NULL;
+
+ bool is_default = false;
+
+ status = contacts_record_get_child_record_at_p(contact,
+ _contacts_contact.number, i, &number);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ status = contacts_record_get_bool(number,
+ _contacts_number.is_default,
+ &is_default);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ if (is_default == FALSE)
+ continue;
+
+ status = contacts_record_get_str_p(number,
+ _contacts_number.number,
+ &tmp);
+
+ if (status != CONTACTS_ERROR_NONE)
+ continue;
+
+ if (tmp) {
+ str = g_strdup(tmp);
+ break;
+ }
+ }
+
+ /* get first number */
+ if (str == NULL) {
+ gchar *tmp = NULL;
+
+ contacts_record_h number = NULL;
+
+ status = contacts_record_get_child_record_at_p(contact,
+ _contacts_contact.number, 0, &number);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ status = contacts_record_get_str_p(number,
+ _contacts_number.number,
+ &tmp);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ str = g_strdup(tmp);
+ }
+
+ return str;
+}
+
+static gint __bluetooth_pb_person_id_from_phonelog_id(gint phonelog_id)
+{
+ contacts_query_h query = NULL;
+ contacts_filter_h filter = NULL;
+ contacts_list_h record_list = NULL;
+
+ contacts_record_h phone_log = NULL;
+ contacts_record_h record = NULL;
+
+ gint status;
+ gint person_id = 0;
+
+ status = contacts_db_get_record(_contacts_phone_log._uri,
+ phonelog_id,
+ &phone_log);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return 0;
+
+ status = contacts_record_get_int(phone_log,
+ _contacts_phone_log.person_id,
+ &person_id);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_record_destroy(phone_log, TRUE);
+ return 0;
+ }
+
+ contacts_record_destroy(phone_log, TRUE);
+
+ if (person_id)
+ return person_id;
+
+ status = contacts_filter_create(_contacts_person_phone_log._uri,
+ &filter);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return 0;
+
+
+ status = contacts_filter_add_int(filter,
+ _contacts_person_phone_log.log_id,
+ CONTACTS_MATCH_EQUAL,
+ phonelog_id);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_filter_destroy(filter);
+ return 0;
+ }
+
+ status = contacts_query_create(_contacts_person_phone_log._uri, &query);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_filter_destroy(filter);
+ return 0;
+ }
+
+ status = contacts_query_set_filter(query, filter);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_filter_destroy(filter);
+ contacts_query_destroy(query);
+ return 0;
+ }
+
+ status = contacts_db_get_records_with_query(query, -1, -1, &record_list);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_filter_destroy(filter);
+ contacts_query_destroy(query);
+
+ return 0;
+ }
+
+ status = contacts_list_first(record_list);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_list_destroy(record_list, TRUE);
+ contacts_filter_destroy(filter);
+ contacts_query_destroy(query);
+
+ return 0;
+ }
+
+ status = contacts_list_get_current_record_p(record_list, &record);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_list_destroy(record_list, TRUE);
+ contacts_filter_destroy(filter);
+ contacts_query_destroy(query);
+
+ return 0;
+ }
+
+ status = contacts_record_get_int(record,
+ _contacts_person_phone_log.person_id,
+ &person_id);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_list_destroy(record_list, TRUE);
+ contacts_filter_destroy(filter);
+ contacts_query_destroy(query);
+
+ return 0;
+ }
+
+ contacts_list_destroy(record_list, TRUE);
+ contacts_filter_destroy(filter);
+ contacts_query_destroy(query);
+
+ return person_id;
+}
+
+/* API for vcard */
+gchar *_bluetooth_pb_vcard_contact(gint person_id,
+ guint64 filter,
+ guint8 format)
+{
+ gchar *str = NULL;
+
+ if (person_id <= 0)
+ return NULL;
+
+ str = __bluetooth_pb_vcard_real_contact_with_properties(person_id, 0,
+ filter, format,
+ NULL);
+ return str;
+}
+
+gchar *_bluetooth_pb_vcard_contact_owner(const gchar *number,
+ guint64 filter,
+ guint8 format)
+{
+ GString *str = g_string_new("BEGIN:VCARD\r\n");
+ gchar *fn;
+ gchar *name;
+
+ fn = _bluetooth_pb_owner_name();
+ name = g_strdup_printf("%s;;;;", fn);
+
+ switch (format) {
+ case VCARD_FORMAT_3_0:
+ g_string_append(str, "VERSION:3.0\r\n");
+
+ __bluetooth_pb_vcard_append_v30(str, "N", NULL, name);
+ __bluetooth_pb_vcard_append_v30(str, "FN", NULL, fn);
+ __bluetooth_pb_vcard_append_v30(str, "TEL", "TYPE=CELL", number);
+ break;
+ case VCARD_FORMAT_2_1:
+ default :
+ g_string_append(str, "VERSION:2.1\r\n");
+
+ __bluetooth_pb_vcard_append_qp_encode_v21(str, "N", NULL, name);
+
+ if (filter == 0 || (filter & VCARD_FN))
+ __bluetooth_pb_vcard_append_qp_encode_v21(str, "FN", NULL, fn);
+
+ __bluetooth_pb_vcard_append_qp_encode_v21(str, "TEL", "CELL", number);
+ break;
+
+ }
+
+ g_string_append(str, "END:VCARD\r\n");
+
+ g_free(fn);
+ g_free(name);
+
+ return g_string_free(str, FALSE);
+}
+
+gchar *_bluetooth_pb_vcard_call(gint phonelog_id,
+ guint64 filter,
+ guint8 format,
+ const gchar *attr)
+{
+ gint person_id = 0;
+
+ gchar *str = NULL;
+
+ if (attr == NULL) {
+ DBG("Unknown attribute type ignored\n");
+ return NULL;
+ }
+
+ person_id = __bluetooth_pb_person_id_from_phonelog_id(phonelog_id);
+
+ DBG("person_id %d\n", person_id);
+
+ if (person_id) {
+ if (filter == 0 || (filter & VCARD_X_IRMC_CALL_DATETIME)) {
+ gchar *datetime = NULL;
+
+ datetime = __bluetooth_pb_phonelog_datetime(phonelog_id);
+
+ str = __bluetooth_pb_vcard_real_contact_with_properties(person_id,
+ phonelog_id,
+ filter, format,
+ "X-IRMC-CALL-DATETIME", attr, datetime,
+ NULL);
+
+ if(datetime)
+ g_free(datetime);
+ }
+ else {
+ str = __bluetooth_pb_vcard_real_contact_with_properties(person_id,
+ phonelog_id,
+ filter, format,
+ NULL);
+ }
+ }
+ else
+ str = __bluetooth_pb_vcard_real_call(phonelog_id, filter, format, attr);
+
+ return str;
+}
+
+gchar *_bluetooth_pb_fn_from_person_id(gint person_id)
+{
+ contacts_record_h person = NULL;
+
+ gint status;
+
+ gchar *str = NULL;
+
+ status = contacts_db_get_record(_contacts_person._uri,
+ person_id,
+ &person);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ status = contacts_record_get_str(person,
+ _contacts_person.display_name,
+ &str);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ contacts_record_destroy(person, TRUE);
+
+ return str;
+}
+
+gchar *_bluetooth_pb_name_from_person_id(gint person_id)
+{
+ contacts_record_h person = NULL;
+ contacts_record_h contact = NULL;
+
+ gint status;
+ gint contact_id = 0;
+
+ gchar *str;
+
+ status = contacts_db_get_record(_contacts_person._uri,
+ person_id,
+ &person);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ status = contacts_record_get_int(person,
+ _contacts_person.display_contact_id,
+ &contact_id);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_record_destroy(person, TRUE);
+ return NULL;
+ }
+
+ contacts_db_get_record(_contacts_contact._uri,
+ contact_id,
+ &contact);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_record_destroy(person, TRUE);
+ return NULL;
+ }
+
+ str = __bluetooth_pb_name_from_contact(contact);
+
+ contacts_record_destroy(contact, TRUE);
+ contacts_record_destroy(person, TRUE);
+
+ return str;
+}
+
+gchar *_bluetooth_pb_number_from_person_id(gint person_id)
+{
+ contacts_record_h person = NULL;
+ contacts_record_h contact = NULL;
+
+ gint status;
+ gint contact_id = 0;
+
+ gchar *str;
+
+ status = contacts_db_get_record(_contacts_person._uri,
+ person_id,
+ &person);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+
+ status = contacts_record_get_int(person,
+ _contacts_person.display_contact_id,
+ &contact_id);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_record_destroy(person, TRUE);
+ return NULL;
+ }
+
+ status = contacts_db_get_record(_contacts_contact._uri,
+ contact_id,
+ &contact);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_record_destroy(person, TRUE);
+ return NULL;
+ }
+
+ str = __bluetooth_pb_number_from_contact(contact);
+
+ contacts_record_destroy(contact, TRUE);
+ contacts_record_destroy(person, TRUE);
+
+ return str;
+}
+
+gchar *_bluetooth_pb_fn_from_phonelog_id(gint phonelog_id)
+{
+ gint person_id = 0;
+ gchar *str = NULL;
+
+ person_id = __bluetooth_pb_person_id_from_phonelog_id(phonelog_id);
+
+ if (person_id > 0)
+ str = _bluetooth_pb_fn_from_person_id(person_id);
+ else
+ str = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
+
+ return str;
+}
+
+gchar *_bluetooth_pb_name_from_phonelog_id(gint phonelog_id)
+{
+ gint person_id = 0;
+ gchar *str = NULL;
+
+ person_id = __bluetooth_pb_person_id_from_phonelog_id(phonelog_id);
+
+ if (person_id > 0)
+ str = _bluetooth_pb_name_from_person_id(person_id);
+ else {
+ gchar *tmp;
+
+ tmp = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
+ str = g_strdup_printf("%s;;;;", tmp);
+
+ g_free(tmp);
+ }
+
+ return str;
+}
+
+gchar *_bluetooth_pb_number_from_phonelog_id(gint phonelog_id)
+{
+ contacts_record_h phone_log;
+
+ gint status;
+
+ gchar *str;
+ gchar *tmp = NULL;
+
+ status = contacts_db_get_record(_contacts_phone_log._uri,
+ phonelog_id, &phone_log);
+
+ if (status != CONTACTS_ERROR_NONE)
+ return NULL;
+
+ contacts_record_get_str_p(phone_log,
+ _contacts_phone_log.address,
+ &tmp);
+
+ if (status != CONTACTS_ERROR_NONE) {
+ contacts_record_destroy(phone_log, TRUE);
+ return NULL;
+ }
+
+ str = g_strdup(tmp);
+
+ contacts_record_destroy(phone_log, TRUE);
+
+ return str;
+}
+
+gchar *_bluetooth_pb_owner_name(void)
+{
+ gchar *name;
+
+ name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
+
+ if (name == NULL)
+ name = g_strdup("My Name");
+
+ return name;
+}
--- /dev/null
+/*
+ * bluetooth-agent
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DEF_BT_PB_VCARD_H_
+#define __DEF_BT_PB_VCARD_H_
+
+#include <glib.h>
+
+/* vcard */
+gchar *_bluetooth_pb_vcard_contact(gint person_id,
+ guint64 filter,
+ guint8 format);
+
+gchar *_bluetooth_pb_vcard_contact_owner(const gchar *number,
+ guint64 filter,
+ guint8 format);
+
+gchar *_bluetooth_pb_vcard_call(gint phonelog_id,
+ guint64 filter,
+ guint8 format,
+ const gchar *attr);
+
+gchar *_bluetooth_pb_fn_from_person_id(gint person_id);
+
+gchar *_bluetooth_pb_name_from_person_id(gint person_id);
+
+gchar *_bluetooth_pb_number_from_person_id(gint person_id);
+
+gchar *_bluetooth_pb_fn_from_phonelog_id(gint phonelog_id);
+
+gchar *_bluetooth_pb_name_from_phonelog_id(gint phonelog_id);
+
+gchar *_bluetooth_pb_number_from_phonelog_id(gint phonelog_id);
+
+gchar *_bluetooth_pb_owner_name(void);
+
+#endif
--- /dev/null
+[D-BUS Service]
+Name=org.bluez.pb_agent
+Exec=/usr/bin/bluetooth-pb-agent
+User=root