--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+PROJECT(data-control C)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+
+INCLUDE_DIRECTORIES (
+ include
+ )
+
+SET(requires "dlog bundle glib-2.0 appsvc pkgmgr-info capi-base-common")
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs REQUIRED ${requires})
+
+FOREACH(flag ${pkgs_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -fPIC -Werror -fvisibility=hidden")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+
+ADD_LIBRARY (${PROJECT_NAME} SHARED
+ src/data-control-map.c
+ src/data-control-sql.c
+ src/data-control-sql-cursor.c
+ src/data-control-provider.c
+ src/data-control-internal.c
+ src/data_control_internal.c
+ src/data_control_map.c
+ src/data_control_sql.c
+ src/data_control_sql_cursor.c
+ src/data_control_provider.c
+ )
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS})
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME}
+ PROPERTIES
+ VERSION ${FULLVER}
+ SOVERSION ${MAJORVER}
+ CLEAN_DIRECT_OUTPUT 1
+ )
+
+SET(VERSION ${FULLVER})
+CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}.pc @ONLY)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+CONFIGURE_FILE(capi-${PROJECT_NAME}.pc.in ${CMAKE_SOURCE_DIR}/capi-${PROJECT_NAME}.pc @ONLY)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/capi-${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION include/appfw FILES_MATCHING PATTERN "*.h")
--- /dev/null
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
--- /dev/null
+
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=/usr
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDE_INSTALL_DIR@/appfw
+
+Name: capi-data-control
+Description: Data Control managed library
+Version: @VERSION@
+Requires: capi-base-common
+Libs: -L${libdir} -ldata-control
+Cflags: -I${includedir}
+
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
--- /dev/null
+
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=/usr
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDE_INSTALL_DIR@/appfw
+
+Name: data-control
+Description: Data Control managed library
+Version: @VERSION@
+Requires: capi-base-common
+Libs: -L${libdir} -ldata-control
+Cflags: -I${includedir}
+
--- /dev/null
+//
+// Copyright (c) 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.
+//
+
+/**
+ * @file data-control-map.h
+ * @brief This is the header file for the key-value structured data control.
+ */
+
+#ifndef _APPFW_DATA_CONTROL_MAP_H_
+#define _APPFW_DATA_CONTROL_MAP_H_
+
+#include <data-control-types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief Called when the result value list is received from the key-value structured data control provider.
+ *
+ * @param [in] request_id The request ID
+ * @param [in] provider The provider handle
+ * @param [in] result_value_list The result value list of the data control request that gets the matching values
+ * @param [in] result_value_count The number of the values
+ * @param [in] provider_result Set to true if the data control provider successfully processed. @n
+ * false otherwise.
+ * @param [in] error The error message from the data control provider
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_map_get_response_cb)(int request_id, datacontrol_h provider,
+ char ** result_value_list, int result_value_count, bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief Called when the response is received from the key-value structured data control provider.
+ *
+ * @param [in] request_id The request ID that identifies the data control
+ * @param [in] provider The provider handle
+ * @param [in] provider_result Set to true if the data control provider successfully processed. @n
+ * false otherwise.
+ * @param [in] error The error message from the data control provider
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_map_set_response_cb)(int request_id, datacontrol_h provider,
+ bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief Called when the response is received from the key-value structured data control provider.
+ *
+ * @param [in] request_id The request ID that identifies the data control
+ * @param [in] provider The provider handle
+ * @param [in] provider_result Set to true if the data control provider successfully processed. @n
+ * false otherwise.
+ * @param [in] error The error message from the data control provider
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_map_add_response_cb)(int request_id, datacontrol_h provider,
+ bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief Called when the response is received from the key-value structured data control provider.
+ *
+ * @param [in] request_id The request ID that identifies the data control
+ * @param [in] provider The provider handle
+ * @param [in] provider_result Set to true if the data control provider successfully processed. @n
+ * false otherwise.
+ * @param [in] error The error message from the data control provider
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_map_remove_response_cb)(int request_id, datacontrol_h provider,
+ bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief The structure type to contain the set of callback functions for handling the response events
+ * of the key-value structured data control.
+ * @see datacontrol_map_get_response_cb()
+ * @see datacontrol_map_set_response_cb()
+ * @see datacontrol_map_add_response_cb()
+ * @see datacontrol_map_remove_response_cb()
+ */
+typedef struct
+{
+ datacontrol_map_get_response_cb get;
+ datacontrol_map_set_response_cb set;
+ datacontrol_map_add_response_cb add;
+ datacontrol_map_remove_response_cb remove;
+} datacontrol_map_response_cb;
+
+/**
+ * @brief Creates a provider handle.
+ * @param [out] provider The provider handle
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_map_destroy()
+ *
+ * The following example demonstrates how to use the %datacontrol_map_create() method.
+ *
+ * @code
+ *
+ * int main()
+ * {
+ * const char *provider_id = "http://tizen.org/datacontrol/provider/example";
+ * const char *data_id = "table";
+ * datacontrol_h provider;
+ * int result = 0;
+ *
+ * result = datacontrol_map_create(&provider);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Creating data control provider is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = datacontrol_map_set_provider_id(provider, provider_id);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Setting providerID is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = datacontrol_map_set_data_id(provider, data_id);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Setting dataID is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * // Executes some operations
+ *
+ * result = datacontrol_map_destroy(provider);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Destorying data control provider is failed with error: %d", result);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_map_create(datacontrol_h *provider);
+
+/**
+ * @brief Destroys the provider handle and releases all its resources.
+ * @param [in] provider The provider handle
+ * @return 0 on success, otherwise a negative error value.
+ * @remark When operations of data control are finished, this function must be called to prevent memory leak.
+ * @see datacontrol_map_create()
+ */
+EXPORT_API int datacontrol_map_destroy(datacontrol_h provider);
+
+/**
+ * @brief Sets the Provider ID.
+ * @param [in] provider The provider handle
+ * @param [in] provider_id The data control provider ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_map_get_provider_id()
+ */
+EXPORT_API int datacontrol_map_set_provider_id(datacontrol_h provider, const char *provider_id);
+
+/**
+ * @brief Gets the Provider ID.
+ * @param [in] provider The provider handle
+ * @param [out] provider_id The data control provider ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_map_set_provider_id()
+ */
+EXPORT_API int datacontrol_map_get_provider_id(datacontrol_h provider, char **provider_id);
+
+/**
+ * @brief Sets the Data ID.
+ * @param [in] provider The provider handle
+ * @param [in] data_id A string for identifying a specific table to operate. @n
+ * The string consists of one or more components separated by a slash('/').
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_map_get_data_id()
+ */
+EXPORT_API int datacontrol_map_set_data_id(datacontrol_h provider, const char *data_id);
+
+/**
+ * @brief Gets the Data ID.
+ * @param [in] provider The provider handle
+ * @param [out] data_id A string for identifying a specific table to operate. @n
+ * The string consists of one or more components separated by a slash('/').
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_map_set_data_id()
+ */
+EXPORT_API int datacontrol_map_get_data_id(datacontrol_h provider, char **data_id);
+
+/**
+ * @brief Registers a callback function for the key-value structured data control response. @n
+ * The application is notified when a data control response is received from the @c provider.
+ * @param [in] provider The provider handle
+ * @param [in] callback The callback function to be called when a response is received.
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_map_unregister_response_cb()
+ */
+EXPORT_API int datacontrol_map_register_response_cb(datacontrol_h provider, datacontrol_map_response_cb* callback, void *user_data);
+
+/**
+ * @brief Unregisters the callback function in @c provider.
+ * @param [in] provider The provider handle
+ * @return 0 on success, otherwise a negative error value.
+ */
+EXPORT_API int datacontrol_map_unregister_response_cb(datacontrol_h provider);
+
+/**
+ * @brief Gets the value list associated with the specified @c key from the key-values map owned by the key-value structured data control provider.
+ *
+ * @param [in] provider The provider handle
+ * @param [in] key The key of the value list to obtain
+ * @param [out] request_id The request ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument
+ *
+ * The following example demonstrates how to use the %datacontrol_map_get() method.
+ *
+ * @code
+ *
+ * void map_get_response_cb(int request_id, datacontrol_h provider,
+ * char **result_value_list, int result_value_count, bool provider_result, const char *error)
+ * {
+ * if (provider_result) {
+ * LOGI("The get operation is successful");
+ * }
+ * else {
+ * LOGI("The get operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * datacontrol_map_response_cb map_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * char *key = "key";
+ *
+ * map_callback.get = map_get_response_cb;
+ * result = datacontrol_map_register_response_cb(provider, &map_callback);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = datacontrol_map_get(provider, key, &req_id);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Getting the value list of the key(%s) is failed with error: %d", key, result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_map_get(datacontrol_h provider, const char *key, int *request_id);
+
+/**
+ * @brief Gets the value list associated with the specified @c key from the key-values map owned by the key-value structured data control provider.
+ *
+ * @param [in] provider The provider handle
+ * @param [in] key The key of the value list to obtain
+ * @param [out] request_id The request ID
+ * @param [in] page_number The page number of the value set @n
+ * It starts from 1.
+ * @param [in] count_per_page The desired maximum count of the data items per page
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument
+ */
+EXPORT_API int datacontrol_map_get_with_page(datacontrol_h provider, const char *key, int *request_id, int page_number, int count_per_page);
+
+/**
+ * @brief Sets the value associated with the specified @c key to a new value.
+ *
+ * @param [in] provider The provider handle
+ * @param [in] key The key of the value to replace
+ * @param [in] old_value The value to replace
+ * @param [in] new_value The new value that replaces the existing value
+ * @param [out] request_id The request ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument
+ *
+ * The following example demonstrates how to use the %datacontrol_map_set() method.
+ *
+ * @code
+ *
+ * void map_set_response_cb(int request_id, datacontrol_h provider, bool provider_result, const char *error)
+ * {
+ * if (provider_result) {
+ * LOGI("The set operation is successful");
+ * }
+ * else {
+ * LOGI("The set operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * datacontrol_map_response_cb map_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * char *key = "key";
+ * char *old_value = "old value";
+ * char *new_value = "new value";
+ *
+ * map_callback.set = map_set_response_cb;
+ * result = datacontrol_map_register_response_cb(provider, &map_callback);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = datacontrol_map_set(provider, key, old_value, new_value, &req_id);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Replacing old_value(%s) with new_value(%s) is failed with error: %d", old_value, new_value, result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_map_set(datacontrol_h provider, const char *key, const char *old_value, const char *new_value, int *request_id);
+
+/**
+ * @brief Adds the @c value associated with the specified @c key to the key-values map owned by the key-value structured data control provider.
+ *
+ * @param [in] provider The provider handle
+ * @param [in] key The key of the value to add
+ * @param [in] value The value to add
+ * @param [out] request_id The request ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument
+ *
+ * The following example demonstrates how to use the %datacontrol_map_add() method.
+ *
+ * @code
+ *
+ * void map_add_response_cb(int request_id, datacontrol_h provider, bool provider_result, const char *error) {
+ * if (provider_result) {
+ * LOGI("The add operation is successful");
+ * }
+ * else {
+ * LOGI("The add operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * datacontrol_map_response_cb map_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * const char *key = "key";
+ * const char *value = "value";
+ *
+ * map_callback.add = map_add_response_cb;
+ * result = datacontrol_map_register_response_cb(provider, &map_callback);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = datacontrol_map_add(provider, key, value, &req_id);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Adding %s-%s pair is failed with error: %d", key, value, result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_map_add(datacontrol_h provider, const char *key, const char *value, int *request_id);
+
+/**
+ * @brief Removes the @c value associated with the specified @c key from the key-values map owned by the key-value structured data control provider.
+ *
+ * @param [in] provider The provider handle
+ * @param [in] key The key of the value to remove
+ * @param [in] value The value to remove
+ * @param [out] request_id The request ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument
+ *
+ * The following example demonstrates how to use the %datacontrol_map_remove() method.
+ *
+ * @code
+ *
+ * void map_remove_response_cb(int request_id, datacontrol_h provider, bool provider_result, const char *error) {
+ * if (provider_result) {
+ * LOGI("The remove operation is successful");
+ * }
+ * else {
+ * LOGI("The remove operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * datacontrol_map_response_cb map_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * const char *key = "key";
+ * const char *value = "value";
+ *
+ * ...
+ *
+ * map_callback.remove = map_remove_response_cb;
+ * result = datacontrol_map_register_response_cb(provider, &map_callback);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = datacontrol_map_remove(provider, key, value, &req_id);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Removing %s-%s pair is failed with error: %d", key, value, result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_map_remove(datacontrol_h provider, const char *key, const char *value, int *request_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _APPFW_DATA_CONTROL_MAP_H_ */
+
--- /dev/null
+//
+// Copyright (c) 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.
+//
+
+/**
+ * @file data-control-provider.h
+ * @brief This is the header file for the data control provider.
+ */
+
+#ifndef _APPFW_DATA_CONTROL_PROVIDER_H_
+#define _APPFW_DATA_CONTROL_PROVIDER_H_
+
+#include <data-control-types.h>
+#include <data-control-sql-cursor.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief Called when the insert request is received from an application using SQL-friendly interface based data control.
+ *
+ * @param [in] request_id The request ID
+ * @param [in] provider The provider handle
+ * @param [in] insert_data The column-value pairs to insert @n
+ * If the value is a string, the value must be wrapped in single quotes, else it does not need to be wrapped in single quotes.
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_provider_sql_insert_request_cb)(int request_id, datacontrol_h provider,
+ bundle *insert_data, void *user_data);
+
+/**
+ * @brief Called when the update request is received from an application using SQL-friendly interface based data control.
+ *
+ * @param [in] request_id The request ID
+ * @param [in] provider The provider handle
+ * @param [in] update_data The column-value pairs to update @n
+ * If the value is a string, the value must be wrapped in single quotes, else it does not need to be wrapped in single quotes.
+ * @param [in] where A filter to select the desired rows to update. @n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_provider_sql_update_request_cb)(int request_id, datacontrol_h provider,
+ bundle *update_data, const char *where, void *user_data);
+
+/**
+ * @brief Called when the delete request is received from an application using SQL-friendly interface based data control.
+ *
+ * @param [in] request_id The request ID
+ * @param [in] provider The provider handle
+ * @param [in] where A filter to select the desired rows to delete. @n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_provider_sql_delete_request_cb)(int request_id, datacontrol_h provider,
+ const char *where, void *user_data);
+
+/**
+ * @brief Called when the select request is received from an application using SQL-friendly interface based data control.
+ *
+ * @param [in] request_id The request ID
+ * @param [in] provider The provider handle
+ * @param [in] column_list The column list to query
+ * @param [in] column_count The total number of columns to be queried
+ * @param [in] where A filter to select the desired rows. @n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param [in] order The sorting order of the rows to query. @n
+ * It is an SQL 'ORDER BY' clause excluding the 'ORDER BY' itself.
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_provider_sql_select_request_cb)(int request_id, datacontrol_h provider,
+ const char **column_list, int column_count, const char *where, const char *order, void *user_data);
+
+/**
+ * @brief Called when the request for obtaining the value list is received from the key-value structured data control consumer.
+ *
+ * @param [in] request_id The request ID
+ * @param [in] provider The provider handle
+ * @param [in] key The key of the value list to obtain
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_provider_map_get_value_request_cb)(int request_id, datacontrol_h provider, const char *key, void *user_data);
+
+/**
+ * @brief Called when the request for replacing the value is received from the key-value structured data control consumer.
+ *
+ * @param [in] request_id The request ID
+ * @param [in] provider The provider handle
+ * @param [in] key The key of the value to replace
+ * @param [in] old_value The value to replace
+ * @param [in] new_value The new value that replaces the existing value
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_provider_map_set_value_request_cb)(int request_id, datacontrol_h provider, const char *key,
+ const char *old_value, const char *new_value, void *user_data);
+
+/**
+ * @brief Called when the request for adding the value is received from the key-value structured data control consumer.
+ *
+ * @param [in] request_id The request ID
+ * @param [in] provider The provider handle
+ * @param [in] key The key of the value to add
+ * @param [in] value The value to add
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_provider_map_add_value_request_cb)(int request_id, datacontrol_h provider, const char *key,
+ const char *value, void *user_data);
+
+/**
+ * @brief Called when the request for removing the value is received from the key-value structured data control consumer.
+ *
+ * @param [in] request_id The request ID
+ * @param [in] provider The provider handle
+ * @param [in] key The key of the value to remove
+ * @param [in] value The value to remove
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_provider_map_remove_value_request_cb)(int request_id, datacontrol_h provider, const char *key,
+ const char *value, void *user_data);
+
+/**
+ * @brief The structure type to contain the set of callback functions for handling the request events
+ * of SQL-friendly interface based data control.
+ * @see datacontrol_provider_sql_select_request_cb()
+ * @see datacontrol_provider_sql_insert_request_cb()
+ * @see datacontrol_provider_sql_update_request_cb()
+ * @see datacontrol_provider_sql_delete_request_cb()
+ */
+typedef struct
+{
+ datacontrol_provider_sql_insert_request_cb insert;
+ datacontrol_provider_sql_select_request_cb select;
+ datacontrol_provider_sql_update_request_cb update;
+ datacontrol_provider_sql_delete_request_cb delete;
+} datacontrol_provider_sql_cb;
+
+/**
+ * @brief The structure type to contain the set of callback functions for handling the request events
+ * from the key-value structured data control consumer.
+ * @see datacontrol_provider_map_get_value_request_cb()
+ * @see datacontrol_provider_map_set_value_request_cb()
+ * @see datacontrol_provider_map_add_value_request_cb()
+ * @see datacontrol_provider_map_remove_value_request_cb()
+ */
+typedef struct
+{
+ datacontrol_provider_map_get_value_request_cb get;
+ datacontrol_provider_map_set_value_request_cb set;
+ datacontrol_provider_map_add_value_request_cb add;
+ datacontrol_provider_map_remove_value_request_cb remove;
+} datacontrol_provider_map_cb;
+
+/**
+ * @brief Registers a callback function for the sql data control request.
+ * The provider is notified when a data control request is received from the client applications.
+ * @param [in] callback The callback function to be called when a data control request is received
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_provider_sql_register_cb(datacontrol_provider_sql_cb *callback, void *user_data);
+
+/**
+ * @brief Unregisters the callback functions.
+ * @return 0 on success, otherwise a negative error value.
+ */
+EXPORT_API int datacontrol_provider_sql_unregister_cb(void);
+
+/**
+ * @brief Registers a callback function for the map data control request.
+ * The provider is notified when a data control request is received from the client applications.
+ * @param [in] callback The callback function to be called when a data control request is received
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_provider_map_register_cb(datacontrol_provider_map_cb *callback, void *user_data);
+
+/**
+ * @brief Unregisters the callback functions.
+ * @return 0 on success, otherwise a negative error value.
+ */
+EXPORT_API int datacontrol_provider_map_unregister_cb(void);
+
+/**
+ * @brief Gets the application ID which sends the data control request.
+ * @param [in] request_id The request ID
+ * @param [out] appid The application ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_provider_get_client_appid(int request_id, char **appid);
+
+/**
+ * @brief Sends the success result and the result set of the select request to the client application.
+ * @param [in] request_id The request ID
+ * @param [in] db_handle The result db handle for the result set
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_provider_send_select_result(int request_id, void *db_handle);
+
+/**
+ * @brief Sends the success result of the insert request and the last inserted row ID to the client application.
+ * @param [in] request_id The request ID
+ * @param [in] row_id The row ID of the database changed by the insert request
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_provider_send_insert_result(int request_id, long long row_id);
+
+/**
+ * @brief Sends the success result of the update request the client application.
+ * @param [in] request_id The request ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_provider_send_update_result(int request_id);
+
+/**
+ * @brief Sends the success result of the delete request the client application.
+ * @param [in] request_id The request ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_provider_send_delete_result(int request_id);
+
+/**
+ * @brief Sends the provider error message to the client application.
+ * @param [in] request_id The request ID
+ * @param [in] error The provider-defined error message
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_provider_send_error(int request_id, const char *error);
+
+/**
+ * @brief Sends the success result of the request for setting, adding and removing the key-value structured data the client application.
+ * @param [in] request_id The request ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_provider_send_map_result(int request_id);
+
+/**
+ * @brief Sends the success result of the request for getting the value list the client application.
+ * @param [in] request_id The request ID
+ * @param [in] value_list The result value list
+ * @param [in] value_count The number of the values
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_provider_send_map_get_value_result(int request_id, char **value_list, int value_count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _APPFW_DATA_CONTROL_PROVIDER_H_ */
+
--- /dev/null
+//
+// Copyright (c) 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.
+//
+
+/**
+ * @file data-control-sql-cursor.h
+ * @brief This is the header file for the cursor of the SQL-friendly interface based data control.
+ */
+
+#ifndef _APPFW_DATA_CONTROL_SQL_ENUMERATOR_H_
+#define _APPFW_DATA_CONTROL_SQL_ENUMERATOR_H_
+
+#include <stdio.h>
+#include "data-control-types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief The structure type to represent a sql result set. This type can be used to enumerate through the result set of an SQL query.
+ */
+typedef struct
+{
+ int resultset_fd;
+ int resultset_row_count;
+ int resultset_col_count;
+ int resultset_col_type_offset;
+ int resultset_col_name_offset;
+ int resultset_content_offset;
+ int resultset_current_offset;
+ int resultset_current_row_count;
+ char* resultset_path;
+} resultset_cursor;
+
+/**
+ * @brief Creates a cursor to enumerate through an SQL result set
+ *
+ * @param [in] path The path of the file containing the SQL result set
+ * @return A pointer to struct @c resultset_cursor
+ */
+resultset_cursor* datacontrol_sql_get_cursor(const char *path);
+
+/**
+ * @brief Moves the cursor to the first position
+ *
+ * @param [in] cursor Navigates the result of the request for the select operation
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * The following example demonstrates how to use the %datacontrol_sql_step_first() method.
+ *
+ * @code
+ *
+ * void sql_select_response_cb(int request_id, datacontrol_h provider, resultset_cursor *cursor, bool provider_result, const char *error)
+ * {
+ * char person_name[32] = {0,};
+ * long long person_number = -1;
+ *
+ * datacontrol_sql_step_first(cursor);
+ * datacontrol_sql_get_text_data(cursor, 0, person_name);
+ * datacontrol_sql_get_int64_data(cursor, 1, &person_number);
+ * printf("The person %s has the number %l", person_name, person_number);
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_sql_step_first(resultset_cursor *cursor);
+
+/**
+ * @brief Moves the cursor to the last position
+ *
+ * @param [in] cursor Navigates the result of data control select request
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * The following example demonstrates how to use the %datacontrol_sql_step_last() method.
+ *
+ * @code
+ *
+ * void sql_select_response_cb(int request_id, datacontrol_h provider, resultset_cursor *cursor, bool provider_result, const char *error)
+ * {
+ * char person_name[32] = {0,};
+ * long long person_number = -1;
+ *
+ * datacontrol_sql_step_last(cursor);
+ * datacontrol_sql_get_text_data(cursor, 0, person_name);
+ * datacontrol_sql_get_int64_data(cursor, 1, &person_number);
+ * printf("The person %s has the number %l", person_name, person_number);
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_sql_step_last(resultset_cursor *cursor);
+
+/**
+ * @brief Moves the cursor to the next position
+ *
+ * @param [in] cursor Navigates the result of the request for the select operation
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * The following example demonstrates how to use the %datacontrol_sql_step_next() method.
+ *
+ * @code
+ *
+ * void sql_select_response_cb(int request_id, datacontrol_h provider, resultset_cursor *cursor, bool provider_result, const char *error)
+ * {
+ * char person_name[32] = {0,};
+ * long long person_number = -1;
+ * while (datacontrol_sql_step_next(cursor) == DATACONTROL_ERROR_NONE) {
+ * datacontrol_sql_get_text_data(cursor, 0, person_name);
+ * datacontrol_sql_get_int64_data(cursor, 1, &person_number);
+ * printf("The person %s has the number %l", person_name, person_number);
+ * }
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_sql_step_next(resultset_cursor *cursor);
+
+/**
+ * @brief Moves the cursor to the previous position
+ *
+ * @param [in] cursor Navigates the result of the request for the select operation
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_sql_step_previous(resultset_cursor *cursor);
+
+/**
+ * @brief Gets the number of columns for this cursor
+ *
+ * @param [in] cursor Navigates the result of the request for the select operation
+ * @return The number of columns in the calling cursor
+ */
+EXPORT_API int datacontrol_sql_get_column_count(resultset_cursor *cursor);
+
+/**
+ * @brief Gets the name of the column indicated by the specified index
+ *
+ * @param [in] cursor Navigates the result of the request for the select operation
+ * @param [in] column_index The index of the destination column
+ * @param [out] name The name of the destination column
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ */
+EXPORT_API int datacontrol_sql_get_column_name(resultset_cursor *cursor, int column_index, char *name);
+
+/**
+ * @brief Gets the size of data in the column indicated by the specified index
+ *
+ * @param [in] cursor Navigates the result of the request for the select operation
+ * @param [in] column_index The index of the destination column
+ * @return The size of data in the column indicated by the specified index. @n
+ * If an error is occurred, a negative value is returned.
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ */
+EXPORT_API int datacontrol_sql_get_column_item_size(resultset_cursor *cursor, int column_index);
+
+/**
+ * @brief Gets the type of the column indicated by the specified index
+ *
+ * @param [in] cursor Navigates the result of the request for the select operation
+ * @param [in] column_index The index of the destination column
+ * @param [out] type The type of the destination column
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ */
+EXPORT_API int datacontrol_sql_get_column_item_type(resultset_cursor *cursor, int column_index, datacontrol_sql_column_type* type);
+
+/**
+ * @brief Gets a blob data from the column indicated by the specified index
+ *
+ * @param [in] cursor Navigates the result of the request for the select operation
+ * @param [in] column_index The index of the destination column
+ * @param [out] data The blob value obtained from the column
+ * @param [out] size The size of the data
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument
+ */
+EXPORT_API int datacontrol_sql_get_blob_data(resultset_cursor *cursor, int column_index, void *data, int size);
+
+/**
+ * @brief Gets an int value from the column indicated by the specified index
+ *
+ * @param [in] cursor Navigates the result of the request for the select operation
+ * @param [in] column_index The index of the destination column
+ * @param [out] data The integer value obtained from the column
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_sql_get_int_data(resultset_cursor *cursor, int column_index, int *data);
+
+/**
+ * @brief Gets a long long value from the column indicated by the specified index
+ *
+ * @param [in] cursor Navigates the result of the request for the select operation
+ * @param [in] column_index The index of the destination column
+ * @param [out] data The 64-bit integer value obtained from the column
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_sql_get_int64_data(resultset_cursor *cursor, int column_index, long long *data);
+
+/**
+ * @brief Gets a double value from the column indicated by the specified index
+ *
+ * @param [in] cursor Navigates the result of the request for the select operation
+ * @param [in] column_index The index of the destination column
+ * @param [out] data The value obtained from the column as double
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+EXPORT_API int datacontrol_sql_get_double_data(resultset_cursor *cursor, int column_index, double *data);
+
+/**
+ * @brief Gets a text value from the column indicated by the specified index
+ *
+ * @param [in] cursor Navigates the result of the request for the select operation
+ * @param [in] column_index The index of the destination column
+ * @param [out] data The value obtained from the column as text
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ */
+EXPORT_API int datacontrol_sql_get_text_data(resultset_cursor *cursor, int column_index, char *data);
+
+/**
+ * @brief Removes the @c cursor containing SQL result set
+ *
+ * @param [in] cursor A pointer to the result set cursor to be removed
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ */
+EXPORT_API int datacontrol_sql_remove_cursor(resultset_cursor *cursor);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _APPFW_DATA_CONTROL_SQL_ENUMERATOR_H_ */
+
--- /dev/null
+//
+// Copyright (c) 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.
+//
+
+/**
+ * @file data-control-sql.h
+ * @brief This is the header file for the SQL-friendly interface based data control.
+ */
+
+#ifndef _APPFW_DATA_CONTROL_SQL_H_
+#define _APPFW_DATA_CONTROL_SQL_H_
+
+#include <data-control-types.h>
+#include <data-control-sql-cursor.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief Called when response is received for insert operation from an application using the SQL-friendly interface based data control.
+ *
+ * @param [in] request_id The request ID
+ * @param [in] provider The provider handle
+ * @param [in] inserted_row_id The inserted row ID set by the data control
+ * @param [in] provider_result Set to true if the data control provider successfully processed. @n
+ * false otherwise.
+ * @param [in] error The error message from the data control provider
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_sql_insert_response_cb)(int request_id, datacontrol_h provider,
+ long long inserted_row_id, bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief Called when response is received for delete operation from an application using the SQL-friendly interface based data control.
+ *
+ * @param [in] request_id The request ID that identifies the data control
+ * @param [in] provider_result Set to true if the data control provider successfully processed. @n
+ * false otherwise.
+ * @param [in] error The error message from the data control provider
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_sql_delete_response_cb)(int request_id, datacontrol_h provider,
+ bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief Called when response is received for select operation from an application using the SQL-friendly interface based data control.
+ *
+ * @param [in] request_id The request ID
+ * @param [in] provider The provider handle
+ * @param [in] enumerator Navigates the result of data control select request
+ * @param [in] provider_result Set to true if the data control provider successfully processed. @n
+ * false otherwise.
+ * @param [in] error The error message from the data control provider
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_sql_select_response_cb)(int request_id, datacontrol_h provider,
+ resultset_cursor *enumerator, bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief Called when response is received for update operation from an application using the SQL-friendly interface based data control.
+ *
+ * @param [in] request_id The request ID
+ * @param [in] provider The provider handle
+ * @param [in] provider_result Set to true if the data control provider successfully processed. @n
+ * false otherwise.
+ * @param [in] error The error message from the data control provider
+ * @param [in] user_data The user data passed from the register function
+ */
+typedef void (*datacontrol_sql_update_response_cb)(int request_id, datacontrol_h provider,
+ bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief The structure type to contain the set of callback functions for handling the response events
+ * of SQL-friendly interface based data control.
+ * @see datacontrol_sql_select_response_cb()
+ * @see datacontrol_sql_insert_response_cb()
+ * @see datacontrol_sql_update_response_cb()
+ * @see datacontrol_sql_delete_response_cb()
+ */
+typedef struct
+{
+ datacontrol_sql_select_response_cb select;
+ datacontrol_sql_insert_response_cb insert;
+ datacontrol_sql_update_response_cb update;
+ datacontrol_sql_delete_response_cb delete;
+} datacontrol_sql_response_cb;
+
+/**
+ * @brief Creates a provider handle.
+ * @param [out] provider The provider handle
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_sql_destroy()
+ *
+ * The following example demonstrates how to use the %datacontrol_sql_create() method.
+ *
+ * @code
+ *
+ * int main()
+ * {
+ * const char *provider_id = "http://tizen.org/datacontrol/provider/example";
+ * const char *data_id = "table";
+ * datacontrol_h provider;
+ * int result = 0;
+ *
+ * result = datacontrol_sql_create(&provider);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Creating data control provider is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = datacontrol_sql_set_provider_id(provider, provider_id);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Setting providerID is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = datacontrol_sql_set_data_id(provider, data_id);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Setting dataID is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * // Executes some operations
+ *
+ * result = datacontrol_sql_destroy(provider);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Destorying data control provider is failed with error: %d", result);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_sql_create(datacontrol_h *provider);
+
+/**
+ * @brief Destroys the provider handle and releases all its resources.
+ * @param [in] provider The provider handle
+ * @return 0 on success, otherwise a negative error value.
+ * @remark When operations of data control are finished, this function must be called to prevent memory leak.
+ * @see datacontrol_sql_create()
+ */
+EXPORT_API int datacontrol_sql_destroy(datacontrol_h provider);
+
+/**
+ * @brief Sets the Provider ID.
+ * @param [in] provider The provider handle
+ * @param [in] provider_id The data control provider ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_sql_get_provider_id()
+ */
+EXPORT_API int datacontrol_sql_set_provider_id(datacontrol_h provider, const char *provider_id);
+
+/**
+ * @brief Gets the Provider ID.
+ * @param [in] provider The provider handle
+ * @param [out] provider_id The data control provider ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_sql_set_provider_id()
+ */
+EXPORT_API int datacontrol_sql_get_provider_id(datacontrol_h provider, char **provider_id);
+
+/**
+ * @brief Sets the Data ID.
+ * @param [in] provider The provider handle
+ * @param [in] data_id A string for identifying a specific table to operate. @n
+ * The string consists of one or more components separated by a slash('/').
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_sql_get_data_id()
+ */
+EXPORT_API int datacontrol_sql_set_data_id(datacontrol_h provider, const char *data_id);
+
+/**
+ * @brief Gets the Data ID.
+ * @param [in] provider The provider handle
+ * @param [out] data_id A string for identifying a specific table to operate. @n
+ * The string consists of one or more components separated by a slash('/').
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_sql_set_data_id()
+ */
+EXPORT_API int datacontrol_sql_get_data_id(datacontrol_h provider, char **data_id);
+
+/**
+ * @brief Registers a callback function for the sql data control response. @n
+ * The application is notified when a data control response is received from the @c provider.
+ * @param [in] provider The provider handle
+ * @param [in] callback The callback function to be called when a response is received.
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_sql_unregister_response_cb()
+ */
+EXPORT_API int datacontrol_sql_register_response_cb(datacontrol_h provider, datacontrol_sql_response_cb* callback, void *user_data);
+
+/**
+ * @brief Unregisters the callback function in @c provider.
+ * @param [in] provider The provider handle
+ * @return 0 on success, otherwise a negative error value.
+ */
+EXPORT_API int datacontrol_sql_unregister_response_cb(datacontrol_h provider);
+
+/**
+ * @brief Deletes rows of a table owned by the SQL-type data control provider
+ *
+ * @remarks If the value is a string, the value must be wrapped in single quotes, else it does not need to be wrapped in single quotes.
+ * @param [in] provider The provider handle
+ * @param [in] where A filter to select the desired rows to delete. @n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param [out] request_id The request ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * The following example demonstrates how to use the %datacontrol_sql_delete() method.
+ *
+ * @code
+ *
+ * void sql_delete_response_cb(int request_id, datacontrol_h provider, bool provider_result, const char *error) {
+ * if (provider_result) {
+ * LOGI("The delete operation is successful");
+ * }
+ * else {
+ * LOGI("The delete operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * datacontrol_sql_response_cb sql_callback;
+ *
+ * int main()
+ * {
+ * const char *where = "group = 'friend'";
+ * int result = 0;
+ * int req_id = 0;
+ *
+ * sql_callback.delete = sql_delete_response_cb;
+ * result = datacontrol_sql_register_response_cb(provider, &sql_callback);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = datacontrol_sql_delete(provider, where, &req_id);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Deleting is failed with error: %d", result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_sql_delete(datacontrol_h provider, const char *where, int *request_id);
+
+/**
+ * @brief Inserts new rows in a table owned by the SQL-type data control provider
+ *
+ * @param [in] provider The provider handle
+ * @param [in] insert_data The column-value pairs to insert. @n
+ * If the value is a string, the value must be wrapped in single quotes,
+ * else it does not need to be wrapped in single quotes.
+ * @param [out] request_id The request ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument
+ *
+ * The following example demonstrates how to use the %datacontrol_sql_insert() method.
+ *
+ * @code
+ *
+ * void sql_insert_response_cb(int request_id, datacontrol_h provider, long long inserted_row_id, bool provider_result, const char *error) {
+ * if (provider_result) {
+ * LOGI("The insert operation is successful");
+ * }
+ * else {
+ * LOGI("The insert operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * datacontrol_sql_response_cb sql_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * bundle *b = NULL;
+ *
+ * sql_callback.insert = sql_insert_response_cb;
+ * result = datacontrol_sql_register_response_cb(provider, &sql_callback);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * b = bundle_create();
+ * bundle_add_str(b, "WORD", "test");
+ * bundle_add_str(b, "WORD_DESC", "test description");
+ *
+ * result = datacontrol_sql_insert(provider, b, &req_id);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Inserting is failed with error: %d", result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * bundle_free(b);
+ * return result;
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_sql_insert(datacontrol_h provider, const bundle* insert_data, int *request_id);
+
+/**
+ * @brief Selects the specified columns to be queried
+ *
+ * @param [in] provider The provider handle
+ * @param [in] column_list The column list to query
+ * @param [in] column_count The total number of columns to be queried
+ * @param [in] where A filter to select the desired rows. @n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param [in] order The sorting order of the rows to query. @n
+ * It is an SQL 'ORDER BY' clause excluding the 'ORDER BY' itself.
+ * @param [out] request_id The request ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * The following example demonstrates how to use the %datacontrol_sql_select() method.
+ *
+ * @code
+ *
+ * void sql_select_response_cb(int request_id, datacontrol_h provider, resultset_cursor *enumerator, bool provider_result, const char *error) {
+ * if (provider_result) {
+ * LOGI("The select operation is successful");
+ * }
+ * else {
+ * LOGI("The select operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * datacontrol_sql_response_cb sql_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * char *column_list[2];
+ * column_list[0] = "WORD";
+ * column_list[1] = "WORD_DESC";
+ * const char *where = "WORD = 'test'";
+ * const char *order = "WORD ASC";
+ *
+ * sql_callback.select = sql_select_response_cb;
+ * result = datacontrol_sql_register_response_cb(provider, &sql_callback);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = datacontrol_sql_select(provider, column_list, 2, where, order, &req_id);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Selecting is failed with error: %d", result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_sql_select(datacontrol_h provider, char **column_list, int column_count, const char *where, const char *order, int *request_id);
+
+/**
+ * @brief Selects the specified columns to be queried
+ *
+ * @param [in] provider The provider handle
+ * @param [in] column_list The column list to query
+ * @param [in] column_count The total number of columns to be queried
+ * @param [in] where A filter to select the desired rows. @n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param [in] order The sorting order of the rows to query. @n
+ * It is an SQL 'ORDER BY' clause excluding the 'ORDER BY' itself.
+ * @param [in] page_number The page number of the result set @n
+ * It starts from 1.
+ * @param [in] count_per_page The desired maximum count of rows on a page
+ * @param [out] request_id The request ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see datacontrol_sql_select()
+ */
+EXPORT_API int datacontrol_sql_select_with_page(datacontrol_h provider, char **column_list, int column_count, const char *where, const char *order, int page_number, int count_per_page, int *request_id);
+
+/**
+ * @brief Updates values of a table owned by the SQL-type data control provider.
+ *
+ * @param [in] provider The provider handle
+ * @param [in] update_data The column-value pairs to update. @n
+ * If the value is a string, the value must be wrapped in single quotes,
+ * else it does not need to be wrapped in single quotes.
+ * @param [in] where A filter to select the desired rows to update. @n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param [out] request_id The request ID
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #DATACONTROL_ERROR_NONE Successful
+ * @retval #DATACONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATACONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATACONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATACONTROL_ERROR_MAX_EXCEEDED Too long argument
+ *
+ * The following example demonstrates how to use the %datacontrol_sql_update() method.
+ *
+ * @code
+ *
+ * void sql_update_response_cb(int request_id, datacontrol_h provider, bool provider_result, const char *error) {
+ * if (provider_result) {
+ * LOGI("The update operation is successful");
+ * }
+ * else {
+ * LOGI("The update operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * datacontrol_sql_response_cb sql_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * const char *where = "WORD = 'test'";
+ * bundle *b = NULL;
+ *
+ * sql_callback.update = sql_update_response_cb;
+ * result = datacontrol_sql_register_response_cb(provider, &sql_callback);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * b = bundle_create();
+ * bundle_add_str(b, "WORD", "test_new");
+ *
+ * result = datacontrol_sql_update(provider, b, where, &req_id);
+ * if (result != DATACONTROL_ERROR_NONE) {
+ * LOGE("Updating is failed with error: %d", result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * bundle_free(b);
+ * return result;
+ * }
+ *
+ * @endcode
+ */
+EXPORT_API int datacontrol_sql_update(datacontrol_h provider, const bundle* update_data, const char *where, int *request_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _APPFW_DATA_CONTROL_SQL_H_ */
+
--- /dev/null
+//
+// Copyright (c) 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.
+//
+
+/**
+ * @file data-control-types.h
+ * @brief This is the header file for data types of the data-control.
+ */
+
+#ifndef _APPFW_DATA_CONTROL_TYPES_H_
+#define _APPFW_DATA_CONTROL_TYPES_H_
+
+#include <errno.h>
+
+#ifdef __GNUC__
+# ifndef EXPORT_API
+# define EXPORT_API __attribute__((visibility("default")))
+# endif
+#else
+# define EXPORT_API
+#endif
+
+/**
+ * @brief Provider handle
+ */
+typedef struct datacontrol_s *datacontrol_h;
+
+/**
+ * @brief Enumerations of different types of columns in an SQL table.
+ */
+typedef enum
+{
+ DATACONTROL_SQL_COLUMN_TYPE_UNDEFINED = 0,
+ DATACONTROL_SQL_COLUMN_TYPE_INT64,
+ DATACONTROL_SQL_COLUMN_TYPE_DOUBLE,
+ DATACONTROL_SQL_COLUMN_TYPE_TEXT,
+ DATACONTROL_SQL_COLUMN_TYPE_BLOB,
+ DATACONTROL_SQL_COLUMN_TYPE_NULL
+} datacontrol_sql_column_type;
+
+/**
+ * @brief Enumerations of the various error-codes an API can return.
+ */
+typedef enum
+{
+ DATACONTROL_ERROR_NONE = 0, /**< Successful */
+ DATACONTROL_ERROR_OUT_OF_MEMORY = -ENOMEM, /**< Out of memory */
+ DATACONTROL_ERROR_IO_ERROR = -EIO, /**< I/O error */
+ DATACONTROL_ERROR_INVALID_PARAMETER = -EINVAL, /**< Invalid parameter */
+ DATACONTROL_ERROR_PERMISSION_DENIED = -EACCES, /**< Permission denied */
+ DATACONTROL_ERROR_MAX_EXCEEDED = -EMSGSIZE /**< Too long argument */
+} datacontrol_error_e;
+
+#endif /* _APPFW_DATA_CONTROL_TYPES_H_ */
+
--- /dev/null
+//
+// Copyright (c) 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.
+//
+
+/**
+ * @file data-control.h
+ * @brief This is the header file for the data control.
+ */
+
+#ifndef _APPFW_DATA_CONTROL_H_
+#define _APPFW_DATA_CONTROL_H_
+
+#include <data-control-sql.h>
+#include <data-control-sql-cursor.h>
+#include <data-control-provider.h>
+
+#endif /* _APPFW_DATA_CONTROL_H_ */
+
--- /dev/null
+//
+// Copyright (c) 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 __TIZEN_APPFW_DATA_CONTROL_H__
+#define __TIZEN_APPFW_DATA_CONTROL_H__
+
+#include <tizen.h>
+#include <data_control_sql.h>
+#include <data_control_map.h>
+#include <data_control_provider.h>
+
+/**
+ * @file data_control.h
+ * @brief This is the header file for the data control.
+ */
+
+#endif /* __TIZEN_APPFW_DATA_CONTROL_H__ */
+
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 __TIZEN_APPFW_DATA_CONTROL_INTERNAL_H__
+#define __TIZEN_APPFW_DATA_CONTROL_INTERNAL_H__
+
+#include <data-control-types.h>
+#include "data_control_types.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int convert_to_tizen_error(datacontrol_error_e error);
+int data_control_error(data_control_error_e error,
+ const char *function, const char *description);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_APPFW_DATA_CONTROL_INTERNAL_H__ */
--- /dev/null
+//
+// Copyright (c) 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 __TIZEN_APPFW_DATA_CONTROL_MAP_H__
+#define __TIZEN_APPFW_DATA_CONTROL_MAP_H__
+
+#include <data_control_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file data_control_map.h
+ * @brief This is the header file for the key-value structured data control.
+ */
+
+/**
+ * @addtogroup CAPI_DATA_CONTROL_CONSUMER_MODULE
+ * @{
+ */
+
+/**
+ * @brief Called when the result value list is received from the key-value structured data control provider.
+ * @since_tizen 2.3
+ *
+ * @remarks You must release @a resule_value_list using free() after it is used. Note that @a result_value list is an array of char *. Its length is @a result_value_count. You should release all the elements in the @a result_value_list array and @a result_value_list itself like the following code.
+ *
+ * @code
+ *
+ * int i;
+ * for (i = 0; i < resule_value_count; i++)
+ * free(result_value_list[i]);
+ * free(result_value_list);
+ *
+ * @endcode
+
+ * @param[in] request_id The request ID
+ * @param[in] provider The provider handle
+ * @param[in] result_value_list The result value list of the data control request that gets the matching values
+ * @param[in] result_value_count The number of the values
+ * @param[in] provider_result Set to @c true if the data control provider is successfully processed, \n
+ * otherwise set to @c false
+ * @param[in] error The error message from the data control provider
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_map_get_response_cb)(int request_id, data_control_h provider,
+ char **result_value_list, int result_value_count, bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief Called when the response is received from the key-value structured data control provider.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID that identifies the data control
+ * @param[in] provider The provider handle
+ * @param[in] provider_result Set to @c true if the data control provider successfully processed, \n
+ * otherwise @c false
+ * @param[in] error The error message from the data control provider
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_map_set_response_cb)(int request_id, data_control_h provider,
+ bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief Called when the response is received from the key-value structured data control provider.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID that identifies the data control
+ * @param[in] provider The provider handle
+ * @param[in] provider_result Set to @c true if the data control provider successfully processed, \n
+ * otherwise set to @c false
+ * @param[in] error The error message from the data control provider
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_map_add_response_cb)(int request_id, data_control_h provider,
+ bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief Called when the response is received from the key-value structured data control provider.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID that identifies the data control
+ * @param[in] provider The provider handle
+ * @param[in] provider_result Set to @c true if the data control provider successfully processed, \n
+ * otherwise set to @c false
+ * @param[in] error The error message from the data control provider
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_map_remove_response_cb)(int request_id, data_control_h provider,
+ bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief The structure type to contain the set of callback functions for handling the response events
+ * of the key-value structured data control.
+ * @since_tizen 2.3
+ *
+ * @see data_control_map_get_response_cb()
+ * @see data_control_map_set_response_cb()
+ * @see data_control_map_add_response_cb()
+ * @see data_control_map_remove_response_cb()
+ */
+typedef struct
+{
+ data_control_map_get_response_cb get_cb; /**< This callback function is called when the response is received for a getting value from the key-value structured data control provider. */
+ data_control_map_set_response_cb set_cb; /**< This callback function is called when the response is received for a setting value from the key-value structured data control provider. */
+ data_control_map_add_response_cb add_cb; /**< This callback function is called when the response is received for a adding value from the key-value structured data control provider. */
+ data_control_map_remove_response_cb remove_cb; /**< This callback function is called when the response is for a removing value received from the key-value structured data control provider. */
+} data_control_map_response_cb;
+
+/**
+ * @brief Creates a provider handle.
+ * @since_tizen 2.3
+ *
+ * @remarks The following example demonstrates how to use the %data_control_map_create() method.
+ *
+ * @code
+ *
+ * int main()
+ * {
+ * const char *provider_id = "http://tizen.org/datacontrol/provider/example";
+ * const char *data_id = "table";
+ * data_control_h provider;
+ * int result = 0;
+ *
+ * result = data_control_map_create(&provider);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Creating data control provider is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = data_control_map_set_provider_id(provider, provider_id);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Setting providerID is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = data_control_map_set_data_id(provider, data_id);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Setting dataID is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * // Executes some operations
+ *
+ * result = data_control_map_destroy(provider);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Destorying data control provider is failed with error: %d", result);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+
+ * @param[out] provider The provider handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see data_control_map_destroy()
+
+ */
+int data_control_map_create(data_control_h *provider);
+
+/**
+ * @brief Destroys the provider handle and releases all its resources.
+ * @since_tizen 2.3
+ *
+ * @remarks When operations of data control are finished, this function must be called to prevent memory leak.
+ *
+ * @param[in] provider The provider handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @see data_control_map_create()
+ */
+int data_control_map_destroy(data_control_h provider);
+
+/**
+ * @brief Sets the Provider ID.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ * @param[in] provider_id The data control provider ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see data_control_map_get_provider_id()
+ */
+int data_control_map_set_provider_id(data_control_h provider, const char *provider_id);
+
+/**
+ * @brief Gets the Provider ID.
+ * @since_tizen 2.3
+ *
+ * @remarks You must release @a provider_id using free() after it is used.
+ *
+ * @param[in] provider The provider handle
+ * @param[out] provider_id The data control provider ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see data_control_map_set_provider_id()
+ */
+int data_control_map_get_provider_id(data_control_h provider, char **provider_id);
+
+/**
+ * @brief Sets the Data ID.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ * @param[in] data_id A string for identifying a specific table to operate \n
+ * The string consists of one or more components separated by a slash('/').
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see data_control_map_get_data_id()
+ */
+int data_control_map_set_data_id(data_control_h provider, const char *data_id);
+
+/**
+ * @brief Gets the data ID.
+ * @since_tizen 2.3
+ *
+ * @remarks You must release @a data_id using free() after it is used.
+ *
+ * @param[in] provider The provider handle
+ * @param[out] data_id A string for identifying a specific table to operate \n
+ * The string consists of one or more components separated by a slash('/').
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see data_control_map_set_data_id()
+ */
+int data_control_map_get_data_id(data_control_h provider, char **data_id);
+
+/**
+ * @brief Registers a callback function for the key-value structured data control response.
+ * The application is notified when a data control response is received from the @a provider.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ * @param[in] callback The callback function to be called when a response is received
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see data_control_map_unregister_response_cb()
+ */
+int data_control_map_register_response_cb(data_control_h provider, data_control_map_response_cb* callback, void *user_data);
+
+/**
+ * @brief Unregisters the callback function in the @a provider.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ */
+int data_control_map_unregister_response_cb(data_control_h provider);
+
+/**
+ * @brief Gets the value list associated with the specified @a key from the key-values map owned by the key-value structured data control provider.
+ * @since_tizen 2.3
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/appmanager.launch
+ *
+ * @remarks If you want to use this api, you must add privileges.
+ * @remarks If the length of value list associated with the @a key is larger than 20, this API only returns the first 20 values.
+ * @remarks The following example demonstrates how to use the %data_control_map_get() method.
+ *
+ * @code
+ *
+ * void map_get_response_cb(int request_id, data_control_h provider,
+ * char **result_value_list, int ret_value_count, bool provider_result, const char *error, void *user_data)
+ * {
+ * if (provider_result) {
+ * LOGI("The get operation is successful");
+ * }
+ * else {
+ * LOGI("The get operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * data_control_map_response_cb map_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * char *key = "key";
+ *
+ * map_callback.get_cb = map_get_response_cb;
+ * result = data_control_map_register_response_cb(provider, &map_callback, NULL);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = data_control_map_get(provider, key, &req_id);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Getting the value list of the key(%s) is failed with error: %d", key, result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+ *
+ * @param[in] provider The provider handle
+ * @param[in] key The key of the value list to obtain
+ * @param[out] request_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_MAX_EXCEEDED Too long argument
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ *
+ * @see data_control_map_get_with_page()
+ */
+int data_control_map_get(data_control_h provider, const char *key, int *request_id);
+
+/**
+ * @brief Gets the value list associated with the specified @a key from the key-values map owned by the key-value structured data control provider.
+ * @since_tizen 2.3
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/appmanager.launch
+ *
+ * @remarks If you want to use this api, you must add privileges.
+ *
+ * @param[in] provider The provider handle
+ * @param[in] key The key of the value list to obtain
+ * @param[out] request_id The request ID
+ * @param[in] page_number The page number of the value set \n
+ * It starts from @c 1.
+ * @param [in] count_per_page The desired maximum count of the data items per page
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_MAX_EXCEEDED Too long argument
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ *
+ * @see data_control_map_get()
+ */
+int data_control_map_get_with_page(data_control_h provider, const char *key, int *request_id, int page_number, int count_per_page);
+
+/**
+ * @brief Sets the value associated with the specified @a key to a new value.
+ * @since_tizen 2.3
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/appmanager.launch
+ *
+ * @remarks If you want to use this api, you must add privileges.
+ * @remarks The following example demonstrates how to use the %data_control_map_set() method.
+ *
+ * @code
+ *
+ * void map_set_response_cb(int request_id, data_control_h provider, bool provider_result, const char *error, void *user_data)
+ * {
+ * if (provider_result) {
+ * LOGI("The set operation is successful");
+ * }
+ * else {
+ * LOGI("The set operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * data_control_map_response_cb map_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * char *key = "key";
+ * char *old_value = "old value";
+ * char *new_value = "new value";
+ *
+ * map_callback.set_cb = map_set_response_cb;
+ * result = data_control_map_register_response_cb(provider, &map_callback, NULL);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = data_control_map_set(provider, key, old_value, new_value, &req_id);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Replacing old_value(%s) with new_value(%s) is failed with error: %d", old_value, new_value, result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+
+ * @param[in] provider The provider handle
+ * @param[in] key The key of the value to replace
+ * @param[in] old_value The value to replace
+ * @param[in] new_value The new value that replaces the existing value
+ * @param[out] request_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_MAX_EXCEEDED Too long argument
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ */
+int data_control_map_set(data_control_h provider, const char *key, const char *old_value, const char *new_value, int *request_id);
+
+/**
+ * @brief Adds the @a value associated with the specified @a key to the key-values map owned by the key-value structured data control provider.
+ * @since_tizen 2.3
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/appmanager.launch
+ *
+ * @remarks If you want to use this api, you must add privileges.
+ * @remarks The following example demonstrates how to use the %data_control_map_add() method.
+ *
+ * @code
+ *
+ * void map_add_response_cb(int request_id, data_control_h provider, bool provider_result, const char *error, void *user_data) {
+ * if (provider_result) {
+ * LOGI("The add operation is successful");
+ * }
+ * else {
+ * LOGI("The add operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * data_control_map_response_cb map_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * const char *key = "key";
+ * const char *value = "value";
+ *
+ * map_callback.add_cb = map_add_response_cb;
+ * result = data_control_map_register_response_cb(provider, &map_callback, NULL);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = data_control_map_add(provider, key, value, &req_id);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Adding %s-%s pair is failed with error: %d", key, value, result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+
+ * @param[in] provider The provider handle
+ * @param[in] key The key of the value to add
+ * @param[in] value The value to add
+ * @param[out] request_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_MAX_EXCEEDED Too long argument
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ */
+int data_control_map_add(data_control_h provider, const char *key, const char *value, int *request_id);
+
+/**
+ * @brief Removes the @a value associated with the specified @a key from the key-values map owned by the key-value structured data control provider.
+ * @since_tizen 2.3
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/appmanager.launch
+ *
+ * @remarks If you want to use this api, you must add privileges.
+ * @remarks The following example demonstrates how to use the %data_control_map_remove() method.
+ *
+ * @code
+ *
+ * void map_remove_response_cb(int request_id, data_control_h provider, bool provider_result, const char *error, void *user_data) {
+ * if (provider_result) {
+ * LOGI("The remove operation is successful");
+ * }
+ * else {
+ * LOGI("The remove operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * data_control_map_response_cb map_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * const char *key = "key";
+ * const char *value = "value";
+ *
+ * map_callback.remove_cb = map_remove_response_cb;
+ * result = data_control_map_register_response_cb(provider, &map_callback, NULL);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = data_control_map_remove(provider, key, value, &req_id);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Removing %s-%s pair is failed with error: %d", key, value, result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+ *
+ * @param[in] provider The provider handle
+ * @param[in] key The key of the value to remove
+ * @param[in] value The value to remove
+ * @param[out] request_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_MAX_EXCEEDED Too long argument
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ */
+int data_control_map_remove(data_control_h provider, const char *key, const char *value, int *request_id);
+
+/**
+* @}
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_APPFW_DATA_CONTROL_MAP_H__ */
--- /dev/null
+//
+// Copyright (c) 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 __TIZEN_APPFW_DATA_CONTROL_PROVIDER_H_
+#define __TIZEN_APPFW_DATA_CONTROL_PROVIDER_H_
+
+#include <data_control_types.h>
+#include <data_control_sql_cursor.h>
+#include <bundle.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file data_control_provider.h
+ * @brief This is the header file for the data control provider.
+ */
+
+/**
+ * @addtogroup CAPI_DATA_CONTROL_PROVIDER_MODULE
+ * @{
+ */
+
+/**
+ * @brief Called when the insert request is received from an application using SQL-friendly interface based data control.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] provider The provider handle
+ * @param[in] insert_data The column-value pairs to insert \n
+ * If the value is a string, the value must be wrapped in single quotes, else it does not need to be wrapped in single quotes.
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_provider_sql_insert_request_cb)(int request_id, data_control_h provider,
+ bundle *insert_data, void *user_data);
+
+/**
+ * @brief Called when the update request is received from an application using SQL-friendly interface based data control.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] provider The provider handle
+ * @param[in] update_data The column-value pairs to update \n
+ * If the value is a string, the value must be wrapped in single quotes, else it does not need to be wrapped in single quotes.
+ * @param[in] where A filter to select the desired rows to update \n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_provider_sql_update_request_cb)(int request_id, data_control_h provider,
+ bundle *update_data, const char *where, void *user_data);
+
+/**
+ * @brief Called when the delete request is received from an application using SQL-friendly interface based data control.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] provider The provider handle
+ * @param[in] where A filter to select the desired rows to delete \n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_provider_sql_delete_request_cb)(int request_id, data_control_h provider,
+ const char *where, void *user_data);
+
+/**
+ * @brief Called when the select request is received from an application using SQL-friendly interface based data control.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] provider The provider handle
+ * @param[in] column_list The column list to query
+ * @param[in] column_count The total number of columns to be queried
+ * @param[in] where A filter to select the desired rows \n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param[in] order The sorting order of the rows to query \n
+ * It is an SQL 'ORDER BY' clause excluding the 'ORDER BY' itself.
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_provider_sql_select_request_cb)(int request_id, data_control_h provider,
+ const char **column_list, int column_count, const char *where, const char *order, void *user_data);
+
+/**
+ * @brief Called when the request for obtaining the value list is received from the key-value structured data control consumer.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] provider The provider handle
+ * @param[in] key The key of the value list to obtain
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_provider_map_get_value_request_cb)(int request_id, data_control_h provider, const char *key, void *user_data);
+
+/**
+ * @brief Called when the request for replacing the value is received from the key-value structured data control consumer.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] provider The provider handle
+ * @param[in] key The key of the value to replace
+ * @param[in] old_value The value to replace
+ * @param[in] new_value The new value that replaces the existing value
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_provider_map_set_value_request_cb)(int request_id, data_control_h provider, const char *key,
+ const char *old_value, const char *new_value, void *user_data);
+
+/**
+ * @brief Called when the request for adding the value is received from the key-value structured data control consumer.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] provider The provider handle
+ * @param[in] key The key of the value to add
+ * @param[in] value The value to add
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_provider_map_add_value_request_cb)(int request_id, data_control_h provider, const char *key,
+ const char *value, void *user_data);
+
+/**
+ * @brief Called when the request for removing the value is received from the key-value structured data control consumer.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] provider The provider handle
+ * @param[in] key The key of the value to remove
+ * @param[in] value The value to remove
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_provider_map_remove_value_request_cb)(int request_id, data_control_h provider, const char *key,
+ const char *value, void *user_data);
+
+/**
+ * @brief The structure type to contain the set of callback functions for handling the request events
+ * of SQL-friendly interface based data control.
+ * @since_tizen 2.3
+ *
+ * @see data_control_provider_sql_select_request_cb()
+ * @see data_control_provider_sql_insert_request_cb()
+ * @see data_control_provider_sql_update_request_cb()
+ * @see data_control_provider_sql_delete_request_cb()
+ */
+typedef struct
+{
+ data_control_provider_sql_insert_request_cb insert_cb; /**< This callback function is called when a request for insert operation is received from other application. */
+ data_control_provider_sql_select_request_cb select_cb; /**< This callback function is called when a request for select operation is received from other application. */
+ data_control_provider_sql_update_request_cb update_cb; /**< This callback function is called when a request for update operation is received from other application. */
+ data_control_provider_sql_delete_request_cb delete_cb; /**< This callback function is called when a request for delete operation is received from other application. */
+} data_control_provider_sql_cb;
+
+/**
+ * @brief The structure type to contain the set of callback functions for handling the request events
+ * from the key-value structured data control consumer.
+ * @since_tizen 2.3
+ *
+ * @see data_control_provider_map_get_value_request_cb()
+ * @see data_control_provider_map_set_value_request_cb()
+ * @see data_control_provider_map_add_value_request_cb()
+ * @see data_control_provider_map_remove_value_request_cb()
+ */
+typedef struct
+{
+ data_control_provider_map_get_value_request_cb get_cb; /**< This callback function is called when a request for getting value is received from other application. */
+ data_control_provider_map_set_value_request_cb set_cb; /**< This callback function is called when a request for setting value is received from other application. */
+ data_control_provider_map_add_value_request_cb add_cb; /**< This callback function is called when a request for adding value is received from other application. */
+ data_control_provider_map_remove_value_request_cb remove_cb; /**< This callback function is called when a request for removing value is received from other application. */
+} data_control_provider_map_cb;
+
+/**
+ * @brief Registers a callback function for the SQL data control request.
+ * The provider is notified when a data control request is received from the client applications.
+ * @since_tizen 2.3
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] callback The callback function to be called when a data control request is received
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ */
+int data_control_provider_sql_register_cb(data_control_provider_sql_cb *callback, void *user_data);
+
+/**
+ * @brief Unregisters the callback functions.
+ * @since_tizen 2.3
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ */
+int data_control_provider_sql_unregister_cb(void);
+
+/**
+ * @brief Registers a callback function for the map data control request.
+ * The provider is notified when a data control request is received from the client applications.
+ * @since_tizen 2.3
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] callback The callback function to be called when a data control request is received
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ */
+int data_control_provider_map_register_cb(data_control_provider_map_cb *callback, void *user_data);
+
+/**
+ * @brief Unregisters the callback functions.
+ * @since_tizen 2.3
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ */
+int data_control_provider_map_unregister_cb(void);
+
+/**
+ * @brief Gets the application ID which sends the data control request.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[out] appid The application ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_provider_get_client_appid(int request_id, char **appid);
+
+/**
+ * @brief Sends the success result and the result set of the select request to the client application.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] db_handle The result DB handle for the result set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ */
+int data_control_provider_send_select_result(int request_id, void *db_handle);
+
+/**
+ * @brief Sends the success result of the insert request and the last inserted row ID to the client application.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] row_id The row ID of the database changed by the insert request
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_provider_send_insert_result(int request_id, long long row_id);
+
+/**
+ * @brief Sends the success result of the update request to the client application.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_provider_send_update_result(int request_id);
+
+/**
+ * @brief Sends the success result of the delete request to the client application.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_provider_send_delete_result(int request_id);
+
+/**
+ * @brief Sends the provider error message to the client application.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] error The provider-defined error message
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_provider_send_error(int request_id, const char *error);
+
+/**
+ * @brief Sends the success result of the request for setting, adding and removing the key-value structured data the client application.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_provider_send_map_result(int request_id);
+
+/**
+ * @brief Sends the success result of the request for getting the value list to the client application.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] value_list The result value list
+ * @param[in] value_count The number of the values
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ */
+int data_control_provider_send_map_get_value_result(int request_id, char **value_list, int value_count);
+
+/**
+ * @brief Creates SQL INSERT statement.
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ * @param[in] insert_map The column-value pairs to insert
+ *
+ * @return The SQL INSERT statement on success, otherwise NULL
+ * @exception DATA_CONTROL_ERROR_NONE Success
+ * @exception DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @exception DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+char* data_control_provider_create_insert_statement(data_control_h provider, bundle *insert_map);
+
+/**
+ * @brief Creates SQL DELETE statement.
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ * @param[in] where A filter to select the desired rows to delete \n
+ * Pass @c NULL if all rows need to be deleted.
+ *
+ * @return The SQL DELETE statement on success, otherwise NULL
+ * @exception DATA_CONTROL_ERROR_NONE Success
+ * @exception DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @exception DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+char* data_control_provider_create_delete_statement(data_control_h provider, const char *where);
+
+/**
+ * @brief Creates SQL UPDATE statement.
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ * @param[in] update_map The column-value pairs to update
+ * @param[in] where A filter to select the desired rows to update
+ *
+ * @return The SQL UPDATE statement on success, otherwise NULL
+ * @exception DATA_CONTROL_ERROR_NONE Success
+ * @exception DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @exception DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+char* data_control_provider_create_update_statement(data_control_h provider, bundle *update_map, const char *where);
+
+/**
+ * @brief Creates SQL SELECT statement.
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ * @param[in] column_list The column names to query \n
+ * Pass @c NULL if all columns need to be selected.
+ * @param[in] column_count The total number of columns to be queried
+ * @param[in] where A filter to select the desired rows
+ * @param[in] order The sorting order of rows to query
+ *
+ * @return The SQL SELECT statement on success, otherwise NULL
+ * @exception DATA_CONTROL_ERROR_NONE Success
+ * @exception DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @exception DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+char* data_control_provider_create_select_statement(data_control_h provider, const char **column_list, int column_count, const char *where, const char *order);
+
+/**
+ * @brief Checks whether the given provider ID matches the provider handle's provider ID.
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ * @param[in] provider_id The provider ID to be compared with handle's provider ID
+ *
+ * @return @c true if the provider_id matches,
+ * otherwise @c false if it does not match
+ * @exception DATA_CONTROL_ERROR_NONE Success
+ * @exception DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+bool data_control_provider_match_provider_id(data_control_h provider, const char *provider_id);
+
+/**
+ * @brief Checks whether the given data ID matches the provider handle's data ID.
+ * @remarks The specific error code can be obtained using the get_last_result() method. Error codes are described in Exception section.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ * @param[in] data_id The data ID to be compared with handle's data ID
+ *
+ * @return @c true if the @a data_id matches,
+ * otherwise @c false if it does not match
+ * @exception DATA_CONTROL_ERROR_NONE Success
+ * @exception DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+bool data_control_provider_match_data_id(data_control_h provider, const char *data_id);
+
+/**
+* @}
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_APPFW_DATA_CONTROL_PROVIDER_H_ */
+
--- /dev/null
+//
+// Copyright (c) 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 __TIZEN_APPFW_DATA_CONTROL_SQL_H__
+#define __TIZEN_APPFW_DATA_CONTROL_SQL_H__
+
+#include <data_control_types.h>
+#include <data_control_sql_cursor.h>
+#include <bundle.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file data_control_sql.h
+ * @brief This is the header file for the SQL-friendly interface based data control.
+ */
+
+/**
+ * @addtogroup CAPI_DATA_CONTROL_CONSUMER_MODULE
+ * @{
+ */
+
+/**
+ * @brief Called when a response is received for an insert operation from an application using the SQL-friendly interface based data control.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] provider The provider handle
+ * @param[in] inserted_row_id The inserted row ID set by the data control
+ * @param[in] provider_result Set to @c true if the data control provider successfully processed, \n
+ * otherwise set to @c false
+ * @param[in] error The error message from the data control provider
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_sql_insert_response_cb)(int request_id, data_control_h provider,
+ long long inserted_row_id, bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief Called when a response is received for a delete operation from an application using the SQL-friendly interface based data control.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID that identifies the data control
+ * @param[in] provider_result Set to @c true if the data control provider successfully processed, \n
+ * otherwise set to @c false
+ * @param[in] error The error message from the data control provider
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_sql_delete_response_cb)(int request_id, data_control_h provider,
+ bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief Called when a response is received for a select operation from an application using the SQL-friendly interface based data control.
+ * @since_tizen 2.3
+ *
+ * @remarks @a enumerator will be removed after this callback is called.
+ *
+ * @param[in] request_id The request ID
+ * @param[in] provider The provider handle
+ * @param[in] enumerator The enumerator for navigating the result of data control select request
+ * @param[in] provider_result Set to @c true if the data control provider successfully processed, \n
+ * otherwise set to @c false
+ * @param[in] error The error message from the data control provider
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_sql_select_response_cb)(int request_id, data_control_h provider,
+ result_set_cursor enumerator, bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief Called when a response is received for an update operation from an application using the SQL-friendly interface based data control.
+ * @since_tizen 2.3
+ *
+ * @param[in] request_id The request ID
+ * @param[in] provider The provider handle
+ * @param[in] provider_result Set to @c true if the data control provider successfully processed, \n
+ * otherwise set to @c false
+ * @param[in] error The error message from the data control provider
+ * @param[in] user_data The user data passed from the register function
+ */
+typedef void (*data_control_sql_update_response_cb)(int request_id, data_control_h provider,
+ bool provider_result, const char *error, void *user_data);
+
+/**
+ * @brief The structure type to contain the set of callback functions for handling the response events
+ * of the SQL-friendly interface based data control.
+ * @since_tizen 2.3
+ *
+ * @see data_control_sql_select_response_cb()
+ * @see data_control_sql_insert_response_cb()
+ * @see data_control_sql_update_response_cb()
+ * @see data_control_sql_delete_response_cb()
+ */
+typedef struct
+{
+ data_control_sql_select_response_cb select_cb; /**< This callback function is called when a response is received for an select operation from an application using the SQL-friendly interface based data control. */
+ data_control_sql_insert_response_cb insert_cb; /**< This callback function is called when a response is received for an insert operation from an application using the SQL-friendly interface based data control. */
+ data_control_sql_update_response_cb update_cb; /**< This callback function is called when a response is received for an update operation from an application using the SQL-friendly interface based data control. */
+ data_control_sql_delete_response_cb delete_cb; /**< This callback function is called when a response is received for a delete operation from an application using the SQL-friendly interface based data control. */
+} data_control_sql_response_cb;
+
+/**
+ * @brief Creates a provider handle.
+ * @since_tizen 2.3
+ *
+ * @remarks The following example demonstrates how to use the %data_control_sql_create() method:
+ *
+ * @code
+ *
+ * int main()
+ * {
+ * const char *provider_id = "http://tizen.org/datacontrol/provider/example";
+ * const char *data_id = "table";
+ * data_control_h provider;
+ * int result = 0;
+ *
+ * result = data_control_sql_create(&provider);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Creating data control provider is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = data_control_sql_set_provider_id(provider, provider_id);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Setting providerID is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = data_control_sql_set_data_id(provider, data_id);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Setting dataID is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * // Executes some operations
+ *
+ * result = data_control_sql_destroy(provider);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Destroying data control provider is failed with error: %d", result);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+
+ * @param[out] provider The provider handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see data_control_sql_destroy()
+ */
+int data_control_sql_create(data_control_h *provider);
+
+/**
+ * @brief Destroys the provider handle and releases all its resources.
+ * @since_tizen 2.3
+ *
+ * @remarks When operations of data control are finished, this function must be called to prevent the memory leak.
+ *
+ * @param[in] provider The provider handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @see data_control_sql_create()
+ */
+int data_control_sql_destroy(data_control_h provider);
+
+/**
+ * @brief Sets the Provider ID.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ * @param[in] provider_id The data control provider ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see data_control_sql_get_provider_id()
+ */
+int data_control_sql_set_provider_id(data_control_h provider, const char *provider_id);
+
+/**
+ * @brief Gets the Provider ID.
+ * @since_tizen 2.3
+ *
+ * @remarks You must release @a provider_id using free() after it is used.
+ *
+ * @param[in] provider The provider handle
+ * @param[out] provider_id The data control provider ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see data_control_sql_set_provider_id()
+ */
+int data_control_sql_get_provider_id(data_control_h provider, char **provider_id);
+
+/**
+ * @brief Sets the data ID.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ * @param[in] data_id A string for identifying a specific table to operate \n
+ * The string consists of one or more components separated by a slash('/').
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see data_control_sql_get_data_id()
+ */
+int data_control_sql_set_data_id(data_control_h provider, const char *data_id);
+
+/**
+ * @brief Gets the data ID.
+ * @since_tizen 2.3
+ *
+ * @remarks You must release @a data_id using free() after it is used.
+ *
+ * @param[in] provider The provider handle
+ * @param[out] data_id A string for identifying a specific table to operate \n
+ * The string consists of one or more components separated by a slash('/').
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see data_control_sql_set_data_id()
+ */
+int data_control_sql_get_data_id(data_control_h provider, char **data_id);
+
+/**
+ * @brief Registers a callback function for the SQL data control response.
+ * @since_tizen 2.3
+ *
+ * remarks The application is notified when a data control response is received from the @a provider.
+ *
+ * @param[in] provider The provider handle
+ * @param[in] callback The callback function to be called when a response is received
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see data_control_sql_unregister_response_cb()
+ */
+int data_control_sql_register_response_cb(data_control_h provider, data_control_sql_response_cb* callback, void *user_data);
+
+/**
+ * @brief Unregisters the callback function in the @a provider.
+ * @since_tizen 2.3
+ *
+ * @param[in] provider The provider handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ */
+int data_control_sql_unregister_response_cb(data_control_h provider);
+
+/**
+ * @brief Deletes rows of a table owned by the SQL-type data control provider.
+ * @since_tizen 2.3
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/appmanager.launch
+ *
+ * @remarks If you want to use this api, you must add privileges.
+ * @remarks If the value is a string, then the value must be wrapped in single quotes, else it does not need to be wrapped in single quotes.
+ * @remarks The following example demonstrates how to use the %data_control_sql_delete() method:
+ *
+ * @code
+ *
+ * void sql_delete_response_cb(int request_id, data_control_h provider, bool provider_result, const char *error, void *user_data) {
+ * if (provider_result) {
+ * LOGI(The delete operation is successful");
+ * }
+ * else {
+ * LOGI("The delete operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * data_control_sql_response_cb sql_callback;
+ *
+ * int main()
+ * {
+ * const char *where = "group = 'friend'";
+ * int result = 0;
+ * int req_id = 0;
+ *
+ * sql_callback.delete_cb = sql_delete_response_cb;
+ * result = data_control_sql_register_response_cb(provider, &sql_callback, void *user_data);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = data_control_sql_delete(provider, where, &req_id);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Deleting is failed with error: %d", result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+ *
+ * @param[in] provider The provider handle
+ * @param[in] where A filter to select the desired rows to delete \n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param[out] request_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ */
+int data_control_sql_delete(data_control_h provider, const char *where, int *request_id);
+
+/**
+ * @brief Inserts new rows in a table owned by the SQL-type data control provider.
+ * @since_tizen 2.3
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/appmanager.launch
+ *
+ * @remarks If you want to use this api, you must add privileges.
+ * @remarks The following example demonstrates how to use the %data_control_sql_insert() method:
+ *
+ * @code
+ *
+ * void sql_insert_response_cb(int request_id, data_control_h provider, long long inserted_row_id, bool provider_result, const char *error, void *user_data) {
+ * if (provider_result) {
+ * LOGI("The insert operation is successful");
+ * }
+ * else {
+ * LOGI("The insert operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * data_control_sql_response_cb sql_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * bundle *b = NULL;
+ *
+ * sql_callback.insert_cb = sql_insert_response_cb;
+ * result = data_control_sql_register_response_cb(provider, &sql_callback, void *user_data);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * b = bundle_create();
+ * bundle_add(b, "WORD", "test");
+ * bundle_add(b, "WORD_DESC", "test description");
+ *
+ * result = data_control_sql_insert(provider, b, &req_id);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Inserting is failed with error: %d", result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * bundle_free(b);
+ * return result;
+ * }
+ *
+ * @endcode
+
+ * @param[in] provider The provider handle
+ * @param[in] insert_data The column-value pairs to insert\ n
+ * If the value is a string, then the value must be wrapped in single quotes,
+ * else it does not need to be wrapped in single quotes.
+ * @param[out] request_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ */
+int data_control_sql_insert(data_control_h provider, const bundle* insert_data, int *request_id);
+
+/**
+ * @brief Selects the specified columns to be queried.
+ * @since_tizen 2.3
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/appmanager.launch
+ *
+ * @remarks If you want to use this api, you must add privileges.
+ * @remarks The following example demonstrates how to use the %data_control_sql_select() method:
+ *
+ * @code
+ *
+ * void sql_select_response_cb(int request_id, data_control_h provider, result_set_cursor *enumerator, bool provider_result, const char *error, void *user_data) {
+ * if (provider_result) {
+ * LOGI("The select operation is successful");
+ * }
+ * else {
+ * LOGI("The select operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * data_control_sql_response_cb sql_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * char *column_list[2];
+ * column_list[0] = "WORD";
+ * column_list[1] = "WORD_DESC";
+ * const char *where = "WORD = 'test'";
+ * const char *order = "WORD ASC";
+ *
+ * sql_callback.select_cb = sql_select_response_cb;
+ * result = data_control_sql_register_response_cb(provider, &sql_callback, void *user_data);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * result = data_control_sql_select(provider, column_list, 2, where, order, &req_id);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Selecting is failed with error: %d", result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * return result;
+ * }
+ *
+ * @endcode
+
+
+ * @param[in] provider The provider handle
+ * @param[in] column_list The column list to query
+ * @param[in] column_count The total number of columns to be queried
+ * @param[in] where A filter to select the desired rows \n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param[in] order The sorting order of the rows to query \n
+ * It is an SQL 'ORDER BY' clause excluding the 'ORDER BY' itself.
+ * @param[out] request_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ */
+int data_control_sql_select(data_control_h provider, char **column_list, int column_count, const char *where, const char *order, int *request_id);
+
+/**
+ * @brief Selects the specified columns to be queried.
+ * @since_tizen 2.3
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/appmanager.launch
+ *
+ * @remarks If you want to use this api, you must add privileges.
+ *
+ * @param[in] provider The provider handle
+ * @param[in] column_list The column list to query
+ * @param[in] column_count The total number of columns to be queried
+ * @param[in] where A filter to select the desired rows \n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param[in] order The sorting order of the rows to query \n
+ * It is an SQL 'ORDER BY' clause excluding the 'ORDER BY' itself.
+ * @param[in] page_number The page number of the result set \n
+ * It starts from @c 1.
+ * @param[in] count_per_page The desired maximum count of rows on a page
+ * @param[out] request_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ * @see data_control_sql_select()
+ */
+int data_control_sql_select_with_page(data_control_h provider, char **column_list, int column_count, const char *where, const char *order, int page_number, int count_per_page, int *request_id);
+
+/**
+ * @brief Updates values of a table owned by the SQL-type data control provider.
+ * @since_tizen 2.3
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/appmanager.launch
+ *
+ * @remarks If you want to use this api, you must add privileges.
+ * @remarks The following example demonstrates how to use the %data_control_sql_update() method:
+ *
+ * @code
+ *
+ * void sql_update_response_cb(int request_id, data_control_h provider, bool provider_result, const char *error, void *user_data) {
+ * if (provider_result) {
+ * LOGI("The update operation is successful");
+ * }
+ * else {
+ * LOGI("The update operation for the request %d is failed. error message: %s", request_id, error);
+ * }
+ * }
+ *
+ * data_control_sql_response_cb sql_callback;
+ *
+ * int main()
+ * {
+ * int result = 0;
+ * int req_id = 0;
+ * const char *where = "WORD = 'test'";
+ * bundle *b = NULL;
+ *
+ * sql_callback.update_cb = sql_update_response_cb;
+ * result = data_control_sql_register_response_cb(provider, &sql_callback, void *user_data);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Registering the callback function is failed with error: %d", result);
+ * return result;
+ * }
+ *
+ * b = bundle_create();
+ * bundle_add(b, "WORD", "test_new");
+ *
+ * result = data_control_sql_update(provider, b, where, &req_id);
+ * if (result != DATA_CONTROL_ERROR_NONE) {
+ * LOGE("Updating is failed with error: %d", result);
+ * }
+ * else {
+ * LOGI("req_id is %d", req_id);
+ * }
+ *
+ * bundle_free(b);
+ * return result;
+ * }
+ *
+ * @endcode
+ *
+ *
+ * @param[in] provider The provider handle
+ * @param[in] update_data The column-value pairs to update \n
+ * If the value is a string, the value must be wrapped in single quotes,
+ * else it does not need to be wrapped in single quotes.
+ * @param[in] where A filter to select the desired rows to update \n
+ * It is an SQL 'WHERE' clause excluding the 'WHERE' itself such as column1 = 'stringValue' and column2 = numericValue.
+ * @param[out] request_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_PERMISSION_DENIED Permission denied
+ */
+int data_control_sql_update(data_control_h provider, const bundle* update_data, const char *where, int *request_id);
+
+/**
+* @}
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_APPFW__DATA_CONTROL_SQL_H__ */
--- /dev/null
+//
+// Copyright (c) 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 __TIZEN_APPFW_DATA_CONTROL_SQL_ENUMERATOR_H_
+#define __TIZEN_APPFW_DATA_CONTROL_SQL_ENUMERATOR_H_
+
+#include <stdio.h>
+#include "data_control_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file data_control_sql_cursor.h
+ * @brief This is the header file for the cursor of the SQL-friendly interface based data control.
+ */
+
+/**
+ * @addtogroup CAPI_DATA_CONTROL_CONSUMER_MODULE
+ * @{
+ */
+
+/**
+ * @brief The structure type to represent a SQL result set.
+ * @details This type can be used to enumerate through the result set of an SQL query.
+ * @since_tizen 2.3
+ */
+typedef struct result_set_s *result_set_cursor;
+
+/**
+ * @brief Moves the cursor to the first position.
+ * @since_tizen 2.3
+ *
+ * @remarks The following example demonstrates how to use the %data_control_sql_step_first() method:
+ *
+ * @code
+ *
+ * void sql_select_response_cb(int request_id, data_control_h provider, result_set_cursor cursor, bool provider_result, const char *error)
+ * {
+ * char person_name[32] = {0,};
+ * long long person_number = -1;
+ *
+ * data_control_sql_step_first(cursor);
+ * data_control_sql_get_text_data(cursor, 0, person_name);
+ * data_control_sql_get_int64_data(cursor, 1, &person_number);
+ * printf("The person %s has the number %l", person_name, person_number);
+ * }
+ *
+ * @endcode
+
+ * @param[in] cursor The cursor that navigates the result of the request for the select operation
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_sql_step_first(result_set_cursor cursor);
+
+/**
+ * @brief Moves the cursor to the last position.
+ * @since_tizen 2.3
+ *
+ * @remarks The following example demonstrates how to use the %data_control_sql_step_last() method:
+ *
+ * @code
+ *
+ * void sql_select_response_cb(int request_id, data_control_h provider, result_set_cursor cursor, bool provider_result, const char *error)
+ * {
+ * char person_name[32] = {0,};
+ * long long person_number = -1;
+ *
+ * data_control_sql_step_last(cursor);
+ * data_control_sql_get_text_data(cursor, 0, person_name);
+ * data_control_sql_get_int64_data(cursor, 1, &person_number);
+ * printf("The person %s has the number %l", person_name, person_number);
+ * }
+ *
+ * @endcode
+
+ * @param[in] cursor The cursor that navigates the result of data control select request
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_sql_step_last(result_set_cursor cursor);
+
+/**
+ * @brief Moves the cursor to the next position.
+ * @since_tizen 2.3
+ *
+ * @remarks The following example demonstrates how to use the %data_control_sql_step_next() method:
+ *
+ * @code
+ *
+ * void sql_select_response_cb(int request_id, data_control_h provider, result_set_cursor cursor, bool provider_result, const char *error)
+ * {
+ * char person_name[32] = {0,};
+ * long long person_number = -1;
+ * while (data_control_sql_step_next(cursor) == DATA_CONTROL_ERROR_NONE) {
+ * data_control_sql_get_text_data(cursor, 0, person_name);
+ * data_control_sql_get_int64_data(cursor, 1, &person_number);
+ * printf("The person %s has the number %l", person_name, person_number);
+ * }
+ * }
+ *
+ * @endcode
+ *
+ * @param[in] cursor The cursor that navigates the result of the request for the select operation
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_sql_step_next(result_set_cursor cursor);
+
+/**
+ * @brief Moves the cursor to the previous position.
+ * @since_tizen 2.3
+ *
+ * @param[in] cursor The cursor that navigates the result of the request for the select operation
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_sql_step_previous(result_set_cursor cursor);
+
+/**
+ * @brief Gets the number of columns for this cursor.
+ * @since_tizen 2.3
+ *
+ * @param[in] cursor The cursor that navigates the result of the request for the select operation
+ *
+ * @return The number of columns in the calling cursor
+ */
+int data_control_sql_get_column_count(result_set_cursor cursor);
+
+/**
+ * @brief Gets the name of the column indicated by the specified index.
+ * @since_tizen 2.3
+ *
+ * @param[in] cursor The cursor that navigates the result of the request for the select operation
+ * @param[in] column_index The index of the destination column
+ * @param[out] name The name of the destination column. You should provide a buffer for the column name. The limit of column name length is 4096 bytes.
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_sql_get_column_name(result_set_cursor cursor, int column_index, char *name);
+
+/**
+ * @brief Gets the size of the data in the column indicated by the specified index.
+ * @since_tizen 2.3
+ *
+ * @param[in] cursor The cursor that navigates the result of the request for the select operation
+ * @param[in] column_index The index of the destination column
+ *
+ * @return The size of data in the column indicated by the specified index \n
+ * If an error is occurred, then a negative value is returned.
+ *
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_sql_get_column_item_size(result_set_cursor cursor, int column_index);
+
+/**
+ * @brief Gets the type of the column indicated by the specified index.
+ * @since_tizen 2.3
+ *
+ * @param[in] cursor The cursor that navigates the result of the request for the select operation
+ * @param[in] column_index The index of the destination column
+ * @param[out] type The type of the destination column
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_sql_get_column_item_type(result_set_cursor cursor, int column_index, data_control_sql_column_type_e* type);
+
+/**
+ * @brief Gets a blob data from the column indicated by the specified index.
+ * @since_tizen 2.3
+ *
+ * @param[in] cursor The cursor that navigates the result of the request for the select operation
+ * @param[in] column_index The index of the destination column
+ * @param[out] data The blob value obtained from the column
+ * @param[out] size The size of the data
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_MAX_EXCEEDED Too long argument
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_sql_get_blob_data(result_set_cursor cursor, int column_index, void *data, int size);
+
+/**
+ * @brief Gets an int value from the column indicated by the specified index.
+ * @since_tizen 2.3
+ *
+ * @param[in] cursor The cursor that navigates the result of the request for the select operation
+ * @param[in] column_index The index of the destination column
+ * @param[out] data The integer value obtained from the column
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_sql_get_int_data(result_set_cursor cursor, int column_index, int *data);
+
+/**
+ * @brief Gets a long long value from the column indicated by the specified index.
+ * @since_tizen 2.3
+ *
+ * @param[in] cursor The cursor that navigates the result of the request for the select operation
+ * @param[in] column_index The index of the destination column
+ * @param[out] data The 64-bit integer value obtained from the column
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_sql_get_int64_data(result_set_cursor cursor, int column_index, long long *data);
+
+/**
+ * @brief Gets a double value from the column indicated by the specified index.
+ * @since_tizen 2.3
+ *
+ * @param[in] cursor The cursor that navigates the result of the request for the select operation
+ * @param[in] column_index The index of the destination column
+ * @param[out] data The value obtained from the column as double
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_sql_get_double_data(result_set_cursor cursor, int column_index, double *data);
+
+/**
+ * @brief Gets a text value from the column indicated by the specified index.
+ * @since_tizen 2.3
+ *
+ * @param[in] cursor The cursor that navigates the result of the request for the select operation
+ * @param[in] column_index The index of the destination column
+ * @param[out] data The value obtained from the column as text. You should provide a buffer for the data. You can get the size of data via data_control_sql_get_column_item_size().
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ */
+int data_control_sql_get_text_data(result_set_cursor cursor, int column_index, char *data);
+
+/**
+* @}
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_APPFW_DATA_CONTROL_SQL_ENUMERATOR_H_ */
+
--- /dev/null
+//
+// Copyright (c) 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 __TIZEN_APPFW__DATA_CONTROL_TYPES_H__
+#define __TIZEN_APPFW__DATA_CONTROL_TYPES_H__
+
+#include <tizen.h>
+
+/**
+ * @file data_control_types.h
+ * @brief This is the header file for data types of the data-control.
+ */
+
+/**
+ * @addtogroup CAPI_DATA_CONTROL_MODULE
+ * @{
+ */
+
+/**
+ * @brief The structure type for the provider handle.
+ * @since_tizen 2.3
+ */
+typedef struct data_control_s *data_control_h;
+
+/**
+ * @brief Enumeration for different types of columns in a SQL table.
+ * @since_tizen 2.3
+ */
+typedef enum
+{
+ DATA_CONTROL_SQL_COLUMN_TYPE_UNDEFINED = 0, /**< undefined type */
+ DATA_CONTROL_SQL_COLUMN_TYPE_INT64, /**< integer type */
+ DATA_CONTROL_SQL_COLUMN_TYPE_DOUBLE, /**< double type */
+ DATA_CONTROL_SQL_COLUMN_TYPE_TEXT, /**< text type */
+ DATA_CONTROL_SQL_COLUMN_TYPE_BLOB, /**< blob type */
+ DATA_CONTROL_SQL_COLUMN_TYPE_NULL /**< null value */
+} data_control_sql_column_type_e;
+
+/**
+ * @brief Enumeration for the various error-codes an API can return.
+ * @since_tizen 2.3
+ */
+typedef enum
+{
+ DATA_CONTROL_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
+ DATA_CONTROL_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
+ DATA_CONTROL_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR, /**< I/O error */
+ DATA_CONTROL_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+ DATA_CONTROL_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
+ DATA_CONTROL_ERROR_MAX_EXCEEDED = TIZEN_ERROR_DATA_CONTROL | 0x01 /**< Too long argument */
+} data_control_error_e;
+
+/**
+* @}
+*/
+
+#endif /* __TIZEN_APPFW__DATA_CONTROL_TYPES_H__ */
+
--- /dev/null
+Name: data-control
+Summary: Data Control library
+Version: 0.0.16
+Release: 1
+Group: Application Framework/Libraries
+License: Apache-2.0
+Source0: %{name}-%{version}.tar.gz
+BuildRequires: cmake
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(bundle)
+BuildRequires: pkgconfig(appsvc)
+BuildRequires: pkgconfig(pkgmgr-info)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(capi-base-common)
+
+# runtime requires
+Requires(post): /sbin/ldconfig
+Requires(post): coreutils
+Requires(postun): /sbin/ldconfig
+
+Provides: capi-data-control
+
+%description
+Data Control library
+
+%package devel
+Summary: Data Control library (Development)
+Group: Application Framework/Development
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+Data Control library (DEV)
+
+
+%prep
+%setup -q
+
+%build
+
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
+%cmake . -DFULLVER=%{version} -DMAJORVER=${MAJORVER}
+
+# Call make instruction with smp support
+%__make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+
+%make_install
+mkdir -p %{buildroot}/tmp/datacontrol/request
+mkdir -p %{buildroot}/tmp/datacontrol/result
+mkdir -p %{buildroot}/usr/share/license
+install LICENSE.APLv2 %{buildroot}/usr/share/license/%{name}
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+
+%files
+%{_libdir}/lib%{name}.so.*
+%manifest %{name}.manifest
+/usr/share/license/%{name}
+
+%files devel
+%{_includedir}/appfw/*.h
+%{_libdir}/pkgconfig/*.pc
+%{_libdir}/lib%{name}.so
+
--- /dev/null
+#include <dlog.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <glib.h>
+#include <pthread.h>
+
+#include <bundle.h>
+#include <pkgmgr-info.h>
+
+#include "data-control-sql-cursor.h"
+#include "data-control-internal.h"
+
+#define MAX_COLUMN_SIZE 512
+#define MAX_STATEMENT_SIZE 1024
+
+int
+_datacontrol_sql_get_cursor(const char *path)
+{
+
+ return 0;
+}
+
+char*
+_datacontrol_create_select_statement(char *data_id, const char **column_list, int column_count, const char *where, const char *order, int page_number, int count_per_page)
+{
+ char *column = calloc(MAX_COLUMN_SIZE, sizeof(char));
+ int i = 0;
+
+ while (i < column_count - 1)
+ {
+ LOGI("column i = %d, %s", i, column_list[i]);
+ strcat(column, column_list[i]);
+ strcat(column, ", ");
+ i++;
+ }
+
+ LOGI("column i = %d, %s", i, column_list[i]);
+ strcat(column, column_list[i]);
+
+ char *statement = calloc(MAX_STATEMENT_SIZE, sizeof(char));
+ snprintf(statement, MAX_STATEMENT_SIZE, "SELECT %s * FROM %s WHERE %s ORDER BY %s", column, data_id, where, order);
+
+ LOGI("SQL statement: %s", statement);
+
+ free(column);
+ return statement;
+}
+
+int
+_datacontrol_create_request_id(void)
+{
+ static int id = 0;
+
+ g_atomic_int_inc(&id);
+
+ return id;
+}
--- /dev/null
+//
+// Copyright (c) 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.
+//
+
+/**
+ * @file data-control-internal.h
+ * @brief This is the header file for private keys of the data-control.
+ */
+
+#ifndef _APPFW_DATA_CONTROL_INTERNAL_H_
+#define _APPFW_DATA_CONTROL_INTERNAL_H_
+
+#undef LOG_TAG
+#ifndef LOG_TAG
+#define LOG_TAG "DATA_CONTROL"
+#endif
+
+#define MAX_LEN_DATACONTROL_REQ_TYPE 8
+#define MAX_LEN_DATACONTROL_COLUMN_COUNT 8
+
+#define OSP_K_LAUNCH_TYPE "__OSP_LAUNCH_TYPE__"
+#define OSP_K_ARG "__OSP_ARGS__"
+#define OSP_K_REQUEST_ID "__OSP_REQUEST_ID__"
+#define OSP_K_DATACONTROL_PROVIDER "__OSP_DATACONTROL_PROVIDER__"
+#define OSP_K_DATACONTROL_DATA "__OSP_DATACONTROL_DATA__"
+#define OSP_K_DATACONTROL_REQUEST_TYPE "__OSP_DATACONTROL_REQUEST_TYPE__"
+#define OSP_K_DATACONTROL_PROTOCOL_VERSION "__OSP_DATACONTROL_PROTOCOL_VERSION__"
+#define OSP_K_CALLER_TYPE "__OSP_CALLER_TYPE__"
+
+#define DATACONTROL_SELECT_STATEMENT "DATACONTROL_SELECT_STATEMENT"
+
+#define DATACONTROL_EMPTY "NULL"
+#define DATACONTROL_SELECT_EXTRA_COUNT 6 // data id, column count, where, order, page, per_page
+
+
+
+#define OSP_V_LAUNCH_TYPE_DATACONTROL "datacontrol"
+#define OSP_V_VERSION_2_1_0_3 "ver_2.1.0.3"
+#define OSP_V_CALLER_TYPE_OSP "osp"
+
+#define DATACONTROL_REQUEST_FILE_PREFIX "/tmp/datacontrol/request"
+#define DATACONTROL_RESULT_FILE_PREFIX "/tmp/datacontrol/result."
+
+
+/**
+ * @brief Enumerations of different type of data control requests.
+ */
+typedef enum
+{
+ DATACONTROL_TYPE_ERROR = -1,
+ DATACONTROL_TYPE_UNDEFINED,
+ DATACONTROL_TYPE_SQL_SELECT,
+ DATACONTROL_TYPE_SQL_INSERT,
+ DATACONTROL_TYPE_SQL_UPDATE,
+ DATACONTROL_TYPE_SQL_DELETE,
+ DATACONTROL_TYPE_MAP_GET,
+ DATACONTROL_TYPE_MAP_SET,
+ DATACONTROL_TYPE_MAP_ADD,
+ DATACONTROL_TYPE_MAP_REMOVE,
+ DATACONTROL_TYPE_MAX = 255
+} datacontrol_request_type;
+
+int
+datacontrol_sql_set_cursor(const char *path);
+
+char*
+_datacontrol_create_select_statement(char *data_id, const char **column_list, int column_count, const char *where, const char *order, int page_number, int count_per_page);
+
+int
+_datacontrol_create_request_id(void);
+
+#endif /* _APPFW_DATA_CONTROL_INTERNAL_H_ */
+
--- /dev/null
+#include <dlog.h>
+#include <errno.h>
+#include <search.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <glib.h>
+#include <pthread.h>
+#include <fcntl.h>
+
+#include <appsvc/appsvc.h>
+#include <aul/aul.h>
+#include <bundle.h>
+#include <pkgmgr-info.h>
+
+#include "data-control-map.h"
+#include "data-control-internal.h"
+
+struct datacontrol_s {
+ char *provider_id;
+ char *data_id;
+};
+
+typedef struct
+{
+ char *provider_id;
+ char *app_id;
+ char *data_id;
+ char *access_info;
+ void *user_data;
+ datacontrol_map_response_cb *map_response_cb;
+} map_response_cb_s;
+
+static void *datacontrol_map_tree_root = NULL;
+static const int MAX_ARGUMENT_SIZE = 16384; // 16KB
+
+static void
+datacontrol_map_call_cb(const char *provider_id, int request_id, datacontrol_request_type type,
+ const char *data_id, bool provider_result, const char *error, char **result_value_list, int result_value_count, void* data)
+{
+ LOGI("datacontrol_map_call_cb, dataID: %s", data_id);
+
+ datacontrol_map_response_cb *callback = NULL;
+
+ map_response_cb_s *map_dc = NULL;
+ map_dc = (map_response_cb_s *)data;
+ callback = map_dc->map_response_cb;
+ if (!callback)
+ {
+ LOGE("no listener set");
+ return;
+ }
+
+ datacontrol_h provider;
+ datacontrol_map_create(&provider);
+
+ datacontrol_map_set_provider_id(provider, provider_id);
+ datacontrol_map_set_data_id(provider, data_id);
+
+ switch (type)
+ {
+ case DATACONTROL_TYPE_MAP_GET:
+ {
+ LOGI("GET VALUE");
+ if (callback != NULL && callback->get != NULL)
+ {
+ callback->get(request_id, provider, result_value_list, result_value_count, provider_result, error, map_dc->user_data);
+ }
+ else
+ {
+ LOGI("No registered callback function");
+ }
+
+ break;
+ }
+ case DATACONTROL_TYPE_MAP_SET:
+ {
+ LOGI("SET VALUE");
+ if (callback != NULL && callback->set != NULL)
+ {
+ callback->set(request_id, provider, provider_result, error, map_dc->user_data);
+ }
+ else
+ {
+ LOGI("No registered callback function");
+ }
+
+ break;
+ }
+ case DATACONTROL_TYPE_MAP_ADD:
+ {
+ LOGI("ADD VALUE");
+ if (callback != NULL && callback->add!= NULL)
+ {
+ callback->add(request_id, provider, provider_result, error, map_dc->user_data);
+ }
+ else
+ {
+ LOGI("No registered callback function");
+ }
+
+ break;
+ }
+ case DATACONTROL_TYPE_MAP_REMOVE:
+ {
+ LOGI("REMOVE VALUE");
+ if (callback != NULL && callback->remove != NULL)
+ {
+ callback->remove(request_id, provider, provider_result, error, map_dc->user_data);
+ }
+ else
+ {
+ LOGI("No registered callback function");
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ datacontrol_map_destroy(provider);
+}
+
+static void
+datacontrol_map_instance_free(void *datacontrol_map_instance)
+{
+ map_response_cb_s *dc = (map_response_cb_s *)datacontrol_map_instance;
+ if (dc)
+ {
+ free(dc->provider_id);
+ free(dc->data_id);
+ free(dc->app_id);
+ free(dc->access_info);
+ free(datacontrol_map_instance);
+ }
+
+ return;
+}
+
+static int
+datacontrol_map_instance_compare(const void *l_datacontrol_map_instance, const void *r_datacontrol_map_instance)
+{
+ map_response_cb_s *dc_left = (map_response_cb_s *)l_datacontrol_map_instance;
+ map_response_cb_s *dc_right = (map_response_cb_s *)r_datacontrol_map_instance;
+ return strcmp(dc_left->provider_id, dc_right->provider_id);
+}
+
+static char**
+datacontrol_map_get_value_list(const char *path, int count)
+{
+ char **value_list = NULL;
+ int i = 0;
+ int fd = 0;
+ int ret = 0;
+
+ value_list = (char **) calloc(count, sizeof(char *));
+ if (value_list == NULL)
+ {
+ LOGE("Failed to create value list");
+ return NULL;
+ }
+
+ SECURE_LOGI("The result file of GET: %s", path);
+ /* TODO - shoud be changed to solve security concerns */
+ fd = open(path, O_RDONLY, 644);
+ if (fd == -1)
+ {
+ SECURE_LOGE("unable to open update_map file: %d", errno);
+ goto ERROR;
+ }
+
+ while (count)
+ {
+ int length = 0;
+ int size = read(fd, &length, sizeof(int));
+ if (size <= 0)
+ {
+ SECURE_LOGE("unable to read the result value file: %d", errno);
+ goto ERROR;
+ }
+
+ value_list[i] = (char *) calloc(length + 1, sizeof(char));
+
+ size = read(fd, value_list[i], length);
+ if (size <= 0)
+ {
+ SECURE_LOGE("unable to read the result value file: %d", errno);
+ ++i;
+ goto ERROR;
+ }
+
+ LOGI("value_list[%d] = %s", i, value_list[i]);
+ ++i;
+ --count;
+ }
+
+ close(fd);
+ ret = remove(path);
+ if (ret == -1)
+ {
+ SECURE_LOGE("unable to remove the result value file(%s). errno = %d", path, errno);
+ }
+
+ return value_list;
+
+ERROR:
+ if (value_list)
+ {
+ int j;
+ for (j = 0; j < i; j++)
+ {
+ free(value_list[j]);
+ }
+ free(value_list);
+ }
+
+ close(fd);
+ ret = remove(path);
+ if (ret == -1)
+ {
+ SECURE_LOGE("unable to remove the result value file(%s). errno = %d", path, errno);
+ }
+ return NULL;
+}
+
+static int
+datacontrol_map_handle_cb(bundle* b, int request_code, appsvc_result_val res, void* data)
+{
+ LOGI("datacontrol_map_handle_cb, request_code: %d, result: %d", request_code, res);
+
+ int ret = 0;
+ const char** result_list = NULL;
+ const char* provider_id = NULL;
+ const char* data_id = NULL;
+ const char* error_message = NULL;
+ datacontrol_request_type request_type = 0;
+ int request_id = -1;
+ int result_list_len = 0;
+ int provider_result = 0;
+ int value_count = 0;
+ const char* result_path = NULL;
+ char** value_list = NULL;
+ const char* p = NULL;
+
+ if (!b)
+ {
+ LOGE("the bundle returned from datacontrol-provider-service is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ p = appsvc_get_data(b, OSP_K_REQUEST_ID);
+ if (!p)
+ {
+ LOGE("Invalid Bundle: request_id is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+ else
+ {
+ request_id = atoi(p);
+ }
+
+ SECURE_LOGI("Request ID: %d", request_id);
+
+ // result list
+ result_list = appsvc_get_data_array(b, OSP_K_ARG, &result_list_len);
+ if (!result_list)
+ {
+ LOGE("Invalid Bundle: arguement list is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ p = result_list[0]; // result list[0] = provider_result
+ if (!p)
+ {
+ LOGE("Invalid Bundle: provider_result is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGI("Provider result: %s", p);
+
+ provider_result = atoi(p);
+
+ error_message = result_list[1]; // result list[1] = error
+ if (!error_message)
+ {
+ LOGE("Invalid Bundle: error_message is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGI("Error message: %s", error_message);
+
+ p = appsvc_get_data(b, OSP_K_DATACONTROL_REQUEST_TYPE);
+ if (!p)
+ {
+ LOGE("Invalid Bundle: data-control request type is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ request_type = (datacontrol_request_type)atoi(p);
+
+ provider_id = appsvc_get_data(b, OSP_K_DATACONTROL_PROVIDER);
+ if (!provider_id)
+ {
+ LOGE("Invalid Bundle: provider_id is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ data_id = appsvc_get_data(b, OSP_K_DATACONTROL_DATA);
+ if (!data_id)
+ {
+ LOGE("Invalid Bundle: data_id is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ SECURE_LOGI("Provider ID: %s, Data ID: %s, Operation type: %d", provider_id, data_id, request_type);
+
+ switch (request_type)
+ {
+ case DATACONTROL_TYPE_MAP_GET:
+ {
+ LOGI("GET RESPONSE");
+ if (provider_result)
+ {
+ value_count = atoi(result_list[2]);
+ result_path = result_list[3];
+ if (!result_path)
+ {
+ LOGE("map query result path is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+ value_list = datacontrol_map_get_value_list(result_path, value_count);
+ }
+ break;
+ }
+ case DATACONTROL_TYPE_MAP_SET:
+ case DATACONTROL_TYPE_MAP_ADD:
+ case DATACONTROL_TYPE_MAP_REMOVE:
+ {
+ LOGI("SET or ADD or REMOVE RESPONSE");
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (request_type >= DATACONTROL_TYPE_MAP_GET && request_type <= DATACONTROL_TYPE_MAP_REMOVE)
+ {
+ datacontrol_map_call_cb(provider_id, request_id, request_type, data_id, provider_result, error_message, value_list, value_count, data);
+ ret = DATACONTROL_ERROR_NONE;
+ }
+ else
+ {
+ ret = DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ return ret;
+}
+
+static void
+app_svc_res_cb_map(bundle* b, int request_code, appsvc_result_val res, void* data)
+{
+ LOGI("app_svc_res_cb_map, request_code: %d, result: %d", request_code, res);
+
+ if (data)
+ {
+ datacontrol_map_handle_cb(b, request_code, res, data);
+ }
+ else
+ {
+ LOGE("error: listener information is null");
+ }
+}
+
+
+static int
+datacontrol_map_request_provider(datacontrol_h provider, datacontrol_request_type type, bundle *arg_list, int request_id)
+{
+ SECURE_LOGI("Map Data control request, type: %d, request id: %d", type, request_id);
+
+ char *app_id = NULL;
+ void *data = NULL;
+
+ if (type < DATACONTROL_TYPE_MAP_GET || type > DATACONTROL_TYPE_MAP_REMOVE)
+ {
+ LOGE("Invalid request type: %d", (int)type);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!datacontrol_map_tree_root)
+ {
+ LOGE("The listener tree is empty");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ map_response_cb_s *map_dc_temp = (map_response_cb_s *)calloc(sizeof(map_response_cb_s),1);
+ if (!map_dc_temp)
+ {
+ LOGE("Failed to create map datacontrol");
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ map_dc_temp->provider_id = strdup(provider->provider_id);
+ if (!map_dc_temp->provider_id)
+ {
+ LOGE("Failed to assign provider id to map data control: %d", errno);
+ free(map_dc_temp);
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ map_dc_temp->data_id = strdup(provider->data_id);
+ if (!map_dc_temp->data_id)
+ {
+ LOGE("Failed to assign data id to map data control: %d", errno);
+ free(map_dc_temp->provider_id);
+ free(map_dc_temp);
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ map_dc_temp->app_id = NULL;
+ map_dc_temp->access_info = NULL;
+ map_dc_temp->user_data = NULL;
+ map_dc_temp->map_response_cb = NULL;
+
+ void *map_dc_returned = NULL;
+ map_dc_returned = tfind(map_dc_temp, &datacontrol_map_tree_root, datacontrol_map_instance_compare);
+
+ datacontrol_map_instance_free(map_dc_temp);
+
+ if (!map_dc_returned)
+ {
+ LOGE("Finding the map datacontrol in the listener tree is failed.");
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ map_response_cb_s *map_dc = *(map_response_cb_s **)map_dc_returned;
+ app_id = map_dc->app_id;
+ data = map_dc;
+
+ SECURE_LOGI("Map datacontrol appid: %s", map_dc->app_id);
+
+ char caller_app_id[255];
+ pid_t pid = getpid();
+ if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0)
+ {
+ SECURE_LOGE("Failed to get appid by pid(%d).", pid);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ appsvc_set_operation(arg_list, APPSVC_OPERATION_DEFAULT);
+ appsvc_set_appid(arg_list, app_id);
+ bundle_add_str(arg_list, OSP_K_CALLER_TYPE, OSP_V_CALLER_TYPE_OSP);
+ bundle_add_str(arg_list, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_DATACONTROL);
+ bundle_add_str(arg_list, OSP_K_DATACONTROL_PROTOCOL_VERSION, OSP_V_VERSION_2_1_0_3);
+ bundle_add_str(arg_list, AUL_K_CALLER_APPID, caller_app_id);
+ bundle_add_str(arg_list, AUL_K_NO_CANCEL, "1");
+
+ char datacontrol_request_operation[MAX_LEN_DATACONTROL_REQ_TYPE] = {0, };
+ snprintf(datacontrol_request_operation, MAX_LEN_DATACONTROL_REQ_TYPE, "%d", (int)(type));
+ bundle_add_str(arg_list, OSP_K_DATACONTROL_REQUEST_TYPE, datacontrol_request_operation);
+
+ char req_id[32] = {0, };
+ snprintf(req_id, 32, "%d", request_id);
+ bundle_add_str(arg_list, OSP_K_REQUEST_ID, req_id);
+
+ // For DataControl CAPI
+ bundle_add_str(arg_list, AUL_K_DATA_CONTROL_TYPE, "CORE");
+
+ SECURE_LOGI("Map data control request - provider id: %s, data id: %s, provider appid: %s, request ID: %s", provider->provider_id, provider->data_id, app_id, req_id);
+
+ pid = -1;
+ int count = 0;
+ const int TRY_COUNT = 4;
+ const int TRY_SLEEP_TIME = 65000;
+ do
+ {
+ pid = appsvc_run_service(arg_list, request_id, app_svc_res_cb_map, data);
+ if (pid >= 0)
+ {
+ SECURE_LOGI("Launch the provider app successfully: %d", pid);
+ return DATACONTROL_ERROR_NONE;
+ }
+ else if (pid == APPSVC_RET_EINVAL)
+ {
+ SECURE_LOGE("not able to launch service: %d", pid);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ count++;
+
+ usleep(TRY_SLEEP_TIME);
+ }
+ while (count < TRY_COUNT);
+
+ SECURE_LOGE("unable to launch service: %d", pid);
+ return DATACONTROL_ERROR_IO_ERROR;
+}
+
+int
+datacontrol_map_create(datacontrol_h *provider)
+{
+ struct datacontrol_s *request;
+
+ if (provider == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ request = malloc(sizeof(struct datacontrol_s));
+ if (request == NULL)
+ {
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ request->provider_id = NULL;
+ request->data_id = NULL;
+
+ *provider = request;
+
+ return 0;
+}
+
+int
+datacontrol_map_destroy(datacontrol_h provider)
+{
+ if (provider == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (provider->provider_id != NULL)
+ {
+ free(provider->provider_id);
+ }
+
+ if (provider->data_id != NULL)
+ {
+ free(provider->data_id);
+ }
+
+ free(provider);
+
+ return 0;
+}
+
+int
+datacontrol_map_set_provider_id(datacontrol_h provider, const char *provider_id)
+{
+ if (provider == NULL || provider_id == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (provider->provider_id != NULL)
+ {
+ free(provider->provider_id);
+ }
+
+ provider->provider_id = strdup(provider_id);
+ if (provider->provider_id == NULL)
+ {
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ return 0;
+}
+
+int
+datacontrol_map_get_provider_id(datacontrol_h provider, char **provider_id)
+{
+ if (provider == NULL || provider_id == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (provider->provider_id != NULL)
+ {
+ *provider_id = strdup(provider->provider_id);
+ if (*provider_id == NULL)
+ {
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ *provider_id = NULL;
+ }
+
+ return 0;
+}
+
+int
+datacontrol_map_set_data_id(datacontrol_h provider, const char *data_id)
+{
+ if (provider == NULL || data_id == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (provider->data_id != NULL)
+ {
+ free(provider->data_id);
+ }
+
+ provider->data_id = strdup(data_id);
+ if (provider->data_id == NULL)
+ {
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ return 0;
+}
+
+int
+datacontrol_map_get_data_id(datacontrol_h provider, char **data_id)
+{
+ if (provider == NULL || data_id == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (provider->data_id != NULL)
+ {
+ *data_id = strdup(provider->data_id);
+ if (*data_id == NULL)
+ {
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ *data_id = NULL;
+ }
+ return 0;
+}
+
+int
+datacontrol_map_register_response_cb(datacontrol_h provider, datacontrol_map_response_cb* callback, void *user_data)
+{
+ int ret = 0;
+ char* app_id = NULL;
+ char* access = NULL;
+
+ ret = pkgmgrinfo_appinfo_get_datacontrol_info(provider->provider_id, "Map", &app_id, &access);
+ if (ret != PMINFO_R_OK)
+ {
+ LOGE("unable to get map data control information: %d", ret);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ SECURE_LOGI("data control provider appid = %s", app_id);
+
+ map_response_cb_s *map_dc_temp = (map_response_cb_s *)calloc(sizeof(map_response_cb_s), 1);
+ if (!map_dc_temp)
+ {
+ LOGE("unable to create a temporary map data control");
+ ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
+ goto EXCEPTION;
+ }
+
+ map_dc_temp->provider_id = strdup(provider->provider_id);
+ if (!map_dc_temp->provider_id)
+ {
+ LOGE("unable to assign provider_id to map data control: %d", errno);
+ ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
+ goto EXCEPTION;
+ }
+
+ map_dc_temp->data_id = strdup(provider->data_id);
+ if (!map_dc_temp->data_id)
+ {
+ LOGE("unable to assign data_id to map data control: %d", errno);
+ ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
+ goto EXCEPTION;
+ }
+
+ map_dc_temp->app_id = app_id;
+ map_dc_temp->access_info = access;
+ map_dc_temp->user_data = user_data;
+ map_dc_temp->map_response_cb = callback;
+
+ void *map_dc_returned = NULL;
+ map_dc_returned = tsearch(map_dc_temp, &datacontrol_map_tree_root, datacontrol_map_instance_compare);
+
+ map_response_cb_s *map_dc = *(map_response_cb_s **)map_dc_returned;
+ if (map_dc != map_dc_temp)
+ {
+ map_dc->map_response_cb = callback;
+ map_dc->user_data = user_data;
+ LOGI("the data control is already set");
+ datacontrol_map_instance_free(map_dc_temp);
+ }
+
+ return DATACONTROL_ERROR_NONE;
+
+EXCEPTION:
+ if (access)
+ free(access);
+ if (app_id)
+ free(app_id);
+ if (map_dc_temp)
+ {
+ if (map_dc_temp->provider_id)
+ free(map_dc_temp->provider_id);
+ if (map_dc_temp->data_id)
+ free(map_dc_temp->data_id);
+ free(map_dc_temp);
+ }
+
+ return ret;
+}
+
+int
+datacontrol_map_unregister_response_cb(datacontrol_h provider)
+{
+ int ret = DATACONTROL_ERROR_NONE;
+ map_response_cb_s *map_dc_temp = (map_response_cb_s *)calloc(sizeof(map_response_cb_s),1);
+
+
+ if (!map_dc_temp)
+ {
+ LOGE("unable to create a temporary map data control");
+ ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
+ goto EXCEPTION;
+ }
+
+ map_dc_temp->provider_id = strdup(provider->provider_id);
+ if (!map_dc_temp->provider_id)
+ {
+ LOGE("unable to assign provider_id to map data control: %d", errno);
+ ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
+ goto EXCEPTION;
+ }
+
+ void *map_dc_returned = NULL;
+
+ map_dc_returned = tdelete(map_dc_temp, &datacontrol_map_tree_root, datacontrol_map_instance_compare);
+ if (map_dc_returned == NULL)
+ {
+ LOGE("invalid parameter");
+ ret = DATACONTROL_ERROR_INVALID_PARAMETER;
+ goto EXCEPTION;
+ }
+
+
+EXCEPTION:
+ if (map_dc_temp)
+ {
+ if (map_dc_temp->provider_id)
+ free(map_dc_temp->provider_id);
+ free(map_dc_temp);
+ }
+
+ return ret;
+}
+
+int
+datacontrol_map_get(datacontrol_h provider, const char *key, int *request_id)
+{
+ return datacontrol_map_get_with_page(provider, key, request_id, 1, 20);
+}
+
+int
+datacontrol_map_get_with_page(datacontrol_h provider, const char *key, int *request_id, int page_number, int count_per_page)
+{
+ if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL)
+ {
+ LOGE("Invalid parameter");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ SECURE_LOGI("Gets the value list from provider_id: %s, data_id: %s", provider->provider_id, provider->data_id);
+
+ long long arg_size = (strlen(provider->data_id) + strlen(key)) * sizeof(wchar_t);
+ if (arg_size > MAX_ARGUMENT_SIZE)
+ {
+ LOGE("The size of sending argument (%lld) exceeds the maximum limit.", arg_size);
+ return DATACONTROL_ERROR_MAX_EXCEEDED;
+ }
+
+ int ret = 0;
+ bundle *b = bundle_create();
+ if (!b)
+ {
+ LOGE("unable to create bundle: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
+ bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+
+ const char* arg_list[4];
+ arg_list[0] = provider->data_id;
+ arg_list[1] = key;
+
+ char page_no_str[32] = {0, };
+ ret = snprintf(page_no_str, 32, "%d", page_number);
+ if (ret < 0)
+ {
+ LOGE("unable to convert page no to string: %d", errno);
+ bundle_free(b);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ char count_per_page_str[32] = {0, };
+ ret = snprintf(count_per_page_str, 32, "%d", count_per_page);
+ if (ret < 0)
+ {
+ LOGE("unable to convert count per page no to string: %d", errno);
+ bundle_free(b);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ arg_list[2] = page_no_str;
+ arg_list[3] = count_per_page_str;
+
+ bundle_add_str_array(b, OSP_K_ARG, arg_list, 4);
+
+ // Set the request id
+ int reqId = _datacontrol_create_request_id();
+ *request_id = reqId;
+
+ ret = datacontrol_map_request_provider(provider, DATACONTROL_TYPE_MAP_GET, b, reqId);
+ bundle_free(b);
+
+ return ret;
+}
+
+int
+datacontrol_map_set(datacontrol_h provider, const char *key, const char *old_value, const char *new_value, int *request_id)
+{
+ if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL || old_value == NULL || new_value == NULL)
+ {
+ LOGE("Invalid parameter");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ SECURE_LOGI("Sets the old value to new value in provider_id: %s, data_id: %s", provider->provider_id, provider->data_id);
+
+ long long arg_size = (strlen(provider->data_id) + strlen(key) + strlen(old_value) + strlen(new_value)) * sizeof(wchar_t);
+ if (arg_size > MAX_ARGUMENT_SIZE)
+ {
+ LOGE("The size of sending argument (%lld) exceeds the maximum limit.", arg_size);
+ return DATACONTROL_ERROR_MAX_EXCEEDED;
+ }
+
+ bundle *b = bundle_create();
+ if (!b)
+ {
+ LOGE("unable to create bundle: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
+ bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+
+ const char* arg_list[4];
+ arg_list[0] = provider->data_id;
+ arg_list[1] = key;
+ arg_list[2] = old_value;
+ arg_list[3] = new_value;
+
+ bundle_add_str_array(b, OSP_K_ARG, arg_list, 4);
+
+ // Set the request id
+ int reqId = _datacontrol_create_request_id();
+ *request_id = reqId;
+
+ int ret = datacontrol_map_request_provider(provider, DATACONTROL_TYPE_MAP_SET, b, reqId);
+ bundle_free(b);
+
+ return ret;
+}
+
+int
+datacontrol_map_add(datacontrol_h provider, const char *key, const char *value, int *request_id)
+{
+ if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL || value == NULL)
+ {
+ LOGE("Invalid parameter");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ SECURE_LOGI("Adds the value in provider_id: %s, data_id: %s", provider->provider_id, provider->data_id);
+
+ long long arg_size = (strlen(provider->data_id) + strlen(key) + strlen(value)) * sizeof(wchar_t);
+ if (arg_size > MAX_ARGUMENT_SIZE)
+ {
+ LOGE("The size of sending argument (%lld) exceeds the maximum limit.", arg_size);
+ return DATACONTROL_ERROR_MAX_EXCEEDED;
+ }
+
+ bundle *b = bundle_create();
+ if (!b)
+ {
+ LOGE("unable to create bundle: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
+ bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+
+ const char* arg_list[3];
+ arg_list[0] = provider->data_id;
+ arg_list[1] = key;
+ arg_list[2] = value;
+
+ bundle_add_str_array(b, OSP_K_ARG, arg_list, 3);
+
+ // Set the request id
+ int reqId = _datacontrol_create_request_id();
+ *request_id = reqId;
+
+ int ret = datacontrol_map_request_provider(provider, DATACONTROL_TYPE_MAP_ADD, b, reqId);
+ bundle_free(b);
+
+ return ret;
+}
+
+int
+datacontrol_map_remove(datacontrol_h provider, const char *key, const char *value, int *request_id)
+{
+ if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || key == NULL || value == NULL)
+ {
+ LOGE("Invalid parameter");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ SECURE_LOGI("Removes the value in provider_id: %s, data_id: %s", provider->provider_id, provider->data_id);
+
+ long long arg_size = (strlen(provider->data_id) + strlen(key) + strlen(value)) * sizeof(wchar_t);
+ if (arg_size > MAX_ARGUMENT_SIZE)
+ {
+ LOGE("The size of sending argument (%lld) exceeds the maximum limit.", arg_size);
+ return DATACONTROL_ERROR_MAX_EXCEEDED;
+ }
+
+ bundle *b = bundle_create();
+ if (!b)
+ {
+ LOGE("unable to create bundle: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
+ bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+
+ const char* arg_list[3];
+ arg_list[0] = provider->data_id;
+ arg_list[1] = key;
+ arg_list[2] = value;
+
+ bundle_add_str_array(b, OSP_K_ARG, arg_list, 3);
+
+ // Set the request id
+ int reqId = _datacontrol_create_request_id();
+ *request_id = reqId;
+
+ int ret = datacontrol_map_request_provider(provider, DATACONTROL_TYPE_MAP_REMOVE, b, reqId);
+ bundle_free(b);
+
+ return ret;
+}
--- /dev/null
+#include <dlog.h>
+#include <errno.h>
+#include <search.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <glib.h>
+#include <pthread.h>
+#include <sqlite3.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <appsvc/appsvc.h>
+#include <aul/aul.h>
+#include <bundle.h>
+#include <pkgmgr-info.h>
+
+#include "data-control-sql.h"
+#include "data-control-provider.h"
+#include "data-control-internal.h"
+
+#define ROW_ID_SIZE 32
+#define RESULT_PATH_MAX 512
+
+#define RESULT_PAGE_NUMBER "RESULT_PAGE_NUMBER"
+#define MAX_COUNT_PER_PAGE "MAX_COUNT_PER_PAGE"
+#define RESULT_VALUE_COUNT "RESULT_VALUE_COUNT"
+
+#define PACKET_INDEX_REQUEST_RESULT 0
+#define PACKET_INDEX_ERROR_MSG 1
+#define PACKET_INDEX_SELECT_RESULT_FILE 2
+#define PACKET_INDEX_ROW_ID 2
+#define PACKET_INDEX_VALUE_COUNT 2
+#define PACKET_INDEX_GET_RESULT_FILE 3
+
+#define PACKET_INDEX_DATAID 0
+#define PACKET_INDEX_COLUMNCOUNT 1
+#define PACKET_INDEX_MAP 2
+
+#define PACKET_INDEX_UPDATEWHERE 3
+#define PACKET_INDEX_DELETEWHERE 1
+
+#define PACKET_INDEX_MAP_KEY 1
+#define PACKET_INDEX_MAP_VALUE_1ST 2
+#define PACKET_INDEX_MAP_VALUE_2ND 3
+#define PACKET_INDEX_MAP_PAGE_NO 2
+#define PACKET_INDEX_MAP_COUNT_PER_PAGE 3
+
+static GHashTable *request_table = NULL;
+
+//static pthread_mutex_t provider_lock = PTHREAD_MUTEX_INITIALIZER;
+
+struct datacontrol_s {
+ char *provider_id;
+ char *data_id;
+};
+
+
+typedef int (*provider_handler_cb) (bundle * b, int request_id, void *data);
+
+static datacontrol_provider_sql_cb* provider_sql_cb = NULL;
+static datacontrol_provider_map_cb* provider_map_cb = NULL;
+static void* provider_map_user_data = NULL;
+static void* provider_sql_user_data = NULL;
+
+static void
+__free_data(gpointer data)
+{
+ if (data)
+ {
+ free(data);
+ data = NULL;
+ }
+}
+
+static void
+__initialize_provider(void)
+{
+ request_table = g_hash_table_new_full(g_int_hash, g_int_equal, __free_data, __free_data);
+}
+
+static int
+__provider_new_request_id(void)
+{
+ static int id = 0;
+
+ g_atomic_int_inc(&id);
+
+ return id;
+}
+
+static char*
+__get_client_pkgid(bundle *b)
+{
+ const char *caller_appid = NULL;
+ char *caller_pkgid = NULL;
+ pkgmgrinfo_appinfo_h app_info_handle = NULL;
+
+ caller_appid = bundle_get_val(b, AUL_K_CALLER_APPID);
+ pkgmgrinfo_appinfo_get_appinfo(caller_appid, &app_info_handle);
+ pkgmgrinfo_appinfo_get_pkgname(app_info_handle, &caller_pkgid);
+ SECURE_LOGI("client pkg id : %s", caller_pkgid);
+
+ return caller_pkgid ? strdup(caller_pkgid) : NULL;
+}
+
+static bundle*
+__get_data_sql(const char *path, int column_count)
+{
+ bundle* b = bundle_create();
+
+ int len = 0;
+ int i = 0;
+ size_t size = 0;
+ char *key = NULL;
+ char *value = NULL;
+ int fd = 0;
+ int ret = 0;
+
+ SECURE_LOGI("The request file of INSERT/UPDATE: %s", path);
+
+ /* TODO - shoud be changed to solve security concerns */
+ fd = open(path, O_RDONLY, 644);
+ if (fd == -1) {
+ SECURE_LOGE("unable to open insert_map file: %d", errno);
+ return b;
+ }
+
+ for (i = 0; i < column_count; i++)
+ {
+ size = read(fd, &len, sizeof(int));
+ if (size < sizeof(int) || len < 0 || len == INT_MAX)
+ {
+ SECURE_LOGE("key length:%d, read():%s, returned:%d", len, strerror(errno), size);
+ break;
+ }
+
+ key = calloc(len + 1, sizeof(char));
+ size = read(fd, key, len); // key
+ if (size < 0)
+ {
+ SECURE_LOGE("key length:%d, read():%s, returned:%d", len, strerror(errno), size);
+ free(key);
+ break;
+ }
+
+ size = read(fd, &len, sizeof(int));
+ if (size < sizeof(int) || len < 0 || len == INT_MAX)
+ {
+ SECURE_LOGE("value length:%d, read():%s, returned:%d", len, strerror(errno), size);
+ free(key);
+ break;
+ }
+
+ value = calloc(len + 1, sizeof(char));
+ size = read(fd, value, len); // value
+ if (size < 0)
+ {
+ SECURE_LOGE("value length:%d, read():%s, returned:%d", len, strerror(errno), size);
+ free(key);
+ free(value);
+ break;
+ }
+
+ LOGI("key: %s, value: %s", key, value);
+
+ bundle_add_str(b, key, value);
+
+ free(key);
+ free(value);
+ }
+
+ fsync(fd);
+ close(fd);
+ ret = remove(path);
+ if (ret == -1)
+ {
+ SECURE_LOGE("unable to remove the request file of INSERT/UPDATE(%s). errno = %d", path, errno);
+ }
+
+ return b;
+}
+
+static int
+__set_select_result(bundle* b, const char* path, void* data)
+{
+ LOGI("__set_select_result");
+ // The provider application should call the sqlite3_open().
+ // and it also should call the sqlite3_prepare_v2() in datacontrol_provider_sql_select_request_cb().
+ // and then, it should call the datacontrol_provider_send_select_result() with a pointer to sqlite3_stmt.
+ // The 3rd param 'data' is the pointer to sqlite3_stmt.
+
+ // In this function, the result set is written in specified file path as specific form.
+ // [sizeof(int)] row count
+ // [sizeof(int)] column count
+ // [sieeof(int)] total size of column names
+ // [sizeof(int)] column type x N
+ // [ variant ] column name x N
+ // [sizeof(int)] type
+ // [sizeof(int)] size
+ // [ varient ] content
+
+ int column_count = 0;
+ int i = 0;
+ char *column_name = NULL;
+ int total_len_of_column_names = 0;
+ int count_per_page = 0;
+ int row_count = 0;
+ sqlite3_stmt *state = (sqlite3_stmt *)data;
+ int fd = 0;
+ char *client_pkgid = NULL;
+
+ if (b ==NULL || path == NULL || data == NULL)
+ {
+ LOGE("The input param is invalid.");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (sqlite3_reset(state) != SQLITE_OK)
+ {
+ LOGE("sqlite3_reset() is failed.");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (sqlite3_step(state) != SQLITE_ROW)
+ {
+ LOGE("The DB does not have another row.");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ client_pkgid = __get_client_pkgid(b);
+
+ /* TODO - shoud be changed to solve security concerns */
+ fd = open(path, O_WRONLY | O_CREAT, 644);
+ if (fd == -1) {
+ SECURE_LOGE("unable to open insert_map file: %d", errno);
+ free(client_pkgid);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+ free(client_pkgid);
+
+ // 1. column count
+ column_count = sqlite3_column_count(state);
+ if (lseek(fd, sizeof(int), SEEK_SET) == -1)
+ {
+ LOGE("lseek is failed. errno = %d", errno);
+ }
+ if (write(fd, &column_count, sizeof(int)) == -1)
+ {
+ LOGE("Writing a column_count to a file descriptor is failed. errno = %d", errno);
+ }
+
+ // 2. column type x column_count
+ // #define SQLITE_INTEGER 1
+ // #define SQLITE_FLOAT 2
+ // #define SQLITE_TEXT 3
+ // #define SQLITE_BLOB 4
+ // #define SQLITE_NULL 5
+ if (lseek(fd, sizeof(int), SEEK_CUR) == -1)
+ {
+ LOGE("lseek is failed. errno = %d", errno);
+ }
+
+ for (i = 0; i < column_count; ++i)
+ {
+ int type = sqlite3_column_type(state, i);
+ if (write(fd, &type, sizeof(int)) == -1)
+ {
+ LOGE("Writing a type to a file descriptor is failed. errno = %d", errno);
+ }
+ }
+
+ // 3. column name x column_count
+ for (i = 0; i < column_count; i++)
+ {
+ column_name = (char *)sqlite3_column_name(state, i);
+ column_name = strcat(column_name, "\n");
+ if (write(fd, column_name, strlen(column_name)) == -1)
+ {
+ LOGE("Writing a column_name to a file descriptor is failed. errno = %d", errno);
+ }
+ total_len_of_column_names += strlen(column_name);
+ }
+
+ // 4. total length of column names
+ if (lseek(fd, sizeof(int) * 2, SEEK_SET) == -1)
+ {
+ LOGE("lseek is failed. errno = %d", errno);
+ }
+ if (write(fd, &total_len_of_column_names, sizeof(int)) == -1)
+ {
+ LOGE("Writing a total_len_of_column_names to a file descriptor is failed. errno = %d", errno);
+ }
+ // 5. type, size and value of each element
+ if (lseek(fd, (sizeof(int) * column_count) + total_len_of_column_names, SEEK_CUR) == -1)
+ {
+ LOGE("lseek is failed. errno = %d", errno);
+ }
+ count_per_page = atoi(bundle_get_val(b, MAX_COUNT_PER_PAGE));
+ do
+ {
+ for (i = 0; i < column_count; ++i)
+ {
+ int type = 0;
+ int size = 0;
+ void* value = NULL;
+ bool is_null_type = false;
+ int column_type = sqlite3_column_type(state, i);
+ long long tmp_long = 0;
+ double tmp_double = 0.0;
+ switch (column_type)
+ {
+ case SQLITE_INTEGER:
+ {
+ type = 1;
+ size = sizeof(long long);
+ tmp_long = sqlite3_column_int64(state, i);
+ value = &tmp_long;
+ break;
+ }
+ case SQLITE_FLOAT:
+ {
+ type = 2;
+ size = sizeof(double);
+ tmp_double = sqlite3_column_double(state, i);
+ value =&tmp_double;
+ break;
+ }
+ case SQLITE_TEXT:
+ {
+ type = 3;
+ value = (char *)sqlite3_column_text(state, i);
+ size = strlen(value);
+ break;
+ }
+ case SQLITE_BLOB:
+ {
+ type = 4;
+ size = sqlite3_column_bytes(state, i);
+ value = (char *)sqlite3_column_blob(state, i);
+ break;
+ }
+ case SQLITE_NULL:
+ {
+ type = 5;
+ size = 0;
+ is_null_type = true;
+ break;
+ }
+ default:
+ {
+ LOGE("The column type is invalid.");
+ break;
+ }
+ }
+
+ if (write(fd, &type, sizeof(int)) == -1)
+ {
+ LOGE("Writing a type to a file descriptor is failed. errno = %d", errno);
+ }
+ if (write(fd, &size, sizeof(int)) == -1)
+ {
+ LOGE("Writing a size to a file descriptor is failed. errno = %d", errno);
+ }
+ if (size > 0 && !is_null_type)
+ {
+ if (write(fd, value, size) == -1)
+ {
+ LOGE("Writing a value to a file descriptor is failed. errno = %d", errno);
+ }
+ }
+ }
+ ++row_count;
+ } while(sqlite3_step(state) == SQLITE_ROW && row_count < count_per_page);
+
+ // 6. row count
+ if (lseek(fd, 0, SEEK_SET) == -1)
+ {
+ LOGE("lseek is failed. errno = %d", errno);
+ }
+ if (write(fd, &row_count, sizeof(int)) == -1)
+ {
+ LOGE("Writing a row_count to a file descriptor is failed. errno = %d", errno);
+ }
+ close(fd);
+
+
+ return DATACONTROL_ERROR_NONE;
+}
+
+static int
+__set_get_value_result(bundle *b, const char* path, char **value_list)
+{
+ int i = 0;
+ int fd = -1;
+ char *client_pkgid = NULL;
+
+ if (b == NULL || path == NULL || value_list == NULL)
+ {
+ LOGE("The input param is invalid.");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ int page_number = atoi(bundle_get_val(b, RESULT_PAGE_NUMBER));
+ int count_per_page = atoi(bundle_get_val(b, MAX_COUNT_PER_PAGE));
+ int value_count = atoi(bundle_get_val(b, RESULT_VALUE_COUNT));
+ int current_offset = (page_number - 1) * count_per_page;
+ int remain_count = value_count - current_offset;
+ remain_count = (remain_count > 0) ? remain_count : 0; // round off to zero if the negative num is found
+ int add_value_count = (count_per_page > remain_count) ? remain_count : count_per_page;
+
+ if (add_value_count < value_count)
+ {
+ bundle_del(b, RESULT_VALUE_COUNT);
+ char value_count_str[32] = {0,};
+ snprintf(value_count_str, 32, "%d", add_value_count);
+ bundle_add_str(b, RESULT_VALUE_COUNT, value_count_str);
+ }
+
+ if (add_value_count <= 0)
+ {
+ LOGI("There is no value list.");
+ return DATACONTROL_ERROR_NONE;
+ }
+
+ client_pkgid = __get_client_pkgid(b);
+ /* TODO - shoud be changed to solve security concerns */
+ fd = open(path, O_WRONLY | O_CREAT, 644);
+ if (fd == -1) {
+ SECURE_LOGE("unable to open insert_map file: %d", errno);
+ free(client_pkgid);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+ free(client_pkgid);
+
+ for (i = 0; i < add_value_count; ++i)
+ {
+ int length = strlen(value_list[current_offset + i]);
+ if (write(fd, &length, sizeof(int)) == -1)
+ {
+ LOGE("Writing a length to a file descriptor is failed. errno = %d", errno);
+ }
+ if (write(fd, value_list[current_offset + i], length) == -1)
+ {
+ LOGE("Writing a value_list to a file descriptor is failed. errno = %d", errno);
+ }
+ }
+
+ fsync(fd);
+ close(fd);
+ return DATACONTROL_ERROR_NONE;
+}
+
+static char*
+__get_result_file_path(bundle *b)
+{
+ LOGI("__get_result_file_path");
+ const char *caller = bundle_get_val(b, AUL_K_CALLER_APPID);
+ if (!caller)
+ {
+ LOGE("caller appid is NULL.");
+ return NULL;
+ }
+
+ const char *caller_req_id = bundle_get_val(b, OSP_K_REQUEST_ID);
+
+ char *result_path = calloc(RESULT_PATH_MAX, sizeof(char));
+ snprintf(result_path, RESULT_PATH_MAX, "%s/%s_%s", DATACONTROL_RESULT_FILE_PREFIX, caller, caller_req_id);
+
+ SECURE_LOGI("result file path: %s", result_path);
+
+ return result_path;
+}
+
+static bundle*
+__set_result(bundle* b, datacontrol_request_type type, void* data)
+{
+ bundle* res;
+ aul_create_result_bundle(b, &res);
+
+ // Set the type
+ char type_str[MAX_LEN_DATACONTROL_REQ_TYPE] = {0,};
+ if (type == DATACONTROL_TYPE_UNDEFINED || type == DATACONTROL_TYPE_ERROR)
+ {
+ char *request_type = (char*)bundle_get_val(b, OSP_K_DATACONTROL_REQUEST_TYPE);
+ strncpy(type_str, request_type, MAX_LEN_DATACONTROL_REQ_TYPE);
+ LOGI("type is %s", type_str);
+ }
+ else
+ {
+ snprintf(type_str, MAX_LEN_DATACONTROL_REQ_TYPE, "%d", (int)type);
+ }
+ bundle_add_str(res, OSP_K_DATACONTROL_REQUEST_TYPE, type_str);
+
+ // Set the provider id
+ char *provider_id = (char*)bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER);
+ bundle_add_str(res, OSP_K_DATACONTROL_PROVIDER, provider_id);
+
+ // Set the data id
+ char *data_id = (char*)bundle_get_val(b, OSP_K_DATACONTROL_DATA);
+ bundle_add_str(res, OSP_K_DATACONTROL_DATA, data_id);
+
+ // Set the caller request id
+ char *request_id = (char*)bundle_get_val(b, OSP_K_REQUEST_ID);
+ bundle_add_str(res, OSP_K_REQUEST_ID, request_id);
+
+ switch(type)
+ {
+ case DATACONTROL_TYPE_SQL_SELECT:
+ {
+ const char* list[3];
+
+ list[PACKET_INDEX_REQUEST_RESULT] = "1"; // request result
+ list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY;
+
+ char *path = __get_result_file_path(b);
+ if (path != NULL)
+ {
+ int ret = __set_select_result(b, path, data);
+ if (ret < 0)
+ {
+ memset(path, 0, RESULT_PATH_MAX);
+ strcpy(path, "NoResultSet");
+ LOGI("Empty ResultSet");
+ }
+ list[PACKET_INDEX_SELECT_RESULT_FILE] = path;
+ }
+ else
+ {
+ list[PACKET_INDEX_SELECT_RESULT_FILE] = DATACONTROL_EMPTY;
+ }
+
+ bundle_add_str_array(res, OSP_K_ARG, list, 3);
+
+ if (path != NULL)
+ {
+ free(path);
+ }
+
+ break;
+ }
+
+ case DATACONTROL_TYPE_SQL_INSERT:
+ {
+ long long row_id = *(long long*)data;
+
+ const char* list[3];
+ list[PACKET_INDEX_REQUEST_RESULT] = "1"; // request result
+ list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY;
+
+ // Set the row value
+ char row_str[ROW_ID_SIZE] = {0,};
+ snprintf(row_str, ROW_ID_SIZE, "%lld", row_id);
+
+ list[PACKET_INDEX_ROW_ID] = row_str;
+
+ bundle_add_str_array(res, OSP_K_ARG, list, 3);
+ break;
+ }
+ case DATACONTROL_TYPE_SQL_UPDATE:
+ case DATACONTROL_TYPE_SQL_DELETE:
+ {
+ const char* list[2];
+ list[PACKET_INDEX_REQUEST_RESULT] = "1"; // request result
+ list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY;
+
+ bundle_add_str_array(res, OSP_K_ARG, list, 2);
+ break;
+ }
+ case DATACONTROL_TYPE_MAP_GET:
+ {
+ const char* list[4];
+
+ list[PACKET_INDEX_REQUEST_RESULT] = "1"; // request result
+ list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY;
+
+ char *path = __get_result_file_path(b);
+ if (path != NULL)
+ {
+ char **value_list = (char **)data;
+ __set_get_value_result(b, path, value_list);
+ list[PACKET_INDEX_VALUE_COUNT] = bundle_get_val(b, RESULT_VALUE_COUNT); // value count
+ list[PACKET_INDEX_GET_RESULT_FILE] = path;
+ }
+ else
+ {
+ list[PACKET_INDEX_VALUE_COUNT] = 0; // value count
+ list[PACKET_INDEX_GET_RESULT_FILE] = DATACONTROL_EMPTY;
+ }
+
+ bundle_add_str_array(res, OSP_K_ARG, list, 4);
+
+ if (path != NULL)
+ {
+ free(path);
+ }
+
+ break;
+ }
+ case DATACONTROL_TYPE_UNDEFINED: // DATACONTROL_TYPE_MAP_SET || ADD || REMOVE
+ {
+ const char* list[2];
+ list[PACKET_INDEX_REQUEST_RESULT] = "1"; // request result
+ list[PACKET_INDEX_ERROR_MSG] = DATACONTROL_EMPTY;
+
+ bundle_add_str_array(res, OSP_K_ARG, list, 2);
+ break;
+ }
+ default: // Error
+ {
+ const char* list[2];
+ list[PACKET_INDEX_REQUEST_RESULT] = "0"; // request result
+ list[PACKET_INDEX_ERROR_MSG] = (char*)data; // error string
+
+ bundle_add_str_array(res, OSP_K_ARG, list, 2);
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+__send_result(bundle* b, datacontrol_request_type type)
+{
+ int ret = aul_send_service_result(b);
+
+ if (ret < 0)
+ {
+ LOGE("Fail to send a result to caller");
+
+ int index = 0;
+
+ switch (type)
+ {
+ case DATACONTROL_TYPE_SQL_SELECT:
+ {
+ index = PACKET_INDEX_SELECT_RESULT_FILE;
+ break;
+ }
+ case DATACONTROL_TYPE_MAP_GET:
+ {
+ index = PACKET_INDEX_GET_RESULT_FILE;
+ break;
+ }
+ default:
+ {
+ bundle_free(b);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+ }
+
+ int len = 0;
+ const char **str_arr = bundle_get_str_array(b, OSP_K_ARG, &len);
+ SECURE_LOGI("result file: %s (%d)", str_arr[index], index);
+ ret = remove(str_arr[index]);
+ if (ret == -1)
+ {
+ SECURE_LOGE("unable to remove the result file. errno = %d", errno);
+ }
+
+ bundle_free(b);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ bundle_free(b);
+ return DATACONTROL_ERROR_NONE;
+}
+
+int
+__datacontrol_handler_cb(bundle *b, int request_id, void* data)
+{
+ LOGI("datacontrol_handler_cb");
+
+ const char *request_type = bundle_get_val(b, OSP_K_DATACONTROL_REQUEST_TYPE);
+ if (request_type == NULL)
+ {
+ LOGE("Invalid data control request");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ // Get the request type
+ datacontrol_request_type type = atoi(request_type);
+ if (type >= DATACONTROL_TYPE_SQL_SELECT && type <= DATACONTROL_TYPE_SQL_DELETE)
+ {
+ if (provider_sql_cb == NULL)
+ {
+ LOGE("SQL callback is not registered.");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+ }
+ else if (type >= DATACONTROL_TYPE_MAP_GET && type <= DATACONTROL_TYPE_MAP_REMOVE)
+ {
+ if (provider_map_cb == NULL)
+ {
+ LOGE("Map callback is not registered.");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+ }
+ else
+ {
+ LOGE("Invalid requeste type");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ int len = 0;
+ const char **arg_list = bundle_get_str_array(b, OSP_K_ARG, &len);
+
+ datacontrol_h provider = malloc(sizeof(struct datacontrol_s));
+
+ // Set the provider ID
+ provider->provider_id = (char*)bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER);
+
+ // Set the data ID
+ provider->data_id = (char*)arg_list[PACKET_INDEX_DATAID];
+
+ // Set the request ID
+ int provider_req_id = __provider_new_request_id();
+
+ SECURE_LOGI("Provider ID: %s, data ID: %s, request type: %s", provider->provider_id, provider->data_id, request_type);
+
+ // Add the data to the table
+ int *key = malloc(sizeof(int));
+ *key = provider_req_id;
+
+ bundle *value = bundle_dup(b);
+ g_hash_table_insert(request_table, key, value);
+
+ switch (type)
+ {
+ case DATACONTROL_TYPE_SQL_SELECT:
+ {
+ int i = 1;
+ int current = 0;
+ int column_count = atoi(arg_list[i++]); // Column count
+
+ LOGI("SELECT column count: %d", column_count);
+
+ const char** column_list = (const char**)malloc(column_count * (sizeof(char *)));
+
+ while (current < column_count)
+ {
+ column_list[current++] = arg_list[i++]; // Column data
+
+ LOGI("Column %d: %s", current, column_list[current-1]);
+ }
+
+ const char *where = arg_list[i++]; // where
+ const char *order = arg_list[i++]; // order
+
+ LOGI("where: %s, order: %s", where, order);
+
+ if (strncmp(where, DATACONTROL_EMPTY, strlen(DATACONTROL_EMPTY)) == 0)
+ {
+ where = NULL;
+ }
+
+ if (strncmp(order, DATACONTROL_EMPTY, strlen(DATACONTROL_EMPTY)) == 0)
+ {
+ order = NULL;
+ }
+
+ const char *page_number = arg_list[i++];
+ const char *per_page = arg_list[i];
+
+ bundle_add_str(value, RESULT_PAGE_NUMBER, page_number);
+ bundle_add_str(value, MAX_COUNT_PER_PAGE, per_page);
+
+ char *statement = _datacontrol_create_select_statement(provider->data_id, column_list, column_count, where, order, atoi(page_number), atoi(per_page));
+
+ // Add a select statement to the bundle
+ bundle_add_str(value, DATACONTROL_SELECT_STATEMENT, statement);
+
+ free(statement);
+
+ provider_sql_cb->select(provider_req_id, provider, column_list, column_count, where, order, provider_sql_user_data);
+
+ free(column_list);
+
+ break;
+ }
+ case DATACONTROL_TYPE_SQL_INSERT:
+ case DATACONTROL_TYPE_SQL_UPDATE:
+ {
+ int column_count = atoi(arg_list[PACKET_INDEX_COLUMNCOUNT]);
+ const char *sql_path = arg_list[PACKET_INDEX_MAP];
+
+ LOGI("INSERT / UPDATE handler");
+ SECURE_LOGI("Data path: %s, Column count: %d", sql_path, column_count);
+
+ bundle* sql = __get_data_sql(sql_path, column_count);
+
+ if (type == DATACONTROL_TYPE_SQL_INSERT)
+ {
+ SECURE_LOGI("INSERT column count: %d, sql_path: %s", column_count, sql_path);
+ provider_sql_cb->insert(provider_req_id, provider, sql, provider_sql_user_data);
+ }
+ else
+ {
+ const char *where = arg_list[PACKET_INDEX_UPDATEWHERE];
+ LOGI("UPDATE from where: %s", where);
+
+ if (strncmp(where, DATACONTROL_EMPTY, strlen(DATACONTROL_EMPTY)) == 0)
+ {
+ where = NULL;
+ }
+ provider_sql_cb->update(provider_req_id, provider, sql, where, provider_sql_user_data);
+ }
+
+ bundle_free(sql);
+ break;
+ }
+ case DATACONTROL_TYPE_SQL_DELETE:
+ {
+ const char *where = arg_list[PACKET_INDEX_DELETEWHERE];
+
+ LOGI("DELETE from where: %s", where);
+ if (strncmp(where, DATACONTROL_EMPTY, strlen(DATACONTROL_EMPTY)) == 0)
+ {
+ where = NULL;
+ }
+ provider_sql_cb->delete(provider_req_id, provider, where, provider_sql_user_data);
+ break;
+ }
+ case DATACONTROL_TYPE_MAP_GET:
+ {
+ const char *map_key = arg_list[PACKET_INDEX_MAP_KEY];
+ const char *page_number= arg_list[PACKET_INDEX_MAP_PAGE_NO];
+ const char *count_per_page = arg_list[PACKET_INDEX_MAP_COUNT_PER_PAGE];
+ bundle_add_str(value, RESULT_PAGE_NUMBER, page_number);
+ bundle_add_str(value, MAX_COUNT_PER_PAGE, count_per_page);
+
+ LOGI("Gets the value list related with the key(%s) from Map datacontrol. ", map_key);
+
+ provider_map_cb->get(provider_req_id, provider, map_key, provider_map_user_data);
+ break;
+ }
+ case DATACONTROL_TYPE_MAP_SET:
+ {
+ const char *map_key = arg_list[PACKET_INDEX_MAP_KEY];
+ const char *old_value = arg_list[PACKET_INDEX_MAP_VALUE_1ST];
+ const char *new_value = arg_list[PACKET_INDEX_MAP_VALUE_2ND];
+
+ LOGI("Sets the old value(%s) of the key(%s) to the new value(%s) in Map datacontrol.", old_value, map_key, new_value);
+
+ provider_map_cb->set(provider_req_id, provider, map_key, old_value, new_value, provider_map_user_data);
+ break;
+ }
+ case DATACONTROL_TYPE_MAP_ADD:
+ {
+ const char *map_key = arg_list[PACKET_INDEX_MAP_KEY];
+ const char *map_value = arg_list[PACKET_INDEX_MAP_VALUE_1ST];
+
+ LOGI("Adds the %s-%s in Map datacontrol.", map_key, map_value);
+
+ provider_map_cb->add(provider_req_id, provider, map_key, map_value, provider_map_user_data);
+ break;
+ }
+ case DATACONTROL_TYPE_MAP_REMOVE:
+ {
+ const char *map_key = arg_list[PACKET_INDEX_MAP_KEY];
+ const char *map_value = arg_list[PACKET_INDEX_MAP_VALUE_1ST];
+
+ LOGI("Removes the %s-%s in Map datacontrol.", map_key, map_value);
+
+ provider_map_cb->remove(provider_req_id, provider, map_key, map_value, provider_map_user_data);
+ break;
+ }
+ default:
+ break;
+ }
+
+ free(provider);
+
+ return DATACONTROL_ERROR_NONE;
+}
+
+int
+datacontrol_provider_sql_register_cb(datacontrol_provider_sql_cb *callback, void *user_data)
+{
+ int ret = DATACONTROL_ERROR_NONE;
+
+ if (callback == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (request_table == NULL)
+ {
+ __initialize_provider();
+ }
+
+ LOGI("datacontrol_provider_sql_register_cb");
+
+ provider_sql_cb = callback;
+ provider_sql_user_data = user_data;
+
+ if (provider_map_cb == NULL) // If the provider_map_cb was registered(not NULL), __datacontrol_handler_cb is set already.
+ {
+ ret = aul_set_data_control_provider_cb(__datacontrol_handler_cb);
+ }
+
+ return ret;
+}
+
+int
+datacontrol_provider_sql_unregister_cb(void)
+{
+ if (provider_map_cb == NULL) // When both SQL_cb and Map_cb are unregisted, unsetting the provider cb is possible.
+ {
+ aul_unset_data_control_provider_cb();
+ }
+ provider_sql_cb = NULL;
+ provider_sql_user_data = NULL;
+
+ return DATACONTROL_ERROR_NONE;
+}
+
+int datacontrol_provider_map_register_cb(datacontrol_provider_map_cb *callback, void *user_data)
+{
+ int ret = DATACONTROL_ERROR_NONE;
+
+ if (callback == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (request_table == NULL)
+ {
+ __initialize_provider();
+ }
+
+ LOGI("datacontrol_provider_map_register_cb");
+
+ provider_map_cb = callback;
+ provider_map_user_data = user_data;
+
+ if (provider_sql_cb == NULL) // If the provider_sql_cb was registered(not NULL), __datacontrol_handler_cb is set already.
+ {
+ ret = aul_set_data_control_provider_cb(__datacontrol_handler_cb);
+ }
+
+ return ret;
+}
+
+int datacontrol_provider_map_unregister_cb(void)
+{
+ if (provider_sql_cb == NULL) // When both SQL_cb and Map_cb are unregisted, unsetting the provider cb is possible.
+ {
+ aul_unset_data_control_provider_cb();
+ }
+ provider_map_cb = NULL;
+ provider_map_user_data = NULL;
+
+ return DATACONTROL_ERROR_NONE;
+}
+
+int
+datacontrol_provider_get_client_appid(int request_id, char **appid)
+{
+ if (request_table == NULL)
+ {
+ __initialize_provider();
+ }
+
+ bundle* b = g_hash_table_lookup(request_table, &request_id);
+ if (!b)
+ {
+ SECURE_LOGE("No data for the request id: %d", request_id);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ const char *caller = bundle_get_val(b, AUL_K_CALLER_APPID);
+ if (!caller)
+ {
+ SECURE_LOGE("No appid for the request id: %d", request_id);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ SECURE_LOGI("Request ID: %d, caller appid: %s", request_id, caller);
+
+ *appid = strdup(caller);
+
+ return DATACONTROL_ERROR_NONE;
+}
+
+int
+datacontrol_provider_send_select_result(int request_id, void *db_handle)
+{
+ SECURE_LOGI("Send a select result for request id: %d", request_id);
+
+ if (request_table == NULL)
+ {
+ __initialize_provider();
+ }
+
+ bundle* b = g_hash_table_lookup(request_table, &request_id);
+ if (!b)
+ {
+ SECURE_LOGE("No data for the request id: %d", request_id);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ bundle* res = __set_result(b, DATACONTROL_TYPE_SQL_SELECT, db_handle);
+
+ return __send_result(res, DATACONTROL_TYPE_SQL_SELECT);
+}
+
+int
+datacontrol_provider_send_insert_result(int request_id, long long row_id)
+{
+ SECURE_LOGI("Send an insert result for request id: %d", request_id);
+
+ if (request_table == NULL)
+ {
+ __initialize_provider();
+ }
+
+ bundle* b = g_hash_table_lookup(request_table, &request_id);
+ if (!b)
+ {
+ SECURE_LOGE("No data for the request id: %d", request_id);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ bundle* res = __set_result(b, DATACONTROL_TYPE_SQL_INSERT, (void*)&row_id);
+
+ return __send_result(res, DATACONTROL_TYPE_SQL_INSERT);
+}
+
+int
+datacontrol_provider_send_update_result(int request_id)
+{
+ SECURE_LOGI("Send an update result for request id: %d", request_id);
+
+ if (request_table == NULL)
+ {
+ __initialize_provider();
+ }
+
+ bundle* b = g_hash_table_lookup(request_table, &request_id);
+ if (!b)
+ {
+ SECURE_LOGE("No data for the request id: %d", request_id);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ bundle* res = __set_result(b, DATACONTROL_TYPE_SQL_UPDATE, NULL);
+
+ return __send_result(res, DATACONTROL_TYPE_SQL_UPDATE);
+}
+
+int
+datacontrol_provider_send_delete_result(int request_id)
+{
+ SECURE_LOGI("Send a delete result for request id: %d", request_id);
+
+ if (request_table == NULL)
+ {
+ __initialize_provider();
+ }
+
+ bundle* b = g_hash_table_lookup(request_table, &request_id);
+ if (!b)
+ {
+ SECURE_LOGE("No data for the request id: %d", request_id);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ bundle* res = __set_result(b, DATACONTROL_TYPE_SQL_DELETE, NULL);
+
+ return __send_result(res, DATACONTROL_TYPE_SQL_DELETE);
+}
+
+int
+datacontrol_provider_send_error(int request_id, const char *error)
+{
+ SECURE_LOGI("Send an error for request id: %d", request_id);
+
+ if (request_table == NULL)
+ {
+ __initialize_provider();
+ }
+
+ bundle* b = g_hash_table_lookup(request_table, &request_id);
+ if (!b)
+ {
+ SECURE_LOGE("No data for the request id: %d", request_id);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ bundle* res = __set_result(b, DATACONTROL_TYPE_ERROR, (void*)error);
+
+ return __send_result(res, DATACONTROL_TYPE_ERROR);
+}
+
+int
+datacontrol_provider_send_map_result(int request_id)
+{
+ SECURE_LOGI("Send a set/add/remove result for request id: %d", request_id);
+
+ if (request_table == NULL)
+ {
+ __initialize_provider();
+ }
+
+ bundle* b = g_hash_table_lookup(request_table, &request_id);
+ if (!b)
+ {
+ SECURE_LOGE("No data for the request id: %d", request_id);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ bundle* res = __set_result(b, DATACONTROL_TYPE_UNDEFINED, NULL);
+
+ return __send_result(res, DATACONTROL_TYPE_UNDEFINED);
+}
+
+int
+datacontrol_provider_send_map_get_value_result(int request_id, char **value_list, int value_count)
+{
+ SECURE_LOGI("Send a get result for request id: %d", request_id);
+
+ if (request_table == NULL)
+ {
+ __initialize_provider();
+ }
+
+ bundle* b = g_hash_table_lookup(request_table, &request_id);
+ if (!b)
+ {
+ SECURE_LOGE("No data for the request id: %d", request_id);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ char value_count_str[32] = {0,};
+ snprintf(value_count_str, 32, "%d", value_count);
+ bundle_add_str(b, RESULT_VALUE_COUNT, value_count_str);
+
+ bundle* res = __set_result(b, DATACONTROL_TYPE_MAP_GET, value_list);
+
+ return __send_result(res, DATACONTROL_TYPE_MAP_GET);
+}
--- /dev/null
+#include <dlog.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "data-control-sql-cursor.h"
+
+#undef LOG_TAG
+#ifndef LOG_TAG
+#define LOG_TAG "DATA_CONTROL"
+#endif
+
+static int *row_offset_list = NULL;
+
+resultset_cursor* datacontrol_sql_get_cursor(const char * path)
+{
+ resultset_cursor *cursor = (resultset_cursor *)calloc(sizeof(resultset_cursor), 1);
+ if (!cursor)
+ {
+ LOGE("unable to create cursor");
+ return NULL;
+ }
+
+ cursor->resultset_row_count = 0;
+ cursor->resultset_col_count = 0;
+ cursor->resultset_col_type_offset = 0;
+ cursor->resultset_col_name_offset = 0;
+ cursor->resultset_content_offset = 0;
+ cursor->resultset_current_offset = 0;
+ cursor->resultset_current_row_count = 0;
+ /* TODO - shoud be changed to solve security concerns */
+ cursor->resultset_fd = open(path, O_RDONLY, 644);
+ if (cursor->resultset_fd == -1)
+ {
+ SECURE_LOGE("unable to open resultset file(%s): %d", path, errno);
+ goto EXCEPTION;
+ }
+
+ cursor->resultset_path = strdup(path);
+ if (!cursor->resultset_path)
+ {
+ SECURE_LOGE("unable to assign path to resultset file: %d", errno);
+ close(cursor->resultset_fd);
+ goto EXCEPTION;
+ }
+
+ return cursor;
+
+EXCEPTION:
+ free(cursor);
+ return NULL;
+}
+
+int datacontrol_sql_step_next(resultset_cursor *cursor)
+{
+ int total_col_name_size = 0;
+ int ret = 0;
+ int fd = cursor->resultset_fd;
+ if (cursor->resultset_current_offset == 0)
+ {
+ ret = lseek(fd, 0, SEEK_SET);
+ if (ret < 0)
+ {
+ LOGE("unable to seek to beginning in the resultset file: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, &(cursor->resultset_row_count), sizeof(int));
+ if (ret <= 0)
+ {
+ LOGE("unable to read the resultset file: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, &(cursor->resultset_col_count), sizeof(int));
+ if (ret <= 0)
+ {
+ LOGE("unable to read the resultset file: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, &(total_col_name_size), sizeof(int));
+ if (ret <= 0)
+ {
+ LOGE("unable to read the resultset file: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ cursor->resultset_col_type_offset = sizeof(int) * 3;
+ cursor->resultset_col_name_offset = cursor->resultset_col_type_offset + (cursor->resultset_col_count) * sizeof(int);
+ cursor->resultset_content_offset = cursor->resultset_col_name_offset + total_col_name_size;
+
+ cursor->resultset_current_offset = cursor->resultset_content_offset;
+
+ row_offset_list = (int *)malloc((cursor->resultset_row_count) * (sizeof(int)));
+ if (!row_offset_list)
+ {
+ LOGE("unable to create row_offset_list");
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ int counter = 0;
+ for (counter = 0; counter < cursor->resultset_row_count; counter++)
+ {
+ row_offset_list[counter] = 0;
+ }
+ row_offset_list[cursor->resultset_current_row_count] = cursor->resultset_current_offset;
+ }
+ else
+ {
+ if (!(cursor->resultset_current_row_count < (cursor->resultset_row_count -1)))
+ {
+ LOGE("Reached to the end of the result set");
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = row_offset_list[cursor->resultset_current_row_count + 1];
+ if (ret == 0) // Move to next offset
+ {
+ int size = 0;
+ int i = 0;
+
+ ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ for (i = 0; i < cursor->resultset_col_count; i++)
+ {
+ ret = lseek(fd, sizeof(int), SEEK_CUR);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, &size, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read the resultset file: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = lseek(fd, size, SEEK_CUR);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ cursor->resultset_current_offset += sizeof(int) * 2 + size;
+ }
+
+ row_offset_list[cursor->resultset_current_row_count + 1] = cursor->resultset_current_offset;
+ }
+ else
+ {
+ cursor->resultset_current_offset = row_offset_list[cursor->resultset_current_row_count + 1];
+ }
+ cursor->resultset_current_row_count++;
+
+ }
+ return DATACONTROL_ERROR_NONE;
+}
+
+int datacontrol_sql_step_last(resultset_cursor *cursor)
+{
+ int ret = 0;
+
+ if (cursor->resultset_current_row_count == (cursor->resultset_row_count - 1))
+ {
+ return DATACONTROL_ERROR_NONE; // Already @ last row
+ }
+
+ if (!row_offset_list)
+ {
+ ret = datacontrol_sql_step_next(cursor); // make a first move
+ if (ret != DATACONTROL_ERROR_NONE)
+ {
+ return ret;
+ }
+ }
+
+ // check if the rowOffsetList contains last row offset
+ if (row_offset_list && row_offset_list[cursor->resultset_row_count - 1] != 0)
+ {
+ cursor->resultset_current_offset = row_offset_list[cursor->resultset_row_count - 1];
+ cursor->resultset_current_row_count = cursor->resultset_row_count - 1;
+ }
+ else
+ {
+ int i = 0;
+ // Move till last row offset.
+ for (i = (cursor->resultset_current_row_count + 1); i < cursor->resultset_row_count; i++)
+ {
+ ret = datacontrol_sql_step_next(cursor); // move till last row data offset
+ if (ret != DATACONTROL_ERROR_NONE)
+ {
+ return ret;
+ }
+
+ }
+ }
+
+ return DATACONTROL_ERROR_NONE;
+}
+
+
+int datacontrol_sql_step_first(resultset_cursor *cursor)
+{
+ if (cursor->resultset_current_offset > 0)
+ {
+ cursor->resultset_current_offset = cursor->resultset_content_offset;
+ cursor->resultset_current_row_count = 0;
+ return DATACONTROL_ERROR_NONE;
+ }
+
+ // MoveFirst is called for the first time before MoveNext() or MoveLast()
+ cursor->resultset_current_offset = 0;
+ return datacontrol_sql_step_next(cursor);
+}
+
+
+int datacontrol_sql_step_previous(resultset_cursor *cursor)
+{
+ if ((cursor->resultset_current_row_count - 1) < 0)
+ {
+ LOGE("invalid request");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+ cursor->resultset_current_offset = row_offset_list[cursor->resultset_current_row_count - 1];
+ cursor->resultset_current_row_count--;
+
+ return DATACONTROL_ERROR_NONE;
+}
+
+
+int datacontrol_sql_get_column_count(resultset_cursor *cursor)
+{
+ return cursor->resultset_col_count;
+}
+
+int datacontrol_sql_get_column_name(resultset_cursor *cursor, int column_index, char *name)
+{
+ char col_name[4096] = {0, };
+ int i = 0;
+ int ret = 0;
+ FILE *fp = fdopen(dup(cursor->resultset_fd), "r");
+ if (fp == NULL)
+ {
+ LOGE("unable to open resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = fseek(fp, cursor->resultset_col_name_offset, SEEK_SET);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ fclose(fp);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ for (i = 0; i < column_index + 1; i++)
+ {
+ if (!(fgets(col_name, 4096, fp)))
+ {
+ LOGE("unable to read a line in the resultset file: %s", strerror(errno));
+ fclose(fp);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+ }
+
+ memset(name, 0, strlen(col_name)); // To avoid copying newline
+ memcpy(name, col_name, strlen(col_name) - 1);
+
+ LOGI("The column name is %s", name);
+
+ fclose(fp);
+ return DATACONTROL_ERROR_NONE;
+}
+
+
+int datacontrol_sql_get_column_item_size(resultset_cursor *cursor, int column_index)
+{
+ int type = -1;
+ int size = 0;
+ int i = 0;
+ int ret = 0;
+
+ int fd = cursor->resultset_fd;
+
+ ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ for (i = 0; i < column_index; i++) // move to column index
+ {
+ ret = read(fd, &type, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, &size, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = lseek(fd, size, SEEK_CUR);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+ }
+
+ ret = read(fd, &type, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, &size, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ return size;
+}
+
+
+int datacontrol_sql_get_column_item_type(resultset_cursor *cursor, int column_index, datacontrol_sql_column_type* col_type)
+{
+ int type = -1;
+ int i = 0;
+ int size = 0;
+ int ret = 0;
+
+ int fd = cursor->resultset_fd;
+
+ ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ for (i = 0; i < column_index; i++) // move to column index
+ {
+ ret = read(fd, &type, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, &size, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = lseek(fd, size, SEEK_CUR);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+ }
+
+ ret = read(fd, &type, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ switch (type)
+ {
+ case DATACONTROL_SQL_COLUMN_TYPE_INT64:
+ *col_type = DATACONTROL_SQL_COLUMN_TYPE_INT64;
+ break;
+
+ case DATACONTROL_SQL_COLUMN_TYPE_DOUBLE:
+ *col_type = DATACONTROL_SQL_COLUMN_TYPE_DOUBLE;
+ break;
+
+ case DATACONTROL_SQL_COLUMN_TYPE_TEXT:
+ *col_type = DATACONTROL_SQL_COLUMN_TYPE_TEXT;
+ break;
+
+ case DATACONTROL_SQL_COLUMN_TYPE_BLOB:
+ *col_type = DATACONTROL_SQL_COLUMN_TYPE_BLOB;
+ break;
+
+ case DATACONTROL_SQL_COLUMN_TYPE_NULL:
+ *col_type = DATACONTROL_SQL_COLUMN_TYPE_NULL;
+ break;
+
+ default:
+ *col_type = DATACONTROL_SQL_COLUMN_TYPE_UNDEFINED;
+ break;
+ }
+
+ return DATACONTROL_ERROR_NONE;
+}
+
+
+int datacontrol_sql_get_blob_data(resultset_cursor *cursor, int column_index, void *buffer, int data_size)
+{
+ int type = -1;
+ int size = 0;
+ int i = 0;
+ int ret = 0;
+
+ int fd = cursor->resultset_fd;
+
+ ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ for (i = 0; i < column_index; i++) // move to column index
+ {
+ ret = read(fd, &type, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, &size, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = lseek(fd, size, SEEK_CUR);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+ }
+
+ ret = read(fd, &type, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ if (type != (int)DATACONTROL_SQL_COLUMN_TYPE_BLOB)
+ {
+ LOGE("type mismatch: requested for BLOB type but %d present:", type);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ ret = read(fd, &size, sizeof(int));
+ if (size > data_size)
+ {
+ LOGE("size is more than the size requested");
+ return DATACONTROL_ERROR_MAX_EXCEEDED; //overflow
+ }
+
+ if (size > 0)
+ {
+ char *data = (char*)malloc((size + 1) * (sizeof(char)));
+ memset(data, 0, size + 1);
+
+ ret = read(fd, data, size);
+ if (ret < size)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ free(data);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ memcpy(buffer, data, size + 1);
+ free(data);
+ }
+ return DATACONTROL_ERROR_NONE;
+}
+
+
+int datacontrol_sql_get_int_data(resultset_cursor *cursor, int column_index, int *data)
+{
+ long long long_value = 0;
+ int ret = -1;
+
+ ret = datacontrol_sql_get_int64_data(cursor, column_index, &long_value);
+ if (ret == 0)
+ {
+ *data = (int) long_value;
+ }
+
+ return ret;
+}
+
+
+int datacontrol_sql_get_int64_data(resultset_cursor *cursor, int column_index, long long *data)
+{
+ int type = -1;
+ int size = 0;
+ int i = 0;
+ int ret = 0;
+
+ int fd = cursor->resultset_fd;
+
+ ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ for (i = 0; i < column_index; i++) // move to column index
+ {
+ ret = read(fd, &type, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, &size, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = lseek(fd, size, SEEK_CUR);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+ }
+
+ ret = read(fd, &type, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ if (type != (int)DATACONTROL_SQL_COLUMN_TYPE_INT64)
+ {
+ LOGE("type mismatch: requested for int type but %d present:", type);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ ret = read(fd, &size, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, data, size);
+ if (ret < size)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ return DATACONTROL_ERROR_NONE;
+}
+
+int datacontrol_sql_get_double_data(resultset_cursor *cursor, int column_index, double *data)
+{
+ int type = -1;
+ int size = 0;
+ int i = 0;
+ int ret = 0;
+
+ int fd = cursor->resultset_fd;
+
+ ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ for (i = 0; i < column_index; i++) // move to column index
+ {
+ ret = read(fd, &type, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, &size, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = lseek(fd, size, SEEK_CUR);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+ }
+
+ ret = read(fd, &type, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ if (type != (int)DATACONTROL_SQL_COLUMN_TYPE_DOUBLE)
+ {
+ LOGE("type mismatch: requested for double type but %d present:", type);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ ret = read(fd, &size, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, data, size);
+ if (ret < size)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ return DATACONTROL_ERROR_NONE;
+}
+
+
+int datacontrol_sql_get_text_data(resultset_cursor *cursor, int column_index, char *buffer)
+{
+ int type = -1;
+ int size = 0;
+ int i = 0;
+ int ret = 0;
+
+ int fd = cursor->resultset_fd;
+
+ ret = lseek(fd, cursor->resultset_current_offset, SEEK_SET);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ for (i = 0; i < column_index; i++) // move to column index
+ {
+ ret = read(fd, &type, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = read(fd, &size, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ ret = lseek(fd, size, SEEK_CUR);
+ if (ret < 0)
+ {
+ LOGE("unable to seek in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+ }
+
+ ret = read(fd, &type, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ if (type != (int)DATACONTROL_SQL_COLUMN_TYPE_TEXT)
+ {
+ LOGE("type mismatch: requested for text type but %d present:", type);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ ret = read(fd, &size, sizeof(int));
+ if (ret == 0)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ if (size > 0)
+ {
+ char *data = (char*)malloc((size + 1) * (sizeof(char)));
+ if(!data)
+ {
+ LOGE("unable to create buffer to read");
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ memset(data, 0, size + 1);
+ ret = read(fd, data, size);
+ if (ret < size)
+ {
+ LOGE("unable to read in the resultset file: %s", strerror(errno));
+ free(data);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ memcpy(buffer, data, size + 1);
+ free(data);
+ }
+
+ return DATACONTROL_ERROR_NONE;
+}
+
+
+int datacontrol_sql_remove_cursor(resultset_cursor *cursor)
+{
+ close(cursor->resultset_fd);
+
+ int ret = remove(cursor->resultset_path);
+ if (ret == -1)
+ {
+ LOGE("unable to remove map query result file: %d", ret);
+ }
+
+ free(row_offset_list);
+ row_offset_list = 0;
+
+ free(cursor->resultset_path);
+ free(cursor);
+
+ return DATACONTROL_ERROR_NONE;
+}
--- /dev/null
+#include <dlog.h>
+#include <errno.h>
+#include <search.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <glib.h>
+#include <pthread.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <appsvc/appsvc.h>
+#include <aul/aul.h>
+#include <bundle.h>
+#include <pkgmgr-info.h>
+
+#include "data-control-sql.h"
+#include "data-control-internal.h"
+
+#define REQUEST_PATH_MAX 512
+#define MAX_REQUEST_ARGUMENT_SIZE 1048576 // 1MB
+
+struct datacontrol_s {
+ char *provider_id;
+ char *data_id;
+};
+
+typedef struct
+{
+ char *provider_id;
+ char *app_id;
+ char *data_id;
+ char *access_info;
+ void *user_data;
+ datacontrol_sql_response_cb *sql_response_cb;
+} sql_response_cb_s;
+
+
+static void *datacontrol_sql_tree_root = NULL;
+
+static void
+datacontrol_sql_call_cb(const char *provider_id, int request_id, datacontrol_request_type type
+ , const char *data_id, bool provider_result, const char *error, long long insert_rowid, resultset_cursor* cursor, void* data)
+{
+ SECURE_LOGI("datacontrol_sql_call_cb, dataID: %s", data_id);
+
+ datacontrol_sql_response_cb *callback = NULL;
+
+ sql_response_cb_s *sql_dc = NULL;
+ sql_dc = (sql_response_cb_s *)data;
+ callback = sql_dc->sql_response_cb;
+ if (!callback)
+ {
+ LOGE("no listener set");
+ return;
+ }
+
+ datacontrol_h provider;
+ datacontrol_sql_create(&provider);
+
+ datacontrol_sql_set_provider_id(provider, provider_id);
+ datacontrol_sql_set_data_id(provider, data_id);
+
+ switch (type)
+ {
+ case DATACONTROL_TYPE_SQL_SELECT:
+ {
+ LOGI("SELECT");
+ if (callback != NULL && callback->select != NULL)
+ {
+ callback->select(request_id, provider, cursor, provider_result, error, sql_dc->user_data);
+ }
+ else
+ {
+ LOGI("No registered callback function");
+ }
+
+ break;
+ }
+ case DATACONTROL_TYPE_SQL_INSERT:
+ {
+ SECURE_LOGI("INSERT row_id: %lld", insert_rowid);
+ if (callback != NULL && callback->insert != NULL)
+ {
+ callback->insert(request_id, provider, insert_rowid, provider_result, error, sql_dc->user_data);
+ }
+ else
+ {
+ LOGI("No registered callback function");
+ }
+
+ break;
+ }
+ case DATACONTROL_TYPE_SQL_UPDATE:
+ {
+ LOGI("UPDATE");
+ if (callback != NULL && callback->update != NULL)
+ {
+ callback->update(request_id, provider, provider_result, error, sql_dc->user_data);
+ }
+ else
+ {
+ LOGI("No registered callback function");
+ }
+
+ break;
+ }
+ case DATACONTROL_TYPE_SQL_DELETE:
+ {
+ LOGI("DELETE");
+ if (callback != NULL && callback->delete != NULL)
+ {
+ callback->delete(request_id, provider, provider_result, error, sql_dc->user_data);
+ }
+ else
+ {
+ LOGI("No registered callback function");
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ datacontrol_sql_destroy(provider);
+}
+
+static void
+datacontrol_sql_instance_free(void *datacontrol_sql_instance)
+{
+ sql_response_cb_s *dc = (sql_response_cb_s *)datacontrol_sql_instance;
+ if (dc)
+ {
+ free(dc->provider_id);
+ free(dc->data_id);
+ free(dc->app_id);
+ free(dc->access_info);
+ free(datacontrol_sql_instance);
+ }
+
+ return;
+}
+
+static int
+datacontrol_sql_instance_compare(const void *l_datacontrol_sql_instance, const void *r_datacontrol_sql_instance)
+{
+ sql_response_cb_s *dc_left = (sql_response_cb_s *)l_datacontrol_sql_instance;
+ sql_response_cb_s *dc_right = (sql_response_cb_s *)r_datacontrol_sql_instance;
+ return strcmp(dc_left->provider_id, dc_right->provider_id);
+}
+
+
+static int
+datacontrol_sql_handle_cb(bundle* b, int request_code, appsvc_result_val res, void* data)
+{
+ SECURE_LOGI("datacontrol_sql_handle_cb, request_code: %d, result: %d", request_code, res);
+
+ int ret = 0;
+ const char** result_list = NULL;
+ resultset_cursor *cursor = NULL;
+ const char* provider_id = NULL;
+ const char* data_id = NULL;
+ const char* error_message = NULL;
+ long long insert_rowid = -1;
+ datacontrol_request_type request_type = 0;
+ int request_id = -1;
+ int result_list_len = 0;
+ int provider_result = 0;
+ const char* resultset_path = NULL;
+ const char* p = NULL;
+
+ if (b)
+ {
+ p = appsvc_get_data(b, OSP_K_REQUEST_ID);
+ if (!p)
+ {
+ LOGE("Invalid Bundle: request_id is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+ else
+ {
+ request_id = atoi(p);
+ }
+
+ SECURE_LOGI("Request ID: %d", request_id);
+
+ // result list
+ result_list = appsvc_get_data_array(b, OSP_K_ARG, &result_list_len);
+ if (!result_list)
+ {
+ LOGE("Invalid Bundle: arguement list is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ p = result_list[0]; // result list[0] = provider_result
+ if (!p)
+ {
+ LOGE("Invalid Bundle: provider_result is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGI("Provider result: %s", p);
+
+ provider_result = atoi(p);
+
+ error_message = result_list[1]; // result list[1] = error
+ if (!error_message)
+ {
+ LOGE("Invalid Bundle: error_message is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGI("Error message: %s", error_message);
+
+ p = appsvc_get_data(b, OSP_K_DATACONTROL_REQUEST_TYPE);
+ if (!p)
+ {
+ LOGE("Invalid Bundle: data-control request type is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ request_type = (datacontrol_request_type)atoi(p);
+
+ provider_id = appsvc_get_data(b, OSP_K_DATACONTROL_PROVIDER);
+ if (!provider_id)
+ {
+ LOGE("Invalid Bundle: provider_id is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ data_id = appsvc_get_data(b, OSP_K_DATACONTROL_DATA);
+ if (!data_id)
+ {
+ LOGE("Invalid Bundle: data_id is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ SECURE_LOGI("Provider ID: %s, Data ID: %s, Operation type: %d", provider_id, data_id, request_type);
+
+ switch (request_type)
+ {
+ case DATACONTROL_TYPE_SQL_SELECT:
+ {
+ LOGI("SELECT RESPONSE");
+ if (provider_result)
+ {
+ resultset_path = result_list[2]; // result list[2]
+ if (!resultset_path)
+ {
+ LOGE("sql query result path is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ SECURE_LOGI("resultset_path: %s", resultset_path);
+
+ if (strcmp(resultset_path, "NoResultSet") != 0) // Result set exists
+ {
+ cursor = datacontrol_sql_get_cursor(resultset_path);
+ if (!cursor)
+ {
+ LOGE("failed to get cursor on sql query resultset");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+ }
+ }
+ break;
+ }
+ case DATACONTROL_TYPE_SQL_INSERT:
+ {
+ LOGI("INSERT RESPONSE");
+ if (provider_result)
+ {
+ p = result_list[2]; // result list[2]
+ if (!p)
+ {
+ LOGE("Invalid Bundle: insert row_id is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ insert_rowid = atoll(p);
+ }
+ break;
+ }
+ case DATACONTROL_TYPE_SQL_UPDATE:
+ case DATACONTROL_TYPE_SQL_DELETE:
+ {
+ LOGI("UPDATE or DELETE RESPONSE");
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ }
+ else
+ {
+ LOGE("the bundle returned from datacontrol-provider-service is null");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (request_type >= DATACONTROL_TYPE_SQL_SELECT && request_type <= DATACONTROL_TYPE_SQL_DELETE)
+ {
+ datacontrol_sql_call_cb(provider_id, request_id, request_type, data_id, provider_result, error_message, insert_rowid, cursor, data);
+ if ((request_type == DATACONTROL_TYPE_SQL_SELECT) && (cursor))
+ {
+ datacontrol_sql_remove_cursor(cursor);
+ }
+
+ ret = DATACONTROL_ERROR_NONE;
+ }
+ else
+ {
+ ret = DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ return ret;
+}
+
+static void
+app_svc_res_cb_sql(bundle* b, int request_code, appsvc_result_val res, void* data)
+{
+ LOGI("app_svc_res_cb_sql, request_code: %d, result: %d", request_code, res);
+
+ if (data)
+ {
+ datacontrol_sql_handle_cb(b, request_code, res, data);
+ }
+ else
+ {
+ LOGE("error: listener information is null");
+ }
+}
+
+
+static int
+datacontrol_sql_request_provider(datacontrol_h provider, datacontrol_request_type type, bundle *arg_list, int request_id)
+{
+ SECURE_LOGI("SQL Data control request, type: %d, request id: %d", type, request_id);
+
+ char *app_id = NULL;
+ void *data = NULL;
+
+ if ((int)type <= (int)DATACONTROL_TYPE_SQL_DELETE)
+ {
+ if ((int)type < (int)DATACONTROL_TYPE_SQL_SELECT)
+ {
+ LOGE("invalid request type: %d", (int)type);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!datacontrol_sql_tree_root)
+ {
+ LOGE("the listener tree is empty");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ sql_response_cb_s *sql_dc_temp = (sql_response_cb_s *)calloc(sizeof(sql_response_cb_s),1);
+ if (!sql_dc_temp)
+ {
+ LOGE("failed to create sql datacontrol");
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ sql_dc_temp->provider_id = strdup(provider->provider_id);
+ if (!sql_dc_temp->provider_id)
+ {
+ LOGE("failed to assign provider id to sql data control: %d", errno);
+ free(sql_dc_temp);
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ sql_dc_temp->data_id = strdup(provider->data_id);
+ if (!sql_dc_temp->data_id)
+ {
+ LOGE("failed to assign data id to sql data control: %d", errno);
+ free(sql_dc_temp->provider_id);
+ free(sql_dc_temp);
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ sql_dc_temp->app_id = NULL;
+ sql_dc_temp->access_info = NULL;
+ sql_dc_temp->user_data = NULL;
+ sql_dc_temp->sql_response_cb = NULL;
+
+ void *sql_dc_returned = NULL;
+ sql_dc_returned = tfind(sql_dc_temp, &datacontrol_sql_tree_root, datacontrol_sql_instance_compare);
+
+ datacontrol_sql_instance_free(sql_dc_temp);
+
+ if (!sql_dc_returned)
+ {
+ LOGE("sql datacontrol returned after tfind is null");
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ sql_response_cb_s *sql_dc = *(sql_response_cb_s **)sql_dc_returned;
+ app_id = sql_dc->app_id;
+ data = sql_dc;
+
+ SECURE_LOGI("SQL datacontrol appid: %s", sql_dc->app_id);
+ }
+
+ char caller_app_id[255];
+ pid_t pid = getpid();
+ if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0)
+ {
+ SECURE_LOGE("Failed to get appid by pid(%d).", pid);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ appsvc_set_operation(arg_list, APPSVC_OPERATION_DEFAULT);
+ appsvc_set_appid(arg_list, app_id);
+ bundle_add_str(arg_list, OSP_K_CALLER_TYPE, OSP_V_CALLER_TYPE_OSP);
+ bundle_add_str(arg_list, OSP_K_LAUNCH_TYPE, OSP_V_LAUNCH_TYPE_DATACONTROL);
+ bundle_add_str(arg_list, OSP_K_DATACONTROL_PROTOCOL_VERSION, OSP_V_VERSION_2_1_0_3);
+ bundle_add_str(arg_list, AUL_K_CALLER_APPID, caller_app_id);
+ bundle_add_str(arg_list, AUL_K_NO_CANCEL, "1");
+
+
+ char datacontrol_request_operation[MAX_LEN_DATACONTROL_REQ_TYPE] = {0, };
+ snprintf(datacontrol_request_operation, MAX_LEN_DATACONTROL_REQ_TYPE, "%d", (int)(type));
+ bundle_add_str(arg_list, OSP_K_DATACONTROL_REQUEST_TYPE, datacontrol_request_operation);
+
+ char req_id[32] = {0, };
+ snprintf(req_id, 32, "%d", request_id);
+ bundle_add_str(arg_list, OSP_K_REQUEST_ID, req_id);
+
+ // For DataControl CAPI
+ bundle_add_str(arg_list, AUL_K_DATA_CONTROL_TYPE, "CORE");
+
+ SECURE_LOGI("SQL data control request - provider id: %s, data id: %s, provider appid: %s, request ID: %s", provider->provider_id, provider->data_id, app_id, req_id);
+
+ pid = -1;
+ int count = 0;
+ const int TRY_COUNT = 4;
+ const int TRY_SLEEP_TIME = 65000;
+ do
+ {
+ pid = appsvc_run_service(arg_list, request_id, app_svc_res_cb_sql, data);
+ if (pid >= 0)
+ {
+ SECURE_LOGI("Launch the provider app successfully: %d", pid);
+ return DATACONTROL_ERROR_NONE;
+ }
+ else if (pid == APPSVC_RET_EINVAL)
+ {
+ SECURE_LOGE("not able to launch service: %d", pid);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ count++;
+
+ usleep(TRY_SLEEP_TIME);
+ }
+ while (count < TRY_COUNT);
+
+ SECURE_LOGE("unable to launch service: %d", pid);
+ return DATACONTROL_ERROR_IO_ERROR;
+}
+
+int
+datacontrol_sql_create(datacontrol_h *provider)
+{
+ struct datacontrol_s *request;
+
+ if (provider == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ request = malloc(sizeof(struct datacontrol_s));
+ if (request == NULL)
+ {
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ request->provider_id = NULL;
+ request->data_id = NULL;
+
+ *provider = request;
+
+ return 0;
+}
+
+int
+datacontrol_sql_destroy(datacontrol_h provider)
+{
+ if (provider == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (provider->provider_id != NULL)
+ {
+ free(provider->provider_id);
+ }
+
+ if (provider->data_id != NULL)
+ {
+ free(provider->data_id);
+ }
+
+ free(provider);
+ return 0;
+}
+
+int
+datacontrol_sql_set_provider_id(datacontrol_h provider, const char *provider_id)
+{
+ if (provider == NULL || provider_id == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (provider->provider_id != NULL)
+ {
+ free(provider->provider_id);
+ }
+
+ provider->provider_id = strdup(provider_id);
+ if (provider->provider_id == NULL)
+ {
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ return 0;
+}
+
+int
+datacontrol_sql_get_provider_id(datacontrol_h provider, char **provider_id)
+{
+ if (provider == NULL || provider_id == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (provider->provider_id != NULL)
+ {
+ *provider_id = strdup(provider->provider_id);
+ if (*provider_id == NULL)
+ {
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ *provider_id = NULL;
+ }
+
+ return 0;
+}
+
+int
+datacontrol_sql_set_data_id(datacontrol_h provider, const char *data_id)
+{
+ if (provider == NULL || data_id == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (provider->data_id != NULL)
+ {
+ free(provider->data_id);
+ }
+
+ provider->data_id = strdup(data_id);
+ if (provider->data_id == NULL)
+ {
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ return 0;
+}
+
+int
+datacontrol_sql_get_data_id(datacontrol_h provider, char **data_id)
+{
+ if (provider == NULL || data_id == NULL)
+ {
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ if (provider->data_id != NULL)
+ {
+ *data_id = strdup(provider->data_id);
+ if (*data_id == NULL)
+ {
+ return DATACONTROL_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ *data_id = NULL;
+ }
+ return 0;
+}
+
+int
+datacontrol_sql_register_response_cb(datacontrol_h provider, datacontrol_sql_response_cb* callback, void *user_data)
+{
+ int ret = 0;
+ char* app_id = NULL;
+ char* access = NULL;
+
+ ret = pkgmgrinfo_appinfo_get_datacontrol_info(provider->provider_id, "Sql", &app_id, &access);
+ if (ret != PMINFO_R_OK)
+ {
+ LOGE("unable to get sql data control information: %d", ret);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ SECURE_LOGI("data control provider appid = %s", app_id);
+
+ sql_response_cb_s *sql_dc_temp = (sql_response_cb_s *)calloc(sizeof(sql_response_cb_s),1);
+ if (!sql_dc_temp)
+ {
+ LOGE("unable to create a temporary sql data control");
+ ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
+ goto EXCEPTION;
+ }
+
+ sql_dc_temp->provider_id = strdup(provider->provider_id);
+ if (!sql_dc_temp->provider_id)
+ {
+ LOGE("unable to assign provider_id to sql data control: %d", errno);
+ ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
+ goto EXCEPTION;
+ }
+
+ sql_dc_temp->data_id = strdup(provider->data_id);
+ if (!sql_dc_temp->data_id)
+ {
+ LOGE("unable to assign data_id to sql data control: %d", errno);
+ ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
+ goto EXCEPTION;
+ }
+
+ sql_dc_temp->app_id = app_id;
+ sql_dc_temp->access_info = access;
+ sql_dc_temp->user_data = user_data;
+ sql_dc_temp->sql_response_cb = callback;
+
+ void *sql_dc_returned = NULL;
+ sql_dc_returned = tsearch(sql_dc_temp, &datacontrol_sql_tree_root, datacontrol_sql_instance_compare);
+
+ sql_response_cb_s *sql_dc = *(sql_response_cb_s **)sql_dc_returned;
+ if (sql_dc != sql_dc_temp)
+ {
+ sql_dc->sql_response_cb = callback;
+ sql_dc->user_data = user_data;
+ LOGI("the data control is already set");
+ datacontrol_sql_instance_free(sql_dc_temp);
+ }
+
+ return DATACONTROL_ERROR_NONE;
+
+EXCEPTION:
+ if (access)
+ free(access);
+ if (app_id)
+ free(app_id);
+ if (sql_dc_temp)
+ {
+ if (sql_dc_temp->provider_id)
+ free(sql_dc_temp->provider_id);
+ if (sql_dc_temp->data_id)
+ free(sql_dc_temp->data_id);
+ free(sql_dc_temp);
+ }
+
+ return ret;
+}
+
+int
+datacontrol_sql_unregister_response_cb(datacontrol_h provider)
+{
+ int ret = DATACONTROL_ERROR_NONE;
+
+ sql_response_cb_s *sql_dc_temp = (sql_response_cb_s *)calloc(sizeof(sql_response_cb_s),1);
+
+ if (!sql_dc_temp)
+ {
+ LOGE("unable to create a temporary sql data control");
+ ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
+ goto EXCEPTION;
+ }
+
+ sql_dc_temp->provider_id = strdup(provider->provider_id);
+ if (!sql_dc_temp->provider_id)
+ {
+ LOGE("unable to assign provider_id to sql data control: %d", errno);
+ ret = DATACONTROL_ERROR_OUT_OF_MEMORY;
+ goto EXCEPTION;
+ }
+
+
+ void *sql_dc_returned = NULL;
+
+ sql_dc_returned = tdelete(sql_dc_temp, &datacontrol_sql_tree_root, datacontrol_sql_instance_compare);
+ if (sql_dc_returned == NULL)
+ {
+ LOGE("invalid parameter");
+ ret = DATACONTROL_ERROR_INVALID_PARAMETER;
+ goto EXCEPTION;
+ }
+
+
+EXCEPTION:
+ if (sql_dc_temp)
+ {
+ if (sql_dc_temp->provider_id)
+ free(sql_dc_temp->provider_id);
+ free(sql_dc_temp);
+ }
+
+ return ret;
+
+}
+
+static void
+bundle_foreach_check_arg_size_cb(const char *key, const int type, const bundle_keyval_t *kv, void *arg_size)
+{
+ char *value = NULL;
+ size_t value_len = 0;
+ bundle_keyval_get_basic_val((bundle_keyval_t*)kv, (void**)&value, &value_len);
+
+ arg_size += (strlen(key) + value_len) * sizeof(wchar_t);
+ return;
+}
+
+static void
+bundle_foreach_cb(const char *key, const int type, const bundle_keyval_t *kv, void *user_data)
+{
+ if (!key || !kv || !user_data)
+ {
+ return;
+ }
+
+ int fd = *(int *)user_data;
+
+ int key_len = strlen(key);
+ char *value = NULL;
+ size_t value_len = 0;
+ bundle_keyval_get_basic_val((bundle_keyval_t*)kv, (void**)&value, &value_len);
+
+ // Write a key
+ if (write(fd, &key_len, sizeof(int)) == -1)
+ {
+ LOGE("Writing a key_len to a file descriptor is failed. errno = %d", errno);
+ }
+ if (write(fd, key, key_len) == -1)
+ {
+ LOGE("Writing a key to a file descriptor is failed. errno = %d", errno);
+ }
+ // Write a value
+ if (write(fd, &value_len, sizeof(int)) == -1)
+ {
+ LOGE("Writing a value_len to a file descriptor is failed. errno = %d", errno);
+ }
+ if (write(fd, value, value_len) == -1)
+ {
+ LOGE("Writing a value to a file descriptor is failed. errno = %d", errno);
+ }
+
+ return;
+}
+
+char *
+__get_provider_pkgid(char* provider_id)
+{
+ char* access = NULL;
+ char *provider_appid = NULL;
+ char *provider_pkgid = NULL;
+ pkgmgrinfo_appinfo_h app_info_handle = NULL;
+
+ int ret = pkgmgrinfo_appinfo_get_datacontrol_info(provider_id, "Sql", &provider_appid, &access);
+ if (ret != PMINFO_R_OK)
+ {
+ LOGE("unable to get sql data control information: %d", ret);
+ return NULL;
+ }
+
+ pkgmgrinfo_appinfo_get_appinfo(provider_appid, &app_info_handle);
+ pkgmgrinfo_appinfo_get_pkgname(app_info_handle, &provider_pkgid);
+ SECURE_LOGI("provider pkg id : %s", provider_pkgid);
+
+ if (access)
+ {
+ free(access);
+ }
+ if (provider_appid)
+ {
+ free(provider_appid);
+ }
+ return provider_pkgid ? strdup(provider_pkgid) : NULL;
+}
+
+int
+datacontrol_sql_insert(datacontrol_h provider, const bundle* insert_data, int *request_id)
+{
+ if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || insert_data == NULL)
+ {
+ LOGE("Invalid parameter");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ SECURE_LOGI("SQL data control, insert to provider_id: %s, data_id: %s", provider->provider_id, provider->data_id);
+
+ int ret = 0;
+
+ char caller_app_id[256] = {0, };
+ pid_t pid = getpid();
+
+ if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0)
+ {
+ SECURE_LOGE("Failed to get appid by pid(%d).", pid);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ // Check size of arguments
+ long long arg_size = 0;
+ bundle_foreach((bundle*)insert_data, bundle_foreach_check_arg_size_cb, &arg_size);
+ arg_size += strlen(provider->data_id) * sizeof(wchar_t);
+ if (arg_size > MAX_REQUEST_ARGUMENT_SIZE)
+ {
+ LOGE("The size of the request argument exceeds the limit, 1M.");
+ return DATACONTROL_ERROR_MAX_EXCEEDED;
+ }
+
+ int reqId = _datacontrol_create_request_id();
+ SECURE_LOGI("request id: %d", reqId);
+ char insert_map_file[REQUEST_PATH_MAX] = {0, };
+ ret = snprintf(insert_map_file, REQUEST_PATH_MAX, "%s/%s_%d", DATACONTROL_REQUEST_FILE_PREFIX, caller_app_id, reqId);
+ if (ret < 0)
+ {
+ LOGE("unable to write formatted output to insert_map_file. errno = %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ SECURE_LOGI("insert_map_file : %s", insert_map_file);
+
+ int fd = 0;
+ char *provider_pkgid = __get_provider_pkgid(provider->provider_id);
+
+ /* TODO - shoud be changed to solve security concerns */
+ fd = open(insert_map_file, O_WRONLY | O_CREAT, 644);
+ if (fd == -1) {
+ SECURE_LOGE("unable to open insert_map file: %d", errno);
+ free(provider_pkgid);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ free(provider_pkgid);
+
+ int count = bundle_get_count((bundle*)insert_data);
+ LOGI("Insert column counts: %d", count);
+
+ bundle_foreach((bundle*)insert_data, bundle_foreach_cb, &fd);
+
+ fsync(fd);
+ close(fd);
+
+ bundle *b = bundle_create();
+ if (!b)
+ {
+ LOGE("unable to create bundle: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
+ bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+
+ char insert_column_count[MAX_LEN_DATACONTROL_COLUMN_COUNT] = {0, };
+ ret = snprintf(insert_column_count, MAX_LEN_DATACONTROL_COLUMN_COUNT, "%d", count);
+ if (ret < 0)
+ {
+ LOGE("unable to convert insert column count to string: %d", errno);
+ bundle_free(b);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ const char* arg_list[3];
+ arg_list[0] = provider->data_id;
+ arg_list[1] = insert_column_count;
+ arg_list[2] = insert_map_file;
+
+ bundle_add_str_array(b, OSP_K_ARG, arg_list, 3);
+
+ // Set the request id
+ *request_id = reqId;
+
+ ret = datacontrol_sql_request_provider(provider, DATACONTROL_TYPE_SQL_INSERT, b, reqId);
+ if (ret != DATACONTROL_ERROR_NONE)
+ {
+ ret = remove(insert_map_file);
+ if (ret == -1)
+ {
+ SECURE_LOGE("unable to remove the insert_map_file. errno = %d", errno);
+ }
+ }
+ bundle_free(b);
+ return ret;
+}
+
+int
+datacontrol_sql_delete(datacontrol_h provider, const char *where, int *request_id)
+{
+ if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL)
+ {
+ LOGE("Invalid parameter");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ bundle *b = bundle_create();
+ if (!b)
+ {
+ LOGE("unable to create bundle: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
+ bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+
+ const char* arg_list[2];
+ arg_list[0] = provider->data_id;
+
+ if (where)
+ {
+ arg_list[1] = where;
+ }
+ else
+ {
+ arg_list[1] = DATACONTROL_EMPTY;
+ }
+
+ bundle_add_str_array(b, OSP_K_ARG, arg_list, 2);
+
+ // Set the request id
+ int reqId = _datacontrol_create_request_id();
+ *request_id = reqId;
+
+ int ret = datacontrol_sql_request_provider(provider, DATACONTROL_TYPE_SQL_DELETE, b, reqId);
+ bundle_free(b);
+ return ret;
+}
+
+int
+datacontrol_sql_select(datacontrol_h provider, char **column_list, int column_count, const char *where, const char *order, int *request_id)
+{
+ return datacontrol_sql_select_with_page(provider, column_list, column_count, where, order, 1, 20, request_id);
+}
+
+int
+datacontrol_sql_select_with_page(datacontrol_h provider, char **column_list, int column_count, const char *where, const char *order, int page_number, int count_per_page, int *request_id)
+{
+ if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL)
+ {
+ LOGE("Invalid parameter");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGI("SQL data control, select to provider_id: %s, data_id: %s, col_count: %d, where: %s, order: %s, page_number: %d, per_page: %d", provider->provider_id, provider->data_id, column_count, where, order, page_number, count_per_page);
+
+ if (column_list == NULL)
+ {
+ LOGE("Invalid parameter");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ int total_arg_count = -1;
+ int ret = 0;
+
+ bundle *b = bundle_create();
+ if (!b)
+ {
+ LOGE("unable to create bundle: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
+ bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+
+ char page[32] = {0, };
+ ret = snprintf(page, 32, "%d", page_number);
+ if (ret < 0)
+ {
+ LOGE("unable to convert page no to string: %d", errno);
+ bundle_free(b);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ char count_per_page_no[32] = {0, };
+ ret = snprintf(count_per_page_no, 32, "%d", count_per_page);
+ if (ret < 0)
+ {
+ LOGE("unable to convert count per page no to string: %d", errno);
+ bundle_free(b);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ total_arg_count = column_count + DATACONTROL_SELECT_EXTRA_COUNT;
+ const char** arg_list = (const char**)malloc(total_arg_count * (sizeof(char *)));
+
+ LOGI("total arg count %d", total_arg_count);
+
+ arg_list[0] = provider->data_id; // arg[0]: data ID
+ int i = 1;
+ if (column_list)
+ {
+ char select_column_count[MAX_LEN_DATACONTROL_COLUMN_COUNT] = {0, };
+ ret = snprintf(select_column_count, MAX_LEN_DATACONTROL_COLUMN_COUNT, "%d", column_count);
+ if(ret < 0)
+ {
+ LOGE("unable to convert select col count to string: %d", errno);
+ free(arg_list);
+ bundle_free(b);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+
+ arg_list[i] = select_column_count; // arg[1]: selected column count
+
+ ++i;
+ int select_col = 0;
+ while (select_col < column_count)
+ {
+ arg_list[i++] = column_list[select_col++];
+ }
+ }
+ else
+ {
+ arg_list[i++] = DATACONTROL_EMPTY;
+ }
+
+ if (where) // arg: where clause
+ {
+ arg_list[i++] = where;
+ }
+ else
+ {
+ arg_list[i++] = DATACONTROL_EMPTY;
+ }
+
+ if (order) // arg: order clause
+ {
+ arg_list[i++] = order;
+ }
+ else
+ {
+ arg_list[i++] = DATACONTROL_EMPTY;
+ }
+
+
+ arg_list[i++] = page; // arg: page number
+
+ arg_list[i] = count_per_page_no; // arg: count per page
+
+ bundle_add_str_array(b, OSP_K_ARG, arg_list, total_arg_count);
+ free(arg_list);
+
+ int reqId = _datacontrol_create_request_id();
+ *request_id = reqId;
+
+ ret = datacontrol_sql_request_provider(provider, DATACONTROL_TYPE_SQL_SELECT, b, reqId);
+ bundle_free(b);
+ return ret;
+}
+
+
+int
+datacontrol_sql_update(datacontrol_h provider, const bundle* update_data, const char *where, int *request_id)
+{
+ if (provider == NULL || provider->provider_id == NULL || provider->data_id == NULL || update_data == NULL || where == NULL)
+ {
+ LOGE("Invalid parameter");
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ int ret = 0;
+
+ char caller_app_id[256] = {0, };
+ pid_t pid = getpid();
+
+ if (aul_app_get_appid_bypid(pid, caller_app_id, sizeof(caller_app_id)) != 0)
+ {
+ SECURE_LOGE("Failed to get appid by pid(%d).", pid);
+ return DATACONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ // Check size of arguments
+ long long arg_size = 0;
+ bundle_foreach((bundle*)update_data, bundle_foreach_check_arg_size_cb, &arg_size);
+ arg_size += strlen(provider->data_id) * sizeof(wchar_t);
+ if (arg_size > MAX_REQUEST_ARGUMENT_SIZE)
+ {
+ LOGE("The size of the request argument exceeds the limit, 1M.");
+ return DATACONTROL_ERROR_MAX_EXCEEDED;
+ }
+
+ int reqId = _datacontrol_create_request_id();
+
+ char update_map_file[REQUEST_PATH_MAX] = {0, };
+ ret = snprintf(update_map_file, REQUEST_PATH_MAX, "%s/%s_%d", DATACONTROL_REQUEST_FILE_PREFIX, caller_app_id, reqId);
+ if (ret < 0)
+ {
+ LOGE("unable to write formatted output to update_map_file: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ SECURE_LOGI("update_map_file : %s", update_map_file);
+
+ int fd = 0;
+ char *provider_pkgid = __get_provider_pkgid(provider->provider_id);
+
+ /* TODO - shoud be changed to solve security concerns */
+ fd = open(update_map_file, O_WRONLY | O_CREAT, 644);
+ if (fd == -1)
+ {
+ SECURE_LOGE("unable to open update_map file: %d", errno);
+ free(provider_pkgid);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ free(provider_pkgid);
+
+ int count = bundle_get_count((bundle*)update_data);
+ bundle_foreach((bundle*)update_data, bundle_foreach_cb, &fd);
+
+ fsync(fd);
+ close(fd);
+
+ bundle *b = bundle_create();
+ if (!b)
+ {
+ LOGE("unable to create bundle: %d", errno);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
+ bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+
+ char update_column_count[MAX_LEN_DATACONTROL_COLUMN_COUNT] = {0, };
+ ret = snprintf(update_column_count, MAX_LEN_DATACONTROL_COLUMN_COUNT, "%d", count);
+ if (ret < 0)
+ {
+ LOGE("unable to convert update col count to string: %d", errno);
+ bundle_free(b);
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+
+ const char* arg_list[4];
+ arg_list[0] = provider->data_id; // list(0): data ID
+ arg_list[1] = update_column_count;
+ arg_list[2] = update_map_file;
+ arg_list[3] = where;
+
+ bundle_add_str_array(b, OSP_K_ARG, arg_list, 4);
+
+ *request_id = reqId;
+
+ ret = datacontrol_sql_request_provider(provider, DATACONTROL_TYPE_SQL_UPDATE, b, reqId);
+ if (ret != DATACONTROL_ERROR_NONE)
+ {
+ ret = remove(update_map_file);
+ if (ret == -1)
+ {
+ SECURE_LOGE("unable to remove the update_map file: %d", errno);
+ }
+ }
+ bundle_free(b);
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <dlog.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <unistd.h>
+
+#include <sys/smack.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include "data_control_internal.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "CAPI_APPFW_DATA_CONTROL"
+
+#define _LOGE(fmt, arg...) LOGE(fmt,##arg)
+#define _LOGD(fmt, arg...) LOGD(fmt, ##arg)
+
+static const char *data_control_error_to_string(data_control_error_e error)
+{
+ switch (error) {
+ case DATA_CONTROL_ERROR_NONE:
+ return "NONE";
+ case DATA_CONTROL_ERROR_INVALID_PARAMETER:
+ return "INVALID_PARAMETER";
+ case DATA_CONTROL_ERROR_OUT_OF_MEMORY:
+ return "OUT_OF_MEMORY";
+ case DATA_CONTROL_ERROR_IO_ERROR:
+ return "IO_ERROR";
+ case DATA_CONTROL_ERROR_PERMISSION_DENIED:
+ return "PERMISSION_DENIED";
+ case DATA_CONTROL_ERROR_MAX_EXCEEDED:
+ return "Too long argument";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+int convert_to_tizen_error(datacontrol_error_e error)
+{
+ switch (error) {
+ case DATACONTROL_ERROR_NONE:
+ return DATA_CONTROL_ERROR_NONE;
+ case DATACONTROL_ERROR_INVALID_PARAMETER:
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ case DATACONTROL_ERROR_OUT_OF_MEMORY:
+ return DATA_CONTROL_ERROR_OUT_OF_MEMORY;
+ case DATACONTROL_ERROR_IO_ERROR:
+ return DATA_CONTROL_ERROR_IO_ERROR;
+ case DATACONTROL_ERROR_PERMISSION_DENIED:
+ return DATA_CONTROL_ERROR_PERMISSION_DENIED;
+ case DATACONTROL_ERROR_MAX_EXCEEDED:
+ return DATA_CONTROL_ERROR_MAX_EXCEEDED;
+ default:
+ return error;
+ }
+}
+
+int data_control_error(data_control_error_e error,
+ const char *function, const char *description)
+{
+ if (description) {
+ _LOGE("[%s] %s(0x%08x) : %s", function,
+ data_control_error_to_string(error), error,
+ description);
+ } else {
+ _LOGE("[%s] %s(0x%08x)", function,
+ data_control_error_to_string(error), error);
+ }
+
+ return error;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 __TIZEN_APPFW_DATA_CONTROL_LOG_H__
+#define __TIZEN_APPFW_DATA_CONTROL_LOG_H__
+
+#include <dlog.h>
+
+#ifdef __GNUC__
+# ifndef EXPORT_API
+# define EXPORT_API __attribute__((visibility("default")))
+# endif
+#else
+# define EXPORT_API
+#endif
+
+#undef LOG_TAG
+#define LOG_TAG "DATA_CONTROL"
+
+#define _LOGE(fmt, arg...) LOGE(fmt, ##arg)
+#define _LOGI(fmt, arg...) LOGI(fmt, ##arg)
+
+#define _SECURE_LOGE(fmt, arg...) SECURE_LOGE(fmt, ##arg)
+#define _SECURE_LOGI(fmt, arg...) SECURE_LOGI(fmt, ##arg)
+
+#endif /* __TIZEN_APPFW_DATA_CONTROL_LOG_H__ */
--- /dev/null
+#include <dlog.h>
+#include <bundle.h>
+#include <errno.h>
+#include <glib.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <data-control-map.h>
+#include "data_control_internal.h"
+#include "data_control_map.h"
+#include "data_control_log.h"
+
+struct data_control_s {
+ char *provider_id;
+ char *data_id;
+};
+
+struct datacontrol_s {
+ char *provider_id;
+ char *data_id;
+};
+
+
+static GHashTable *response_table = NULL;
+
+datacontrol_map_response_cb datacontrol_map_cb;
+
+void
+__map_get_response(int request_id, datacontrol_h provider,
+ char **result_value_list, int result_value_count, bool provider_result, const char *error, void *user_data)
+{
+ _LOGI("map_get_response");
+
+ data_control_map_response_cb *callback = (data_control_map_response_cb*)g_hash_table_lookup(response_table, provider->provider_id);
+ if (callback)
+ {
+ callback->get_cb(request_id, (data_control_h)provider, result_value_list, result_value_count, provider_result, error, user_data);
+ }
+}
+
+void
+__map_set_response(int request_id, datacontrol_h provider, bool provider_result, const char *error, void *user_data)
+{
+ _LOGI("map_set_response");
+
+ data_control_map_response_cb *callback = (data_control_map_response_cb*)g_hash_table_lookup(response_table, provider->provider_id);
+ if (callback)
+ {
+ callback->set_cb(request_id, (data_control_h)provider, provider_result, error, user_data);
+ }
+}
+
+void
+__map_add_response(int request_id, datacontrol_h provider, bool provider_result, const char *error, void *user_data)
+{
+ _LOGI("map_add_response");
+
+ data_control_map_response_cb *callback = (data_control_map_response_cb*)g_hash_table_lookup(response_table, provider->provider_id);
+ if (callback)
+ {
+ callback->add_cb(request_id, (data_control_h)provider, provider_result, error, user_data);
+ }
+}
+
+void
+__map_remove_response(int request_id, datacontrol_h provider, bool provider_result, const char *error, void *user_data)
+{
+ _LOGI("map_remove_response");
+
+ data_control_map_response_cb *callback = (data_control_map_response_cb*)g_hash_table_lookup(response_table, provider->provider_id);
+ if (callback)
+ {
+ callback->remove_cb(request_id, (data_control_h)provider, provider_result, error, user_data);
+ }
+}
+
+static void
+__free_data(gpointer data)
+{
+ if (data)
+ {
+ g_free(data);
+ data = NULL;
+ }
+}
+
+static void
+__initialize(void)
+{
+ response_table = g_hash_table_new_full(g_str_hash, g_str_equal, __free_data, __free_data);
+
+ datacontrol_map_cb.get = __map_get_response;
+ datacontrol_map_cb.set = __map_set_response;
+ datacontrol_map_cb.add = __map_add_response;
+ datacontrol_map_cb.remove = __map_remove_response;
+}
+
+EXPORT_API int
+data_control_map_create(data_control_h *provider)
+{
+ return convert_to_tizen_error(datacontrol_map_create((datacontrol_h*)provider));
+}
+
+EXPORT_API int
+data_control_map_destroy(data_control_h provider)
+{
+ return convert_to_tizen_error(datacontrol_map_destroy((datacontrol_h)provider));
+}
+
+EXPORT_API int
+data_control_map_set_provider_id(data_control_h provider, const char *provider_id)
+{
+ return convert_to_tizen_error(datacontrol_map_set_provider_id((datacontrol_h)provider, provider_id));
+}
+
+EXPORT_API int
+data_control_map_get_provider_id(data_control_h provider, char **provider_id)
+{
+ return convert_to_tizen_error(datacontrol_map_get_provider_id((datacontrol_h)provider, provider_id));
+}
+
+EXPORT_API int
+data_control_map_set_data_id(data_control_h provider, const char *data_id)
+{
+ return convert_to_tizen_error(datacontrol_map_set_data_id((datacontrol_h)provider, data_id));
+}
+
+EXPORT_API int
+data_control_map_get_data_id(data_control_h provider, char **data_id)
+{
+ return convert_to_tizen_error(datacontrol_map_get_data_id((datacontrol_h)provider, data_id));
+}
+
+EXPORT_API int
+data_control_map_register_response_cb(data_control_h provider, data_control_map_response_cb* callback, void *user_data)
+{
+
+ if (response_table == NULL)
+ {
+ __initialize();
+ }
+
+ if (callback == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ char *id = strdup(provider->provider_id);
+ if (id == NULL)
+ {
+ return DATA_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ data_control_map_response_cb *cb
+ = (data_control_map_response_cb *)malloc(sizeof(data_control_map_response_cb));
+ if (cb == NULL)
+ {
+ free(id);
+ return DATA_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ memcpy(cb, callback, sizeof(data_control_map_response_cb));
+ g_hash_table_insert(response_table, id, cb);
+
+ return convert_to_tizen_error(datacontrol_map_register_response_cb((datacontrol_h)provider, &datacontrol_map_cb, user_data));
+}
+
+EXPORT_API int
+data_control_map_unregister_response_cb(data_control_h provider)
+{
+ if (provider->provider_id)
+ {
+ g_hash_table_remove(response_table, provider->provider_id);
+ }
+
+ return convert_to_tizen_error(datacontrol_map_unregister_response_cb((datacontrol_h)provider));
+}
+
+EXPORT_API int
+data_control_map_get(data_control_h provider, const char *key, int *request_id)
+{
+ return convert_to_tizen_error(datacontrol_map_get((datacontrol_h)provider, key, request_id));
+}
+
+EXPORT_API int
+data_control_map_get_with_page(data_control_h provider, const char *key, int *request_id, int page_number, int count_per_page)
+{
+ return convert_to_tizen_error(datacontrol_map_get_with_page((datacontrol_h)provider, key, request_id, page_number, count_per_page));
+}
+
+EXPORT_API int
+data_control_map_set(data_control_h provider, const char *key, const char *old_value, const char *new_value, int *request_id)
+{
+ return convert_to_tizen_error(datacontrol_map_set((datacontrol_h)provider, key, old_value, new_value, request_id));
+}
+
+EXPORT_API int
+data_control_map_add(data_control_h provider, const char *key, const char *value, int *request_id)
+{
+ return convert_to_tizen_error(datacontrol_map_add((datacontrol_h)provider, key, value, request_id));
+}
+
+EXPORT_API int
+data_control_map_remove(data_control_h provider, const char *key, const char *value, int *request_id)
+{
+ return convert_to_tizen_error(datacontrol_map_remove((datacontrol_h)provider, key, value, request_id));
+}
--- /dev/null
+#include <stdlib.h>
+
+#include <dlog.h>
+#include <bundle.h>
+
+#include <data-control-provider.h>
+
+#include "data_control_provider.h"
+#include "data_control_sql.h"
+#include "data_control_log.h"
+#include "data_control_internal.h"
+
+#define INSERT_STMT_CONST_LEN 25
+#define DELETE_STMT_CONST_LEN 12
+#define UPDATE_STMT_CONST_LEN 15
+#define SELECT_STMT_CONST_LEN 13
+#define WHERE_COND_CONST_LEN 7
+#define ORDER_CLS_CONST_LEN 10
+
+struct data_control_s {
+ char *provider_id;
+ char *data_id;
+};
+
+struct datacontrol_s {
+ char *provider_id;
+ char *data_id;
+};
+
+typedef struct
+{
+ int no_of_elements;
+ int length;
+ char** keys;
+ char** vals;
+}key_val_pair;
+
+static data_control_provider_sql_cb sql_provider_callback;
+static data_control_provider_map_cb map_provider_callback;
+
+datacontrol_provider_sql_cb sql_internal_callback;
+datacontrol_provider_map_cb map_internal_callback;
+
+void
+__sql_insert_request_cb(int request_id, datacontrol_h provider, bundle *insert_data, void *user_data)
+{
+ _LOGI("sql_insert_request");
+
+ if (sql_provider_callback.insert_cb)
+ {
+ sql_provider_callback.insert_cb(request_id, (data_control_h)provider, insert_data, user_data);
+ }
+}
+
+void
+__sql_update_request_cb(int request_id, datacontrol_h provider, bundle *update_data, const char *where, void *user_data)
+{
+ _LOGI("sql_update_request");
+
+ if (sql_provider_callback.update_cb)
+ {
+ sql_provider_callback.update_cb(request_id, (data_control_h)provider, update_data, where, user_data);
+ }
+}
+
+void
+__sql_delete_request_cb(int request_id, datacontrol_h provider, const char *where, void *user_data)
+{
+ _LOGI("sql_delete_request");
+
+ if (sql_provider_callback.delete_cb)
+ {
+ sql_provider_callback.delete_cb(request_id, (data_control_h)provider, where, user_data);
+ }
+}
+
+void
+__sql_select_request_cb(int request_id, datacontrol_h provider, const char **column_list, int column_count, const char *where, const char *order, void *user_data)
+{
+ _LOGI("sql_select_request");
+
+ if (sql_provider_callback.select_cb)
+ {
+ sql_provider_callback.select_cb(request_id, (data_control_h)provider, column_list, column_count, where, order, user_data);
+ }
+}
+
+void
+__map_get_request_cb(int request_id, datacontrol_h provider, const char *key, void *user_data)
+{
+ _LOGI("map_get_request");
+
+ if (map_provider_callback.get_cb)
+ {
+ map_provider_callback.get_cb(request_id, (data_control_h)provider, key, user_data);
+ }
+}
+
+void
+__map_set_request_cb(int request_id, datacontrol_h provider, const char *key, const char *old_value, const char *new_value, void *user_data)
+{
+ _LOGI("map_set_request");
+
+ if (map_provider_callback.set_cb)
+ {
+ map_provider_callback.set_cb(request_id, (data_control_h)provider, key, old_value, new_value, user_data);
+ }
+}
+
+void
+__map_add_request_cb(int request_id, datacontrol_h provider, const char *key, const char *value, void *user_data)
+{
+ _LOGI("map_add_request");
+
+ if (map_provider_callback.add_cb)
+ {
+ map_provider_callback.add_cb(request_id, (data_control_h)provider, key, value, user_data);
+ }
+}
+
+void
+__map_remove_request_cb(int request_id, datacontrol_h provider, const char *key, const char *value, void *user_data)
+{
+ _LOGI("map_remove_request");
+
+ if (map_provider_callback.remove_cb)
+ {
+ map_provider_callback.remove_cb(request_id, (data_control_h)provider, key, value, user_data);
+ }
+}
+
+EXPORT_API int
+data_control_provider_sql_register_cb(data_control_provider_sql_cb *callback, void *user_data)
+{
+ if (!callback)
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+
+ sql_provider_callback = *callback;
+
+ sql_internal_callback.insert = __sql_insert_request_cb;
+ sql_internal_callback.update = __sql_update_request_cb;
+ sql_internal_callback.delete = __sql_delete_request_cb;
+ sql_internal_callback.select = __sql_select_request_cb;
+
+ return datacontrol_provider_sql_register_cb(&sql_internal_callback, user_data);
+}
+
+EXPORT_API int
+data_control_provider_sql_unregister_cb(void)
+{
+ memset(&sql_provider_callback, 0, sizeof(data_control_provider_sql_cb));
+
+ return datacontrol_provider_sql_unregister_cb();
+}
+
+EXPORT_API int
+data_control_provider_map_register_cb(data_control_provider_map_cb *callback, void *user_data)
+{
+ if (!callback)
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+
+ map_provider_callback = *callback;
+
+ map_internal_callback.get = __map_get_request_cb;
+ map_internal_callback.set = __map_set_request_cb;
+ map_internal_callback.add = __map_add_request_cb;
+ map_internal_callback.remove = __map_remove_request_cb;
+
+ return datacontrol_provider_map_register_cb(&map_internal_callback, user_data);
+}
+
+EXPORT_API int
+data_control_provider_map_unregister_cb(void)
+{
+ memset(&map_provider_callback, 0, sizeof(data_control_provider_map_cb));
+
+ return datacontrol_provider_map_unregister_cb();
+}
+
+EXPORT_API int
+data_control_provider_get_client_appid(int request_id, char **appid)
+{
+ return datacontrol_provider_get_client_appid(request_id, appid);
+}
+
+EXPORT_API int
+data_control_provider_send_select_result(int request_id, void *db_handle)
+{
+ return datacontrol_provider_send_select_result(request_id, db_handle);
+}
+
+EXPORT_API int
+data_control_provider_send_insert_result(int request_id, long long row_id)
+{
+ return datacontrol_provider_send_insert_result(request_id, row_id);
+}
+
+EXPORT_API int
+data_control_provider_send_update_result(int request_id)
+{
+ return datacontrol_provider_send_update_result(request_id);
+}
+
+EXPORT_API int
+data_control_provider_send_delete_result(int request_id)
+{
+ return datacontrol_provider_send_delete_result(request_id);
+}
+
+EXPORT_API int
+data_control_provider_send_error(int request_id, const char *error)
+{
+ return datacontrol_provider_send_error(request_id, error);
+}
+
+static void bundle_foreach_cb(const char *key, const int type, const bundle_keyval_t *kv, void *user_data)
+{
+ if (!key || !kv || !user_data)
+ {
+ return;
+ }
+
+ key_val_pair* pair = (key_val_pair *)user_data;
+ int index = pair->no_of_elements;
+
+ pair->keys[index] = strdup(key);
+
+ char *value = NULL;
+ size_t value_len = 0;
+
+ bundle_keyval_get_basic_val((bundle_keyval_t *)kv, (void**)&value, &value_len);
+ pair->vals[index] = strdup(value);
+ pair->length += strlen(key) + value_len;
+
+ ++(pair->no_of_elements);
+
+ return;
+}
+
+EXPORT_API char*
+data_control_provider_create_insert_statement(data_control_h provider, bundle *insert_map)
+{
+ int row_count = bundle_get_count(insert_map);
+ if (provider == NULL || row_count == 0)
+ {
+ set_last_result(DATA_CONTROL_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ key_val_pair *cols = (key_val_pair *) calloc(sizeof(key_val_pair), 1);
+ if (cols == NULL)
+ {
+ set_last_result(DATA_CONTROL_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ cols->no_of_elements = 0;
+ cols->length = 0;
+ cols->keys = (char **) calloc(sizeof(char *), row_count);
+ if (cols->keys == NULL)
+ {
+ free(cols);
+ set_last_result(DATA_CONTROL_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ cols->vals = (char **) calloc(sizeof(char *), row_count);
+ if (cols->vals == NULL)
+ {
+ free(cols->keys);
+ free(cols);
+ set_last_result(DATA_CONTROL_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ int index = 0;
+ bundle_foreach(insert_map, bundle_foreach_cb, (void*)(cols));
+
+ char* data_id = NULL;
+ data_control_sql_get_data_id(provider, &data_id);
+
+ int sql_len = INSERT_STMT_CONST_LEN + strlen(data_id) + (row_count - 1) * 4 + (cols->length) + 1;
+
+ _LOGI("SQL statement length: %d", sql_len);
+
+ char* sql = (char *) calloc(sizeof(char), sql_len);
+ if (sql == NULL)
+ {
+ free(data_id);
+ free(cols->keys);
+ free(cols->vals);
+ free(cols);
+ set_last_result(DATA_CONTROL_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+ memset(sql, 0, sql_len);
+
+ sprintf(sql, "INSERT INTO %s (", data_id);
+ free(data_id);
+
+ for(index = 0; index < row_count - 1; index++)
+ {
+ strcat(sql, cols->keys[index]);
+ strcat(sql, ", ");
+ }
+
+ strcat(sql, cols->keys[index]);
+ strcat(sql, ") VALUES (");
+
+ for(index = 0; index < row_count - 1; index++)
+ {
+ strcat(sql, cols->vals[index]);
+ strcat(sql, ", ");
+ }
+
+ strcat(sql, cols->vals[index]);
+ strcat(sql, ")");
+
+ _LOGI("SQL statement is: %s", sql);
+
+ for(index = 0; index < row_count; index++)
+ {
+ free(cols->keys[index]);
+ free(cols->vals[index]);
+ }
+ free(cols->keys);
+ free(cols->vals);
+ free(cols);
+
+ return sql;
+}
+
+EXPORT_API char*
+data_control_provider_create_delete_statement(data_control_h provider, const char *where)
+{
+ char* data_id = NULL;
+
+ if (provider == NULL)
+ {
+ set_last_result(DATA_CONTROL_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ data_control_sql_get_data_id(provider, &data_id);
+
+ int cond_len = (where != NULL) ? (WHERE_COND_CONST_LEN + strlen(where)) : 0;
+ int sql_len = DELETE_STMT_CONST_LEN + strlen(data_id) + cond_len + 1;
+
+ _LOGI("SQL statement length: %d", sql_len);
+
+ char* sql = (char *) calloc(sizeof(char), sql_len);
+ if (sql == NULL)
+ {
+ free(data_id);
+ set_last_result(DATA_CONTROL_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+ memset(sql, 0, sql_len);
+
+ sprintf(sql, "DELETE FROM %s", data_id);
+ if (where)
+ {
+ strcat(sql, " WHERE ");
+ strcat(sql, where);
+ }
+
+ _LOGI("SQL statement is: %s", sql);
+
+ free(data_id);
+ return sql;
+}
+
+EXPORT_API char*
+data_control_provider_create_update_statement(data_control_h provider, bundle *update_map, const char *where)
+{
+ int row_count = bundle_get_count(update_map);
+ if (provider == NULL || row_count == 0)
+ {
+ set_last_result(DATA_CONTROL_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ key_val_pair *cols = (key_val_pair *) calloc(sizeof(key_val_pair), 1);
+ if (cols == NULL)
+ {
+ set_last_result(DATA_CONTROL_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ cols->no_of_elements = 0;
+ cols->length = 0;
+ cols->keys = (char **) calloc(sizeof(char *), row_count);
+ if (cols->keys == NULL)
+ {
+ free(cols);
+ set_last_result(DATA_CONTROL_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+ cols->vals = (char **) calloc(sizeof(char *), row_count);
+ if (cols->vals == NULL)
+ {
+ free(cols->keys);
+ free(cols);
+ set_last_result(DATA_CONTROL_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ int index = 0;
+ bundle_foreach(update_map, bundle_foreach_cb, (void*)(cols));
+
+ char* data_id = NULL;
+ data_control_sql_get_data_id(provider, &data_id);
+
+ int cond_len = (where != NULL) ? (WHERE_COND_CONST_LEN + strlen(where)) : 0;
+ int sql_len = UPDATE_STMT_CONST_LEN + strlen(data_id) + (cols->length) + (row_count - 1) * 5 + cond_len + 1;
+
+ _LOGI("SQL statement length: %d", sql_len);
+
+ char* sql = (char *) calloc(sizeof(char), sql_len);
+ if (sql == NULL)
+ {
+ free(data_id);
+ free(cols->keys);
+ free(cols->vals);
+ free(cols);
+ set_last_result(DATA_CONTROL_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+ memset(sql, 0, sql_len);
+
+ sprintf(sql, "UPDATE %s SET ", data_id);
+ free(data_id);
+
+ for(index = 0; index < row_count - 1; index++)
+ {
+ strcat(sql, cols->keys[index]);
+ strcat(sql, " = ");
+ strcat(sql, cols->vals[index]);
+ strcat(sql, ", ");
+ }
+
+ strcat(sql, cols->keys[index]);
+ strcat(sql, " = ");
+ strcat(sql, cols->vals[index]);
+
+ if (where)
+ {
+ strcat(sql, " WHERE ");
+ strcat(sql, where);
+ }
+
+ _LOGI("SQL statement is: %s", sql);
+
+ for(index = 0; index < row_count; index++)
+ {
+ free(cols->keys[index]);
+ free(cols->vals[index]);
+ }
+ free(cols->keys);
+ free(cols->vals);
+ free(cols);
+
+ return sql;
+}
+
+EXPORT_API char*
+data_control_provider_create_select_statement(data_control_h provider, const char **column_list, int column_count, const char *where, const char *order)
+{
+ int index = 0;
+ int col_name_length = 0;
+ if (provider == NULL)
+ {
+ set_last_result(DATA_CONTROL_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ if (column_list)
+ {
+ for (index = 0; index < column_count; index++)
+ {
+ col_name_length += strlen(column_list[index]);
+ }
+ if (column_count > 0)
+ {
+ col_name_length += (column_count - 1) * 2;
+ }
+ }
+ else
+ {
+ col_name_length = 1;
+ }
+
+ char* data_id = NULL;
+ data_control_sql_get_data_id(provider, &data_id);
+
+ int cond_len = (where != NULL) ? (WHERE_COND_CONST_LEN + strlen(where)) : 0;
+ int order_len = (order != NULL) ? (ORDER_CLS_CONST_LEN + strlen(order)) : 0;
+ int sql_len = SELECT_STMT_CONST_LEN + col_name_length + strlen(data_id) + cond_len + order_len + 1;
+
+ _LOGI("SQL statement length: %d", sql_len);
+
+ char* sql = (char *) calloc(sizeof(char), sql_len);
+ if (sql == NULL)
+ {
+ free(data_id);
+ set_last_result(DATA_CONTROL_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+ memset(sql, 0, sql_len);
+
+ strcpy(sql, "SELECT ");
+ if (!column_list)
+ {
+ strcat(sql, "*");
+ }
+ else
+ {
+ for (index = 0; index < column_count - 1; index++)
+ {
+ strcat(sql, column_list[index]);
+ strcat(sql, ", ");
+ }
+ strcat(sql, column_list[index]);
+ }
+
+ strcat(sql, " FROM ");
+ strcat(sql, data_id);
+
+ if (where)
+ {
+ strcat(sql, " WHERE ");
+ strcat(sql, where);
+ }
+ if (order)
+ {
+ strcat(sql, " ORDER BY ");
+ strcat(sql, order);
+ }
+
+ _LOGI("SQL statement is: %s", sql);
+
+ free(data_id);
+ return sql;
+}
+
+EXPORT_API bool
+data_control_provider_match_provider_id(data_control_h provider, const char *provider_id)
+{
+ int ret = DATA_CONTROL_ERROR_NONE;
+ char* prov_id = NULL;
+ if(provider == NULL || provider_id == NULL)
+ {
+ set_last_result(DATA_CONTROL_ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ ret = data_control_sql_get_provider_id(provider, &prov_id);
+ set_last_result(ret);
+ if (ret != DATA_CONTROL_ERROR_NONE)
+ {
+ return false;
+ }
+
+ if (strcmp(prov_id, provider_id) == 0)
+ {
+ free(prov_id);
+ return true;
+ }
+ else
+ {
+ free(prov_id);
+ return false;
+ }
+}
+
+EXPORT_API bool
+data_control_provider_match_data_id(data_control_h provider, const char *data_id)
+{
+ int ret = DATA_CONTROL_ERROR_NONE;
+ char* data = NULL;
+ if(provider == NULL || data_id == NULL)
+ {
+ set_last_result(DATA_CONTROL_ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ ret = data_control_sql_get_data_id(provider, &data);
+ set_last_result(ret);
+ if (ret != DATA_CONTROL_ERROR_NONE)
+ {
+ return false;
+ }
+
+ if (strcmp(data, data_id) == 0)
+ {
+ free(data);
+ return true;
+ }
+ else
+ {
+ free(data);
+ return false;
+ }
+}
+
+EXPORT_API int
+data_control_provider_send_map_result(int request_id)
+{
+ return datacontrol_provider_send_map_result(request_id);
+}
+
+EXPORT_API int
+data_control_provider_send_map_get_value_result(int request_id, char **value_list, int value_count)
+{
+ return datacontrol_provider_send_map_get_value_result(request_id, value_list, value_count);
+}
--- /dev/null
+#include <dlog.h>
+#include <bundle.h>
+#include <errno.h>
+#include <glib.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <data-control-sql.h>
+#include "data_control_internal.h"
+#include "data_control_sql.h"
+#include "data_control_log.h"
+
+struct data_control_s {
+ char *provider_id;
+ char *data_id;
+};
+
+struct datacontrol_s {
+ char *provider_id;
+ char *data_id;
+};
+
+
+static GHashTable *response_table = NULL;
+
+datacontrol_sql_response_cb datacontrol_sql_cb;
+
+void
+__sql_insert_response(int req_id, datacontrol_h provider, long long insert_rowid, bool provider_result, const char *error, void *user_data)
+{
+ _LOGI("sql_insert_response");
+
+ data_control_sql_response_cb *callback = (data_control_sql_response_cb*)g_hash_table_lookup(response_table, provider->provider_id);
+ if (callback)
+ {
+ callback->insert_cb(req_id, (data_control_h)provider, insert_rowid, provider_result, error, user_data);
+ }
+}
+
+void
+__sql_update_response(int req_id, datacontrol_h provider, bool provider_result, const char *error, void *user_data)
+{
+ _LOGI("sql_update_response");
+
+ data_control_sql_response_cb *callback = (data_control_sql_response_cb*)g_hash_table_lookup(response_table, provider->provider_id);
+ if (callback)
+ {
+ callback->update_cb(req_id, (data_control_h)provider, provider_result, error, user_data);
+ }
+}
+
+void
+__sql_delete_response(int req_id, datacontrol_h provider, bool provider_result, const char *error, void *user_data)
+{
+ _LOGI("sql_delete_response");
+
+ data_control_sql_response_cb *callback = (data_control_sql_response_cb*)g_hash_table_lookup(response_table, provider->provider_id);
+ if (callback)
+ {
+ callback->delete_cb(req_id, (data_control_h)provider, provider_result, error, user_data);
+ }
+}
+
+void
+__sql_select_response(int req_id, datacontrol_h provider, resultset_cursor* enumerator, bool provider_result, const char *error, void *user_data)
+{
+ _LOGI("sql_select_response");
+
+ data_control_sql_response_cb *callback = (data_control_sql_response_cb*)g_hash_table_lookup(response_table, provider->provider_id);
+ if (callback)
+ {
+ callback->select_cb(req_id, (data_control_h)provider, (result_set_cursor)enumerator, provider_result, error, user_data);
+ }
+}
+
+static void
+__free_data(gpointer data)
+{
+ if (data)
+ {
+ g_free(data);
+ data = NULL;
+ }
+}
+
+static void
+__initialize(void)
+{
+ response_table = g_hash_table_new_full(g_str_hash, g_str_equal, __free_data, __free_data);
+
+ datacontrol_sql_cb.insert = __sql_insert_response;
+ datacontrol_sql_cb.delete = __sql_delete_response;
+ datacontrol_sql_cb.select = __sql_select_response;
+ datacontrol_sql_cb.update = __sql_update_response;
+}
+
+EXPORT_API int
+data_control_sql_create(data_control_h *provider)
+{
+ return datacontrol_sql_create((datacontrol_h*)provider);
+}
+
+EXPORT_API int
+data_control_sql_destroy(data_control_h provider)
+{
+ return datacontrol_sql_destroy((datacontrol_h)provider);
+}
+
+EXPORT_API int
+data_control_sql_set_provider_id(data_control_h provider, const char *provider_id)
+{
+ return datacontrol_sql_set_provider_id((datacontrol_h)provider, provider_id);
+}
+
+EXPORT_API int
+data_control_sql_get_provider_id(data_control_h provider, char **provider_id)
+{
+ return datacontrol_sql_get_provider_id((datacontrol_h)provider, provider_id);
+}
+
+EXPORT_API int
+data_control_sql_set_data_id(data_control_h provider, const char *data_id)
+{
+ return datacontrol_sql_set_data_id((datacontrol_h)provider, data_id);
+}
+
+EXPORT_API int
+data_control_sql_get_data_id(data_control_h provider, char **data_id)
+{
+ return datacontrol_sql_get_data_id((datacontrol_h)provider, data_id);
+}
+
+EXPORT_API int
+data_control_sql_register_response_cb(data_control_h provider, data_control_sql_response_cb* callback, void *user_data)
+{
+ if (response_table == NULL)
+ {
+ __initialize();
+ }
+
+ if (callback == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ char *id = strdup(provider->provider_id);
+ if (id == NULL)
+ {
+ return DATA_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ data_control_sql_response_cb *cb
+ = (data_control_sql_response_cb *)malloc(sizeof(data_control_sql_response_cb));
+ if (cb == NULL)
+ {
+ free(id);
+ return DATA_CONTROL_ERROR_OUT_OF_MEMORY;
+ }
+
+ memcpy(cb, callback, sizeof(data_control_sql_response_cb));
+ g_hash_table_insert(response_table, id, cb);
+
+ return datacontrol_sql_register_response_cb((datacontrol_h)provider, &datacontrol_sql_cb, user_data);
+}
+
+EXPORT_API int
+data_control_sql_unregister_response_cb(data_control_h provider)
+{
+ if (provider->provider_id)
+ {
+ g_hash_table_remove(response_table, provider->provider_id);
+ }
+
+ return datacontrol_sql_unregister_response_cb((datacontrol_h)provider);
+}
+
+EXPORT_API int
+data_control_sql_insert(data_control_h provider, const bundle* insert_data, int *request_id)
+{
+ return datacontrol_sql_insert((datacontrol_h)provider, insert_data, request_id);
+}
+
+EXPORT_API int
+data_control_sql_delete(data_control_h provider, const char *where, int *request_id)
+{
+ return datacontrol_sql_delete((datacontrol_h)provider, where, request_id);
+}
+
+EXPORT_API int
+data_control_sql_select(data_control_h provider, char **column_list, int column_count, const char *where, const char *order, int *request_id)
+{
+ return datacontrol_sql_select((datacontrol_h)provider, column_list, column_count, where, order, request_id);
+}
+
+EXPORT_API int
+data_control_sql_select_with_page(data_control_h provider, char **column_list, int column_count, const char *where, const char *order, int page_number, int count_per_page, int *request_id)
+{
+ return datacontrol_sql_select_with_page((datacontrol_h)provider, column_list, column_count, where, order, page_number, count_per_page, request_id);
+}
+
+
+EXPORT_API int
+data_control_sql_update(data_control_h provider, const bundle* update_data, const char *where, int *request_id)
+{
+ return datacontrol_sql_update((datacontrol_h)provider, update_data, where, request_id);
+}
+
--- /dev/null
+
+#include <dlog.h>
+#include <data-control-sql-cursor.h>
+
+#include "data_control_sql_cursor.h"
+
+struct result_set_s
+{
+ int result_set_fd;
+ int result_set_row_count;
+ int result_set_col_count;
+ int result_set_col_type_offset;
+ int result_set_col_name_offset;
+ int result_set_content_offset;
+ int result_set_current_offset;
+ int result_set_current_row_count;
+ char* result_set_path;
+};
+
+EXPORT_API int
+data_control_sql_step_next(result_set_cursor cursor)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_step_next((resultset_cursor*)cursor);
+}
+
+EXPORT_API int
+data_control_sql_step_last(result_set_cursor cursor)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_step_last((resultset_cursor*)cursor);
+}
+
+
+EXPORT_API int
+data_control_sql_step_first(result_set_cursor cursor)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_step_first((resultset_cursor*)cursor);
+}
+
+
+EXPORT_API int
+data_control_sql_step_previous(result_set_cursor cursor)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_step_previous((resultset_cursor*)cursor);
+}
+
+
+EXPORT_API int
+data_control_sql_get_column_count(result_set_cursor cursor)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_get_column_count((resultset_cursor*)cursor);
+}
+
+EXPORT_API int
+data_control_sql_get_column_name(result_set_cursor cursor, int column_index, char *name)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_get_column_name((resultset_cursor*)cursor, column_index, name);
+}
+
+
+EXPORT_API int
+data_control_sql_get_column_item_size(result_set_cursor cursor, int column_index)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_get_column_item_size((resultset_cursor*)cursor, column_index);
+}
+
+
+EXPORT_API int
+data_control_sql_get_column_item_type(result_set_cursor cursor, int column_index, data_control_sql_column_type_e* col_type)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_get_column_item_type((resultset_cursor*)cursor, column_index, (datacontrol_sql_column_type*)col_type);
+}
+
+
+EXPORT_API int
+data_control_sql_get_blob_data(result_set_cursor cursor, int column_index, void *buffer, int data_size)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_get_blob_data((resultset_cursor*)cursor, column_index, buffer, data_size);
+}
+
+
+EXPORT_API int
+data_control_sql_get_int_data(result_set_cursor cursor, int column_index, int *data)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_get_int_data((resultset_cursor*)cursor, column_index, data);
+}
+
+
+EXPORT_API int
+data_control_sql_get_int64_data(result_set_cursor cursor, int column_index, long long *data)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_get_int64_data((resultset_cursor*)cursor, column_index, data);
+}
+
+EXPORT_API int
+data_control_sql_get_double_data(result_set_cursor cursor, int column_index, double *data)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_get_double_data((resultset_cursor*)cursor, column_index, data);
+}
+
+
+EXPORT_API int
+data_control_sql_get_text_data(result_set_cursor cursor, int column_index, char *buffer)
+{
+ if (cursor == NULL)
+ {
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+ return datacontrol_sql_get_text_data((resultset_cursor*)cursor, column_index, buffer);
+}
+