diff options
author | gloryj.kim <gloryj.kim@samsung.com> | 2015-06-02 20:07:17 +0900 |
---|---|---|
committer | gloryj.kim <gloryj.kim@samsung.com> | 2015-06-02 20:07:17 +0900 |
commit | 73435351b469a7437b8d4aedd105b59c34b8526e (patch) | |
tree | ac0f913425815e84cfc9ddf6e5c20288d1d24481 | |
parent | 7cbedf051bad1b76d3cba64a76b1181aa913a9e4 (diff) | |
download | download-provider-accepted/tizen/2.4/mobile/20151029.025153.tar.gz download-provider-accepted/tizen/2.4/mobile/20151029.025153.tar.bz2 download-provider-accepted/tizen/2.4/mobile/20151029.025153.zip |
Push new sources from Tizen 2.4submit/tizen_2.4/20151028.065556accepted/tizen/2.4/mobile/20151029.025153
Change-Id: If2be781597be2fbf185237d0ee538a3626a66444
219 files changed, 22291 insertions, 0 deletions
@@ -0,0 +1,2 @@ +Kwangmin Bang <justine.bang@samsung.com>
+Jungki Kwak <jungki.kwak@samsung.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..cc6859b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,102 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +MESSAGE("PROJECT : ${PKG_NAME}") + +# DEFINES + +SET(VERSION ${PKG_VERSION}-${PKG_RELEASE}) +MESSAGE("VERSION : ${VERSION}") + +IF(DEFINED SUPPORT_WIFI_DIRECT) + MESSAGE("SUPPORT_WIFI_DIRECT: ${SUPPORT_WIFI_DIRECT}") + IF(SUPPORT_WIFI_DIRECT) + ADD_DEFINITIONS(-DSUPPORT_WIFI_DIRECT) + ENDIF(SUPPORT_WIFI_DIRECT) +ENDIF(DEFINED SUPPORT_WIFI_DIRECT) + +IF(DEFINED SUPPORT_LOG_MESSAGE) + MESSAGE("SUPPORT_LOG_MESSAGE: ${SUPPORT_LOG_MESSAGE}") + IF(SUPPORT_LOG_MESSAGE) + ADD_DEFINITIONS(-DSUPPORT_LOG_MESSAGE) + ENDIF(SUPPORT_LOG_MESSAGE) +ENDIF(DEFINED SUPPORT_LOG_MESSAGE) + +IF(DEFINED IPC_SOCKET) + ADD_DEFINITIONS(-DIPC_SOCKET=\"${IPC_SOCKET}\") +ENDIF(DEFINED IPC_SOCKET) + +IF(DEFINED NOTIFY_DIR) + ADD_DEFINITIONS(-DNOTIFY_DIR=\"${NOTIFY_DIR}\") +ENDIF(DEFINED NOTIFY_DIR) + +IF(DEFINED LOCALE_DIR) + ADD_DEFINITIONS(-DLOCALE_DIR=\"${LOCALE_DIR}\") +ENDIF(DEFINED LOCALE_DIR) + +IF(DEFINED SUPPORT_SECURITY_PRIVILEGE) + MESSAGE("SUPPORT_SECURITY_PRIVILEGE: ${SUPPORT_SECURITY_PRIVILEGE}") + IF(SUPPORT_SECURITY_PRIVILEGE) + ADD_DEFINITIONS(-DSUPPORT_SECURITY_PRIVILEGE) + ENDIF(SUPPORT_SECURITY_PRIVILEGE) +ENDIF(DEFINED SUPPORT_SECURITY_PRIVILEGE) + +IF(DEFINED SUPPORT_COMPANION_MODE) + MESSAGE("SUPPORT_COMPANION_MODE: ${SUPPORT_COMPANION_MODE}") + IF(SUPPORT_COMPANION_MODE) + ADD_DEFINITIONS(-DSUPPORT_COMPANION_MODE) + ENDIF(SUPPORT_COMPANION_MODE) +ENDIF(DEFINED SUPPORT_COMPANION_MODE) + +IF (TIZEN_2_3_UX) + MESSAGE("TIZEN_2_3_UX:On") + ADD_DEFINITIONS("-D_TIZEN_2_3_UX") +ENDIF(TIZEN_2_3_UX) + +IF(DEFINED SUPPORT_KNOX) + MESSAGE("SUPPORT_KNOX: ${SUPPORT_KNOX}") + IF(SUPPORT_KNOX) + ADD_DEFINITIONS(-DSUPPORT_KNOX) + ENDIF(SUPPORT_KNOX) +ENDIF(DEFINED SUPPORT_KNOX) + +# BUILD + +ADD_SUBDIRECTORY(agent) +ADD_SUBDIRECTORY(provider-interface) +ADD_SUBDIRECTORY(provider) +# i18n +IF(TIZEN_2_3_UX) +ADD_SUBDIRECTORY(po/tizen2.3) +ELSE(TIZEN_2_3_UX) +ADD_SUBDIRECTORY(po/redwood) +ENDIF(TIZEN_2_3_UX) + +# INSTALL + +PROJECT(${PKG_NAME} C) +SET(PACKAGE_DESCRIPTION "Defines for ${PROJECT_NAME}") + +CONFIGURE_FILE(download-provider.pc.in download-provider.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/download-provider.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/systemd/download-provider.service DESTINATION /usr/lib64/systemd/system) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/systemd/download-provider.socket DESTINATION /usr/lib64/systemd/system) + +# install images +IF(TIZEN_2_3_UX) +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/res/images/tizen2.3/ DESTINATION ${IMAGE_DIR}) +ELSE(TIZEN_2_3_UX) +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/res/images/redwood/ DESTINATION ${IMAGE_DIR}) +ENDIF(TIZEN_2_3_UX) + +IF(DEFINED LICENSE_DIR) + CONFIGURE_FILE(LICENSE.APLv2 share/license/${PROJECT_NAME}) + INSTALL(FILES share/license/${PROJECT_NAME} DESTINATION ${LICENSE_DIR}) +ENDIF(DEFINED LICENSE_DIR) + +INSTALL(FILES ${CMAKE_SOURCE_DIR}/dump-download-provider.sh DESTINATION ${CMAKE_LOG_DUMP_SCRIPT_DIR}) + +#IF(SUPPORT_KNOX) + MESSAGE("INSTALL download-provider.res") + INSTALL (FILES ${CMAKE_SOURCE_DIR}/download-provider.res DESTINATION /usr/share/download-provider) +#ENDIF(SUPPORT_KNOX) diff --git a/LICENSE.APLv2 b/LICENSE.APLv2 new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.APLv2 @@ -0,0 +1,202 @@ + + 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. @@ -0,0 +1,3 @@ +Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Apache License, Version 2. +Please, see the LICENSE file for Apache License terms and conditions. diff --git a/agent/CMakeLists.txt b/agent/CMakeLists.txt new file mode 100755 index 0000000..c92fc48 --- /dev/null +++ b/agent/CMakeLists.txt @@ -0,0 +1,116 @@ +PROJECT(downloadagent2 C) + +SET(VERSION "0.1.0") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-D_TARGET") + SET(CMAKE_C_FLAGS_RELEASE "-mabi=aapcs-linux -msoft-float -O2") +ENDIF("${ARCH}" MATCHES "^arm.*") + +#DA Engine Include Directory +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include) + +SET(SRCS_PATH ".") +SET(SRCS_DA + ${SRCS_PATH}/download-agent-interface.c + ${SRCS_PATH}/download-agent-client-mgr.c + ${SRCS_PATH}/download-agent-dl-mgr.c + ${SRCS_PATH}/download-agent-dl-info.c + ${SRCS_PATH}/download-agent-http-mgr.c + ${SRCS_PATH}/download-agent-http-msg-handler.c + ${SRCS_PATH}/download-agent-encoding.c + ${SRCS_PATH}/download-agent-file.c + ${SRCS_PATH}/download-agent-plugin-conf.c + ${SRCS_PATH}/download-agent-mime-util.c +) + +SET(HEADERS + include/download-agent-defs.h + include/download-agent-interface.h +) + +INCLUDE(FindPkgConfig) + +MESSAGE("SUPPORT_SYS_RESOURCE: ${SUPPORT_SYS_RESOURCE}") +IF (SUPPORT_SYS_RESOURCE) +pkg_check_modules(subpkgs REQUIRED + xdgmime + vconf + capi-network-connection + dlog + system-resource + storage +) +ELSE (SUPPORT_SYS_RESOURCE) +pkg_check_modules(subpkgs REQUIRED + xdgmime + vconf + capi-network-connection + dlog + storage +) +ENDIF (SUPPORT_SYS_RESOURCE) + +IF ("${HTTP_LIB}" MATCHES "libcurl") + MESSAGE("HTTP_LIB: ${HTTP_LIB}") + pkg_check_modules(httppkgs REQUIRED + libcurl + ) + LIST(APPEND SRCS_DA + ${SRCS_PATH}/download-agent-plugin-libcurl.c + ) +ENDIF ("${HTTP_LIB}" MATCHES "libcurl") + +IF (SUPPORT_OMA_DRM) + MESSAGE("SUPPORT_OMA_DRM: ${SUPPORT_OMA_DRM}") + ADD_DEFINITIONS("-D_ENABLE_OMA_DRM") + LIST(APPEND SRCS_DA + ${SRCS_PATH}/download-agent-plugin-drm.c + ) + pkg_check_modules(drmpkgs REQUIRED + drm-client + drm-trusted + ) +ENDIF (SUPPORT_OMA_DRM) + +IF (SUPPORT_SYS_RESOURCE) + ADD_DEFINITIONS("-D_ENABLE_SYS_RESOURCE") +ENDIF (SUPPORT_SYS_RESOURCE) + +IF (SUPPORT_DOWNLOAD_BOOSTER) + MESSAGE("SUPPORT_DOWNLOAD_BOOSTER:${SUPPORT_DOWNLOAD_BOOSTER}") + ADD_DEFINITIONS("-D_RAF_SUPPORT") + ADD_DEFINITIONS("-D_DOWNLOAD_BOOSTER_SUPPORT") +ENDIF (SUPPORT_DOWNLOAD_BOOSTER) + +FOREACH(flag ${subpkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +FOREACH(flag ${httppkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +IF (SUPPORT_OMA_DRM) + FOREACH(flag ${drmpkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") + ENDFOREACH(flag) + #This is request of DRM Team. + ADD_DEFINITIONS("-D_FILE_OFFSET_BITS=64") +ENDIF (SUPPORT_OMA_DRM) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -Wall") + +ADD_DEFINITIONS("-D_ENABLE_DLOG") +#This should be removed when release a target +ADD_DEFINITIONS("-D_SAMSUNG_MIME_POLICY") + +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS_DA}) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${subpkgs_LDFLAGS} ${httppkgs_LDFLAGS} ${drmpkgs_LDFLAGS}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION}) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) diff --git a/agent/download-agent-client-mgr.c b/agent/download-agent-client-mgr.c new file mode 100755 index 0000000..82dd516 --- /dev/null +++ b/agent/download-agent-client-mgr.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2012 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 <stdlib.h> + +#include "download-agent-client-mgr.h" + +da_ret_t send_client_paused_info(da_info_t *da_info) +{ + req_info_t *req_info = DA_NULL; + NULL_CHECK_RET(da_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + + if (da_info->is_cb_update && da_info->cb_info.paused_cb) { + da_info->cb_info.paused_cb(da_info->da_id, + req_info->user_req_data, req_info->user_client_data); + DA_LOGV("id[%d]", da_info->da_id); + } else { + DA_LOGV("No CB:id[%d]", da_info->da_id); + } + + return DA_RESULT_OK; +} + +da_ret_t send_client_update_dl_info(da_info_t *da_info) +{ + download_info_t *info = DA_NULL; + file_info_t *file_info = DA_NULL; + http_info_t *http_info = DA_NULL; + req_info_t *req_info = DA_NULL; + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + if (da_info->is_cb_update && da_info->cb_info.download_info_cb) { + info = (download_info_t *)calloc(1, sizeof(download_info_t)); + if (!info) + return DA_ERR_FAIL_TO_MEMALLOC; + info->download_id = da_info->da_id; + info->file_size = http_info->content_len_from_header; + if (http_info->content_type_from_header) + info->file_type = strdup(http_info->content_type_from_header); + if (file_info->file_path) + info->tmp_saved_path = strdup(file_info->file_path); + if (file_info->pure_file_name) + info->content_name = strdup(file_info->pure_file_name); + if (http_info->etag_from_header) { + info->etag = strdup(http_info->etag_from_header); + //DA_SECURE_LOGI("etag[%s]", info->etag); + } + da_info->cb_info.download_info_cb(info, + req_info->user_req_data, req_info->user_client_data); + DA_LOGD("id[%d]", info->download_id); + //DA_LOGI("id[%d]total_size[%lu]", info->download_id, info->file_size); + //if (http_info->content_type_from_header) + //DA_SECURE_LOGI("mime_type[%s]", http_info->content_type_from_header); + } else { + DA_LOGI("No CB:id[%d]", da_info->da_id); + } + return DA_RESULT_OK; +} + +da_ret_t send_client_update_progress_info(da_info_t *da_info) +{ + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + + if (!file_info->is_updated) + return DA_RESULT_OK; + + if (da_info->is_cb_update && da_info->cb_info.progress_cb) { + da_info->cb_info.progress_cb(da_info->da_id, + file_info->bytes_written_to_file, + req_info->user_req_data, req_info->user_client_data); + DA_LOGV("id[%d],size[%llu]", da_info->da_id, + file_info->bytes_written_to_file); + } else { + DA_LOGI("No CB:id[%d]", da_info->da_id); + } + file_info->is_updated = DA_FALSE; + return DA_RESULT_OK; +} + +da_ret_t send_client_finished_info(da_info_t *da_info, int err) +{ + finished_info_t *info = DA_NULL; + file_info_t *file_info = DA_NULL; + http_info_t *http_info = DA_NULL; + req_info_t *req_info = DA_NULL; + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + if (da_info->is_cb_update && da_info->cb_info.finished_cb) { + info = (finished_info_t *)calloc(1, sizeof(finished_info_t)); + if (!info) + return DA_ERR_FAIL_TO_MEMALLOC; + info->download_id = da_info->da_id; + if (http_info->http_msg_response) + info->http_status = http_info->http_msg_response->status_code; + else + DA_LOGE("http_msg_response is NULL"); + if (file_info->file_path) + info->saved_path = strdup(file_info->file_path); + if (http_info->etag_from_header) + info->etag = strdup(http_info->etag_from_header); + info->err = err; + da_info->cb_info.finished_cb(info, + req_info->user_req_data, req_info->user_client_data); + DA_LOGD("id[%d]", info->download_id); + //DA_LOGI("id[%d],err[%d], http_status[%d]", info->download_id, + //info->err, info->http_status); + } else { + DA_LOGI("No CB:id[%d]", da_info->da_id); + } + return DA_RESULT_OK; +} + diff --git a/agent/download-agent-dl-info.c b/agent/download-agent-dl-info.c new file mode 100644 index 0000000..6e49145 --- /dev/null +++ b/agent/download-agent-dl-info.c @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2012 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 <string.h> +#include <stdlib.h> + +#include "download-agent-dl-info.h" +#include "download-agent-http-mgr.h" +#include "download-agent-http-msg-handler.h" + +static pthread_mutex_t mutex_da_info_list = PTHREAD_MUTEX_INITIALIZER; + +static void __init_da_info(int id) +{ + da_info_t *da_info = DA_NULL; + file_info_t *file_info = DA_NULL; + http_info_t *http_info = DA_NULL; + req_info_t *req_info = DA_NULL; + + da_info = (da_info_t *)calloc(1, sizeof(da_info_t)); + if (!da_info) { + DA_LOGE("Fail to calloc. id[%d]",id); + da_info_list[id] = DA_NULL; + return; + } + file_info = (file_info_t *)calloc(1, sizeof(file_info_t)); + if (!file_info) { + DA_LOGE("Fail to calloc. id[%d]",id); + free(da_info); + da_info_list[id] = DA_NULL; + return; + } + http_info = (http_info_t *)calloc(1, sizeof(http_info_t)); + if (!http_info) { + DA_LOGE("Fail to calloc. id[%d]",id); + free(da_info); + free(file_info); + da_info_list[id] = DA_NULL; + return; + } + req_info = (req_info_t *)calloc(1, sizeof(req_info_t)); + if (!req_info) { + DA_LOGE("Fail to calloc. id[%d]",id); + free(da_info); + free(file_info); + free(http_info); + da_info_list[id] = DA_NULL; + return; + } + + da_info->da_id = DA_INVALID_ID; + da_info->tid = DA_INVALID_ID; + memset(&(da_info->cb_info), 0x00, sizeof(da_cb_t)); + da_info->is_cb_update = DA_FALSE; + da_info->http_info = http_info; + da_info->file_info = file_info; + da_info->req_info = req_info; + da_info->update_time = 0; + da_info_list[id] = da_info; +} + +da_ret_t init_http_msg_t(http_msg_t **http_msg) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *temp = DA_NULL; + temp = (http_msg_t *)calloc(1, sizeof(http_msg_t)); + if (!temp) { + DA_LOGE("Fail to calloc. id"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + *http_msg = temp; + return ret; +} + +void destroy_http_msg_t(http_msg_t *http_msg) +{ + if (http_msg) + free(http_msg); + http_msg = DA_NULL; + return; +} + +da_ret_t get_available_da_id(int *available_id) +{ + da_ret_t ret = DA_ERR_ALREADY_MAX_DOWNLOAD; + int i = 0; + + DA_MUTEX_LOCK(&mutex_da_info_list); + for (i = 0; i < DA_MAX_ID; i++) { + if (da_info_list[i] == DA_NULL) { + *available_id = i; + DA_LOGV("available download id[%d]", *available_id); + __init_da_info(i); + ret = DA_RESULT_OK; + break; + } + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); + + return ret; +} + +da_ret_t get_da_info_with_da_id(int id, da_info_t **out_info) +{ + da_ret_t ret = DA_ERR_INVALID_ARGUMENT; + int i = 0; + + DA_MUTEX_LOCK(&mutex_da_info_list); + for (i = 0; i < DA_MAX_ID; i++) { + if (DA_NULL != da_info_list[i] && da_info_list[i]->da_id == id) { + *out_info = da_info_list[i]; + ret = DA_RESULT_OK; + break; + } + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); + + return ret; +} + +da_ret_t __is_supporting_protocol(const char *url) +{ + da_ret_t ret = DA_RESULT_OK; + int wanted_str_len = 0; + char *protocol = NULL; + char *wanted_str_start = NULL; + char *wanted_str_end = NULL; + + if (DA_NULL == url || strlen(url) < 1) + return DA_ERR_INVALID_URL; + + wanted_str_start = (char*)url; + wanted_str_end = strstr(url, "://"); + if (!wanted_str_end) { + DA_LOGE("No protocol on this url"); + return DA_ERR_INVALID_URL; + } + + wanted_str_len = wanted_str_end - wanted_str_start; + protocol = (char*)calloc(1, wanted_str_len + 1); + if (!protocol) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + strncpy(protocol, wanted_str_start, wanted_str_len); + + if (strlen(protocol) < 1) + ret = DA_ERR_UNSUPPORTED_PROTOCAL; + else if (strcasecmp(protocol, "http") != 0 && + strcasecmp(protocol, "https") != 0) + ret = DA_ERR_UNSUPPORTED_PROTOCAL; + + free(protocol); + return ret; +} + +da_ret_t copy_user_input_data(da_info_t *da_info, const char *url, + req_data_t *ext_data, da_cb_t *da_cb_data) +{ + da_ret_t ret = DA_RESULT_OK; + + if (!url || !da_info) { + DA_LOGE("Invalid Param"); + return DA_ERR_INVALID_ARGUMENT; + } + + ret = __is_supporting_protocol(url); + if (ret != DA_RESULT_OK) { + DA_SECURE_LOGE("url[%s]", url); + return ret; + } + + if (ext_data) { + req_info_t *req_info = da_info->req_info; + + if (ext_data->request_header_count > 0) { + int i = 0; + int count = ext_data->request_header_count; + req_info->req_header = (char **)calloc(count, sizeof(char *)); + if(DA_NULL == req_info->req_header) { + DA_LOGE("Fail to calloc"); + free(req_info); + da_info->req_info = DA_NULL; + return DA_ERR_FAIL_TO_MEMALLOC; + } + for (i = 0; i < count; i++) { + if (ext_data->request_header[i]) + req_info->req_header[i] = + strdup(ext_data->request_header[i]); + } + req_info->req_header_count = count; + } + + if (url) + req_info->url = strdup(url); + if (ext_data->install_path) + req_info->install_path = strdup(ext_data->install_path); + if (ext_data->file_name) + req_info->file_name = strdup(ext_data->file_name); + if (ext_data->etag) + req_info->etag = strdup(ext_data->etag); + if (ext_data->temp_file_path) + req_info->temp_file_path = strdup(ext_data->temp_file_path); + if (ext_data->pkg_name) + req_info->pkg_name = strdup(ext_data->pkg_name); + req_info->network_bonding = ext_data->network_bonding; + if (ext_data->user_req_data) + req_info->user_req_data = ext_data->user_req_data; + if (ext_data->user_client_data) + req_info->user_client_data = ext_data->user_client_data; + da_info->req_info = req_info; + } + if (da_cb_data) { + da_info->is_cb_update = DA_TRUE; + memcpy(&(da_info->cb_info), da_cb_data, sizeof(da_cb_t)); + } + return ret; +} + +static void __destroy_http_msg(http_msg_t *msg) +{ + msg->curl = DA_NULL; + free(msg); +} + +static void __destroy_http_msg_request(http_msg_request_t *msg) +{ + if (msg) { + http_msg_request_destroy(&msg); + free(msg); + } +} + +static void __destroy_http_msg_response(http_msg_response_t *msg) +{ + if (msg) { + http_msg_response_destroy(&msg); + free(msg); + } +} + +static void __destroy_req_info(req_info_t *req_info) +{ + if (req_info) { + free(req_info->url); + if (req_info->req_header && req_info->req_header_count > 0) { + int i = 0; + int count = req_info->req_header_count; + for (i = 0; i < count; i++) { + free(req_info->req_header[i]); + req_info->req_header[i] = DA_NULL; + } + free(req_info->req_header); + req_info->req_header = DA_NULL; + req_info->req_header_count = 0; + } + free(req_info->install_path); + free(req_info->file_name); + free(req_info->etag); + free(req_info->temp_file_path); + free(req_info->pkg_name); + req_info->user_req_data = DA_NULL; + req_info->user_client_data = DA_NULL; + free(req_info); + } +} + +void destroy_http_info(http_info_t *http_info) +{ + if (http_info) { + DA_LOGI("[TEST] location_url[%p]",http_info->location_url); + free(http_info->location_url); + free(http_info->proxy_addr); + free(http_info->content_type_from_header); + free(http_info->etag_from_header); + free(http_info->file_name_from_header); + if (http_info->http_msg_request) { + __destroy_http_msg_request(http_info->http_msg_request); + http_info->http_msg_request = DA_NULL; + } + if (http_info->http_msg_response) { + __destroy_http_msg_response(http_info->http_msg_response); + http_info->http_msg_response = DA_NULL; + } + if (http_info->http_msg) { + __destroy_http_msg(http_info->http_msg); + http_info->http_msg = DA_NULL; + } + DA_MUTEX_DESTROY(&(http_info->mutex_state)); + DA_MUTEX_DESTROY(&(http_info->mutex_http)); + DA_COND_DESTROY(&(http_info->cond_http)); + http_info->state = HTTP_STATE_READY_TO_DOWNLOAD; + http_info->http_method = HTTP_METHOD_GET; + http_info->content_len_from_header = 0; + http_info->total_size = 0; + http_info->error_code = 0; + free(http_info); + } +} + +void destroy_file_info(file_info_t *file_info) +{ + if (file_info) { + file_info->file_handle = DA_NULL; + free(file_info->pure_file_name); + free(file_info->extension); + free(file_info->file_path); + free(file_info->mime_type); + free(file_info->buffer); + file_info->buffer_len = 0; + file_info->file_size = 0; +#ifdef _RAF_SUPPORT + file_info->file_size_of_temp_file = 0; +#endif + file_info->bytes_written_to_file = 0; + file_info->is_updated = DA_FALSE; + free(file_info); + } +} + +// For pause and resume case +void reset_http_info_for_resume(http_info_t *http_info) +{ + if (http_info) { + DA_LOGI("[TEST] location_url[%p]",http_info->location_url); + free(http_info->location_url); + http_info->location_url = DA_NULL; + free(http_info->proxy_addr); + http_info->proxy_addr = DA_NULL; + free(http_info->content_type_from_header); + http_info->content_type_from_header = DA_NULL; + if (http_info->http_msg_response) { + __destroy_http_msg_response(http_info->http_msg_response); + http_info->http_msg_response = DA_NULL; + } + if (http_info->http_msg) { + __destroy_http_msg(http_info->http_msg); + http_info->http_msg = DA_NULL; + } + http_info->http_method = HTTP_METHOD_GET; + http_info->content_len_from_header = 0; + http_info->total_size = 0; + } +} + +void reset_http_info(http_info_t *http_info) +{ + if (http_info) { + DA_LOGI("[TEST] location_url[%p]",http_info->location_url); + free(http_info->location_url); + http_info->location_url = DA_NULL; + free(http_info->proxy_addr); + http_info->proxy_addr = DA_NULL; + free(http_info->content_type_from_header); + http_info->content_type_from_header = DA_NULL; + if (http_info->http_msg_request) { + __destroy_http_msg_request(http_info->http_msg_request); + http_info->http_msg_request = DA_NULL; + } + if (http_info->http_msg_response) { + __destroy_http_msg_response(http_info->http_msg_response); + http_info->http_msg_response = DA_NULL; + } + if (http_info->http_msg) { + __destroy_http_msg(http_info->http_msg); + http_info->http_msg = DA_NULL; + } + http_info->http_method = HTTP_METHOD_GET; + http_info->content_len_from_header = 0; + http_info->total_size = 0; + } +} + +da_bool_t is_valid_download_id(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + DA_MUTEX_LOCK(&mutex_da_info_list); + if (DA_NULL == da_info_list[download_id]) { + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return DA_FALSE; + } + if (is_stopped_state(da_info_list[download_id])) { + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return DA_TRUE; + } + if (da_info_list[download_id]->da_id != DA_INVALID_ID) { + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return DA_TRUE; + } else { + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return DA_FALSE; + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return ret; +} + +void destroy_da_info_list() +{ + int i = 0; + DA_MUTEX_LOCK(&mutex_da_info_list); + for (i = 0; i < DA_MAX_ID; i++) { + if(DA_NULL != da_info_list[i]) { + if (da_info_list[i]->req_info) { + __destroy_req_info(da_info_list[i]->req_info); + da_info_list[i]->req_info = DA_NULL; + } + if (da_info_list[i]->http_info) { + destroy_http_info(da_info_list[i]->http_info); + da_info_list[i]->http_info = DA_NULL; + } + if (da_info_list[i]->file_info) { + destroy_file_info(da_info_list[i]->file_info); + da_info_list[i]->file_info = DA_NULL; + } + free(da_info_list[i]); + da_info_list[i] = DA_NULL; + } + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); +} + +void destroy_da_info(int id) +{ + da_info_t *da_info = DA_NULL; + DA_MUTEX_LOCK(&mutex_da_info_list); + da_info = da_info_list[id]; + if (da_info) { + if (da_info->req_info) { + __destroy_req_info(da_info->req_info); + da_info->req_info = DA_NULL; + } + if (da_info->http_info) { + destroy_http_info(da_info->http_info); + da_info->http_info = DA_NULL; + } + if (da_info->file_info) { + destroy_file_info(da_info->file_info); + da_info->file_info = DA_NULL; + } + da_info->da_id = DA_INVALID_ID; + da_info->tid = DA_INVALID_ID; + memset(&(da_info->cb_info), 0x00, sizeof(da_cb_t)); + free(da_info); + da_info_list[id] = DA_NULL; + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); +} diff --git a/agent/download-agent-dl-mgr.c b/agent/download-agent-dl-mgr.c new file mode 100755 index 0000000..e57f3f3 --- /dev/null +++ b/agent/download-agent-dl-mgr.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2012 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 <stdlib.h> +#include <sys/syscall.h> +#include <signal.h> + +#ifdef _ENABLE_SYS_RESOURCE +#include "resourced.h" +#endif + +#include "download-agent-dl-mgr.h" +#include "download-agent-dl-info.h" +#include "download-agent-http-mgr.h" + +void __thread_clean_up_handler_for_start_download(void *arg) +{ + DA_LOGI("cleanup for thread id[%lu]", pthread_self()); +} + +da_ret_t __download_content(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + if (!da_info) { + DA_LOGE("NULL CHECK!: da_info"); + ret = DA_ERR_INVALID_ARGUMENT; + return ret; + } + + ret = request_http_download(da_info); + return ret; +} + + +static void *__thread_start_download(void *data) +{ + da_info_t *da_info = DA_NULL; + req_info_t *req_info = DA_NULL; + int da_id = DA_INVALID_ID; + +// DA_LOGV(""); + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, DA_NULL); + + da_info = (da_info_t *)data; + NULL_CHECK_RET_OPT(da_info, DA_NULL); + req_info = da_info->req_info; + NULL_CHECK_RET_OPT(req_info, DA_NULL); + + da_id = da_info->da_id; + pthread_cleanup_push(__thread_clean_up_handler_for_start_download, DA_NULL); +#ifdef _ENABLE_SYS_RESOURCE + if (req_info->pkg_name) { + pid_t tid = (pid_t) syscall(SYS_gettid); + da_info->tid = (pid_t) syscall(SYS_gettid); + DA_SECURE_LOGI("pkg_name[%s] threadid[%lu]", + req_info->pkg_name,pthread_self()); + if (join_app_performance(req_info->pkg_name, tid) != + RESOURCED_ERROR_OK) { + DA_LOGE("Can not put app to network performance id[%d]", da_id); + } + } +#endif + __download_content(da_info); + destroy_da_info(da_id); + pthread_cleanup_pop(0); + DA_LOGI("=====EXIT thread : da_id[%d]=====", da_id); + pthread_exit((void *)DA_NULL); + return DA_NULL; +} + +da_ret_t start_download(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + pthread_attr_t thread_attr; + pthread_t tid; + if (pthread_attr_init(&thread_attr) != 0) { + ret = DA_ERR_FAIL_TO_CREATE_THREAD; + goto ERR; + } + + if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) != 0) { + ret = DA_ERR_FAIL_TO_CREATE_THREAD; + goto ERR; + } + + if (pthread_create(&(tid), &thread_attr, + __thread_start_download, da_info) < 0) { + DA_LOGE("Fail to make thread:id[%d]", da_info->da_id); + ret = DA_ERR_FAIL_TO_CREATE_THREAD; + } else { + if (tid < 1) { + DA_LOGE("The thread start is failed before calling this"); +// When http resource is leaked, the thread ID is initialized at error handling section of thread_start_download() +// Because the thread ID is initialized, the ptrhead_detach should not be called. This is something like timing issue between threads. +// thread info and basic_dl_input is freed at thread_start_download(). And it should not returns error code in this case. + ret = DA_ERR_FAIL_TO_CREATE_THREAD; + goto ERR; + } + } + da_info->thread_id = tid; + DA_LOGI("Thread create:thread id[%lu]", da_info->thread_id); +ERR: + if (DA_RESULT_OK != ret) { + destroy_da_info(da_info->da_id); + } + return ret; +} + +da_ret_t cancel_download(int dl_id, da_bool_t is_enable_cb) +{ + da_ret_t ret = DA_RESULT_OK; + da_info_t *da_info = DA_NULL; + + DA_LOGV(""); + + ret = get_da_info_with_da_id(dl_id, &da_info); + if (ret != DA_RESULT_OK || !da_info) { + return DA_ERR_INVALID_ARGUMENT; + } + da_info->is_cb_update = is_enable_cb; + ret = request_to_cancel_http_download(da_info); + if (ret != DA_RESULT_OK) + goto ERR; + DA_LOGI("Download cancel Successful for download id[%d]", da_info->da_id); + +ERR: + return ret; +} + +da_ret_t suspend_download(int dl_id, da_bool_t is_enable_cb) +{ + da_ret_t ret = DA_RESULT_OK; + da_info_t *da_info = DA_NULL; + + DA_LOGV(""); + + ret = get_da_info_with_da_id(dl_id, &da_info); + if (ret != DA_RESULT_OK || !da_info) { + return DA_ERR_INVALID_ARGUMENT; + } + da_info->is_cb_update = is_enable_cb; + ret = request_to_suspend_http_download(da_info); + if (ret != DA_RESULT_OK) + goto ERR; + DA_LOGV("Download Suspend Successful for download id[%d]", da_info->da_id); +ERR: + return ret; + +} + +da_ret_t resume_download(int dl_id) +{ + da_ret_t ret = DA_RESULT_OK; + da_info_t *da_info = DA_NULL; + + DA_LOGV(""); + + ret = get_da_info_with_da_id(dl_id, &da_info); + if (ret != DA_RESULT_OK || !da_info) { + return DA_ERR_INVALID_ARGUMENT; + } + da_info->is_cb_update = DA_TRUE; + ret = request_to_resume_http_download(da_info); + if (ret != DA_RESULT_OK) + goto ERR; + DA_LOGV("Download Resume Successful for download id[%d]", da_info->da_id); +ERR: + return ret; +} + diff --git a/agent/download-agent-encoding.c b/agent/download-agent-encoding.c new file mode 100755 index 0000000..3f14fca --- /dev/null +++ b/agent/download-agent-encoding.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2012 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 <string.h> +#include <stdlib.h> +#include "glib.h" + +#include "download-agent-debug.h" +#include "download-agent-encoding.h" + +da_ret_t _parsing_base64_encoded_str(const char *in_encoded_str, + char **out_charset_type, + char *out_encoding_type, + char **out_raw_encoded_str); + +da_bool_t is_base64_encoded_word(const char *in_str) +{ + const char *haystack = DA_NULL; + char first_needle[8] = {0,}; + char second_needle[8] = {0,}; + char *found_str = DA_NULL; + + if (!in_str) { + DA_LOGE("input string is NULL"); + return DA_FALSE; + } + + haystack = in_str; + if (haystack[0] == '"') { + snprintf(first_needle, sizeof(first_needle), "%s", "\"=?"); // "=? + snprintf(second_needle, sizeof(second_needle), "%s", "?=\""); // ?=" + } else { + snprintf(first_needle, sizeof(first_needle), "%s", "=?"); // =? + snprintf(second_needle, sizeof(second_needle), "%s", "?="); // ?= + } + + found_str = strstr(haystack, first_needle); + if (found_str) { + if (found_str == haystack) { + haystack = haystack + strlen(haystack) - strlen(second_needle); + if(!strcmp(haystack, second_needle)) + return DA_TRUE; + } + } + return DA_FALSE; +} + +da_ret_t decode_base64_encoded_str(const char *in_encoded_str, + char **out_decoded_ascii_str) +{ + da_ret_t ret = DA_RESULT_OK; + const char *org_str = DA_NULL; + char *charset_type = NULL; + char encoding_type = '\0'; + char *raw_encoded_str = NULL; + char *decoded_str = NULL; + const gchar *g_encoded_text = NULL; + guchar *g_decoded_text = NULL; + gsize g_decoded_text_len = 0; + + DA_SECURE_LOGD("input str = [%s]", in_encoded_str); + + org_str = in_encoded_str; + if(!org_str) { + DA_LOGE("Input string is NULL"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + ret = _parsing_base64_encoded_str(org_str, &charset_type, + &encoding_type, &raw_encoded_str); + if(ret != DA_RESULT_OK) { + goto ERR; + } + + if(encoding_type != 'B') { + DA_LOGE("Encoded Word is not encoded with Base64, but %c. We can only handle Base64.", encoding_type); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + /* + * on glib/gtype.h + * typedef char gchar; + * typedef unsigned char guchar; + * + */ + g_encoded_text = (const gchar*)raw_encoded_str; + g_decoded_text = g_base64_decode(g_encoded_text, &g_decoded_text_len); + + if(g_decoded_text) { + DA_SECURE_LOGD("g_decoded_text = [%s]", g_decoded_text); + decoded_str = (char*)calloc(1, g_decoded_text_len+1); + if(!decoded_str) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } else { + memcpy(decoded_str, g_decoded_text, g_decoded_text_len); + } + } + DA_SECURE_LOGD("decoded_str = [%s]", decoded_str); + +ERR: + *out_decoded_ascii_str = decoded_str; + if(charset_type) { + free(charset_type); + charset_type = NULL; + } + if(raw_encoded_str) { + free(raw_encoded_str); + raw_encoded_str = NULL; + } + if(g_decoded_text) { + g_free(g_decoded_text); + } + return ret; +} + +da_ret_t _parsing_base64_encoded_str(const char *in_encoded_str, + char **out_charset_type, + char *out_encoding_type, + char **out_raw_encoded_str) +{ + da_ret_t ret = DA_RESULT_OK; + const char *org_str = DA_NULL; // e.g. =?UTF-8?B?7Jew7JWE7JmA7IKs7J6QLmpwZw==?= + char *charset_type = NULL; // e.g. UTF-8 + char encoding_type = '\0'; // e.g. B (means Base64) + char *raw_encoded_str = NULL; // e.g. 7Jew7JWE7JmA7IKs7J6QLmpwZw== + char *haystack = DA_NULL; + char needle[8] = {0,}; + char *wanted_str = DA_NULL; + int wanted_str_len = 0; + char *wanted_str_start = DA_NULL; + char *wanted_str_end = DA_NULL; + + org_str = in_encoded_str; + if (!org_str) { + DA_LOGE("Input string is NULL"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + // strip "=?" + haystack = (char*)org_str; + snprintf(needle, sizeof(needle), "=?"); + wanted_str_end = strstr(haystack, needle); + if (!wanted_str_end) { + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } else { + wanted_str = wanted_str_end + strlen(needle); + } + + // for charset + haystack = wanted_str_start = wanted_str; + needle[0] = '?'; + wanted_str_end = strchr(haystack, needle[0]); + if (!wanted_str_end) { + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } else { + wanted_str_len = wanted_str_end - wanted_str_start + 1; + wanted_str = (char*)calloc(1, wanted_str_len+1); + if (!wanted_str) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } else { + snprintf(wanted_str, wanted_str_len+1, "%s", wanted_str_start); + charset_type = wanted_str; + wanted_str = DA_NULL; + } + + DA_LOGV("charset [%s]", charset_type); + } + + // for encoding + encoding_type = *(++wanted_str_end); + DA_LOGV("encoding [%c]", encoding_type); + + // for raw encoded str + haystack = wanted_str_start = wanted_str_end + 1; + snprintf(needle, sizeof(needle), "?="); + wanted_str_end = strstr(haystack, needle); + if (!wanted_str_end) { + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } else { + wanted_str_len = wanted_str_end - wanted_str_start + 1; + wanted_str = (char*)calloc(1, wanted_str_len+1); + if (!wanted_str) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } else { + snprintf(wanted_str, wanted_str_len+1, "%s", wanted_str_start); + raw_encoded_str = wanted_str; + wanted_str = NULL; + } + + DA_SECURE_LOGD("raw encoded str [%s]", raw_encoded_str); + } +ERR: + if (ret != DA_RESULT_OK) { + if (charset_type) { + free(charset_type); + charset_type = NULL; + } + } + *out_charset_type = charset_type; + *out_encoding_type = encoding_type; + *out_raw_encoded_str = raw_encoded_str; + return ret; +} + +void decode_url_encoded_str(const char *in_encoded_str, char **out_str) +{ + char *in = NULL; + char *out = NULL; + *out_str = calloc(1, strlen(in_encoded_str) + 1); + if (*out_str == NULL) + return; + out = *out_str; + in = (char *)in_encoded_str; + while (*in) + { + if (*in == '%') { + int hex = 0; + in++; + if (sscanf(in, "%2x", &hex) <= 0) { + return; + } else { + *out = hex; + in++; + } + } else if (*in == '+') { + *out = ' '; + } else { + *out = *in; + } + in++; + out++; + } +} diff --git a/agent/download-agent-file.c b/agent/download-agent-file.c new file mode 100755 index 0000000..ea901e2 --- /dev/null +++ b/agent/download-agent-file.c @@ -0,0 +1,908 @@ +/* + * Copyright (c) 2012 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 <stdlib.h> +#include <dirent.h> +#include <unistd.h> +#include <string.h> +#include <sys/vfs.h> +#include <math.h> +#include <errno.h> + +#include "download-agent-debug.h" +#include "download-agent-file.h" +#include "download-agent-mime-util.h" +/* FIXME Later */ +#include "download-agent-http-msg-handler.h" +#include "download-agent-plugin-drm.h" +#include "download-agent-plugin-conf.h" +#include <storage.h> + + +#define NO_NAME_TEMP_STR "No name" +#define MAX_SUFFIX_COUNT 1000000000 + +da_ret_t __saved_file_open(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *actual_file_path = DA_NULL; + void *fd = DA_NULL; + + DA_LOGV(""); + + actual_file_path = file_info->file_path; + if (!actual_file_path) + return DA_ERR_INVALID_ARGUMENT; + + fd = fopen(actual_file_path, "a+"); // for resume + if (fd == DA_NULL) { + DA_LOGE("File open failed"); + if (errno == ENOSPC) + ret = DA_ERR_DISK_FULL; + else + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + + file_info->file_handle = fd; + //DA_SECURE_LOGD("file path for saving[%s]", file_info->file_path); + +ERR: + if (DA_RESULT_OK != ret) { + file_info->file_handle = DA_NULL; + } + return ret; +} + +da_ret_t __divide_file_name_into_pure_name_N_extesion(const char *in_file_name, char **out_pure_file_name, char **out_extension) +{ + char *file_name = DA_NULL; + char *tmp_ptr = DA_NULL; + char temp_file[DA_MAX_FILE_PATH_LEN] = {0,}; + char tmp_ext[DA_MAX_STR_LEN] = {0,}; + int len = 0; + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + + if (!in_file_name) + return DA_ERR_INVALID_ARGUMENT; + + file_name = (char *)in_file_name; + tmp_ptr = strrchr(file_name, '.'); + if (tmp_ptr) + tmp_ptr++; + if (tmp_ptr && out_extension) { + strncpy((char*) tmp_ext, tmp_ptr, sizeof(tmp_ext) - 1); + *out_extension = strdup((const char*) tmp_ext); + DA_SECURE_LOGD("extension [%s]", *out_extension); + } + + if (!out_pure_file_name) + return ret; + + if (tmp_ptr) + len = tmp_ptr - file_name - 1; + else + len = strlen(file_name); + + if (len >= DA_MAX_FILE_PATH_LEN) { + strncpy((char*) temp_file, file_name, + DA_MAX_FILE_PATH_LEN - 1); + } else { + strncpy((char*) temp_file, file_name, len); + } + + delete_prohibited_char((char*) temp_file, + strlen((char*) temp_file)); + if (strlen(temp_file) < 1) { + *out_pure_file_name = strdup(NO_NAME_TEMP_STR); + } else { + *out_pure_file_name = strdup( + (const char*) temp_file); + } + + DA_LOGV( "pure file name [%s]", *out_pure_file_name); + return ret; +} + +da_ret_t __file_write_buf_make_buf(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + + DA_LOGV(""); + + buffer = (char*) calloc(1, DA_FILE_BUF_SIZE); + if (DA_NULL == buffer) { + DA_LOGE("Calloc failure "); + ret = DA_ERR_FAIL_TO_MEMALLOC; + } else { + file_info->buffer_len = 0; + file_info->buffer = buffer; + } + + return ret; +} + +da_ret_t __file_write_buf_destroy_buf(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + NULL_CHECK_RET(file_info); + + free(file_info->buffer); + file_info->buffer = DA_NULL; + file_info->buffer_len = 0; + + return ret; +} + +da_ret_t __file_write_buf_flush_buf(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + int buffer_size = 0; + int write_success_len = 0; + void *fd = DA_NULL; + + // DA_LOGV(""); + + buffer = file_info->buffer; + buffer_size = file_info->buffer_len; + + if (buffer_size == 0) { + DA_LOGE("no data on buffer.."); + return ret; + } + + fd = file_info->file_handle; + if (DA_NULL == fd) { + DA_LOGE("There is no file handle."); + + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + + write_success_len = fwrite(buffer, sizeof(char), buffer_size, + (FILE *) fd); + /* FIXME : This can be necessary later due to progressive download. + * The solution for reducing fflush is needed */ + //fflush((FILE *) fd); + if (write_success_len != buffer_size) { + DA_LOGE("write fails "); + if (errno == ENOSPC) + ret = DA_ERR_DISK_FULL; + else + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + file_info->bytes_written_to_file += write_success_len; + file_info->is_updated = DA_TRUE; + file_info->buffer_len = 0; +ERR: + return ret; +} + +da_ret_t __file_write_buf_copy_to_buf(file_info_t *file_info, char *body, + int body_len) +{ + da_ret_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + int buffer_size = 0; + + DA_LOGV(""); + + NULL_CHECK_RET(file_info->buffer); + buffer = file_info->buffer; + buffer_size = file_info->buffer_len; + + memcpy(buffer + buffer_size, body, body_len); + file_info->buffer_len += body_len; + + return ret; +} + +da_ret_t __file_write_buf_directly_write(file_info_t *file_info, + char *body, int body_len) +{ + da_ret_t ret = DA_RESULT_OK; + size_t write_success_len = 0; + void *fd = DA_NULL; + + // DA_LOGV(""); + + fd = file_info->file_handle; + if (DA_NULL == fd) { + DA_LOGE("There is no file handle."); + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + + write_success_len = fwrite(body, sizeof(char), (size_t)body_len, + (FILE *) fd); + /* FIXME : This can be necessary later due to progressive download. + * The solution for reducing fflush is needed */ + //fflush((FILE *) fd); + if (write_success_len != (size_t)body_len) { + DA_LOGE("write fails "); + if (errno == ENOSPC) + ret = DA_ERR_DISK_FULL; + else + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + file_info->bytes_written_to_file += write_success_len; + DA_LOGV( "write %llu bytes", write_success_len); + file_info->is_updated = DA_TRUE; + +ERR: + return ret; +} + +/* Priority to derive extension + * 1. extension name which client set + * 2. according to MIME-Type + * 3. if MIME-Type is ambiguous or blank, + * 3-1. derived from <Content-Disposition> field's "filename" attribute + * 3-2. derived from url + * 4. if url does not have extension, leave blank for extension + */ +char *__get_extension_name(char *mime_type, + char *file_name_from_header, char *url) +{ + char *extension = DA_NULL; + + /* Priority 1 */ + if (mime_type && !is_ambiguous_MIME_Type(mime_type)) { + char *extension = DA_NULL; + da_ret_t ret = get_extension_from_mime_type(mime_type, &extension); + if (ret == DA_RESULT_OK && extension) + return extension; + } + /* Priority 2-1 */ + if (file_name_from_header) { + char *extension = DA_NULL; + DA_SECURE_LOGI("Content-Disposition :[%s]", file_name_from_header); + __divide_file_name_into_pure_name_N_extesion(file_name_from_header, + DA_NULL, &extension); + if (extension) + return extension; + } + /* Priority 2-2 */ + if (url) { + DA_LOGV("Get extension from url"); + da_bool_t b_ret = da_get_extension_name_from_url(url, &extension); + if (b_ret && extension) + return extension; + } + return DA_NULL; +} + +/** Priority for deciding file name + * 1. file name which client set + * 2. 'filename' option on HTTP response header's Content-Disposition field + * 3. requesting URL + * 4. Otherwise, define it as "No name" + */ +da_ret_t __get_candidate_file_name(char *user_file_name, char *url, + char *file_name_from_header, + char **out_pure_file_name, char **out_extension) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + + /* Priority 1 */ + if (user_file_name) { + __divide_file_name_into_pure_name_N_extesion( + user_file_name, out_pure_file_name, out_extension); + } + if (*out_pure_file_name) + return ret; + /* Priority 2 */ + if (file_name_from_header) { + DA_SECURE_LOGI("Content-Disposition:[%s]", file_name_from_header); + __divide_file_name_into_pure_name_N_extesion(file_name_from_header, + out_pure_file_name, DA_NULL); + } + if (*out_pure_file_name) + return ret ; + /* Priority 3 */ + if (url) { + DA_LOGV("Get file name from url"); + da_get_file_name_from_url(url, out_pure_file_name); + } + if (*out_pure_file_name) + return ret ; + /* Priority 4 */ + *out_pure_file_name = strdup(NO_NAME_TEMP_STR); + if (*out_pure_file_name == DA_NULL) + ret = DA_ERR_FAIL_TO_MEMALLOC; + return ret; +} + +da_ret_t __decide_file_path(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *extension = DA_NULL; + char *file_name = DA_NULL; + char *tmp_file_path = DA_NULL; + char *install_dir = DA_DEFAULT_INSTALL_PATH_FOR_PHONE; + char *user_file_name = DA_NULL; + char *file_name_from_header = DA_NULL; + char *url = DA_NULL; + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + http_info_t *http_info = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + if (req_info->install_path) + install_dir = req_info->install_path; + user_file_name = req_info->file_name; + /* If there is location url from response header in case of redirection, + * it try to parse the file name from the location url */ + if (http_info->location_url) { + url = http_info->location_url; + DA_LOGI("[TEST] location_url[%s][%p]",http_info->location_url, http_info->location_url); + } else + url = req_info->url; + + file_name_from_header = http_info->file_name_from_header; + + /* extension is extracted only if User set specific name */ + ret = __get_candidate_file_name(user_file_name, url, file_name_from_header, + &file_name, &extension); + if (ret != DA_RESULT_OK) + goto ERR; + + if (file_name && strpbrk(file_name, DA_INVALID_PATH_STRING) != NULL) { + DA_LOGI("Invalid string at file name"); + free(file_name); + file_name = strdup(NO_NAME_TEMP_STR); + if (!file_name) { + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + + } + + DA_SECURE_LOGI("candidate file name [%s]", file_name); + + if (!extension) { + extension = __get_extension_name(file_info->mime_type, + file_name_from_header, url); + } + if (file_name && !file_info->pure_file_name) { + file_info->pure_file_name = file_name; + file_name = DA_NULL; + } + if (extension && !file_info->extension) { + DA_LOGV("candidate extension [%s]", extension); + file_info->extension = extension; + extension = DA_NULL; + } + + // for resume + tmp_file_path = get_full_path_avoided_duplication(install_dir, + file_info->pure_file_name, file_info->extension); + if (tmp_file_path) { + file_info->file_path = tmp_file_path; + tmp_file_path = DA_NULL; + } else { + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + +ERR: + DA_SECURE_LOGI("decided file path [%s]", file_info->file_path); + free(file_name); + free(extension); + return ret; +} + +// for resume with new download request +da_ret_t __decide_file_path_for_resume(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *extension = DA_NULL; + char *file_name = DA_NULL; + char *file_path = DA_NULL; + char *ptr = DA_NULL; + char *ptr2 = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(file_info); + + file_path = file_info->file_path; + ptr = strrchr(file_path, '/'); + if (ptr) { + ptr++; + ptr2 = strrchr(ptr, '.'); + if (ptr2) { + int len = 0; + len = ptr2 - ptr; + ptr2++; + extension = strdup(ptr2); + file_name = calloc(1, len + 1); + if (file_name) + snprintf(file_name, len + 1, "%s", ptr); + } else { + file_name = strdup(ptr); + } + } + + if (file_name && !file_info->pure_file_name) { + file_info->pure_file_name = file_name; + file_name = DA_NULL; + } else { + free(file_name); + } + if (extension && !file_info->extension) { + DA_LOGV( "candidate extension [%s]", extension); + file_info->extension = extension; + extension = DA_NULL; + } else { + free(extension); + } + return ret; +} + +da_ret_t start_file_writing(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + + /* resume case */ + if (req_info->etag || req_info->temp_file_path) { + char *file_path = DA_NULL; + char *origin_path = DA_NULL; + file_path = req_info->temp_file_path; + if (!file_path) + return DA_ERR_INVALID_ARGUMENT; + origin_path = file_info->file_path; + file_info->file_path = strdup(file_path); + free(origin_path); + ret = __decide_file_path_for_resume(file_info); + } else { + ret = __decide_file_path(da_info); + } + + if (ret != DA_RESULT_OK) + goto ERR; + + if (req_info->etag || req_info->temp_file_path) { + da_size_t file_size = 0; + get_file_size(req_info->temp_file_path, &file_size); + if (file_size < 1) + goto ERR; +#ifdef _RAF_SUPPORT + file_info->file_size_of_temp_file = file_size; +#endif + file_info->bytes_written_to_file = file_size; + } else { + file_info->bytes_written_to_file = 0; + } + ret = __saved_file_open(file_info); +ERR: + return ret; +} + +da_ret_t start_file_append(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + + NULL_CHECK_RET(file_info); + + ret = __saved_file_open(file_info); + return ret; +} + +da_ret_t file_write_ongoing(file_info_t *file_info, char *body, int body_len) +{ + da_ret_t ret = DA_RESULT_OK; + int buffer_size = 0; + char *buffer = DA_NULL; + + DA_LOGV(""); + + buffer = file_info->buffer; + buffer_size = file_info->buffer_len; + + if (DA_NULL == buffer) { + if (body_len < DA_FILE_BUF_SIZE) { + ret = __file_write_buf_make_buf(file_info); + if (ret != DA_RESULT_OK) + goto ERR; + __file_write_buf_copy_to_buf(file_info, body, body_len); + } else { + ret = __file_write_buf_directly_write(file_info, + body, body_len); + if (ret != DA_RESULT_OK) + goto ERR; + } + } else { + if (DA_FILE_BUF_SIZE <= body_len) { + ret = __file_write_buf_flush_buf(file_info); + if (ret != DA_RESULT_OK) + goto ERR; + ret = __file_write_buf_directly_write(file_info, + body, body_len); + if (ret != DA_RESULT_OK) + goto ERR; + } else if ((DA_FILE_BUF_SIZE - buffer_size) <= body_len) { + ret = __file_write_buf_flush_buf(file_info); + if (ret != DA_RESULT_OK) + goto ERR; + __file_write_buf_copy_to_buf(file_info, body, body_len); + } else { + __file_write_buf_copy_to_buf(file_info, body, body_len); + } + } +ERR: + if (ret != DA_RESULT_OK) { + file_info->buffer_len = 0; + free(file_info->buffer); + file_info->buffer = DA_NULL; + } + return ret; +} + +#ifdef _RAF_SUPPORT +da_ret_t file_write_complete_for_raf(file_info_t *file_info) { + da_ret_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + da_size_t wrriten_size = 0; + da_size_t file_size = 0; + void *fd = DA_NULL; + + DA_LOGV(""); + fd = file_info->file_handle; + + wrriten_size = file_info->bytes_written_to_file; + // test code + get_file_size(file_info->file_path, &file_size); + DA_LOGI("wrriten_size:%llu file_size:%llu file[%s]", + wrriten_size, file_size, file_info->file_path); + if (fd) { + fclose(fd); + fd = DA_NULL; + } + file_info->file_handle = DA_NULL; + if (wrriten_size < file_size) { + DA_LOGD("Try truncate"); + if (truncate(file_info->file_path, wrriten_size) < 0) { + DA_LOGE("Fail to ftruncate: errno[%d,%s]", errno, strerror(errno)); + } + DA_LOGD("Try truncate done"); + } + + ERR: + return ret; +} +#endif + +da_ret_t file_write_complete(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + unsigned int buffer_size = 0; + void *fd = DA_NULL; + + DA_LOGV(""); + + buffer = file_info->buffer; + buffer_size = file_info->buffer_len; + + if (DA_NULL == buffer) { + DA_LOGE("file buffer is NULL"); + } else { + if (buffer_size != 0) { + ret = __file_write_buf_flush_buf(file_info); + if (ret != DA_RESULT_OK) + goto ERR; + } + __file_write_buf_destroy_buf(file_info); + } + fd = file_info->file_handle; + + if (fd) { + fclose(fd); + fd = DA_NULL; + } + file_info->file_handle = DA_NULL; +ERR: + return ret; +} + +da_ret_t discard_download(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + FILE *f_handle = DA_NULL; + + DA_LOGV(""); + + f_handle = file_info->file_handle; + if (f_handle) { + fclose(f_handle); + file_info->file_handle = DA_NULL; + } + return ret; +} + +void clean_paused_file(file_info_t *file_info) +{ + char *paused_file_path = DA_NULL; + FILE *fd = DA_NULL; + + DA_LOGV(""); + + fd = file_info->file_handle; + if (fd) { + fclose(fd); + file_info->file_handle = DA_NULL; + } + + paused_file_path = file_info->file_path; + file_info->bytes_written_to_file = 0; // Ignore resume flow after failed or cancled. + remove_file((const char*) paused_file_path); + + return; +} + +da_bool_t is_file_exist(const char *file_path) +{ + struct stat dir_state; + int stat_ret; + + if (file_path == DA_NULL) { + DA_LOGE("file path is DA_NULL"); + return DA_FALSE; + } + stat_ret = stat(file_path, &dir_state); + if (stat_ret == 0) { + if (dir_state.st_mode & S_IFREG) { + //DA_SECURE_LOGD("Exist! %s is a regular file & its size = %lu", file_path, dir_state.st_size); + return DA_TRUE; + } + + return DA_FALSE; + } + return DA_FALSE; + +} + +void get_file_size(char *file_path, da_size_t *out_file_size) +{ + struct stat dir_state; + int stat_ret; + + *out_file_size = -1; + + if (file_path == DA_NULL) { + DA_LOGE("file path is DA_NULL"); + return; + } + /* Please do not use ftell() to obtain file size, use stat instead. + * This is a guide from www.securecoding.cert.org + * : FIO19-C. Do not use fseek() and ftell() to compute the size of a file + */ + stat_ret = stat(file_path, &dir_state); + if (stat_ret == 0) { + if (dir_state.st_mode & S_IFREG) { + DA_LOGV( "size = %lu", dir_state.st_size); + *out_file_size = dir_state.st_size; + } + } + return; +} + +char *get_full_path_avoided_duplication(char *in_dir, + char *in_candidate_file_name, char *in_extension) +{ + char *dir = in_dir; + char *file_name = in_candidate_file_name; + char *extension = in_extension; + char *final_path = DA_NULL; + + int dir_path_len = 0; + int final_path_len = 0; + int extension_len = 0; + + int suffix_count = 0; /* means suffix on file name. up to "_99" */ + int suffix_len = (int)log10(MAX_SUFFIX_COUNT + 1) + 1; /* 1 means "_" */ + + if (!in_dir || !in_candidate_file_name) + return DA_NULL; + + //DA_SECURE_LOGI("in_candidate_file_name=[%s],in_extension=[%s]", + //in_candidate_file_name, in_extension); + + if (extension) + extension_len = strlen(extension); + + // to remove trailing slash from dir path + dir_path_len = strlen(dir); + if (dir[dir_path_len - 1] == '/') { + dir[dir_path_len - 1] = '\0'; + --dir_path_len; + } + + /* first 1 for "/", second 1 for ".", last 1 for DA_NULL */ + final_path_len = dir_path_len + 1 + strlen(file_name) + 1 + + suffix_len + extension_len + 1; + + final_path = (char*)calloc(1, final_path_len); + if (!final_path) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + return DA_NULL; + } + + do { + /* e.g) /tmp/abc.jpg + * if there is no extension name, just make a file name without extension */ + if (0 == extension_len) { + if (suffix_count == 0) { + snprintf(final_path, final_path_len, + "%s/%s", dir, file_name); + } else { + snprintf(final_path, final_path_len, + "%s/%s_%d", dir, file_name, suffix_count); + } + } else { + if (suffix_count == 0) { + snprintf(final_path, final_path_len, + "%s/%s.%s", dir, file_name, extension); + } else { + snprintf(final_path, final_path_len, + "%s/%s_%d.%s", + dir, file_name, suffix_count, extension); + } + } + if (is_file_exist(final_path)) { + suffix_count++; + if (suffix_count > MAX_SUFFIX_COUNT) { + free(final_path); + final_path = DA_NULL; + break; + } else { + memset(final_path, 0x00, final_path_len); + continue; + } + } + break; + } while (1); + + //DA_SECURE_LOGD("decided path = [%s]", final_path); + return final_path; +} + + +da_ret_t check_drm_convert(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + da_bool_t ret_b = DA_TRUE; + + DA_LOGD(""); + + NULL_CHECK_RET(file_info); + +#ifdef _ENABLE_OMA_DRM + + /* In case of OMA DRM 1.0 SD, it is not necessary to call DRM convert API. + * Because it is already converted itself. + * And, the case will return fail because The SD is not supported now. + */ + if (is_content_drm_dcf(file_info->mime_type)) { + DA_LOGI("DRM SD case"); + unlink(file_info->file_path); + free(file_info->file_path); + file_info->file_path = DA_NULL; + return DA_ERR_DRM_FAIL; + } + if (is_content_drm_dm(file_info->mime_type)) { + char *actual_file_path = DA_NULL; + char *out_file_path = DA_NULL; + + actual_file_path = file_info->file_path; + DA_SECURE_LOGD("actual_file_path = %s", actual_file_path); + if (!actual_file_path) + return DA_ERR_INVALID_ARGUMENT; + ret_b = EDRM_convert(actual_file_path, &out_file_path); + unlink(actual_file_path); + free(actual_file_path); + if (!ret_b) + ret = DA_ERR_DRM_FAIL; + file_info->file_path = out_file_path; + } else { + return ret; + } +#endif + + return ret; +} + +void remove_file(const char *file_path) +{ + DA_LOGV(""); + + if (file_path && is_file_exist(file_path)) { + DA_SECURE_LOGD("remove file [%s]", file_path); + if (unlink(file_path) < 0) { + DA_LOGE("file removing failed."); + } + } +} + +da_ret_t get_available_memory(char *dir_path, da_size_t len) +{ + da_ret_t ret = DA_RESULT_OK; + int fs_ret = 0; + //struct statfs filesys_info = {0, }; + struct statvfs filesys_info; + + DA_LOGV(""); + + if (!dir_path) + return DA_ERR_INVALID_INSTALL_PATH; + + //fs_ret = statfs(dir_path, &filesys_info); + // Using this as it considers FOTA memory while returning available memory + fs_ret = storage_get_internal_memory_size(&filesys_info); + + if (fs_ret != 0) { + // DA_LOGE("statfs error[%s]", strerror(errno)); + return DA_ERR_INVALID_ARGUMENT; + // return DA_ERR_INVALID_INSTALL_PATH; + } + + double available_size = (double)filesys_info.f_bsize * filesys_info.f_bavail; + double total_size = (double)filesys_info.f_frsize * filesys_info.f_blocks; + DA_SECURE_LOGI(" total = %lf ", total_size); + DA_SECURE_LOGI(" available = %lf ",available_size); + + DA_LOGV("Available Memory(f_bavail) : %lu", filesys_info.f_bavail); + DA_LOGV("Available Memory(f_bsize) : %d", filesys_info.f_bsize); + DA_LOGD("Available Memory(kbytes) : %d", (filesys_info.f_bavail/1024)*filesys_info.f_bsize); + DA_LOGV("Content: %llu", len); + if (available_size < (len + + SAVE_FILE_BUFFERING_SIZE_50KB)) /* 50KB buffering */ + ret = DA_ERR_DISK_FULL; + + return ret; +} diff --git a/agent/download-agent-http-mgr.c b/agent/download-agent-http-mgr.c new file mode 100755 index 0000000..3a2feb9 --- /dev/null +++ b/agent/download-agent-http-mgr.c @@ -0,0 +1,1519 @@ +/* + * Copyright (c) 2012 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 <stdlib.h> +#include <string.h> +#include <errno.h> +#include <time.h> + +#include "download-agent-dl-info.h" +#include "download-agent-file.h" +#include "download-agent-mime-util.h" +#include "download-agent-client-mgr.h" +#include "download-agent-http-msg-handler.h" +#include "download-agent-plugin-conf.h" +#include "download-agent-plugin-drm.h" +#include "download-agent-plugin-libcurl.h" + +void __http_update_cb(http_raw_data_t *data, void *user_param); + +#define CONVERT_STR(NAME) (#NAME) + +static const char *__get_state_str(http_state_t state) +{ + char *str = NULL; + switch(state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + str = CONVERT_STR(HTTP_STATE_READY_TO_DOWNLOAD); + break; + case HTTP_STATE_REDIRECTED: + str = CONVERT_STR(HTTP_STATE_REDIRECTED); + break; + case HTTP_STATE_DOWNLOAD_REQUESTED: + str = CONVERT_STR(HTTP_STATE_DOWNLOAD_REQUESTED); + break; + case HTTP_STATE_DOWNLOAD_STARTED: + str = CONVERT_STR(HTTP_STATE_DOWNLOAD_STARTED); + break; + case HTTP_STATE_DOWNLOADING: + str = CONVERT_STR(HTTP_STATE_DOWNLOADING); + break; + case HTTP_STATE_DOWNLOAD_FINISH: + str = CONVERT_STR(HTTP_STATE_DOWNLOAD_FINISH); + break; + case HTTP_STATE_REQUEST_CANCEL: + str = CONVERT_STR(HTTP_STATE_REQUEST_CANCEL); + break; + case HTTP_STATE_REQUEST_PAUSE: + str = CONVERT_STR(HTTP_STATE_REQUEST_PAUSE); + break; + case HTTP_STATE_REQUEST_RESUME: + str = CONVERT_STR(HTTP_STATE_REQUEST_RESUME); + break; + case HTTP_STATE_CANCELED: + str = CONVERT_STR(HTTP_STATE_CANCELED); + break; + case HTTP_STATE_FAILED: + str = CONVERT_STR(HTTP_STATE_FAILED); + break; + case HTTP_STATE_PAUSED: + str = CONVERT_STR(HTTP_STATE_PAUSED); + break; + case HTTP_STATE_RESUMED: + str = CONVERT_STR(HTTP_STATE_RESUMED); + break; + case HTTP_STATE_ABORTED: + str = CONVERT_STR(HTTP_STATE_ABORTED); + break; + case HTTP_STATE_WAIT_FOR_NET_ERR: + str = CONVERT_STR(HTTP_STATE_WAIT_FOR_NET_ERR); + break; + default: + str = "Unknown State"; + break; + } + return str; +} + +void __init_http_info(http_info_t *http_info) +{ + DA_LOGV(""); + + http_info->state = HTTP_STATE_READY_TO_DOWNLOAD; + http_info->update_cb = __http_update_cb; + DA_MUTEX_INIT(&(http_info->mutex_state), DA_NULL); + DA_MUTEX_INIT(&(http_info->mutex_http), DA_NULL); + DA_COND_INIT(&(http_info->cond_http), DA_NULL); +} + +void __parsing_user_request_header(char *user_request_header, + char **out_field, char **out_value) +{ + int len = 0; + char *pos = NULL; + char *temp_pos = NULL; + char *field = NULL; + char *value = NULL; + + DA_LOGV(""); + + if (!user_request_header) { + DA_LOGE("NULL CHECK!: user_request_header"); + goto ERR; + } + + pos = strchr(user_request_header, ':'); + if (!pos) { + DA_LOGE("Fail to parse"); + goto ERR; + } + temp_pos = (char *)user_request_header; + while (*temp_pos) + { + if (temp_pos == pos || *temp_pos == ' ') { + len = temp_pos - user_request_header; + break; + } + temp_pos++; + } + if (len < 1) { + DA_LOGE("Wrong field name"); + goto ERR; + } + field = (char *)calloc(1, len + 1); + if (!field) { + DA_LOGE("Fail to calloc"); + goto ERR; + } + strncpy(field, user_request_header, len); + pos++; + while (*pos) + { + if (*pos != ' ') + break; + pos++; + } + len = strlen(pos) + 1; + value = (char *)calloc(1, len + 1); + if (!value) { + DA_LOGE("Fail to calloc"); + goto ERR; + } + strncpy(value, pos, len); + *out_field = field; + *out_value = value; + DA_SECURE_LOGD("field[%s], value[%s]", field, value); + + return; +ERR: + if (field) { + free(field); + field = NULL; + } + return; +} + + +da_ret_t __set_http_request_hdr(req_info_t *req_info, http_info_t *http_info, file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_request_t *http_msg_request = NULL; + char *user_agent = NULL; + int count = 0; + + DA_LOGV(""); + + NULL_CHECK_RET(req_info); + NULL_CHECK_RET(http_info); + NULL_CHECK_RET(file_info); + NULL_CHECK_RET_OPT(req_info->url, DA_ERR_INVALID_URL); + count = req_info->req_header_count; + + ret = http_msg_request_create(&http_msg_request); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = http_msg_request_set_url(http_msg_request, req_info->url); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = get_user_agent_string(&user_agent); + if (user_agent && ret == DA_RESULT_OK) + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_UAGENT, user_agent); + + + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_ACCEPT_LANGUAGE, "en"); + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_ACCEPT_CHARSET, "utf-8"); + + if (req_info->req_header && count > 0) { + int i = 0; + for (i = 0; i < count; i++) { + char *field = NULL; + char *value = NULL; + __parsing_user_request_header(req_info->req_header[i], + &field, &value); + if (field && value) { + http_msg_request_add_field(http_msg_request, field, value); + if (field) { + free(field); + field = NULL; + } + if (value) { + free(value); + value= NULL; + } + } else { + if (field) { + free(field); + field = NULL; + } + if (value) { + free(value); + value= NULL; + } + DA_LOGE("Fail to parse user request header"); + } + } + } + if (req_info->etag) { + char buff[64] = {0,}; + da_size_t size = 0; + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_IF_RANGE, req_info->etag); + get_file_size(req_info->temp_file_path, &size); +#ifdef _RAF_SUPPORT + file_info->file_size_of_temp_file = size; +#endif + snprintf(buff, sizeof(buff)-1, "bytes=%llu-", size); + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_RANGE, buff); + } + + http_info->http_msg_request = http_msg_request; + free(user_agent); + return ret; +ERR: + if (http_msg_request) + http_msg_request_destroy(&http_msg_request); + + return ret; + +} + +da_ret_t __create_http_resume_hdr(req_info_t *req_info, http_info_t *http_info, + file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + da_bool_t b_ret = DA_FALSE; + char *value = NULL; + char temp_size_str[32] = { 0, }; + char *etag_from_response = NULL; + char *date_from_response = NULL; + http_msg_response_t *first_response = NULL; + http_msg_request_t *resume_request = NULL; + http_msg_request_t *old_request = NULL; + + DA_LOGV(""); + + first_response = http_info->http_msg_response; + if (first_response) { + b_ret = http_msg_response_get_ETag(first_response, &value); + if (b_ret) { + etag_from_response = value; + value = NULL; + DA_SECURE_LOGD("[ETag][%s]", etag_from_response); + } + b_ret = http_msg_response_get_date(first_response, &value); + if (b_ret) { + date_from_response = value; + value = NULL; + DA_LOGV("[Date][%s]", date_from_response); + } + DA_SECURE_LOGD("downloaded_size[%u]", file_info->bytes_written_to_file); + snprintf(temp_size_str, sizeof(temp_size_str), "bytes=%llu-", + file_info->bytes_written_to_file); + DA_SECURE_LOGD("size str[%s]", temp_size_str); + free(first_response); + http_info->http_msg_response = DA_NULL; + } + old_request = http_info->http_msg_request; + free(old_request); + http_info->http_msg_request = DA_NULL; + + ret = __set_http_request_hdr(req_info, http_info, file_info); + if (ret != DA_RESULT_OK) + goto ERR; + + resume_request = http_info->http_msg_request; + if (etag_from_response) { + http_msg_request_add_field(resume_request, HTTP_FIELD_IF_RANGE, + etag_from_response); + } else { + if (date_from_response) { + http_msg_request_add_field(resume_request, + HTTP_FIELD_IF_RANGE, date_from_response); + } + } + + if (strlen(temp_size_str) > 0) + http_msg_request_add_field(resume_request, HTTP_FIELD_RANGE, + temp_size_str); + +ERR: + if (etag_from_response) { + free(etag_from_response); + etag_from_response = NULL; + } + if (date_from_response) { + free(date_from_response); + date_from_response = NULL; + } + return ret; +} + + +da_ret_t __start_transaction(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info; + DA_LOGV(""); + + if (!da_info) { + DA_LOGE("NULL CHECK!: da_info"); + return DA_ERR_INVALID_ARGUMENT; + } + http_info = da_info->http_info; + if (!http_info) { + DA_LOGE("NULL CHECK!: http_info"); + return DA_ERR_INVALID_ARGUMENT; + } + http_info->http_method = HTTP_METHOD_GET; + http_info->proxy_addr = get_proxy_address(); + + ret = PI_http_start(da_info); + + return ret; +} + +da_ret_t __start_resume_transaction(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + + ret = __create_http_resume_hdr(req_info, http_info, + file_info); + if (ret != DA_RESULT_OK) + return ret; + + reset_http_info_for_resume(http_info); + if (file_info->file_path) { + req_info->temp_file_path = strdup(file_info->file_path); + } else { + DA_LOGE("file_path cannot be NULL in resume case"); + return DA_ERR_INVALID_ARGUMENT; + } + ret = __start_transaction(da_info); + return ret; +} + + +da_ret_t __start_new_transaction(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + + if (!da_info) { + DA_LOGE("NULL CHECK!: da_info"); + return DA_ERR_INVALID_ARGUMENT; + } + + ret = __set_http_request_hdr(da_info->req_info, da_info->http_info, da_info->file_info); + if (ret != DA_RESULT_OK) + return ret; + + ret = __start_transaction(da_info); + return ret; +} + +int __check_wait_for_auto_retry(http_info_t *http_info) +{ + da_ret_t ret = DA_RESULT_OK; + struct timespec ts; + struct timeval tp; + NULL_CHECK_RET_OPT(http_info, 0); + gettimeofday(&tp, NULL); + ts.tv_sec = tp.tv_sec + DA_MAX_TIME_OUT; + ts.tv_nsec = tp.tv_usec * 1000; + DA_LOGI("Network Fail case, wait for a while"); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_WAIT_FOR_NET_ERR; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + ret = pthread_cond_timedwait(&(http_info->cond_http), + &(http_info->mutex_http), &ts); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + if (ret == ETIMEDOUT) { + DA_LOGI("Waiting is done by timeout"); + } else if (ret != 0) { + DA_LOGE("fail to pthread_cond_waittime[%d][%s]",ret, strerror(ret)); + } else { + DA_LOGI("Waiting is done by control"); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + DA_LOGI("http_state[%s]", __get_state_str(http_info->state)); + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + return 1; + } + + return 0; +} + +// In download thread +da_ret_t request_http_download(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + req_info_t *req_info = DA_NULL; + http_info_t *http_info = DA_NULL; + http_state_t http_state = 0; + da_bool_t need_wait = DA_TRUE; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + __init_http_info(http_info); + + do { + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s][%d]",__get_state_str(http_info->state), da_info->da_id); + switch (http_state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_REQUESTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = __start_new_transaction(da_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_LOGD("http_state[%s][%d]",__get_state_str(http_info->state), da_info->da_id); + http_info->error_code = ret; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + if (ret == DA_ERR_NETWORK_FAIL && http_state != HTTP_STATE_PAUSED) { + DA_LOGE("Network failed"); + if (__check_wait_for_auto_retry(http_info) == 1) + need_wait = DA_TRUE; + else + need_wait = DA_FALSE; + } + break; + case HTTP_STATE_REDIRECTED: + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_DOWNLOAD_STARTED: + case HTTP_STATE_DOWNLOADING: + case HTTP_STATE_REQUEST_PAUSE: + DA_LOGE("Cannot enter here:[%s][id]", + __get_state_str(http_info->state), da_info->da_id); + break; + case HTTP_STATE_REQUEST_CANCEL: + break; + case HTTP_STATE_REQUEST_RESUME: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_READY_TO_DOWNLOAD; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + need_wait = DA_TRUE; + break; + case HTTP_STATE_CANCELED: + need_wait = DA_FALSE; + ret = DA_RESULT_USER_CANCELED; + break; + case HTTP_STATE_PAUSED: + DA_LOGD("error_code[%d]", http_info->error_code); + send_client_paused_info(da_info); + DA_LOGD("Waiting thread for paused state"); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + pthread_cond_wait(&(http_info->cond_http),&(http_info->mutex_http)); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + DA_LOGD("Wake up thread due to resume"); + break; + case HTTP_STATE_RESUMED: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_REQUESTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = __start_resume_transaction(da_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + if (ret == DA_ERR_NETWORK_FAIL && http_state != HTTP_STATE_PAUSED) { + DA_LOGE("Network failed"); + if (__check_wait_for_auto_retry(http_info) == 1) + need_wait = DA_TRUE; + else + need_wait = DA_FALSE; + } + break; + case HTTP_STATE_DOWNLOAD_FINISH: + need_wait = DA_FALSE; + if (ret == DA_RESULT_OK) + ret = check_drm_convert(da_info->file_info); + break; + case HTTP_STATE_FAILED: + if (ret == DA_ERR_NETWORK_FAIL) { + if (__check_wait_for_auto_retry(http_info) == 1) + need_wait = DA_TRUE; + else + need_wait = DA_FALSE; + } else { + need_wait = DA_FALSE; + } + break; + case HTTP_STATE_ABORTED: + need_wait = DA_FALSE; + break; + default: + break; + } + } while (need_wait == DA_TRUE); + DA_LOGD("Final http_state[%s][%d] err[%d]",__get_state_str(http_info->state), da_info->da_id, ret); + if (http_info->state != HTTP_STATE_PAUSED) + send_client_finished_info(da_info ,ret); + DA_LOGI("=== Exiting http_download ret[%d] ===", ret); + return ret; +} + +da_ret_t __disconnect_transaction(http_info_t *http_info) +{ + da_ret_t ret = DA_RESULT_OK; + DA_LOGD(""); + ret = PI_http_disconnect(http_info); + return ret; +} + +da_ret_t __handle_event_abort(http_info_t *http_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_state_t state = 0; + + DA_LOGD(""); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGV("http_state[%s]", __get_state_str(state)); + + switch (state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + case HTTP_STATE_REDIRECTED: + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_DOWNLOAD_STARTED: + case HTTP_STATE_DOWNLOADING: + case HTTP_STATE_REQUEST_CANCEL: + case HTTP_STATE_REQUEST_PAUSE: + case HTTP_STATE_REQUEST_RESUME: + case HTTP_STATE_CANCELED: + case HTTP_STATE_PAUSED: + case HTTP_STATE_RESUMED: + case HTTP_STATE_ABORTED: + case HTTP_STATE_WAIT_FOR_NET_ERR: + /* IF the network session is terminated due to some error, + * the state can be aborted.(data aborted case) */ + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_ABORTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + __disconnect_transaction(http_info); + break; + case HTTP_STATE_DOWNLOAD_FINISH: + break; + default: + DA_LOGE("Cannot enter here"); + break; + } + return ret; +} + +da_ret_t __check_enough_memory(http_info_t *http_info, char *user_install_path) +{ + da_ret_t ret = DA_RESULT_OK; + da_size_t cont_len = 0; + char *dir_path = DA_DEFAULT_INSTALL_PATH_FOR_PHONE; + + DA_LOGV(""); + NULL_CHECK_RET(http_info); + cont_len = http_info->content_len_from_header; + if (cont_len > 0) { + if (user_install_path) + dir_path = user_install_path; + ret = get_available_memory(dir_path, cont_len); + } + return ret; +} + +da_ret_t request_to_abort_http_download(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + ret = __handle_event_abort(da_info->http_info); + return ret; +} + +da_ret_t request_to_cancel_http_download(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + http_state_t http_state = 0; + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); + switch (http_state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + ret = PI_http_cancel(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_CANCELED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + if (da_info->thread_id > 0) { + if (pthread_cancel(da_info->thread_id) != 0) { + DA_LOGE("Fail to cancel thread id[%d] err[%s]", + da_info->thread_id, strerror(errno)); + } else { + DA_LOGI("====Exit thread with cancel:da_id[%d]===", + da_info->da_id); + } + } + break; + case HTTP_STATE_WAIT_FOR_NET_ERR: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_CANCELED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + DA_COND_SIGNAL(&(http_info->cond_http)); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + break; + case HTTP_STATE_PAUSED: + reset_http_info(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_CANCELED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_DOWNLOAD_STARTED: + case HTTP_STATE_DOWNLOADING: + case HTTP_STATE_REQUEST_RESUME: + case HTTP_STATE_RESUMED: + ret = PI_http_cancel(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_REQUEST_CANCEL; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_DOWNLOAD_FINISH: + ret = DA_ERR_INVALID_STATE; + break; + case HTTP_STATE_REQUEST_CANCEL: + DA_LOGV("cancel is already in progress... "); + ret = DA_ERR_INVALID_STATE; + break; + default: + ret = DA_ERR_INVALID_STATE; + DA_LOGE("Cannot enter here"); + break; + } + return ret; +} + +da_ret_t request_to_suspend_http_download(da_info_t *da_info) +{ + + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + http_state_t http_state = 0; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); + + switch (http_state) { + case HTTP_STATE_PAUSED: + case HTTP_STATE_REQUEST_PAUSE: + DA_LOGI("Already paused. http_state[%s]", __get_state_str(http_state)); + ret = DA_ERR_ALREADY_SUSPENDED; + break; + case HTTP_STATE_READY_TO_DOWNLOAD: + DA_LOGE("Download has not been started yet"); + ret = DA_ERR_INVALID_STATE; + break; + case HTTP_STATE_WAIT_FOR_NET_ERR: + DA_LOGD("error_code[%d]", http_info->error_code); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_PAUSED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + DA_COND_SIGNAL(&(http_info->cond_http)); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + break; + default: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_REQUEST_PAUSE; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("error_code[%d]", http_info->error_code); + if (http_info->error_code != DA_ERR_NETWORK_FAIL) + ret = PI_http_pause(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_PAUSED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + + break; + } + return ret; +} + +da_ret_t request_to_resume_http_download(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + http_state_t http_state = 0; + int retry_count = 0; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); + + switch (http_state) { + case HTTP_STATE_PAUSED: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_RESUMED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("Wake up thread for paused state"); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + DA_COND_SIGNAL(&(http_info->cond_http)); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + DA_LOGD("error_code[%d]", http_info->error_code); + if (http_info->error_code != DA_ERR_NETWORK_FAIL) { + ret = PI_http_unpause(http_info); + if (ret != DA_RESULT_OK) + PI_http_cancel(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOADING; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + + } + break; + case HTTP_STATE_REQUEST_PAUSE: + DA_LOGD("Waiting to handle pause request"); + do { + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + if (http_state == HTTP_STATE_PAUSED) { + DA_LOGD("Change to paused state"); + ret = PI_http_unpause(http_info); + break; + } + retry_count++; + } while(retry_count < 10000); + if (ret != DA_RESULT_OK || retry_count >= 10000) + PI_http_cancel(http_info); + break; + case HTTP_STATE_RESUMED: + ret = DA_ERR_ALREADY_RESUMED; + break; + default: + DA_LOGE("Fail to resume. Invalid state check. http_state[%s]", + __get_state_str(http_state)); + ret = DA_ERR_INVALID_STATE; + // If resume is failed due to invalid state, the previous pause should be canceled. + PI_http_cancel(http_info); + break; + } + return ret; +} + +da_ret_t __check_resume_download_is_available( + req_info_t *req_info, http_info_t *http_info, file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + da_bool_t b_ret = DA_FALSE; + char *origin_ETag = NULL; + char *new_ETag = NULL; + da_size_t remained_content_len = 0; + char *value = NULL; + da_size_t size = 0; + char *temp_file_path = DA_NULL; + char *dir_path = DA_DEFAULT_INSTALL_PATH_FOR_PHONE; + + DA_LOGV(""); + + origin_ETag = req_info->etag; + + b_ret = http_msg_response_get_content_length(http_info->http_msg_response, + &size); + if (b_ret) { + remained_content_len = size; + size = 0; + DA_SECURE_LOGD("remained_content_len[%llu]", remained_content_len); + } + + b_ret = http_msg_response_get_ETag(http_info->http_msg_response, &value); + if (b_ret) { + new_ETag = value; + value = NULL; + DA_SECURE_LOGD("new ETag[%s]", new_ETag); + } else { + goto ERR; + } + + if (origin_ETag && new_ETag && + 0 != strncmp(origin_ETag, new_ETag, strlen(new_ETag))) { + DA_LOGE("ETag is not identical! revoke!"); + /* FIXME Later : Need to detail error exception handling */ + ret = DA_ERR_NETWORK_FAIL; + /*ret = DA_ERR_MISMATCH_HTTP_HEADER; */ + goto ERR; + } + + if (remained_content_len > 0) { + if (req_info->install_path) + dir_path = req_info->install_path; + ret = get_available_memory(dir_path, remained_content_len); + if (ret != DA_RESULT_OK) + goto ERR; + } + + if (!http_info->content_type_from_header) { + b_ret = http_msg_response_get_content_type(http_info->http_msg_response, + &value); + if (b_ret) { + http_info->content_type_from_header = value; + value = NULL; + DA_SECURE_LOGD("Content-Type[%s]", + http_info->content_type_from_header); + } + } + temp_file_path = req_info->temp_file_path; + if (!temp_file_path) { + DA_LOGE("Temporary file path cannot be NULL"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + get_file_size(temp_file_path, &size); + http_info->content_len_from_header = remained_content_len + size; + DA_SECURE_LOGD("Content-Length[%llu]", http_info->content_len_from_header); +ERR: + if (new_ETag) { + free(new_ETag); + new_ETag = DA_NULL; + } + return ret; +} + + +da_ret_t __check_content_type_is_matched(http_info_t *http_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *content_type_from_server = DA_NULL; + + DA_LOGV(""); + + content_type_from_server = http_info->content_type_from_header; + if (content_type_from_server == DA_NULL) { + DA_LOGV("http header has no Content-Type field, no need to compare"); + return DA_RESULT_OK; + } + return ret; +} + +da_ret_t __handle_http_status_code(http_info_t *http_info, + file_info_t *file_info, req_info_t *req_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + http_msg_response_t *http_msg_response = DA_NULL; + char *location = DA_NULL; + char *if_range_str = DA_NULL; + char *range_str = DA_NULL; + int http_status = 0; + + NULL_CHECK_RET(http_info); + NULL_CHECK_RET(file_info); + NULL_CHECK_RET(req_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); + http_msg_response = http_info->http_msg_response; + NULL_CHECK_RET(http_msg_response); + http_status = http_msg_response->status_code; + switch (http_status) { + case 200: + case 201: + case 202: + case 203: +// Although expecting 206, 200 response is received. Remove temporary file and reset file info + if (http_info->http_msg_request && + http_msg_request_get_if_range(http_info->http_msg_request, &if_range_str) == DA_TRUE && + http_msg_request_get_range(http_info->http_msg_request, &range_str) == DA_TRUE) { + DA_LOGI("Server do not support if-range option"); + clean_paused_file(file_info); + } + free(if_range_str); + free(range_str); + if (http_state == HTTP_STATE_REQUEST_RESUME) + clean_paused_file(file_info); + ret = __check_content_type_is_matched(http_info); + if (ret != DA_RESULT_OK) + goto ERR; + ret = __check_enough_memory(http_info, req_info->install_path); + if (ret != DA_RESULT_OK) + goto ERR; + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_STARTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + + case 206: + DA_LOGV("HTTP Status is %d - Partial download for resume!", http_status); + /* The resume can be started with start API. + * So the state should be not HTTP_STATE_RESUME_REQUESTED but HTTP_STATE_DOWNLOAD_REQUESTED*/ + if (http_state == HTTP_STATE_DOWNLOAD_REQUESTED) { + ret = __check_resume_download_is_available(req_info, http_info, file_info); + if (ret != DA_RESULT_OK) + goto ERR; + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_STARTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + + } else if (http_state == HTTP_STATE_REQUEST_RESUME) { + ///FIXME later : how get previous response header + ///ret = __check_this_partial_download_is_available(http_info, + /// previous_ http_msg_response); + //if (ret != DA_RESULT_OK) + //goto ERR; + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_RESUMED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + } else { + DA_LOGE("This download is not resumed, revoke"); + ret = DA_ERR_INVALID_STATE; + goto ERR; + } + break; + + case 300: + case 301: + case 302: + case 303: + case 305: + case 306: + case 307: + DA_LOGV("HTTP Status is %d - redirection!",http_status); + if (http_msg_response_get_location(http_msg_response, &location)) { + DA_SECURE_LOGD("location = %s\n", location); + http_info->location_url = location; + DA_LOGI("[TEST] location_url[%p]",http_info->location_url); + } + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_REDIRECTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + http_msg_response_destroy(&http_msg_response); + http_info->http_msg_response = DA_NULL; + break; + + case 100: + case 101: + case 102: + case 204: + case 304: + DA_LOGV("HTTP Status is %d - 204 server got the request, \ + but no content to reply back, \ + 304 means not modified!", http_status); + ret = DA_ERR_SERVER_RESPOND_BUT_SEND_NO_CONTENT; + break; + + case 416: // Requested range not satisfiable + case 503: + case 504: + default: +/// GET_REQUEST_HTTP_RESULT(request_info) +/// = DA_ERR_UNREACHABLE_SERVER; + DA_LOGI("set internal error code : DA_ERR_UNREACHABLE_SERVER"); + break; + } + +ERR: + return ret; +} + +da_ret_t __check_before_downloading(da_info_t *da_info, http_state_t state) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + req_info_t *req_info = DA_NULL; + file_info_t *file_info = DA_NULL; + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + DA_LOGD("state:%s",__get_state_str(state)); + // resume case + if (req_info->temp_file_path && file_info->bytes_written_to_file > 0) { + ret = start_file_append(file_info); + } else if (state == HTTP_STATE_DOWNLOAD_STARTED) { + ret = start_file_writing(da_info); + } else { + DA_LOGE("Cannot enter here!"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + if (DA_RESULT_OK != ret) + goto ERR; + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOADING; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + + ret = send_client_update_dl_info(da_info); +ERR: + return ret; +} + +da_ret_t __handle_event_http_header(http_raw_data_t *raw_data, da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + http_info_t *http_info = DA_NULL; + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + http_msg_response_t *http_msg_response = DA_NULL; + da_size_t size = 0; + char *mime_type = DA_NULL; + char *etag = DA_NULL; + char *file_name = DA_NULL; + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + NULL_CHECK_RET(raw_data); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGV("http_state[%s]", __get_state_str(http_state)); + http_msg_response = http_info->http_msg_response; + switch (http_state) { + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_REQUEST_PAUSE: + case HTTP_STATE_REQUEST_RESUME: + case HTTP_STATE_REDIRECTED: + http_msg_response_get_content_length(http_msg_response, &size); + http_info->content_len_from_header = size; + http_msg_response_get_content_type(http_msg_response, &mime_type); + http_info->content_type_from_header = mime_type; + if (mime_type) + file_info->mime_type = strdup(mime_type); + http_msg_response_get_ETag(http_msg_response, &etag); + http_info->etag_from_header = etag; + http_msg_response_get_content_disposition( + http_msg_response, DA_NULL, &file_name); + http_info->file_name_from_header = file_name; + ret = __handle_http_status_code(http_info, file_info, req_info); + if (ret != DA_RESULT_OK) { + DA_LOGE("Fail to handle http status code"); + goto ERR; + } +#ifdef _RAF_SUPPORT + char *val = NULL; + http_msg_response_get_RAF_mode(http_msg_response, &val); + if (!val) { + DA_LOGE("Fail to raf mode value from response header"); + } else { + DA_LOGI("[RAF] val[%s:%s]", HTTP_FIELD_RAF_MODE, val); + if (strncmp(val, "yes", strlen("yes")) == 0) { + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_STARTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = __check_before_downloading(da_info, http_info->state); + if (ret != DA_RESULT_OK) { + free(val); + goto ERR; + } + http_info->is_raf_mode_confirmed = DA_TRUE; + ret = PI_http_set_file_name_to_curl(http_info->http_msg, file_info->file_path); + if (ret != DA_RESULT_OK) { + DA_LOGE("Fail to set file name to curl"); + free(val); + goto ERR; + } + } + free(val); + } +#endif + break; + case HTTP_STATE_REQUEST_CANCEL: + DA_LOGV("Cancel is in progress.. http_state[%s]", + __get_state_str(http_state)); + break; + + default: + DA_LOGE("http_state[%s]", __get_state_str(http_state)); + goto ERR; + } + +ERR: + if (ret != DA_RESULT_OK) { + DA_LOGE("Request to cancel due to error[%d]", ret); + PI_http_cancel(http_info); + http_info->error_code = ret; + discard_download(file_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_FAILED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + } + free(raw_data); + return ret; +} + +da_ret_t __handle_event_http_packet(http_raw_data_t *raw_data, da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + http_info_t *http_info = DA_NULL; + file_info_t *file_info = DA_NULL; + time_t t; + struct tm *lc_time; + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + NULL_CHECK_RET(raw_data); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + + switch (http_state) { + case HTTP_STATE_DOWNLOAD_STARTED: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_FALSE) { +#endif + ret = __check_before_downloading(da_info, http_state); + if (ret != DA_RESULT_OK) + goto ERR; + ret = file_write_ongoing(file_info, + raw_data->body, raw_data->body_len); + if (ret != DA_RESULT_OK) + goto ERR; +#ifdef _RAF_SUPPORT + } else { + file_info->bytes_written_to_file = + raw_data->received_len + file_info->file_size_of_temp_file; + file_info->is_updated = DA_TRUE; + } +#endif + ret = send_client_update_progress_info(da_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = HTTP_STATE_DOWNLOADING; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_RESUMED: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_FALSE) { +#endif + __check_before_downloading(da_info, http_state); + ret = file_write_ongoing(file_info, + raw_data->body, raw_data->body_len); + if (ret != DA_RESULT_OK) + goto ERR; +#ifdef _RAF_SUPPORT + } else { + file_info->bytes_written_to_file = + raw_data->received_len + file_info->file_size_of_temp_file; + file_info->is_updated = DA_TRUE; + } +#endif + ret = send_client_update_progress_info(da_info); + break; + case HTTP_STATE_REDIRECTED: + DA_LOGV("http_state[%s]", __get_state_str(http_state)); + break; + case HTTP_STATE_DOWNLOADING: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_FALSE) { +#endif + /* Should this function before updating download info + * Because it extract mime type at once only if first download updating at client */ + ret = file_write_ongoing(file_info, + raw_data->body, raw_data->body_len); + if (ret != DA_RESULT_OK) + goto ERR; +#ifdef _RAF_SUPPORT + } else { + file_info->bytes_written_to_file = + raw_data->received_len + file_info->file_size_of_temp_file; + file_info->is_updated = DA_TRUE; + } +#endif + // send event every 1 second. + if ((t = time(DA_NULL)) > 0) { + if ((lc_time = localtime(&t)) != DA_NULL) { + if (da_info->update_time != lc_time->tm_sec) { + da_info->update_time = lc_time->tm_sec; + ret = send_client_update_progress_info(da_info); + } + } else { + DA_LOGE("Fail to call localtime[%s]",strerror(errno)); + ret = send_client_update_progress_info(da_info); + } + } else { + DA_LOGE("Fail to call time[%s]",strerror(errno)); + ret = send_client_update_progress_info(da_info); + } + break; + case HTTP_STATE_REQUEST_PAUSE: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_FALSE) { +#endif + DA_LOGV("http_state[%s]", __get_state_str(http_state)); + ret = file_write_ongoing(file_info, + raw_data->body, raw_data->body_len); + if (ret != DA_RESULT_OK) + goto ERR; +#ifdef _RAF_SUPPORT + } else { + file_info->bytes_written_to_file = + raw_data->received_len + file_info->file_size_of_temp_file; + file_info->is_updated = DA_TRUE; + } +#endif + + break; + default: + DA_LOGE("Do nothing! http_state is in case[%s]", + __get_state_str(http_state)); + goto ERR; + } +ERR: + if (ret != DA_RESULT_OK) { + DA_LOGE("Request to cancel due to error[%d]", ret); + PI_http_cancel(http_info); + http_info->error_code = ret; + discard_download(da_info->file_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_FAILED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + } + if (raw_data->body) + free(raw_data->body); + free(raw_data); + return ret; +} + +da_ret_t __check_file_size_with_header_content_size(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + unsigned long long tmp_file_size = 0; + + DA_LOGV(""); + + if (file_info->file_size > 0) { + +#ifdef _ENABLE_OMA_DRM + if (is_content_drm_dm(file_info->mime_type)) { + /* FIXME Later : How can get the file size of DRM file. */ + return ret; + } +#endif + + get_file_size(file_info->file_path, &tmp_file_size); + + if (tmp_file_size != file_info->file_size) { + DA_SECURE_LOGE("Real file size[%llu], MISMATCH CONTENT SIZE", + tmp_file_size); + ret = DA_ERR_MISMATCH_CONTENT_SIZE; + } + } + return ret; +} + +da_ret_t __handle_event_http_final(http_raw_data_t *raw_data, da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + http_info_t *http_info = DA_NULL; + file_info_t *file_info = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + NULL_CHECK_RET(raw_data); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); + + switch (http_state) { + case HTTP_STATE_REDIRECTED: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_READY_TO_DOWNLOAD; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_DOWNLOAD_REQUESTED: + DA_LOGV("case HTTP_STATE_DOWNLOAD_REQUESTED"); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_FINISH; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_DOWNLOADING: + DA_LOGD("case HTTP_STATE_DOWNLOADING"); +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_TRUE) { + ret = file_write_complete_for_raf(file_info); + } else { + ret = file_write_complete(file_info); + } +#else + ret = file_write_complete(file_info); +#endif + if (ret != DA_RESULT_OK) { + discard_download(file_info); + goto ERR; + } + ret = __check_file_size_with_header_content_size(file_info); + if(ret != DA_RESULT_OK) { + discard_download(file_info) ; + goto ERR; + } + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_FINISH; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = send_client_update_progress_info(da_info); + break; + case HTTP_STATE_REQUEST_PAUSE: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_TRUE) { + if (file_info->file_handle) + ret = file_write_complete_for_raf(file_info); + } else { + ret = file_write_complete(file_info); + } +#else + if (file_info->file_handle) { + ret = file_write_complete(file_info); +// send_client_update_progress_info(da_info); + } +#endif + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_PAUSED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGV("Server Notification code is set to NULL"); + break; + case HTTP_STATE_ABORTED: + case HTTP_STATE_CANCELED: + discard_download(file_info); + break; + case HTTP_STATE_REQUEST_CANCEL: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_TRUE) { + ret = file_write_complete_for_raf(file_info); + } else { + ret = file_write_complete(file_info); + } +#else + ret = file_write_complete(file_info); +#endif + if (ret != DA_RESULT_OK) + goto ERR; + discard_download(file_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_CANCELED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_PAUSED: + DA_LOGD("Remain paused stated"); + break; + default: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_TRUE) { + ret = file_write_complete_for_raf(file_info); + } else { + ret = file_write_complete(file_info); + } +#else + ret = file_write_complete(file_info); +#endif + if (ret != DA_RESULT_OK) + goto ERR; + discard_download(file_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_FAILED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + } + +ERR: + /* When file complete is failed */ + if (DA_RESULT_OK != ret) { + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_FINISH; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + } + if (raw_data->body) + free(raw_data->body); + free(raw_data); + return ret; +} + +void __http_update_cb(http_raw_data_t *data, void *user_param) +{ + http_raw_data_t *raw_data = DA_NULL; + da_info_t *da_info = DA_NULL; + if (!data || !user_param) { + DA_LOGE("NULL CHECK!: data, user_param"); + return; + } + DA_LOGV(""); + raw_data = data; + da_info = (da_info_t *)user_param; + + switch(data->type) { + case HTTP_EVENT_GOT_HEADER: + __handle_event_http_header(raw_data, da_info); + break; + case HTTP_EVENT_GOT_PACKET: + __handle_event_http_packet(raw_data, da_info); + break; + case HTTP_EVENT_FINAL: + __handle_event_http_final(raw_data, da_info); + break; +/* + case HTTP_EVENT_ABORT: + ret = __handle_event_http_abort(raw_data, da_info); + break; +*/ + } +} + +da_bool_t is_stopped_state(da_info_t *da_info) +{ + http_info_t *http_info = DA_NULL; + http_state_t http_state; + NULL_CHECK_RET_OPT(da_info, DA_FALSE); + http_info = da_info->http_info; + NULL_CHECK_RET_OPT(http_info, DA_FALSE); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + switch (http_state) { + case HTTP_STATE_REQUEST_CANCEL: + case HTTP_STATE_CANCELED: + case HTTP_STATE_FAILED: + case HTTP_STATE_ABORTED: + //case HTTP_STATE_REQUEST_PAUSE: + //case HTTP_STATE_REQUEST_RESUME: + //case HTTP_STATE_WAIT_FOR_NET_ERR: + return DA_TRUE; + default: + return DA_FALSE; + } + return DA_FALSE; +} diff --git a/agent/download-agent-http-msg-handler.c b/agent/download-agent-http-msg-handler.c new file mode 100755 index 0000000..231a61d --- /dev/null +++ b/agent/download-agent-http-msg-handler.c @@ -0,0 +1,1125 @@ +/* + * Copyright (c) 2012 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 <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include "download-agent-http-msg-handler.h" +#include "download-agent-debug.h" +#include "download-agent-encoding.h" + +// '.' and ';' are request from Vodafone +#define IS_TERMINATING_CHAR(c) ( ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) +#define IS_TERMINATING_CHAR_EX(c) ( ((c) == '"') || ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) +#define IS_URI_TERMINATING_CHAR(c) ( ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) + +enum parsing_type { + WITH_PARSING_OPTION, + WITHOUT_PARSING_OPTION +}; + +static da_ret_t __http_header_add_field(http_header_t **head, + const char *field, const char *value, enum parsing_type type); +static void __http_header_destroy_all_field(http_header_t **head); +static da_bool_t __get_http_header_for_field( + http_msg_response_t *http_msg_response, const char *in_field, + http_header_t **out_header); +static void __exchange_header_value(http_header_t *header, + const char *in_raw_value); +static http_header_options_t *__create_http_header_option(const char *field, + const char *value); +static void __http_header_destroy_all_option(http_header_options_t **head); +static da_bool_t __get_http_header_option_for_field( + http_header_options_t *header_option, const char *in_field, + char **out_value); +static http_header_options_t *__parsing_N_create_option_str(char *org_str); +static http_header_options_t *__parsing_options(char *org_str); +static void __parsing_raw_value(http_header_t *http_header); + +da_ret_t http_msg_request_create(http_msg_request_t **http_msg_request) +{ + http_msg_request_t *temp_http_msg_request = NULL; + +// DA_LOGV(""); + + temp_http_msg_request = (http_msg_request_t *)calloc(1, + sizeof(http_msg_request_t)); + if (!temp_http_msg_request) { + *http_msg_request = NULL; + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + + temp_http_msg_request->http_method = NULL; + temp_http_msg_request->url = NULL; + temp_http_msg_request->head = NULL; + temp_http_msg_request->http_body = NULL; + + *http_msg_request = temp_http_msg_request; + DA_LOGV( "http_msg_request: %x", (unsigned int)(*http_msg_request)); + + return DA_RESULT_OK; +} + +void http_msg_request_destroy(http_msg_request_t **http_msg_request) +{ + http_msg_request_t *temp_http_msg_request = *http_msg_request; + + DA_LOGV(""); + + if (temp_http_msg_request) { + if (temp_http_msg_request->http_method) { + free(temp_http_msg_request->http_method); + temp_http_msg_request->http_method = NULL; + } + if (temp_http_msg_request->url) { + free(temp_http_msg_request->url); + temp_http_msg_request->url = NULL; + } + if (temp_http_msg_request->http_body) { + free(temp_http_msg_request->http_body); + temp_http_msg_request->http_body = NULL; + } + __http_header_destroy_all_field(&(temp_http_msg_request->head)); + free(temp_http_msg_request); + *http_msg_request = NULL; + } +} + +da_ret_t http_msg_request_set_url(http_msg_request_t *http_msg_request, + const char *url) +{ + DA_LOGV(""); + + if (!http_msg_request) { + DA_LOGE("http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + if (!url) { + DA_LOGE("url is NULL; DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_URL; + } + + http_msg_request->url = strdup(url); + DA_SECURE_LOGI("http url[%s]", http_msg_request->url); + return DA_RESULT_OK; +} + +da_ret_t http_msg_request_get_url(http_msg_request_t *http_msg_request, + const char **url) +{ + DA_LOGV(""); + + if (!http_msg_request) { + DA_LOGE("http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + if (http_msg_request->url) { + *url = http_msg_request->url; + return DA_RESULT_OK; + } else { + *url = DA_NULL; + return DA_ERR_INVALID_ARGUMENT; + } +} + +da_ret_t http_msg_request_add_field(http_msg_request_t *http_msg_request, + const char *field, const char *value) +{ + // DA_LOGV(""); + + if (!http_msg_request) { + DA_LOGE("Check NULL! : http_msg_request"); + return DA_ERR_INVALID_ARGUMENT; + } + + return __http_header_add_field(&(http_msg_request->head), field, value, WITHOUT_PARSING_OPTION); +} + +da_ret_t http_msg_response_create(http_msg_response_t **http_msg_response) +{ + http_msg_response_t *temp_http_msg_response = NULL; + + DA_LOGV(""); + + temp_http_msg_response = (http_msg_response_t *)calloc(1, + sizeof(http_msg_response_t)); + if (!temp_http_msg_response) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + return DA_ERR_FAIL_TO_MEMALLOC; + } else { + temp_http_msg_response->status_code = 0; + temp_http_msg_response->head = NULL; + *http_msg_response = temp_http_msg_response; + return DA_RESULT_OK; + } +} + +void http_msg_response_destroy(http_msg_response_t **http_msg_response) +{ + http_msg_response_t *temp_http_msg_response = *http_msg_response; + + DA_LOGV(""); + if (temp_http_msg_response) { + __http_header_destroy_all_field(&(temp_http_msg_response->head)); + free(temp_http_msg_response); + *http_msg_response = DA_NULL; + } +} + +da_ret_t http_msg_response_add_field(http_msg_response_t *http_msg_response, + const char *field, const char *value) +{ + DA_LOGV(""); + + if (!http_msg_response) { + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + return __http_header_add_field(&(http_msg_response->head), field, value, WITH_PARSING_OPTION); +} + +da_ret_t __http_header_add_field(http_header_t **head, + const char *field, const char *value, enum parsing_type type) +{ + http_header_t *pre = NULL; + http_header_t *cur = NULL; + + //DA_SECURE_LOGD("[%s][%s]", field, value); + + pre = cur = *head; + while (cur) { + pre = cur; + /* Replace default value with user wanted value + * Remove the value which is stored before and add a new value. + */ + if (cur->field && cur->raw_value && + strncasecmp(cur->field, field, strlen(field)) == 0) { + DA_SECURE_LOGD("Remove value for replacement [%s][%s]", cur->field, cur->raw_value); + if (cur->field) { + free(cur->field); + cur->field = NULL; + } + if (cur->raw_value) { + free(cur->raw_value); + cur->raw_value= NULL; + } + } + cur = cur->next; + } + + cur = (http_header_t *)calloc(1, sizeof(http_header_t)); + if (cur) { + cur->field = strdup(field); + cur->raw_value = strdup(value); + cur->options = NULL; + cur->next = NULL; + + if (type == WITHOUT_PARSING_OPTION) { + cur->value = strdup(value); + cur->options = NULL; + } else { + __parsing_raw_value(cur); + } + + if (pre) + pre->next = cur; + else + *head = cur; + } else { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + + return DA_RESULT_OK; +} + +void __http_header_destroy_all_field(http_header_t **head) +{ + http_header_t *pre = NULL; + http_header_t *cur = NULL; + + cur = *head; + + while (cur) { + if (cur->field) { + free(cur->field); + cur->field = DA_NULL; + } + if (cur->value) { + free(cur->value); + cur->value = DA_NULL; + } + if (cur->raw_value) { + free(cur->raw_value); + cur->raw_value = DA_NULL; + } + __http_header_destroy_all_option(&(cur->options)); + free(cur->options); + cur->options = DA_NULL; + pre = cur; + cur = cur->next; + free(pre); + } + *head = DA_NULL; +} + +http_header_options_t *__create_http_header_option(const char *field, + const char *value) +{ + http_header_options_t *option = NULL; + + option = (http_header_options_t *)calloc(1, + sizeof(http_header_options_t)); + if (option) { + if (field) + option->field = strdup(field); + if (value) + option->value = strdup(value); + option->next = NULL; + } + return option; +} + +void __http_header_destroy_all_option(http_header_options_t **head) +{ + http_header_options_t *pre = NULL; + http_header_options_t *cur = NULL; + + // DA_LOGV(""); + + cur = *head; + + while (cur) { + if (cur->field) { + DA_SECURE_LOGD("field= %s", cur->field); + free(cur->field); + cur->field = DA_NULL; + } + if (cur->value) { + free(cur->value); + cur->value = DA_NULL; + } + pre = cur; + cur = cur->next; + free(pre); + } + *head = DA_NULL; +} + +da_ret_t http_msg_request_get_iter(http_msg_request_t *http_msg_request, + http_msg_iter_t *http_msg_iter) +{ + DA_LOGV(""); + + if (!http_msg_request) { + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + *http_msg_iter = http_msg_request->head; + + return DA_RESULT_OK; +} + +da_ret_t http_msg_response_get_iter(http_msg_response_t *http_msg_response, + http_msg_iter_t *http_msg_iter) +{ + if (!http_msg_response) { + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + *http_msg_iter = http_msg_response->head; + return DA_RESULT_OK; +} + +da_bool_t http_msg_get_field_with_iter(http_msg_iter_t *http_msg_iter, + char **out_field, char **out_value) +{ + http_header_t *cur = *http_msg_iter; + + if (cur) { + *out_field = cur->field; + *out_value = cur->value; + *http_msg_iter = cur->next; + return DA_TRUE; + } else { + return DA_FALSE; + } +} + +da_bool_t http_msg_get_header_with_iter(http_msg_iter_t *http_msg_iter, + char **out_field, http_header_t **out_header) +{ + http_header_t *cur = *http_msg_iter; + + if (cur) { + *out_field = cur->field; + *out_header = cur; + *http_msg_iter = cur->next; + return DA_TRUE; + } else { + return DA_FALSE; + } +} + +http_header_options_t *__parsing_N_create_option_str(char *org_str) +{ + char *option_field = NULL; + char *option_value = NULL; + int option_field_len = 0; + int option_value_len = 0; + char *org_pos = NULL; + int org_str_len = 0; + char *working_str = NULL; + char *working_pos = NULL; + char *working_pos_field_start = NULL; + char *working_pos_value_start = NULL; + da_bool_t is_inside_quotation = DA_FALSE; + da_bool_t is_working_for_field = DA_TRUE; + int i = 0; + http_header_options_t *option = NULL; + + // DA_LOGV(""); + + if (!org_str) + return NULL; + + org_str_len = strlen(org_str); + if (org_str_len <= 0) + return NULL; + + working_str = (char *)calloc(1, org_str_len + 1); + if (!working_str) + return NULL; + + org_pos = org_str; + working_pos_field_start = working_pos = working_str; + + for (i = 0; i < org_str_len; i++) { + if (*org_pos == '"') + is_inside_quotation = !is_inside_quotation; + if (is_inside_quotation) { + // Leave anything including blank if it is inside of double quotation mark. + *working_pos = *org_pos; + is_working_for_field ? option_field_len++ + : option_value_len++; + working_pos++; + org_pos++; + } else { + if (*org_pos == ' ') { + org_pos++; + } else if (*org_pos == '=') { + if (is_working_for_field) { + is_working_for_field = DA_FALSE; + working_pos_value_start = working_pos; + } + org_pos++; + } else { + *working_pos = *org_pos; + is_working_for_field ? option_field_len++ + : option_value_len++; + working_pos++; + org_pos++; + } + } + } + + if (option_field_len > 0 && working_pos_field_start) { + option_field = (char *)calloc(1, option_field_len + 1); + if (option_field) + strncpy(option_field, working_pos_field_start, + option_field_len); + } + if (option_value_len > 0 && working_pos_value_start) { + option_value = (char *)calloc(1, option_value_len + 1); + if (option_value) + strncpy(option_value, working_pos_value_start, + option_value_len); + } + if (working_str) { + free(working_str); + working_pos = working_str = NULL; + } + + DA_SECURE_LOGD("option_field = [%s], option_value = [%s]", + option_field, option_value); + + if (option_field || option_value) { + option = __create_http_header_option( + option_field, option_value); + if (option_field) { + free(option_field); + option_field = NULL; + } + if (option_value) { + free(option_value); + option_value = NULL; + } + } + return option; +} + +http_header_options_t *__parsing_options(char *org_str) +{ + da_ret_t ret = DA_RESULT_OK; + http_header_options_t *head = NULL; + http_header_options_t *pre = NULL; + http_header_options_t *cur = NULL; + + int wanted_str_len = 0; + char *wanted_str = NULL; + char *wanted_str_start = NULL; + char *wanted_str_end = NULL; + char *cur_pos = NULL; + + DA_LOGV(""); + + if (!org_str) + return NULL; + + /* Do Not use strtok(). It's not thread safe. */ + // DA_SECURE_LOGD("org_str = %s", org_str); + + cur_pos = org_str; + + while (cur_pos) { + wanted_str_start = cur_pos; + wanted_str_end = strchr(cur_pos, ';'); + if (wanted_str_end) { + cur_pos = wanted_str_end + 1; + } else { + wanted_str_end = org_str + strlen(org_str); + cur_pos = NULL; + } + wanted_str_len = wanted_str_end - wanted_str_start; + wanted_str = (char *)calloc(1, wanted_str_len + 1); + if (!wanted_str) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + strncpy(wanted_str, wanted_str_start, wanted_str_len); + + // DA_SECURE_LOGD("wanted_str = [%s]", wanted_str); + cur = __parsing_N_create_option_str(wanted_str); + if (pre) { + pre->next = cur; + pre = cur; + } else { + head = pre = cur; + } + + free(wanted_str); + wanted_str = NULL; + } + +ERR: + if (ret != DA_RESULT_OK) + __http_header_destroy_all_option(&head); + return head; +} + +void __parsing_raw_value(http_header_t *http_header_field) +{ + char *raw_value = NULL; + char *option_str_start = NULL; + char *trimed_value = NULL; + int trimed_value_len = 0; + char *trimed_value_start = NULL; + char *trimed_value_end = NULL; + + raw_value = http_header_field->raw_value; + // DA_SECURE_LOGD("raw_value = [%s]", raw_value); + + if (!raw_value) + return; + + trimed_value_start = raw_value; + trimed_value_end = strchr(raw_value, ';'); + if (!trimed_value_end) { + // No options + http_header_field->value = strdup(raw_value); + http_header_field->options = NULL; + + return; + } + + // for trimed value + trimed_value_len = trimed_value_end - trimed_value_start; + trimed_value = (char *)calloc(1, trimed_value_len + 1); + if (!trimed_value) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + return; + } + strncpy(trimed_value, trimed_value_start, trimed_value_len); + http_header_field->value = trimed_value; + + // for option parsing + option_str_start = trimed_value_end + 1; + http_header_field->options = __parsing_options(option_str_start); + + /////////////// show + http_header_options_t *cur = NULL; + cur = http_header_field->options; + while (cur) { +// DA_SECURE_LOGD("field = [%s], value = [%s]", cur->field, cur->value); + cur = cur->next; + } +} + +da_bool_t __get_http_header_option_for_field( + http_header_options_t *header_option, const char *in_field, + char **out_value) +{ + http_header_options_t *cur = NULL; + + // DA_LOGV(""); + + if (!header_option) { + DA_LOGE("input header_option is NULL."); + return DA_FALSE; + } + + cur = header_option; + while (cur) { + if (cur->field) { + if (!strncasecmp(cur->field, in_field, strlen(cur->field)) && + cur->value) { + DA_SECURE_LOGD("[%s][%s]", cur->field, cur->value); + *out_value = cur->value; + return DA_TRUE; + } + + } + cur = cur->next; + } + return DA_FALSE; +} + +da_bool_t __get_http_header_for_field(http_msg_response_t *http_msg_response, + const char *in_field, http_header_t **out_header) +{ + http_msg_iter_t http_msg_iter; + http_header_t *header = NULL; + char *field = NULL; + + //DA_LOGV(""); + + http_msg_response_get_iter(http_msg_response, &http_msg_iter); + while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) { + if (field && header && !strncasecmp(field, in_field, strlen(field))) { + //DA_SECURE_LOGD("[%s][%s]", field, header->value); + *out_header = header; + return DA_TRUE; + } + } + + return DA_FALSE; +} + +da_bool_t __get_http_req_header_for_field(http_msg_request_t *http_msg_request, + const char *in_field, http_header_t **out_header) +{ + http_msg_iter_t http_msg_iter; + http_header_t *header = NULL; + char *field = NULL; + + //DA_LOGV(""); + + http_msg_request_get_iter(http_msg_request, &http_msg_iter); + while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) { + if (field && header && !strncasecmp(field, in_field, strlen(field))) { + //DA_SECURE_LOGD("[%s][%s]", field, header->value); + *out_header = header; + return DA_TRUE; + } + } + + return DA_FALSE; +} + +void __exchange_header_value(http_header_t *header, const char *in_raw_value) +{ + DA_LOGV(""); + + if (!header || !in_raw_value) + return; + + __http_header_destroy_all_option(&(header->options)); + + if (header->value) { + free(header->value); + header->value = DA_NULL; + } + if (header->raw_value) + free(header->raw_value); + header->raw_value = strdup(in_raw_value); + + __parsing_raw_value(header); +} + +da_bool_t http_msg_response_get_content_type( + http_msg_response_t *http_msg_response, char **out_type) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_CONTENT_TYPE, &header); + if (!b_ret) { + DA_LOGV("no Content-Type"); + return DA_FALSE; + } + if (out_type) + *out_type = strdup(header->value); + + return DA_TRUE; +} + +void http_msg_response_set_content_type(http_msg_response_t *http_msg_response, + const char *in_type) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + if (!http_msg_response || !in_type) + return; + + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_CONTENT_TYPE, &header); + if (b_ret) { + if (header->raw_value && (!strncmp(header->raw_value, in_type, + strlen(header->raw_value)))) + return; + + DA_SECURE_LOGD("exchange Content-Type to [%s] from [%s]", in_type, header->value); + __exchange_header_value(header, in_type); + } else { + __http_header_add_field(&(http_msg_response->head), + HTTP_FIELD_CONTENT_TYPE, in_type, WITH_PARSING_OPTION); + } +} + +da_bool_t http_msg_response_get_content_length( + http_msg_response_t *http_msg_response, da_size_t *out_length) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_CONTENT_LENGTH, &header); + if (!b_ret) { + DA_LOGV( "no Content-Length"); + return DA_FALSE; + } + + if (out_length) + *out_length = atoll(header->value); + + return DA_TRUE; +} + +da_bool_t http_msg_response_get_content_disposition( + http_msg_response_t *http_msg_response, char **out_disposition, + char **out_file_name) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + char *file_name = NULL; + char *wanted_str = NULL; + char *wanted_str_start = NULL; + char *wanted_str_end = NULL; + char *decoded_str = NULL; + int wanted_str_len = 0; + + DA_LOGV(""); + + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_CONTENT_DISPOSITION, &header); + if (!b_ret) { + DA_LOGV( "no Content-Disposition"); + return DA_FALSE; + } + if (out_disposition) + *out_disposition = strdup(header->value); + if (!out_file_name) + return DA_FALSE; + + b_ret = __get_http_header_option_for_field(header->options, "filename", + &file_name); + if (!b_ret) { + DA_LOGV( "no option"); + return DA_FALSE; + } + + // eliminate double quotation mark if it exists on derived value + wanted_str_start = strchr(file_name, '"'); + if (!wanted_str_start) { + *out_file_name = strdup(file_name); + return DA_TRUE; + } else { + // DA_SECURE_LOGD("wanted_str_start = [%s]", wanted_str_start); + wanted_str_start++; + wanted_str_end = strchr(wanted_str_start, '"'); + if (wanted_str_end) { + wanted_str_len = wanted_str_end - wanted_str_start; + wanted_str = (char*)calloc(1, wanted_str_len + 1); + if (!wanted_str) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + return DA_FALSE; + } + strncpy(wanted_str, wanted_str_start, wanted_str_len); + + b_ret = is_base64_encoded_word(wanted_str); + if (b_ret) { + DA_LOGV("It's base64 encoded-word string"); + if (DA_RESULT_OK == decode_base64_encoded_str( + wanted_str, &decoded_str)) { + DA_SECURE_LOGD("base64 decoded str = [%s]", decoded_str); + free(wanted_str); + wanted_str = decoded_str; + decoded_str = NULL; + } else { + DA_LOGV("Fail to base64 decode. Just use un-decoded string."); + } + } else { + DA_LOGV("It's NOT base64 encoded-word string"); + } + decode_url_encoded_str(wanted_str, &decoded_str); + /* If it is url encoded string */ + if (decoded_str) { + DA_SECURE_LOGD("Url decoded str = [%s]", decoded_str); + free(wanted_str); + wanted_str = decoded_str; + decoded_str = NULL; + } + *out_file_name = wanted_str; + DA_SECURE_LOGI("out_file_name = [%s]", *out_file_name); + return DA_TRUE; + } else { + DA_LOGE("Not matched \" !"); + return DA_FALSE; + } + } +} + +da_bool_t http_msg_response_get_ETag(http_msg_response_t *http_msg_response, + char **out_value) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_ETAG, + &header); + if (!b_ret) { + DA_LOGV( "no ETag"); + return DA_FALSE; + } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; +} + +#ifdef _RAF_SUPPORT +da_bool_t http_msg_response_get_RAF_mode(http_msg_response_t *http_msg_response, + char **out_value) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_RAF_MODE, + &header); + if (!b_ret) { + DA_LOGV( "no RAF mode"); + return DA_FALSE; + } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; +} +#endif + +da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response, + char **out_value) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_DATA, &header); + if (!b_ret) { + DA_LOGV( "no Date"); + return DA_FALSE; + } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; +} + +da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response, + char **out_value) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_LOCATION, &header); + if (!b_ret) { + DA_LOGV( "no Location"); + return DA_FALSE; + } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; +} + +char *__stristr(const char *long_str, const char *find_str) +{ + int i = 0; + int length_long = 0; + int length_find = 0; + char *ret_ptr = NULL; + char *org_ptr = NULL; + char *look_ptr = NULL; + + if (long_str == NULL || find_str == NULL) { + DA_LOGE("INVALID ARGUMENT"); + return NULL; + } + + length_long = strlen(long_str); + length_find = strlen(find_str); + + org_ptr = (char*)calloc(1, length_long + 1); + + if (org_ptr == NULL) { + DA_LOGE("INVALID ARGUMENT"); + return NULL; + } + + look_ptr = (char*)calloc(1, length_find + 1); + + if (look_ptr == NULL) { + DA_LOGE("INVALID ARGUMENT"); + free(org_ptr); + return NULL; + } + + while (i < length_long) { + if (isalpha(long_str[i]) != 0) { + if (isupper(long_str[i]) != 0) { + org_ptr[i] = long_str[i]; + } else { + org_ptr[i] = toupper(long_str[i]); + } + } else { + org_ptr[i] = long_str[i]; + } + i++; + } + + i = 0; + + while (i < length_find) { + if (isalpha(find_str[i]) != 0) { + if (isupper(find_str[i]) != 0) { + look_ptr[i] = find_str[i]; + } else { + look_ptr[i] = toupper(find_str[i]); + } + } else { + look_ptr[i] = find_str[i]; + } + i++; + } + + ret_ptr = strstr(org_ptr, look_ptr); + + if (ret_ptr == 0) { + free(org_ptr); + free(look_ptr); + return NULL; + } else { + i = ret_ptr - org_ptr; + } + + free(org_ptr); + free(look_ptr); + + return (char*)(long_str + i); +} + +/* This is not used. But it can be needed if there is no http header parser at http library.*/ +da_bool_t extract_attribute_from_header( + char *szHeadStr, + const char *szFindStr, + char **ppRtnValue) +{ + char *pValuePos = NULL; + int index = 0; + int startPos = 0; + int strLen = 0; + int need_to_end_quataion_mark = 0; + + if (szHeadStr == DA_NULL || szFindStr == DA_NULL) { + DA_LOGE("INVALID ARGUMENT"); + return DA_FALSE; + } + if (strlen(szHeadStr) <= 0 || strlen(szFindStr) <= 0) { + DA_LOGE("INVALID ARGUMENT");; + + return DA_FALSE; + } + if (ppRtnValue == NULL) { + return DA_FALSE; + } + + pValuePos = __stristr(szHeadStr, (char*)szFindStr); + if (pValuePos == NULL) { + *ppRtnValue = NULL; + goto ERR; + } + + index = strlen(szFindStr); + + while (pValuePos[index] != ':' && pValuePos[index] != '=') { + index++; + + if (pValuePos[index] == '\0') { + return DA_FALSE; + } + } + + index++; + + /* jump space */ + while (pValuePos[index] == ' ') { + index++; + } + + /* jump quatation mark */ + while (pValuePos[index] == '"') { + need_to_end_quataion_mark = 1; + index++; + } + + startPos = index; + + /* Find the end of data. */ + if (0 == strncasecmp(szFindStr, HTTP_FIELD_LOCATION, + strlen(HTTP_FIELD_LOCATION)))//terminate character list does not contain ';' in case of URI + { + while (DA_FALSE == IS_URI_TERMINATING_CHAR(pValuePos[index])) { + index++; + } + } else if (need_to_end_quataion_mark) { + while (DA_FALSE == IS_TERMINATING_CHAR_EX(pValuePos[index])) { + index++; + } + } else { + while (DA_FALSE == IS_TERMINATING_CHAR(pValuePos[index])) { + index++; + } + } + + strLen = index - startPos; + + if (strLen < 1) { + DA_LOGE(" strLen is < 1"); + goto ERR; + } + + *ppRtnValue = (char*)calloc(1, sizeof(char) * (strLen + 1)); + + if (*ppRtnValue == NULL) { + DA_LOGE(" *ppRtnValue is NULL"); + goto ERR; + } + + strncpy(*ppRtnValue, pValuePos + startPos, strLen); + *(*ppRtnValue + strLen) = '\0'; + + return DA_TRUE; +ERR: + if (*ppRtnValue) { + free(*ppRtnValue); + *ppRtnValue = NULL; + } + return DA_FALSE; +} + +da_bool_t http_msg_request_get_if_range(http_msg_request_t *http_msg_request, + char **out_value) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_IF_RANGE, + &header); + if (!b_ret) { + DA_LOGV( "no If Range"); + return DA_FALSE; + } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; +} + +da_bool_t http_msg_request_get_range(http_msg_request_t *http_msg_request, + char **out_value) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_RANGE, + &header); + if (!b_ret) { + DA_LOGV( "no Range"); + return DA_FALSE; + } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; +} diff --git a/agent/download-agent-interface.c b/agent/download-agent-interface.c new file mode 100755 index 0000000..0b19813 --- /dev/null +++ b/agent/download-agent-interface.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2012 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 "download-agent-interface.h" +#include "download-agent-dl-mgr.h" + +int da_init() +{ + DA_LOGV(""); + da_ret_t ret = DA_RESULT_OK; + DA_LOGI("Return ret = %d", ret); + return ret; +} + +int da_deinit() +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + destroy_da_info_list(); + DA_LOGI("====== da_deint EXIT ====="); + return ret; +} + +int da_start_download(const char *url, req_data_t *ext_data, + da_cb_t *da_cb_data, int *download_id) +{ + da_ret_t ret = DA_RESULT_OK; + int req_header_count = 0; + int i = 0; + int da_id = DA_INVALID_ID; + da_info_t *da_info = DA_NULL; + + *download_id = DA_INVALID_ID; + + if (ext_data->request_header_count > 0) { + DA_LOGI("request_header_count[%d]", ext_data->request_header_count); + for (i = 0; i < ext_data->request_header_count; i++) { + if (ext_data->request_header[i]) { + req_header_count++; + DA_SECURE_LOGI("request_header[%s]", ext_data->request_header[i]); + } + } + DA_LOGI("actual request_header_count[%d]", req_header_count); + if (ext_data->request_header_count != req_header_count) { + DA_LOGE("Request header count is not matched with number of request header array"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + } + + if (ext_data->install_path) + DA_SECURE_LOGI("install path[%s]", ext_data->install_path); + if (ext_data->file_name) + DA_SECURE_LOGI("file_name[%s]", ext_data->file_name); + if (ext_data->temp_file_path) + DA_SECURE_LOGI("temp_file_path[%s]", ext_data->temp_file_path); + if (ext_data->etag) + DA_SECURE_LOGI("etag[%s]", ext_data->etag); + if (ext_data->pkg_name) + DA_SECURE_LOGI("pkg_name[%s]", ext_data->pkg_name); + if (ext_data->network_bonding) + DA_LOGD("network bonding option[%d]", ext_data->network_bonding); + if (ext_data->user_req_data) + DA_LOGI("user_req_data[%p]", ext_data->user_req_data); + if (ext_data->user_client_data) + DA_LOGI("user_client_data[%p]", ext_data->user_client_data); + + ret = get_available_da_id(&da_id); + if (ret != DA_RESULT_OK) + goto ERR; + + da_info = da_info_list[da_id]; + da_info->da_id = da_id; + + ret = copy_user_input_data(da_info, url, ext_data, da_cb_data); + if (ret != DA_RESULT_OK) + goto ERR; + *download_id = da_id; + ret = start_download(da_info); +ERR: + DA_LOGI("Return:id[%d],ret[%d]", *download_id, ret); + return ret; +} + +int da_cancel_download(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV("download_id[%d]", download_id); + ret = cancel_download(download_id, DA_TRUE); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} + +int da_cancel_download_without_update(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + DA_LOGV("download_id[%d]", download_id); + ret = cancel_download(download_id, DA_FALSE); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} + +int da_suspend_download(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + DA_LOGV("download_id[%d]", download_id); + ret = suspend_download(download_id, DA_TRUE); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} + +int da_suspend_download_without_update(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + DA_LOGV("download_id[%d]", download_id); + ret = suspend_download(download_id, DA_FALSE); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} + + +int da_resume_download(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + DA_LOGV("download_id[%d]", download_id); + ret = resume_download(download_id); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} + +int da_is_valid_download_id(int download_id) +{ + da_bool_t ret = DA_FALSE; + ret = is_valid_download_id(download_id); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} diff --git a/agent/download-agent-mime-util.c b/agent/download-agent-mime-util.c new file mode 100755 index 0000000..71e08eb --- /dev/null +++ b/agent/download-agent-mime-util.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2012 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 <string.h> +#include <stdlib.h> + +#include <xdgmime.h> + +#include "download-agent-debug.h" +#include "download-agent-mime-util.h" +#include "download-agent-pthread.h" + +#define IS_PROHIBITED_CHAR(c) ((c) == ';' || (c) == '\\' || (c) == '/' || (c) == ':' || (c) == '*' || (c) == '?' || (c) == '"' || (c) == '>' || (c) == '<' || (c) == '|' || (c) == '(' || (c) == ')') +#define IS_SPACE_CHARACTER(c) ((c) == '\t') + +#define MAX_EXT_TABLE_INDEX 16 +Ext_translation_table ext_trans_table [MAX_EXT_TABLE_INDEX] = { + {"*.xla", "*.xls"}, + {"*.pot", "*.ppt"}, + {"*.xsl", "*.xml"}, + {"*.spl", "*.swf"}, + {"*.oga", "*.ogg"}, + {"*.jpe", "*.jpg"},//5 + {"*.CSSL", "*.css"}, + {"*.htm", "*.html"}, + {"*.hxx", "*.hpp"}, + {"*.c++", "*.cpp"}, + {"CMakeLists.txt", "*.cmake"},//10 + {"*.ime", "*.imy"}, + {"Makefile", "makefile"}, + {"*.3g2", "*.3gp"}, + {"*.mp2", "*.mpg"}, + {"*.divx", "*.avi"},//15 + }; +/* This is samsung mime policy + * 1. if the mime is audio/m4a, the extension name is defined as "m4a" for launching music player +*/ +#ifdef _SAMSUNG_MIME_POLICY +#define MAX_SEC_MIME_TABLE_INDEX 1 +struct sec_mime_table_t { + char *mime; + char *ext; +}; +struct sec_mime_table_t sec_mime_table [MAX_SEC_MIME_TABLE_INDEX] = { + {"audio/m4a", "m4a"}, +}; +#endif + +const char *ambiguous_MIME_Type_list[] = { + "text/plain", + "application/octet-stream" +}; + +/* Because xdgmime is not thread safety, this mutex is necessary */ +pthread_mutex_t mutex_for_xdgmime = PTHREAD_MUTEX_INITIALIZER; + +da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type) +{ + if (!in_mime_type) + return DA_FALSE; + + int index = 0; + int list_size = sizeof(ambiguous_MIME_Type_list) / sizeof(const char *); + for (index = 0 ; index < list_size ; index++) { + if (0 == strncmp(in_mime_type, ambiguous_MIME_Type_list[index], + strlen(ambiguous_MIME_Type_list[index]))) { + //DA_SECURE_LOGD("It is ambiguous! [%s]", ambiguous_MIME_Type_list[index]); + return DA_TRUE; + } + } + + return DA_FALSE; +} + +da_ret_t da_mime_get_ext_name(char *mime, char **ext) +{ + da_ret_t ret = DA_RESULT_OK; + const char **extlist = DA_NULL; + const char *unaliased_mimetype = DA_NULL; + char ext_temp[DA_MAX_STR_LEN] = {0,}; + char *temp = NULL; + + DA_LOGV(""); + + if (DA_NULL == mime || DA_NULL == ext) { + ret = DA_ERR_INVALID_ARGUMENT; + DA_LOGE("Invalid mime type"); + goto ERR; + } +// DA_SECURE_LOGD("mime str[%s]ptr[%p]len[%d]",mime,mime,strlen(mime)); + /* unaliased_mimetype means representative mime among similar types */ + DA_MUTEX_LOCK(&mutex_for_xdgmime); + unaliased_mimetype = xdg_mime_unalias_mime_type(mime); + + if (unaliased_mimetype == DA_NULL) { + ret = DA_ERR_INVALID_MIME_TYPE; + DA_LOGI("Invalid mime type : No unsaliased mime type"); + DA_MUTEX_UNLOCK(&mutex_for_xdgmime); + goto ERR; + } + DA_SECURE_LOGD("unaliased_mimetype[%s]\n",unaliased_mimetype); + + /* Get extension name from shared-mime-info */ + extlist = xdg_mime_get_file_names_from_mime_type(unaliased_mimetype); + DA_MUTEX_UNLOCK(&mutex_for_xdgmime); + if (extlist == DA_NULL || *extlist == DA_NULL) { + int i = 0; + ret = DA_ERR_INVALID_MIME_TYPE; + DA_LOGV("No extension list"); +#ifdef _SAMSUNG_MIME_POLICY + for (i = 0; i < MAX_SEC_MIME_TABLE_INDEX; i++) + { + if (strncmp(sec_mime_table[i].mime, mime, strlen(mime)) == 0) { + strncpy(ext_temp, sec_mime_table[i].ext, DA_MAX_STR_LEN-1); + ret = DA_RESULT_OK; + break; + } + } +#endif + } else { /* For drm case, this else statement is needed */ +// DA_LOGD("extlist[%s]\n",*extlist); + strncpy(ext_temp, *extlist, DA_MAX_STR_LEN - 1); + /* If only one extension name is existed, don't enter here */ + while (*extlist != NULL) { + int i = 0; + /* If there are existed many extension names, + * try to search common extension name from table + * with first mime type at extension list*/ + for (i = 0; i < MAX_EXT_TABLE_INDEX; i++) + { + if (strncmp(ext_trans_table[i].standard,*extlist, + strlen(*extlist)) == 0) { + memset(ext_temp, 0x00, DA_MAX_STR_LEN); + strncpy(ext_temp,ext_trans_table[i].normal, DA_MAX_STR_LEN-1); + break; + } + } + DA_LOGV("index[%d]\n",i); + /* If there is a mime at extension transform table */ + if (i < MAX_EXT_TABLE_INDEX) { + break; + } +// DA_LOGD("extlist[%s]\n",*extlist); + extlist++; + } +// DA_SECURE_LOGD("extension from shared mime info[%s]",ext_temp); + } + + if (strlen(ext_temp) < 1) { + /* If there is no mime string for OMA descriptor mime type */ + if (strncmp(DD_MIME_STR, mime, strlen(DD_MIME_STR)) == 0) { + strncpy(ext_temp, DD_EXT_STR, DA_MAX_STR_LEN - 1); + ret = DA_RESULT_OK; + /* If there is no extension name for "applicaion/vnd.oma.drm.messeages" + * at shared-mime-info*/ + } else if (strncmp(DRM_MIME_MSG_STR, mime, strlen(DRM_MIME_MSG_STR)) == + 0) { + strncpy(ext_temp, DRM_EXT_STR, DA_MAX_STR_LEN - 1); + /* If there is extension name at extlist, the return value can have an error.*/ + ret = DA_RESULT_OK; + } else { + ret = DA_ERR_INVALID_MIME_TYPE; + DA_LOGI("Invalid mime type : no extension name at list"); + } + } + if (ret != DA_RESULT_OK) + goto ERR; + + temp = strchr(ext_temp,'.'); + if (temp == NULL) + temp = ext_temp; + else + temp++; + + DA_SECURE_LOGD("final extension name:[%s]",temp); + *ext = (char*)calloc(1, strlen(temp) + 1); + if (*ext != DA_NULL) { + strncpy(*ext, temp,strlen(temp)); + } else { + ret = DA_ERR_FAIL_TO_MEMALLOC ; + goto ERR ; + } +ERR: + return ret; +} + +da_bool_t da_get_extension_name_from_url(char *url, char **ext) +{ + da_bool_t ret = DA_TRUE; + char *buff = DA_NULL; + char *temp_str = DA_NULL; + int buf_len = 0; + + DA_LOGV(""); + + if (DA_NULL == url || DA_NULL == ext) { + ret = DA_FALSE; + DA_LOGE("Invalid Argument"); + return ret; + } + + if ((temp_str = strrchr(url,'/'))) { + if ((buff = strrchr(temp_str,'.'))) { + char *q = DA_NULL; + buff++; + /* check to exist "?" after extension name */ + q = strrchr(buff,'?'); + if (q) { + buf_len = strlen(buff) - strlen(q); + } else { + buf_len = strlen(buff); + } + *ext = (char*) calloc(1, buf_len + 1) ; + + if (DA_NULL == *ext) { + ret = DA_FALSE; + DA_LOGE("Memory Fail"); + goto ERR; + } + strncpy(*ext,buff,buf_len); + DA_SECURE_LOGD("extention name[%s]",*ext); + return ret; + } + } +ERR: + if (*ext) { + free(*ext); + *ext = DA_NULL; + } + return ret; +} + +/* FIXME move this function to another file */ +da_bool_t da_get_file_name_from_url(char *url, char **name) +{ + da_bool_t ret = DA_TRUE; + char *buff = DA_NULL; + char *Start = NULL; + char *End = NULL; + char c = 0; + int i = 0; + int j = 0; + int len_name = 0; + char name_buff[DA_MAX_FILE_PATH_LEN] = {0,}; + + DA_LOGV(""); + + if (DA_NULL == url || DA_NULL == name) { + ret = DA_FALSE; + DA_LOGE("Invalid Argument"); + goto ERR; + } + + if (!strstr(url, "http") && !strstr(url, "https")) { + ret = DA_FALSE; + DA_LOGE("Invalid Argument"); + goto ERR; + } + + buff = (char*) calloc(1, strlen(url) +1); + if(DA_NULL == buff) { + ret = DA_FALSE; + DA_LOGE("Memory Fail"); + goto ERR; + } + + while((c = url[i++]) != 0) { + if(c == '%') { + char buffer[3] = {0,}; + buffer[0] = url[i++]; + buffer[1] = url[i++]; + buff[j++] = (char)strtol(buffer,NULL,16); + } else { + buff[j++] = c; + } + } + End = strstr(buff, "?"); + if (DA_NULL != End) { + Start = End -1; + while(*(Start) != '/') { + Start--; + } + if ((*(Start) == '/') && ((len_name = (End - Start)) > 1)) { + Start++; + if (DA_MAX_FILE_PATH_LEN <= len_name) { + strncpy(name_buff, Start, DA_MAX_FILE_PATH_LEN-1); + name_buff[DA_MAX_FILE_PATH_LEN-1] = '\0'; + } else { + strncpy(name_buff, Start, len_name); + name_buff[len_name] = '\0'; + } + } else { + ret = DA_FALSE; + goto ERR ; /*Name not found*/ + } + } else { + int urlLen = strlen (buff); + int Start_pos = 0; + Start_pos = urlLen - 1; + + while(Start_pos > 0) { + if(buff[Start_pos] == '/') + break; + Start_pos--; + } + Start_pos++; + if (Start_pos == 0 || urlLen - Start_pos <= 0) { + ret = DA_FALSE; + goto ERR; + } + while(Start_pos < urlLen) { + name_buff[len_name++] = buff[Start_pos++]; + if (DA_MAX_FILE_PATH_LEN <= len_name) { + name_buff[DA_MAX_FILE_PATH_LEN-1] ='\0'; + break; + } + } + } + + if (len_name) { + End = strrchr(name_buff, '.'); + if (End != NULL) { + *End = '\0'; + } +// DA_SECURE_LOGD("file name BEFORE removing prohibited character = %s", name_buff); + delete_prohibited_char(name_buff, strlen(name_buff)); + len_name = strlen(name_buff); + *name = (char*) calloc(1, len_name + 1); + if (*name) { + strncpy(*name, name_buff,len_name); + } + } +// DA_SECURE_LOGD("Extracted file name : %s", *name); +ERR: + if (buff) { + free (buff); + buff = DA_NULL; + } + return ret; +} + +void delete_prohibited_char(char *szTarget, int str_len) +{ + char *chk_str = NULL; + int i = 0; + int j = 0; + int tar_len = 0; + + if(szTarget == NULL || str_len <= 0 || strlen(szTarget) != str_len) { + DA_LOGE("Invaild Parameter\n"); + return; + } + + chk_str = (char *)calloc(1, str_len + 1); + if(chk_str == NULL) + return; + + while(szTarget[j] != '\0') { + if(IS_PROHIBITED_CHAR(szTarget[j]) == DA_FALSE && + IS_SPACE_CHARACTER(szTarget[j]) == DA_FALSE) { + chk_str[i] = szTarget[j]; + i++; + } + j++; + } + + chk_str[i] = '\0'; + tar_len = strlen(chk_str); + + if(tar_len <= 0) + szTarget[0] = '\0'; + else { + for(i = 0; i < tar_len; i++) + { + szTarget[i] = chk_str[i]; + } + szTarget[i] = '\0'; + } + + if(chk_str != NULL) { + free(chk_str); + } + return; +} + +#ifdef _ENABLE_OMA_DRM +da_bool_t is_content_drm_dcf(char *content_type) +{ + if (content_type == DA_NULL) + return DA_FALSE; + + if (0 == strcmp(content_type, DRM_MIME_CONTENT_STR)) { + DA_LOGV("DRM_DM content"); + return DA_TRUE; + } else { + return DA_FALSE; + } +} + +da_bool_t is_content_drm_dm(char *content_type) +{ + if (content_type == DA_NULL) + return DA_FALSE; + + if (0 == strcmp(content_type, DRM_MIME_MSG_STR)) { + DA_LOGV("DRM_DM content"); + return DA_TRUE; + } else { + return DA_FALSE; + } +} +#endif + +da_ret_t get_extension_from_mime_type(char *mime_type, char **extension) +{ + da_ret_t ret = DA_RESULT_OK; + char *ext = DA_NULL; + + DA_LOGV(""); + if (DA_NULL == mime_type || DA_NULL == extension) { + DA_LOGE("received mime_type is null"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } +// DA_SECURE_LOGD("input mime type = %s", mime_type); + if (DA_RESULT_OK != (ret = da_mime_get_ext_name(mime_type, &ext))) { + DA_LOGE("can't find proper extension!"); + goto ERR; + } + *extension = ext; +// DA_SECURE_LOGD("found extension = %s", *extension); + +ERR: + return ret; +} + diff --git a/agent/download-agent-plugin-conf.c b/agent/download-agent-plugin-conf.c new file mode 100755 index 0000000..6cb76cb --- /dev/null +++ b/agent/download-agent-plugin-conf.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012 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 <string.h> +#include <stdlib.h> +#include <glib-object.h> +#include "vconf.h" +#include "vconf-keys.h" +#include "net_connection.h" + +#include "download-agent-plugin-conf.h" +#include "download-agent-debug.h" +#include "download-agent-file.h" + +#define DEFAULT_UA_STR "Mozilla/5.0 (Linux; U; Tizen 1.0; en-us) AppleWebKit/534.46 (KHTML, like Gecko) Mobile Tizen Browser/1.0" + +da_ret_t __get_conf_string(const char *key, char **out_string) +{ + if (!key || !out_string) { + DA_LOGE("Invalid Argument"); + return DA_ERR_INVALID_ARGUMENT; + } + + *out_string = vconf_get_str(key); + return DA_RESULT_OK; +} + +da_ret_t get_user_agent_string(char **uagent_str) +{ + da_ret_t ret = DA_RESULT_OK; + char *key = DA_NULL; + + DA_LOGV(""); + + if (!uagent_str) { + DA_LOGE("Invalid Argument"); + return DA_ERR_INVALID_ARGUMENT; + } + + key = VCONFKEY_BROWSER_USER_AGENT; + ret = __get_conf_string(key, uagent_str); + if(ret == DA_RESULT_OK) { + if(*uagent_str) { +// DA_SECURE_LOGD("getting uagent_str = \n%s", *uagent_str); + return ret; + } + } + DA_LOGI("No UA information from vconf !!"); + *uagent_str = strdup(DEFAULT_UA_STR); + DA_LOGV("Set default UA"); + return ret; +} + +char *get_proxy_address(void) +{ + char *proxy = NULL; + char *proxyRet = NULL; + connection_h handle = NULL; + connection_address_family_e family = CONNECTION_ADDRESS_FAMILY_IPV4; + + DA_LOGV(""); + if (connection_create(&handle) < 0) { + DA_LOGE("Fail to create connection handle"); + return NULL; + } + + if (connection_get_proxy(handle, family, &proxyRet) < 0) { + DA_LOGE("Fail to get proxy address"); + connection_destroy(handle); + return NULL; + } + + if (proxyRet) { + DA_SECURE_LOGD("===== Proxy address[%s] =====", proxyRet); + proxy = strdup(proxyRet); + free(proxyRet); + proxyRet = NULL; + connection_destroy(handle); + return proxy; + } + + if (connection_destroy(handle) < 0) { + DA_LOGE("Fail to desctory connection handle"); + return NULL; + } + return NULL; +} +#ifdef _RAF_SUPPORT +// test code +void get_smart_bonding_vconf() +{ + int ret = 0; + vconf_get_int("file/private/wifi/network_bonding", &ret); + DA_LOGI("Smart Bonding Vconf:%d", ret); +} +#endif diff --git a/agent/download-agent-plugin-drm.c b/agent/download-agent-plugin-drm.c new file mode 100644 index 0000000..22e6f34 --- /dev/null +++ b/agent/download-agent-plugin-drm.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2012 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 <string.h> + +#include "drm_client.h" +#include "drm_client_types.h" +#include "drm_trusted_client.h" +#include "drm_trusted_client_types.h" + +#include "download-agent-debug.h" +#include "download-agent-plugin-drm.h" + + +void __EDRM_clean_up() +{ + int ret = 0; + ret = drm_trusted_handle_request(DRM_TRUSTED_REQ_TYPE_CLIENT_CLEAN_UP, NULL, NULL); + if (DRM_RETURN_SUCCESS == ret) { + DA_LOGD( "Clean up successfull"); + } else { + DA_LOGE("ret[%0x%x]",ret); + } +} + +da_bool_t EDRM_convert(const char *in_file_path, char **out_file_path) +{ + drm_trusted_conv_info_s input; + drm_trusted_conv_resp_info_s output; + size_t len = 0; + int ret = 0; + + memset(&input, 0x0, sizeof(drm_trusted_conv_info_s)); + memset(&output, 0x0, sizeof(drm_trusted_conv_resp_info_s)); + + len = strlen(in_file_path); + if (len >= sizeof(input.filePath)) + len = sizeof(input.filePath) - 1; + memcpy(input.filePath, in_file_path, len); + + ret = drm_trusted_convert_dm(&input, &output); + + if (DRM_TRUSTED_RETURN_SUCCESS != ret) { + DA_LOGE("ret[%0x%x]",ret); + __EDRM_clean_up(); + return DA_FALSE; + } else { + DA_SECURE_LOGD("Returned filePath[%s]", output.filePath); + *out_file_path = strdup(output.filePath); + } + __EDRM_clean_up(); + return DA_TRUE; +} + +da_ret_t EDRM_wm_get_license(char *rights_url, char **out_content_url) +{ + int ret = 0; + int len = 0; + drm_initiator_info_s init_info; + drm_web_server_resp_data_s resp_data; + + if (rights_url == NULL) + return DA_ERR_DRM_FAIL; + + memset(&init_info, 0, sizeof(init_info)); + memset(&resp_data, 0, sizeof(resp_data)); + strncpy(init_info.initiator_url, rights_url, + DRM_MAX_LEN_INITIATOR_URL - 1); + len = strlen(rights_url); + if (len > DRM_MAX_LEN_INITIATOR_URL - 1) + init_info.initiator_url_len = (unsigned int)len; + else + init_info.initiator_url_len = DRM_MAX_LEN_INITIATOR_URL; + ret = drm_process_request(DRM_REQUEST_TYPE_SUBMIT_INITIATOR_URL, + &init_info, &resp_data); + if (DRM_RETURN_SUCCESS == ret) { + DA_SECURE_LOGD("resp_data.content_url = %s", resp_data.content_url); + /* Rights or Domain Certificate are installed successfully */ + /* Check for contentURL */ + if (strlen(resp_data.content_url) > 0) { + char *content_url = NULL; + size_t content_url_len = 0; + content_url_len = strlen(resp_data.content_url); + content_url = (char *)calloc(1, content_url_len + 1); + if (content_url) { + strncpy(content_url, resp_data.content_url, + content_url_len); + *out_content_url = content_url; + DA_SECURE_LOGD("drm sumitted initiator url " + "succeeded with [%s]", *out_content_url); + __EDRM_clean_up(); + return DA_RESULT_OK; + } else { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + __EDRM_clean_up(); + return DA_ERR_FAIL_TO_MEMALLOC; + } + } else { + DA_LOGV("content_url is NULL.\ + Join/Leave Domain, Metering case."); + *out_content_url = DA_NULL; + __EDRM_clean_up(); + return DA_RESULT_OK; + } + } else { + DA_LOGE("drm_process_request() failed"); + __EDRM_clean_up(); + return DA_ERR_DRM_FAIL; + } +} + diff --git a/agent/download-agent-plugin-libcurl.c b/agent/download-agent-plugin-libcurl.c new file mode 100644 index 0000000..1fee899 --- /dev/null +++ b/agent/download-agent-plugin-libcurl.c @@ -0,0 +1,702 @@ +/* + * Copyright (c) 2012 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 <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "glib.h" + +#include "download-agent-dl-info.h" +#include "download-agent-http-msg-handler.h" +#include "download-agent-plugin-libcurl.h" + +da_bool_t using_content_sniffing = DA_FALSE; + +int __translate_error_code(int curl_error) +{ + switch (curl_error) { + case CURLE_OPERATION_TIMEDOUT: + return DA_ERR_HTTP_TIMEOUT; + case CURLE_SSL_CONNECT_ERROR: + case CURLE_SSL_ENGINE_NOTFOUND: + case CURLE_SSL_ENGINE_SETFAILED: + case CURLE_SSL_CERTPROBLEM: + case CURLE_SSL_CIPHER: + case CURLE_SSL_CACERT: + case CURLE_SSL_ENGINE_INITFAILED: + case CURLE_SSL_CACERT_BADFILE: + case CURLE_SSH: + case CURLE_SSL_SHUTDOWN_FAILED: + case CURLE_SSL_CRL_BADFILE: + case CURLE_SSL_ISSUER_ERROR: + return DA_ERR_SSL_FAIL; + case CURLE_TOO_MANY_REDIRECTS: + return DA_ERR_TOO_MANY_REDIRECTS; + case CURLE_OUT_OF_MEMORY: + return DA_ERR_FAIL_TO_MEMALLOC; + case CURLE_UNSUPPORTED_PROTOCOL: + case CURLE_URL_MALFORMAT: + case CURLE_COULDNT_RESOLVE_PROXY: + case CURLE_COULDNT_RESOLVE_HOST: + case CURLE_COULDNT_CONNECT: + case CURLE_REMOTE_ACCESS_DENIED: + case CURLE_HTTP_POST_ERROR: + case CURLE_BAD_DOWNLOAD_RESUME: + return DA_ERR_CONNECTION_FAIL; + case CURLE_ABORTED_BY_CALLBACK: + return DA_RESULT_USER_CANCELED; + default: + return DA_ERR_NETWORK_FAIL; + } +} + +int my_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *user) +{ + switch(type) { + case CURLINFO_TEXT: + if (data) + DA_SECURE_LOGI("[curl] Info:%s", data); + break; + case CURLINFO_HEADER_OUT: + DA_LOGD("[curl] Send header"); + if (data) + DA_SECURE_LOGI("[curl] %s", data); + break; + case CURLINFO_DATA_OUT: + DA_LOGD("[curl] Send data"); + if (data) + DA_SECURE_LOGI("[curl] %s", data); + break; + case CURLINFO_SSL_DATA_OUT: + DA_LOGD("[curl] Send SSL data"); + break; + case CURLINFO_HEADER_IN: + DA_LOGD("[curl] Recv header"); + if (data) + DA_SECURE_LOGI("[curl] %s", data); + break; +#if 0 + case CURLINFO_DATA_IN: + DA_LOGD("[curl] Recv data"); + if (data) + DA_SECURE_LOGI("[curl] %d", strlen(data)); + break; +#endif + case CURLINFO_SSL_DATA_IN: + DA_SECURE_LOGI("[curl] Recv SSL data"); + break; + default: + return 0; + } + return 0; +} + +void __parse_raw_header(const char *raw_data, http_info_t *http_info) +{ + char *ptr = DA_NULL; + char *ptr2 = DA_NULL; + int len = 0; + char *field = DA_NULL; + char *value = DA_NULL; + http_msg_response_t *http_msg_response = NULL; + + if (!raw_data || !http_info) { + DA_LOGE("NULL Check!: raw_data or http_info"); + return; + } + + if (!http_info->http_msg_response) { + http_info->http_msg_response = (http_msg_response_t *)calloc(1, + sizeof(http_msg_response_t)); + if (!http_info->http_msg_response) { + DA_LOGE("Fail to calloc"); + return; + } + http_info->http_msg_response->head = DA_NULL; + } + http_msg_response = http_info->http_msg_response; + + ptr = strchr(raw_data, ':'); + if (!ptr) + return; + len = ptr - (char *)raw_data; + field = (char *)calloc(len + 1, sizeof(char)); + if (!field) { + DA_LOGE("Fail to calloc"); + return; + } + memcpy(field, raw_data, len); + field[len] = '\0'; + ptr++; + while(ptr) { + if (*ptr == ' ') + ptr++; + else + break; + } + ptr2 = strchr(raw_data, '\n'); + if (ptr2) { + len = ptr2 - ptr -1; + } else { + len = strlen(ptr); + } + value = (char *)calloc(len + 1, sizeof(char)); + if (!value) { + DA_LOGE("Fail to calloc"); + free(field); + return; + } + memcpy(value, ptr, len); + value[len] = '\0'; + http_msg_response_add_field(http_msg_response, field, value); + free(field); + free(value); +} + +void __store_header(void *msg, da_info_t *da_info, size_t header_size, + const char *sniffed_type) +{ + http_info_t *http_info = DA_NULL; + + if (!da_info || !msg) { + DA_LOGE("NULL Check!: da_info or msg"); + return; + } + http_info = da_info->http_info; + if (!http_info) { + DA_LOGE("NULL Check!: http_info"); + return; + } + + // FIXME later : check status code and redirection case check. + + if (strncmp(msg, HTTP_FIELD_END_OF_FIELD, + strlen(HTTP_FIELD_END_OF_FIELD)) == 0) { + long status = 0; + CURLcode res; + CURL *curl; + http_raw_data_t *raw_data = DA_NULL; + curl = http_info->http_msg->curl; + res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status); + if (res != CURLE_OK) { + DA_LOGE("Fail to get response status code"); + return; + } + DA_LOGV("status code[%d]", (int)status); + if (http_info->http_msg_response) { + http_info->http_msg_response->status_code = (int)status; + } + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + return; + } + + raw_data->status_code = (int)status; + raw_data->type = HTTP_EVENT_GOT_HEADER; + + if (http_info->update_cb) { + http_info->update_cb(raw_data, da_info); + } else { + free(raw_data); + } + return; + } + DA_LOGI("%s",(char *)msg); + __parse_raw_header((const char *)msg, http_info); +} + +size_t __http_gotheaders_cb(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + da_info_t *da_info = DA_NULL; + if (!ptr || !userdata) { + DA_LOGE("Check NULL!: ptr, userdata"); + return 0; + } + da_info = (da_info_t *)userdata; + if (da_info->http_info && da_info->http_info->http_msg + && da_info->http_info->http_msg->is_cancel_reqeusted) { + DA_LOGI("Cancel requested"); + return -1; + } + if (!using_content_sniffing) + __store_header(ptr, da_info, (size * nmemb), DA_NULL); + else + DA_LOGV("ignore because content sniffing is turned on"); +/* +#ifdef _RAF_SUPPORT + DA_LOGI("[RAF] __http_gotheaders_cb done"); +#endif +*/ + return (size * nmemb); +} + +#ifdef _RAF_SUPPORT +da_ret_t PI_http_set_file_name_to_curl(http_msg_t *http_msg, char *file_path) +{ + NULL_CHECK_RET(http_msg); + NULL_CHECK_RET(file_path); + DA_LOGI("[RAF]set file_path[%s]", file_path); + curl_easy_setopt(http_msg->curl, CURLOPT_BOOSTER_RAF_FILE, file_path); + return DA_RESULT_OK; +} +#endif + +size_t __http_gotchunk_cb(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + http_info_t *http_info = DA_NULL; + da_info_t *da_info = DA_NULL; + http_raw_data_t *raw_data = DA_NULL; + if (!ptr || !userdata) { + DA_LOGE("Check NULL!: ptr, stream"); + return 0; + } + da_info = (da_info_t *)userdata; + NULL_CHECK_RET_OPT(da_info, 0); + http_info = da_info->http_info; + NULL_CHECK_RET_OPT(http_info, 0); + NULL_CHECK_RET_OPT(http_info->http_msg, 0); + if (da_info->http_info->http_msg->is_cancel_reqeusted) { + DA_LOGI("Cancel requested"); + return -1; + } + //DA_LOGV("size=%ld, nmemb=%ld, datalen=%ld", size, nmemb, strlen((const char *)ptr)); +#ifdef _RAF_SUPPORT + //DA_LOGI("size=%ld, nmemb=%ld, datalen=%ld", size, nmemb, strlen((const char *)ptr)); + if (http_info->is_raf_mode_confirmed) { + DA_LOGI("[RAF] return chunked callback"); + return (size * nmemb); + } +#endif + + if (ptr && size * nmemb > 0) { + if (http_info->update_cb) { + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + return 0; + } + raw_data->body = (char *)calloc(size, nmemb); + if (!(raw_data->body)) { + DA_LOGE("Fail to calloc"); + free(raw_data); + return 0; + } + memcpy(raw_data->body, ptr, size * nmemb); + raw_data->body_len = size*nmemb; + raw_data->type = HTTP_EVENT_GOT_PACKET; + http_info->update_cb(raw_data, da_info); + } + } + return (size * nmemb); +} + +long __http_finished_cb(void *ptr) +{ + if (!ptr) { + DA_LOGE("Check NULL!: ptr"); + return CURL_CHUNK_END_FUNC_FAIL; + } + DA_LOGI(""); + return CURL_CHUNK_END_FUNC_OK; +} + + +da_ret_t __set_proxy_on_soup_session(char *proxy_addr, CURL *curl) +{ + da_ret_t ret = DA_RESULT_OK; + + if (proxy_addr && strlen(proxy_addr) > 0) { + DA_SECURE_LOGI("received proxy[%s]", proxy_addr); + if (!strstr(proxy_addr, "0.0.0.0")) { + if (strstr((const char *)proxy_addr, "http") == DA_NULL) { + char *tmp_str = DA_NULL; + int needed_len = 0; + + needed_len = strlen(proxy_addr) + strlen( + SCHEME_HTTP) + 1; + tmp_str = (char *) calloc(1, needed_len); + if (!tmp_str) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + snprintf(tmp_str, needed_len, "%s%s", + SCHEME_HTTP, proxy_addr); + + curl_easy_setopt(curl, CURLOPT_PROXY, proxy_addr); + + free(tmp_str); + } else { + DA_LOGV("There is \"http\" on uri, so, push this address to soup directly."); + curl_easy_setopt(curl, CURLOPT_PROXY, proxy_addr); + } + } + } +ERR: + return ret; +} + +struct curl_slist *__fill_soup_msg_header(CURL *curl, http_info_t *info) +{ + http_msg_request_t *input_http_msg_request; + struct curl_slist *headers = DA_NULL; + + if (!curl) { + DA_LOGE("NULL Check!: curl"); + return DA_NULL; + } + input_http_msg_request = info->http_msg_request; + + if (input_http_msg_request) { + char *field = DA_NULL; + char *value = DA_NULL; + char *buff = DA_NULL; + int len = 0; + http_header_t *cur = DA_NULL; + cur = input_http_msg_request->head; + while (cur) { + field = cur->field; + value = cur->value; + if (field && value) { + len = strlen(field) + strlen(value) + 1; + buff = (char *)calloc(len + 1, sizeof(char)); + if (!buff) { + DA_LOGE("Fail to memalloc"); + break; + } +// DA_SECURE_LOGI("[%s] %s", field, value); + snprintf(buff, len + 1, "%s:%s", field, value); + headers = curl_slist_append(headers, (const char *)buff); + free(buff); + buff = DA_NULL; + } + cur = cur->next; + } + } else { + DA_LOGE("NULL Check!: input_http_msg_request"); + return DA_NULL; + } + if (input_http_msg_request->http_body) { + char buff[256] = {0,}; + int body_len = strlen(input_http_msg_request->http_body); + snprintf(buff, sizeof(buff), "%s:%d", HTTP_FIELD_CONTENT_LENGTH, + body_len); + headers = curl_slist_append(headers, buff); + memset(buff, 0x00, 256); + snprintf(buff, sizeof(buff), "%s:text/plain", HTTP_FIELD_CONTENT_TYPE); + headers = curl_slist_append(headers, buff); + headers = curl_slist_append(headers, input_http_msg_request->http_body); + } + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + return headers; +} + +#ifdef _RAF_SUPPORT +int __http_progress_cb(void *clientp, double dltotal, double dlnow, + double ultotal, double ulnow) +{ + da_info_t *da_info = DA_NULL; + http_info_t *http_info = DA_NULL; + http_raw_data_t *raw_data = DA_NULL; +/* + if (dlnow > 0 || ulnow > 0) + DA_LOGI("[RAF]dlnow/ulnow[%llu/%llu][%llu,%llu]", (da_size_t)dlnow, (da_size_t)ulnow, (da_size_t)dltotal, (da_size_t)ultotal); +*/ + +/* + if (dlnow == 0) { + DA_LOGI("[RAF]dlnow is zero. Why is this callback called although there is zero size?"); + } +*/ + NULL_CHECK_RET_OPT(clientp, -1); + da_info = (da_info_t *)clientp; + http_info = da_info->http_info; + NULL_CHECK_RET_OPT(http_info, -1); + NULL_CHECK_RET_OPT(http_info->http_msg, -1); + + if (http_info->http_msg->is_cancel_reqeusted) { + DA_LOGI("Cancel requested"); + return -1; + } + + if (dlnow > 0) { + if (http_info->update_cb) { + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + return 0; + } + raw_data->received_len = (da_size_t)dlnow; + raw_data->type = HTTP_EVENT_GOT_PACKET; + http_info->update_cb(raw_data, da_info); + } + } + return CURLE_OK; +} +#endif + +da_ret_t PI_http_start(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_method_t http_method; + CURL *curl = DA_NULL; + CURLcode res; + http_msg_t *http_msg = DA_NULL; + char *url = DA_NULL; + http_info_t *http_info = DA_NULL; + long http_status = 0; + struct curl_httppost* post = NULL; + struct curl_slist *headers = DA_NULL; + char err_buffer[CURL_ERROR_SIZE] = {0,}; + + DA_LOGV(""); +#ifdef _RAF_SUPPORT + // test code + get_smart_bonding_vconf(); +#endif + NULL_CHECK_GOTO(da_info); + NULL_CHECK_GOTO(da_info->req_info); + url = da_info->req_info->url; + NULL_CHECK_GOTO(url); + http_info = da_info->http_info; + NULL_CHECK_GOTO(http_info); + + http_method = http_info->http_method; + ret = init_http_msg_t(&http_msg); + if (ret != DA_RESULT_OK) + goto ERR; + http_info->http_msg = http_msg; + + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + + if (!curl) { + DA_LOGE("Fail to create curl"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + DA_LOGI("curl[%p]", curl); + + curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, MAX_SESSION_COUNT); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, MAX_TIMEOUT); + + __set_proxy_on_soup_session(http_info->proxy_addr, curl); + + curl_easy_setopt(curl, CURLOPT_URL, url); + switch (http_method) { + case HTTP_METHOD_GET: + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); + break; + case HTTP_METHOD_POST: + // FIXME later : If the post method is supprot, the post data should be set with curl_fromadd + curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); + DA_LOGI("Need more information for post filed"); + break; + case HTTP_METHOD_HEAD: + DA_LOGI("Donnot implement yet"); + break; + default: + DA_LOGE("Cannot enter here"); + break; + } + + if (using_content_sniffing) { + /* FIXME later*/ + } else { + /* FIXME later*/ + } + headers = __fill_soup_msg_header(curl, http_info); + + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, __http_gotheaders_cb); // can replace to started_cb + curl_easy_setopt(curl, CURLOPT_HEADERDATA, da_info); // param .. same with CURLOPT_WRITEHEADER + curl_easy_setopt(curl, CURLOPT_HEADER, 0L); // does not include header to body + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, __http_gotchunk_cb); // can replace to progress_ + curl_easy_setopt(curl, CURLOPT_WRITEDATA, da_info); // param .. same with CURLOPT_WRITEHEADERcb + curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, __http_finished_cb); + curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, da_info); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); +// curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, err_buffer); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); +#ifdef _RAF_SUPPORT + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, __http_progress_cb); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, da_info); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); +#endif + + if (da_info->req_info->network_bonding) { +#ifdef _DOWNLOAD_BOOSTER_SUPPORT + DA_LOGI("network bonding enable"); + curl_easy_setopt(curl, CURLOPT_MULTIRAT_NEEDED, 1L); +#endif +#ifdef _RAF_SUPPORT + curl_easy_setopt(curl, CURLOPT_BOOSTER_RAF_MODE, 1L); +#endif + } + http_msg->curl = curl; + res = curl_easy_perform(curl); + DA_LOGD("perform done! res[%d]",res); + if (res != CURLE_OK) { + //DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res)); + DA_LOGE("Fail to perform :%d[%s]", res, curl_multi_strerror(res)); + if (strlen(err_buffer) > 1) + DA_LOGE("Fail to error buffer[%s]", err_buffer); + } + if (res != CURLE_OK) { + //DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res)); + DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res)); + if (strlen(err_buffer) > 1) + DA_LOGE("Fail to error buffer[%s]", err_buffer); + } else { + res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status); + if (res != CURLE_OK) { + //DA_LOGE("Fail to get response code:%d[%s]", res, curl_easy_strerror(res)); + DA_LOGE("Fail to get response code:%d[%s]", res, curl_easy_strerror(res)); + ret = DA_ERR_FAIL_TO_MEMALLOC;; + goto ERR; + } else { + DA_LOGD("Response Http Status code[%d]", (int)http_status); + } + } + if (http_info->update_cb) { + http_raw_data_t *raw_data = DA_NULL; + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + if (http_msg->is_cancel_reqeusted || + res == CURLE_ABORTED_BY_CALLBACK) { + DA_LOGI("canceled exit. Err[%d]", http_info->error_code); + if (http_info->error_code < 0) + ret = http_info->error_code; + else + ret = DA_RESULT_USER_CANCELED; + } else if ((http_status > 0 && http_status < 100)) { + raw_data->error = __translate_error_code(res); + ret = DA_ERR_NETWORK_FAIL; + } else if (res != CURLE_OK) { + raw_data->error = __translate_error_code(res); + ret = DA_ERR_NETWORK_FAIL; + } else { + raw_data->status_code = (int)http_status; + } + raw_data->type = HTTP_EVENT_FINAL; + http_info->update_cb(raw_data, da_info); + } + if (DA_NULL != headers) + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + http_msg->curl = DA_NULL; + DA_MUTEX_INIT(&(http_msg->mutex), DA_NULL); +ERR: + DA_LOGD("Done"); + return ret; + +} + +da_ret_t PI_http_disconnect(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + + DA_LOGD(""); + NULL_CHECK_RET(info); + http_msg = info->http_msg; + NULL_CHECK_RET(http_msg); + DA_LOGV("session [%p]", http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + if (http_msg->is_paused) + PI_http_unpause(info); + if (http_msg->curl) + curl_easy_cleanup(http_msg->curl); + + http_msg->curl = DA_NULL; + http_msg->is_paused = DA_FALSE; + http_msg->is_cancel_reqeusted = DA_FALSE; + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + DA_MUTEX_DESTROY(&(http_msg->mutex)); + destroy_http_msg_t(http_msg); + info->http_msg = DA_NULL; + return ret; +} + +da_ret_t PI_http_cancel(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(info); + http_msg = info->http_msg; + NULL_CHECK_RET(http_msg); + NULL_CHECK_RET(http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + DA_LOGI("curl[%p]", http_msg->curl); + http_msg->is_cancel_reqeusted = DA_TRUE; + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + DA_LOGD("Done - soup cancel"); + return ret; +} + +da_ret_t PI_http_pause(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + CURLcode res = CURLE_OK; + DA_LOGV(""); + + NULL_CHECK_RET(info); + http_msg = info->http_msg; + NULL_CHECK_RET(http_msg); + DA_LOGD("curl [%p]", http_msg->curl); + NULL_CHECK_RET(http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + DA_LOGE("curl_easy_pause call"); + res = curl_easy_pause(http_msg->curl, CURLPAUSE_ALL); + DA_LOGE("curl_easy_pause:%d", res); + if (res == CURLE_OK) { + http_msg->is_paused = DA_TRUE; + } else { + ret = DA_ERR_CANNOT_SUSPEND; + } + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + return ret; +} + +da_ret_t PI_http_unpause(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + CURLcode res = CURLE_OK; + DA_LOGV(""); + + NULL_CHECK_RET(info); + http_msg = info->http_msg; + DA_LOGV("curl [%p]", http_msg->curl); + NULL_CHECK_RET(http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + res = curl_easy_pause(http_msg->curl, CURLPAUSE_CONT); + if (res == CURLE_OK) + http_msg->is_paused = DA_FALSE; + else + ret = DA_ERR_CANNOT_RESUME; + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + return ret; +} diff --git a/agent/download-agent-plugin-libcurl.c~ b/agent/download-agent-plugin-libcurl.c~ new file mode 100644 index 0000000..0c221d2 --- /dev/null +++ b/agent/download-agent-plugin-libcurl.c~ @@ -0,0 +1,702 @@ +/* + * Copyright (c) 2012 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 <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "glib.h" + +#include "download-agent-dl-info.h" +#include "download-agent-http-msg-handler.h" +#include "download-agent-plugin-libcurl.h" + +da_bool_t using_content_sniffing = DA_FALSE; + +int __translate_error_code(int curl_error) +{ + switch (curl_error) { + case CURLE_OPERATION_TIMEDOUT: + return DA_ERR_HTTP_TIMEOUT; + case CURLE_SSL_CONNECT_ERROR: + case CURLE_SSL_ENGINE_NOTFOUND: + case CURLE_SSL_ENGINE_SETFAILED: + case CURLE_SSL_CERTPROBLEM: + case CURLE_SSL_CIPHER: + case CURLE_SSL_CACERT: + case CURLE_SSL_ENGINE_INITFAILED: + case CURLE_SSL_CACERT_BADFILE: + case CURLE_SSH: + case CURLE_SSL_SHUTDOWN_FAILED: + case CURLE_SSL_CRL_BADFILE: + case CURLE_SSL_ISSUER_ERROR: + return DA_ERR_SSL_FAIL; + case CURLE_TOO_MANY_REDIRECTS: + return DA_ERR_TOO_MANY_REDIRECTS; + case CURLE_OUT_OF_MEMORY: + return DA_ERR_FAIL_TO_MEMALLOC; + case CURLE_UNSUPPORTED_PROTOCOL: + case CURLE_URL_MALFORMAT: + case CURLE_COULDNT_RESOLVE_PROXY: + case CURLE_COULDNT_RESOLVE_HOST: + case CURLE_COULDNT_CONNECT: + case CURLE_REMOTE_ACCESS_DENIED: + case CURLE_HTTP_POST_ERROR: + case CURLE_BAD_DOWNLOAD_RESUME: + return DA_ERR_CONNECTION_FAIL; + case CURLE_ABORTED_BY_CALLBACK: + return DA_RESULT_USER_CANCELED; + default: + return DA_ERR_NETWORK_FAIL; + } +} + +int my_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *user) +{ + switch(type) { + case CURLINFO_TEXT: + if (data) + DA_SECURE_LOGI("[curl] Info:%s", data); + break; + case CURLINFO_HEADER_OUT: + DA_LOGD("[curl] Send header"); + if (data) + DA_SECURE_LOGI("[curl] %s", data); + break; + case CURLINFO_DATA_OUT: + DA_LOGD("[curl] Send data"); + if (data) + DA_SECURE_LOGI("[curl] %s", data); + break; + case CURLINFO_SSL_DATA_OUT: + DA_LOGD("[curl] Send SSL data"); + break; + case CURLINFO_HEADER_IN: + DA_LOGD("[curl] Recv header"); + if (data) + DA_SECURE_LOGI("[curl] %s", data); + break; +#if 0 + case CURLINFO_DATA_IN: + DA_LOGD("[curl] Recv data"); + if (data) + DA_SECURE_LOGI("[curl] %d", strlen(data)); + break; +#endif + case CURLINFO_SSL_DATA_IN: + DA_SECURE_LOGI("[curl] Recv SSL data"); + break; + default: + return 0; + } + return 0; +} + +void __parse_raw_header(const char *raw_data, http_info_t *http_info) +{ + char *ptr = DA_NULL; + char *ptr2 = DA_NULL; + int len = 0; + char *field = DA_NULL; + char *value = DA_NULL; + http_msg_response_t *http_msg_response = NULL; + + if (!raw_data || !http_info) { + DA_LOGE("NULL Check!: raw_data or http_info"); + return; + } + + if (!http_info->http_msg_response) { + http_info->http_msg_response = (http_msg_response_t *)calloc(1, + sizeof(http_msg_response_t)); + if (!http_info->http_msg_response) { + DA_LOGE("Fail to calloc"); + return; + } + http_info->http_msg_response->head = DA_NULL; + } + http_msg_response = http_info->http_msg_response; + + ptr = strchr(raw_data, ':'); + if (!ptr) + return; + len = ptr - (char *)raw_data; + field = (char *)calloc(len + 1, sizeof(char)); + if (!field) { + DA_LOGE("Fail to calloc"); + return; + } + memcpy(field, raw_data, len); + field[len] = '\0'; + ptr++; + while(ptr) { + if (*ptr == ' ') + ptr++; + else + break; + } + ptr2 = strchr(raw_data, '\n'); + if (ptr2) { + len = ptr2 - ptr -1; + } else { + len = strlen(ptr); + } + value = (char *)calloc(len + 1, sizeof(char)); + if (!value) { + DA_LOGE("Fail to calloc"); + free(field); + return; + } + memcpy(value, ptr, len); + value[len] = '\0'; + http_msg_response_add_field(http_msg_response, field, value); + free(field); + free(value); +} + +void __store_header(void *msg, da_info_t *da_info, size_t header_size, + const char *sniffed_type) +{ + http_info_t *http_info = DA_NULL; + + if (!da_info || !msg) { + DA_LOGE("NULL Check!: da_info or msg"); + return; + } + http_info = da_info->http_info; + if (!http_info) { + DA_LOGE("NULL Check!: http_info"); + return; + } + + // FIXME later : check status code and redirection case check. + + if (strncmp(msg, HTTP_FIELD_END_OF_FIELD, + strlen(HTTP_FIELD_END_OF_FIELD)) == 0) { + long status = 0; + CURLcode res; + CURL *curl; + http_raw_data_t *raw_data = DA_NULL; + curl = http_info->http_msg->curl; + res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status); + if (res != CURLE_OK) { + DA_LOGE("Fail to get response status code"); + return; + } + DA_LOGV("status code[%d]", (int)status); + if (http_info->http_msg_response) { + http_info->http_msg_response->status_code = (int)status; + } + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + return; + } + + raw_data->status_code = (int)status; + raw_data->type = HTTP_EVENT_GOT_HEADER; + + if (http_info->update_cb) { + http_info->update_cb(raw_data, da_info); + } else { + free(raw_data); + } + return; + } + DA_LOGI("%s",(char *)msg); + __parse_raw_header((const char *)msg, http_info); +} + +size_t __http_gotheaders_cb(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + da_info_t *da_info = DA_NULL; + if (!ptr || !userdata) { + DA_LOGE("Check NULL!: ptr, userdata"); + return 0; + } + da_info = (da_info_t *)userdata; + if (da_info->http_info && da_info->http_info->http_msg + && da_info->http_info->http_msg->is_cancel_reqeusted) { + DA_LOGI("Cancel requested"); + return -1; + } + if (!using_content_sniffing) + __store_header(ptr, da_info, (size * nmemb), DA_NULL); + else + DA_LOGV("ignore because content sniffing is turned on"); +/* +#ifdef _RAF_SUPPORT + DA_LOGI("[RAF] __http_gotheaders_cb done"); +#endif +*/ + return (size * nmemb); +} + +#ifdef _RAF_SUPPORT +da_ret_t PI_http_set_file_name_to_curl(http_msg_t *http_msg, char *file_path) +{ + NULL_CHECK_RET(http_msg); + NULL_CHECK_RET(file_path); + DA_LOGI("[RAF]set file_path[%s]", file_path); + curl_easy_setopt(http_msg->curl, CURLOPT_BOOSTER_RAF_FILE, file_path); + return DA_RESULT_OK; +} +#endif + +size_t __http_gotchunk_cb(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + http_info_t *http_info = DA_NULL; + da_info_t *da_info = DA_NULL; + http_raw_data_t *raw_data = DA_NULL; + if (!ptr || !userdata) { + DA_LOGE("Check NULL!: ptr, stream"); + return 0; + } + da_info = (da_info_t *)userdata; + NULL_CHECK_RET_OPT(da_info, 0); + http_info = da_info->http_info; + NULL_CHECK_RET_OPT(http_info, 0); + NULL_CHECK_RET_OPT(http_info->http_msg, 0); + if (da_info->http_info->http_msg->is_cancel_reqeusted) { + DA_LOGI("Cancel requested"); + return -1; + } + //DA_LOGV("size=%ld, nmemb=%ld, datalen=%ld", size, nmemb, strlen((const char *)ptr)); +#ifdef _RAF_SUPPORT + //DA_LOGI("size=%ld, nmemb=%ld, datalen=%ld", size, nmemb, strlen((const char *)ptr)); + if (http_info->is_raf_mode_confirmed) { + DA_LOGI("[RAF] return chunked callback"); + return (size * nmemb); + } +#endif + + if (ptr && size * nmemb > 0) { + if (http_info->update_cb) { + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + return 0; + } + raw_data->body = (char *)calloc(size, nmemb); + if (!(raw_data->body)) { + DA_LOGE("Fail to calloc"); + free(raw_data); + return 0; + } + memcpy(raw_data->body, ptr, size * nmemb); + raw_data->body_len = size*nmemb; + raw_data->type = HTTP_EVENT_GOT_PACKET; + http_info->update_cb(raw_data, da_info); + } + } + return (size * nmemb); +} + +long __http_finished_cb(void *ptr) +{ + if (!ptr) { + DA_LOGE("Check NULL!: ptr"); + return CURL_CHUNK_END_FUNC_FAIL; + } + DA_LOGI(""); + return CURL_CHUNK_END_FUNC_OK; +} + + +da_ret_t __set_proxy_on_soup_session(char *proxy_addr, CURL *curl) +{ + da_ret_t ret = DA_RESULT_OK; + + if (proxy_addr && strlen(proxy_addr) > 0) { + DA_SECURE_LOGI("received proxy[%s]", proxy_addr); + if (!strstr(proxy_addr, "0.0.0.0")) { + if (strstr((const char *)proxy_addr, "http") == DA_NULL) { + char *tmp_str = DA_NULL; + int needed_len = 0; + + needed_len = strlen(proxy_addr) + strlen( + SCHEME_HTTP) + 1; + tmp_str = (char *) calloc(1, needed_len); + if (!tmp_str) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + snprintf(tmp_str, needed_len, "%s%s", + SCHEME_HTTP, proxy_addr); + + curl_easy_setopt(curl, CURLOPT_PROXY, proxy_addr); + + free(tmp_str); + } else { + DA_LOGV("There is \"http\" on uri, so, push this address to soup directly."); + curl_easy_setopt(curl, CURLOPT_PROXY, proxy_addr); + } + } + } +ERR: + return ret; +} + +struct curl_slist *__fill_soup_msg_header(CURL *curl, http_info_t *info) +{ + http_msg_request_t *input_http_msg_request; + struct curl_slist *headers = DA_NULL; + + if (!curl) { + DA_LOGE("NULL Check!: curl"); + return DA_NULL; + } + input_http_msg_request = info->http_msg_request; + + if (input_http_msg_request) { + char *field = DA_NULL; + char *value = DA_NULL; + char *buff = DA_NULL; + int len = 0; + http_header_t *cur = DA_NULL; + cur = input_http_msg_request->head; + while (cur) { + field = cur->field; + value = cur->value; + if (field && value) { + len = strlen(field) + strlen(value) + 1; + buff = (char *)calloc(len + 1, sizeof(char)); + if (!buff) { + DA_LOGE("Fail to memalloc"); + break; + } +// DA_SECURE_LOGI("[%s] %s", field, value); + snprintf(buff, len + 1, "%s:%s", field, value); + headers = curl_slist_append(headers, (const char *)buff); + free(buff); + buff = DA_NULL; + } + cur = cur->next; + } + } else { + DA_LOGE("NULL Check!: input_http_msg_request"); + return DA_NULL; + } + if (input_http_msg_request->http_body) { + char buff[256] = {0,}; + int body_len = strlen(input_http_msg_request->http_body); + snprintf(buff, sizeof(buff), "%s:%d", HTTP_FIELD_CONTENT_LENGTH, + body_len); + headers = curl_slist_append(headers, buff); + memset(buff, 0x00, 256); + snprintf(buff, sizeof(buff), "%s:text/plain", HTTP_FIELD_CONTENT_TYPE); + headers = curl_slist_append(headers, buff); + headers = curl_slist_append(headers, input_http_msg_request->http_body); + } + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + return headers; +} + +#ifdef _RAF_SUPPORT +int __http_progress_cb(void *clientp, double dltotal, double dlnow, + double ultotal, double ulnow) +{ + da_info_t *da_info = DA_NULL; + http_info_t *http_info = DA_NULL; + http_raw_data_t *raw_data = DA_NULL; +/* + if (dlnow > 0 || ulnow > 0) + DA_LOGI("[RAF]dlnow/ulnow[%llu/%llu][%llu,%llu]", (da_size_t)dlnow, (da_size_t)ulnow, (da_size_t)dltotal, (da_size_t)ultotal); +*/ + +/* + if (dlnow == 0) { + DA_LOGI("[RAF]dlnow is zero. Why is this callback called although there is zero size?"); + } +*/ + NULL_CHECK_RET_OPT(clientp, -1); + da_info = (da_info_t *)clientp; + http_info = da_info->http_info; + NULL_CHECK_RET_OPT(http_info, -1); + NULL_CHECK_RET_OPT(http_info->http_msg, -1); + + if (http_info->http_msg->is_cancel_reqeusted) { + DA_LOGI("Cancel requested"); + return -1; + } + + if (dlnow > 0) { + if (http_info->update_cb) { + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + return 0; + } + raw_data->received_len = (da_size_t)dlnow; + raw_data->type = HTTP_EVENT_GOT_PACKET; + http_info->update_cb(raw_data, da_info); + } + } + return CURLE_OK; +} +#endif + +da_ret_t PI_http_start(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_method_t http_method; + CURL *curl = DA_NULL; + CURLcode res; + http_msg_t *http_msg = DA_NULL; + char *url = DA_NULL; + http_info_t *http_info = DA_NULL; + long http_status = 0; + struct curl_httppost* post = NULL; + struct curl_slist *headers = DA_NULL; + char err_buffer[CURL_ERROR_SIZE] = {0,}; + + DA_LOGV(""); +#ifdef _RAF_SUPPORT + // test code + get_smart_bonding_vconf(); +#endif + NULL_CHECK_GOTO(da_info); + NULL_CHECK_GOTO(da_info->req_info); + url = da_info->req_info->url; + NULL_CHECK_GOTO(url); + http_info = da_info->http_info; + NULL_CHECK_GOTO(http_info); + + http_method = http_info->http_method; + ret = init_http_msg_t(&http_msg); + if (ret != DA_RESULT_OK) + goto ERR; + http_info->http_msg = http_msg; + + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + + if (!curl) { + DA_LOGE("Fail to create curl"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + DA_LOGI("curl[%p]", curl); + + curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, MAX_SESSION_COUNT); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, MAX_TIMEOUT); + + __set_proxy_on_soup_session(http_info->proxy_addr, curl); + + curl_easy_setopt(curl, CURLOPT_URL, url); + switch (http_method) { + case HTTP_METHOD_GET: + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); + break; + case HTTP_METHOD_POST: + // FIXME later : If the post method is supprot, the post data should be set with curl_fromadd + curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); + DA_LOGI("Need more information for post filed"); + break; + case HTTP_METHOD_HEAD: + DA_LOGI("Donnot implement yet"); + break; + default: + DA_LOGE("Cannot enter here"); + break; + } + + if (using_content_sniffing) { + /* FIXME later*/ + } else { + /* FIXME later*/ + } + headers = __fill_soup_msg_header(curl, http_info); + + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, __http_gotheaders_cb); // can replace to started_cb + curl_easy_setopt(curl, CURLOPT_HEADERDATA, da_info); // param .. same with CURLOPT_WRITEHEADER + curl_easy_setopt(curl, CURLOPT_HEADER, 0L); // does not include header to body + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, __http_gotchunk_cb); // can replace to progress_ + curl_easy_setopt(curl, CURLOPT_WRITEDATA, da_info); // param .. same with CURLOPT_WRITEHEADERcb + curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, __http_finished_cb); + curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, da_info); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); +// curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, err_buffer); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); +#ifdef _RAF_SUPPORT + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, __http_progress_cb); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, da_info); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); +#endif + + if (da_info->req_info->network_bonding) { +#ifdef _DOWNLOAD_BOOSTER_SUPPORT + DA_LOGI("network bonding enable"); + curl_easy_setopt(curl, CURLOPT_MULTIRAT_NEEDED, 1L); +#endif +#ifdef _RAF_SUPPORT + curl_easy_setopt(curl, CURLOPT_BOOSTER_RAF_MODE, 1L); +#endif + } + http_msg->curl = curl; + res = curl_easy_perform(curl); + DA_LOGD("perform done! res[%d]",res); + if (res != CURLE_OK) { + //DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res)); + DA_LOGE("Fail to perform :%d[%s]", res, curl_multi_strerror(res)); + if (strlen(err_buffer) > 1) + DA_LOGE("Fail to error buffer[%s]", err_buffer); + } + if (res != CURLE_OK) { + //DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res)); + DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res)); + if (strlen(err_buffer) > 1) + DA_LOGE("Fail to error buffer[%s]", err_buffer); + } else { + res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status); + if (res != CURLE_OK) { + //DA_LOGE("Fail to get response code:%d[%s]", res, curl_easy_strerror(res)); + DA_LOGE("Fail to get response code:%d[%s]", res, curl_easy_strerror(res)); + ret = DA_ERR_FAIL_TO_MEMALLOC;; + goto ERR; + } else { + DA_LOGD("Response Http Status code[%d]", (int)http_status); + } + } + if (http_info->update_cb) { + http_raw_data_t *raw_data = DA_NULL; + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + if (http_msg->is_cancel_reqeusted || + res == CURLE_ABORTED_BY_CALLBACK) { + DA_LOGI("canceled exit. Err[%d]", http_info->error_code); + if (http_info->error_code < 0) + ret = http_info->error_code; + else + ret = DA_RESULT_USER_CANCELED; + } else if ((http_status > 0 && http_status < 100)) { + raw_data->error = __translate_error_code(res); + ret = DA_ERR_NETWORK_FAIL; + } else if (res != CURLE_OK) { + raw_data->error = __translate_error_code(res); + ret = DA_ERR_NETWORK_FAIL; + } else { + raw_data->status_code = (int)http_status; + } + raw_data->type = HTTP_EVENT_FINAL; + http_info->update_cb(raw_data, da_info); + } + if (DA_NULL != headers) + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + http_msg->curl = DA_NULL; + DA_MUTEX_INIT(&(http_msg->mutex), DA_NULL); +ERR: + DA_LOGD("Done"); + return ret; + +} + +da_ret_t PI_http_disconnect(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + + DA_LOGD(""); + NULL_CHECK_RET(info); + http_msg = info->http_msg; + NULL_CHECK_RET(http_msg); + DA_LOGV("session [%p]", http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + if (http_msg->is_paused) + PI_http_unpause(info); + if (http_msg->curl) + curl_easy_cleanup(http_msg->curl); + + http_msg->curl = DA_NULL; + http_msg->is_paused = DA_FALSE; + http_msg->is_cancel_reqeusted = DA_FALSE; + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + DA_MUTEX_DESTROY(&(http_msg->mutex)); + destroy_http_msg_t(http_msg); + info->http_msg = DA_NULL; + return ret; +} + +da_ret_t PI_http_cancel(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(info); + http_msg = info->http_msg; + NULL_CHECK_RET(http_msg); + NULL_CHECK_RET(http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + DA_LOGI("curl[%p]", http_msg->curl); + http_msg->is_cancel_reqeusted = DA_TRUE; + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + DA_LOGD("Done - soup cancel"); + return ret; +} + +da_ret_t PI_http_pause(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + CURLcode res = CURLE_OK; + DA_LOGV(""); + + NULL_CHECK_RET(info); + http_msg = info->http_msg; + NULL_CHECK_RET(http_msg); + DA_LOGD("curl [%p]", http_msg->curl); + NULL_CHECK_RET(http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + DA_LOGE("curl_easy_pause call"); + curl_easy_pause(http_msg->curl, CURLPAUSE_ALL); + DA_LOGE("curl_easy_pause:%d", res); + if (res == CURLE_OK) { + http_msg->is_paused = DA_TRUE; + } else { + ret = DA_ERR_CANNOT_SUSPEND; + } + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + return ret; +} + +da_ret_t PI_http_unpause(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + CURLcode res = CURLE_OK; + DA_LOGV(""); + + NULL_CHECK_RET(info); + http_msg = info->http_msg; + DA_LOGV("curl [%p]", http_msg->curl); + NULL_CHECK_RET(http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + res = curl_easy_pause(http_msg->curl, CURLPAUSE_CONT); + if (res == CURLE_OK) + http_msg->is_paused = DA_FALSE; + else + ret = DA_ERR_CANNOT_RESUME; + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + return ret; +} diff --git a/agent/include/download-agent-client-mgr.h b/agent/include/download-agent-client-mgr.h new file mode 100755 index 0000000..b2ce1c8 --- /dev/null +++ b/agent/include/download-agent-client-mgr.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012 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 DOWNLOAD_AGENT_CLIENT_MGR_H +#define DOWNLOAD_AGENT_CLIENT_MGR_H + +#include "download-agent-dl-info.h" + +da_ret_t send_client_paused_info(da_info_t *da_info); +da_ret_t send_client_update_dl_info(da_info_t *da_info); +da_ret_t send_client_update_progress_info(da_info_t *da_info); +da_ret_t send_client_finished_info(da_info_t *da_info, int err); + +#endif diff --git a/agent/include/download-agent-debug.h b/agent/include/download-agent-debug.h new file mode 100755 index 0000000..23c2a66 --- /dev/null +++ b/agent/include/download-agent-debug.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2012 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 _DOWNLOAD_AGENT_DEBUG_H +#define _DOWNLOAD_AGENT_DEBUG_H + +#include "download-agent-type.h" + +#include <stdio.h> +#include <stdarg.h> +#include <pthread.h> + +// ansi color +#define COLOR_RED "\033[0;31m" +#define COLOR_GREEN "\033[0;32m" +#define COLOR_BROWN "\033[0;33m" +#define COLOR_LIGHTBLUE "\033[0;37m" +#define COLOR_END "\033[0;m" + +#ifdef _ENABLE_DLOG +#include <unistd.h> +#include <syscall.h> +#include <dlog.h> + + #ifdef LOG_TAG + #undef LOG_TAG + #endif /* LOG_TAG */ + + #define LOG_TAG "DP_DA" + #define DA_LOGV(format, ...) ((void)0)//LOGD("[%d]:"format, syscall(__NR_gettid), ##__VA_ARGS__) + #define DA_LOGD(format, ...) LOGD(COLOR_LIGHTBLUE "[%d]:"format COLOR_END, syscall(__NR_gettid), ##__VA_ARGS__) + #define DA_LOGI(format, ...) LOGI(COLOR_BROWN "[%d]:"format COLOR_END, syscall(__NR_gettid), ##__VA_ARGS__) + #define DA_LOGE(format, ...) LOGE(COLOR_RED "[%d]:"format COLOR_END, syscall(__NR_gettid), ##__VA_ARGS__) + #define DA_SECURE_LOGD(format, ...) SECURE_LOGD(COLOR_GREEN format COLOR_END, ##__VA_ARGS__) + #define DA_SECURE_LOGI(format, ...) SECURE_LOGI(COLOR_GREEN format COLOR_END, ##__VA_ARGS__) + #define DA_SECURE_LOGE(format, ...) SECURE_LOGE(COLOR_GREEN format COLOR_END, ##__VA_ARGS__) +#else + +#include <unistd.h> +#include <syscall.h> + + #define DA_LOGD(format, ...) do {\ + fprintf(stderr, "[DA][%d][%s():%d] "format"\n",syscall(__NR_gettid), __FUNCTION__,__LINE__, ##__VA_ARGS__);\ + }while(0) + #define DA_LOGE(format, ...) do {\ + fprintf(stderr, "[DA][%d][ERR][%s():%d]\n",syscall(__NR_gettid), __FUNCTION__,__LINE__, ##__VA_ARGS__);\ + }while(0) + #define DA_LOGV DA_LOGD + #define DA_LOGI DA_LOGD + #define DA_SECURE_LOGD(format, ...) ((void)0) + #define DA_SECURE_LOGI(format, ...) ((void)0) + #define DA_SECURE_LOGE(format, ...) ((void)0) +#endif /* _ENABLE_DLOG */ + +#endif /* DOWNLOAD_AGENT_DEBUG_H */ diff --git a/agent/include/download-agent-defs.h b/agent/include/download-agent-defs.h new file mode 100755 index 0000000..d5b6a5e --- /dev/null +++ b/agent/include/download-agent-defs.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2012 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 _DOWNLOAD_AGENT_DEFS_H +#define _DOWNLOAD_AGENT_DEFS_H + +#ifndef DEPRECATED +#define DEPRECATED __attribute__((deprecated)) +#endif + +/** + * Max count to download files simultaneously. \n + * Main reason for this restriction is because of Network bandwidth. + */ +#define DA_MAX_DOWNLOAD_REQ_AT_ONCE 50 +#define DA_MAX_TIME_OUT 65 + +#define DA_RESULT_OK 0 + +#define DA_TRUE 1 +#define DA_FALSE 0 +#define DA_NULL (void *)0 +#define DA_INVALID_ID -1 + +#define DA_RESULT_USER_CANCELED -10 + +// InputError Input error (-100 ~ -199) +// Client passed wrong parameter +#define DA_ERR_INVALID_ARGUMENT -100 +#define DA_ERR_INVALID_DL_REQ_ID -101 +#define DA_ERR_INVALID_URL -103 +#define DA_ERR_INVALID_INSTALL_PATH -104 +#define DA_ERR_INVALID_MIME_TYPE -105 + +// Client passed correct parameter, but Download Agent rejects the request because of internal policy. +#define DA_ERR_ALREADY_CANCELED -160 +#define DA_ERR_ALREADY_SUSPENDED -161 +#define DA_ERR_ALREADY_RESUMED -162 +#define DA_ERR_CANNOT_SUSPEND -170 +#define DA_ERR_CANNOT_RESUME -171 +#define DA_ERR_INVALID_STATE -190 +#define DA_ERR_ALREADY_MAX_DOWNLOAD -191 +#define DA_ERR_UNSUPPORTED_PROTOCAL -192 + +// System error (-200 ~ -299) +#define DA_ERR_FAIL_TO_MEMALLOC -200 +#define DA_ERR_FAIL_TO_CREATE_THREAD -210 +#define DA_ERR_FAIL_TO_ACCESS_FILE -230 +#define DA_ERR_DISK_FULL -240 + +// Network error (-400 ~ -499) +#define DA_ERR_NETWORK_FAIL -400 +#define DA_ERR_UNREACHABLE_SERVER -410 +#define DA_ERR_CONNECTION_FAIL -420 +#define DA_ERR_HTTP_TIMEOUT -430 +#define DA_ERR_SSL_FAIL -440 +#define DA_ERR_TOO_MANY_REDIRECTS -450 +#define DA_ERR_NETWORK_UNAUTHORIZED -460 + +// HTTP error - not conforming with HTTP spec (-500 ~ -599) +#define DA_ERR_MISMATCH_CONTENT_TYPE -500 +#define DA_ERR_SERVER_RESPOND_BUT_SEND_NO_CONTENT -501 +#define DA_ERR_MISMATCH_CONTENT_SIZE -502 + +// DRM error - not conforming with DRM spec (-600 ~ -699) +#define DA_ERR_DRM_FAIL -600 + +// string to check invalid characters in path before using open() and fopen() API's +#define DA_INVALID_PATH_STRING ";\\\":*?<>|()" + +#endif + diff --git a/agent/include/download-agent-dl-info.h b/agent/include/download-agent-dl-info.h new file mode 100644 index 0000000..820135e --- /dev/null +++ b/agent/include/download-agent-dl-info.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2012 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 _DOWNLOAD_AGENT_INFO_H +#define _DOWNLOAD_AGENT_INFO_H + +#include "download-agent-type.h" +#include "download-agent-interface.h" +#include "download-agent-pthread.h" + +#include "curl/curl.h" + +typedef struct { + CURL *curl; + pthread_mutex_t mutex; + da_bool_t is_paused; + da_bool_t is_cancel_reqeusted; +} http_msg_t; + +typedef enum { + HTTP_STATE_READY_TO_DOWNLOAD = 0, + HTTP_STATE_REDIRECTED = 1, + HTTP_STATE_DOWNLOAD_REQUESTED = 2, + HTTP_STATE_DOWNLOAD_STARTED = 3, + HTTP_STATE_DOWNLOADING = 4, + HTTP_STATE_DOWNLOAD_FINISH = 5, + HTTP_STATE_REQUEST_CANCEL = 6, + HTTP_STATE_REQUEST_PAUSE = 7, + HTTP_STATE_REQUEST_RESUME = 8, + HTTP_STATE_CANCELED = 9, + HTTP_STATE_FAILED = 10, + HTTP_STATE_PAUSED = 11, + HTTP_STATE_RESUMED = 12, + HTTP_STATE_ABORTED = 13, + HTTP_STATE_WAIT_FOR_NET_ERR = 14, +} http_state_t; + +typedef enum { + HTTP_METHOD_GET = 1, + HTTP_METHOD_HEAD, + HTTP_METHOD_POST +} http_method_t; + +typedef struct { + char *url; + char **req_header; + int req_header_count; + char *install_path; + char *file_name; + char *etag; + char *temp_file_path; + char *pkg_name; + int network_bonding; + void *user_req_data; + void *user_client_data; +} req_info_t; + +typedef enum { + HTTP_EVENT_GOT_HEADER = 0, + HTTP_EVENT_GOT_PACKET, + HTTP_EVENT_FINAL, +// HTTP_EVENT_ABORT +} http_event_type_t; + +typedef struct _http_header_options_t http_header_options_t; +struct _http_header_options_t{ + char *field; + char *value; + http_header_options_t *next; +}; + +typedef struct _http_header_t http_header_t; +typedef http_header_t *http_msg_iter_t; +struct _http_header_t{ + char *field; + char *value; + http_header_options_t *options; + char *raw_value; // raw string including options + http_header_t *next; +}; + +typedef struct{ + char *http_method; + char *url; + http_header_t *head; + char *http_body; +} http_msg_request_t; + + +typedef struct{ + int status_code; + http_header_t *head; +} http_msg_response_t; + +typedef struct { + http_event_type_t type; + char *body; + int body_len; +#ifdef _RAF_SUPPORT + da_size_t received_len; +#endif + int status_code; + int error; +} http_raw_data_t; + +typedef void (*http_update_cb) (http_raw_data_t *data, void *user_param); + +typedef struct { + char *location_url; + http_state_t state; + pthread_mutex_t mutex_state; + pthread_mutex_t mutex_http; + pthread_cond_t cond_http; + http_msg_request_t *http_msg_request; + http_msg_response_t *http_msg_response; + http_method_t http_method; + http_msg_t *http_msg; + char *proxy_addr; + char *content_type_from_header; + char *file_name_from_header; + da_size_t content_len_from_header; + char *etag_from_header; + int error_code; // for error value for http abort. + da_size_t total_size; +#ifdef _RAF_SUPPORT + da_bool_t is_raf_mode_confirmed; +#endif + http_update_cb update_cb; +} http_info_t; + +typedef struct { + void *file_handle; + char *pure_file_name; + char *extension; + char *file_path; /* malloced in set_file_path_for_final_saving */ + char *mime_type;// For drm converting + char *buffer; + da_size_t buffer_len; + da_size_t file_size; /* http header's Content-Length has higher priority than DD's <size> */ + da_size_t bytes_written_to_file; /* The file size to be written at actual file */ +#ifdef _RAF_SUPPORT + da_size_t file_size_of_temp_file; /* If the temporary file is existed, the file size of it */ +#endif + da_bool_t is_updated; /* The flag for updating progress event only if the data is wrriten to file not buffer */ +} file_info_t; + +typedef struct { + int da_id; + int tid; + pthread_t thread_id; + http_info_t *http_info; + file_info_t *file_info; + req_info_t *req_info; + da_cb_t cb_info; + da_bool_t is_cb_update; + int update_time; +} da_info_t; + +da_info_t *da_info_list[DA_MAX_ID]; + +#define GET_STATE_MUTEX(INFO) (INFO->mutex_state) +#define GET_STATE(INFO) (INFO->state) +#define CHANGE_STATE(STATE,INFO) {\ + DA_MUTEX_LOCK (&GET_STATE_MUTEX(INFO));\ + GET_STATE(INFO) = STATE;\ + DA_LOGV("Changed state[%d]", GET_STATE(INFO));\ + DA_MUTEX_UNLOCK (&GET_STATE_MUTEX(INFO));\ + } + +da_ret_t get_available_da_id(int *available_id); +da_ret_t copy_user_input_data(da_info_t *da_info, const char *url, + req_data_t *ext_data, da_cb_t *da_cb_data); +da_bool_t is_valid_download_id(int id); +void destroy_da_info(int id); +void destroy_da_info_list(void); +da_ret_t get_da_info_with_da_id(int id, da_info_t **out_info); +da_ret_t init_http_msg_t(http_msg_t **http_msg); +void destroy_http_msg_t(http_msg_t *http_msg); +void reset_http_info(http_info_t *http_info); +void reset_http_info_for_resume(http_info_t *http_info); +void destroy_http_info(http_info_t *http_info); +void destroy_file_info(file_info_t *file_info); + +#endif /* _DOWNLOAD_AGENT_INFO_H */ diff --git a/agent/include/download-agent-dl-mgr.h b/agent/include/download-agent-dl-mgr.h new file mode 100755 index 0000000..c6be7c7 --- /dev/null +++ b/agent/include/download-agent-dl-mgr.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012 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 _Download_Agent_Basic_H +#define _Download_Agent_Basic_H + +#include "download-agent-dl-info.h" + +da_ret_t start_download(da_info_t *da_info); +da_ret_t cancel_download(int dl_id, da_bool_t is_enable_cb); +da_ret_t suspend_download(int dl_id, da_bool_t is_enable_cb); +da_ret_t resume_download(int dl_id); + +#endif diff --git a/agent/include/download-agent-encoding.h b/agent/include/download-agent-encoding.h new file mode 100755 index 0000000..49e74e9 --- /dev/null +++ b/agent/include/download-agent-encoding.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012 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 _Download_Agent_Encoding_H +#define _Download_Agent_Encoding_H + +#include "download-agent-type.h" + +da_bool_t is_base64_encoded_word(const char *in_str); +da_ret_t decode_base64_encoded_str(const char *in_encoded_str, + char **out_decoded_ascii_str); +void decode_url_encoded_str(const char *in_encoded_str, char **out_str); + +#endif // _Download_Agent_Encoding_H diff --git a/agent/include/download-agent-file.h b/agent/include/download-agent-file.h new file mode 100755 index 0000000..2788fdd --- /dev/null +++ b/agent/include/download-agent-file.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012 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 _DOWNLOAD_AGENT_FILE_H +#define _DOWNLOAD_AGENT_FILE_H + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "download-agent-type.h" +#include "download-agent-dl-info.h" + +#define DA_FILE_BUF_SIZE (1024*32) //bytes + +da_ret_t check_drm_convert(file_info_t *file_info); +da_bool_t is_file_exist(const char *file_path); +void get_file_size(char *file_path, da_size_t *out_file_size); +da_ret_t file_write_ongoing(file_info_t *file_info, char *body, int body_len); +da_ret_t file_write_complete(file_info_t *file_info); +#ifdef _RAF_SUPPORT +da_ret_t file_write_complete_for_raf(file_info_t *file_info); +#endif +da_ret_t start_file_writing(da_info_t *da_info); +da_ret_t start_file_append(file_info_t *file_info); +da_ret_t discard_download(file_info_t *file_info) ; +void clean_paused_file(file_info_t *file_info); +char *get_full_path_avoided_duplication(char *in_dir, + char *in_candidate_file_name, char *in_extension); +void remove_file(const char *file_path); +da_ret_t get_available_memory(char *dir_path, da_size_t len); +#endif diff --git a/agent/include/download-agent-http-mgr.h b/agent/include/download-agent-http-mgr.h new file mode 100755 index 0000000..95a0b3a --- /dev/null +++ b/agent/include/download-agent-http-mgr.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012 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 _Download_Agent_Http_Mgr_H +#define _Download_Agent_Http_Mgr_H + +#include <string.h> + +#include "download-agent-type.h" +#include "download-agent-dl-mgr.h" + +#define DA_MAX_SESSION_INFO DA_MAX_DOWNLOAD_ID + +da_ret_t request_http_download(da_info_t *da_info); +da_ret_t request_to_cancel_http_download(da_info_t *da_info); +da_ret_t request_to_abort_http_download(da_info_t *da_info); +da_ret_t request_to_suspend_http_download(da_info_t *da_info); +da_ret_t request_to_resume_http_download(da_info_t *da_info); +da_bool_t is_stopped_state(da_info_t *da_info); + +#endif diff --git a/agent/include/download-agent-http-msg-handler.h b/agent/include/download-agent-http-msg-handler.h new file mode 100755 index 0000000..70abbda --- /dev/null +++ b/agent/include/download-agent-http-msg-handler.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012 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 _Download_Agent_Http_Msg_Handler_H +#define _Download_Agent_Http_Msg_Handler_H + +#include "download-agent-type.h" +#include "download-agent-dl-info.h" + +// Reqeust Header +#define HTTP_FIELD_UAGENT "User-Agent" +#define HTTP_FIELD_HOST "Host" +#define HTTP_FIELD_UAPROF "X-Wap-Profile" +#define HTTP_FIELD_IF_MATCH "If-Match" +#define HTTP_FIELD_RANGE "Range" +#define HTTP_FIELD_IF_RANGE "If-Range" +#define HTTP_FIELD_ACCEPT_LANGUAGE "Accept-Language" +#define HTTP_FIELD_ACCEPT_CHARSET "Accept-Charset" + +// Response Header +#define HTTP_FIELD_CONTENT_LENGTH "Content-Length" +#define HTTP_FIELD_CONTENT_TYPE "Content-Type" +#define HTTP_FIELD_CONTENT_DISPOSITION "Content-Disposition" +#define HTTP_FIELD_LOCATION "Location" +#define HTTP_FIELD_DATA "Date" +#define HTTP_FIELD_ETAG "ETag" +#ifdef _RAF_SUPPORT +#define HTTP_FIELD_RAF_MODE "x-direct-write" +#endif + +#define HTTP_FIELD_END_OF_FIELD "\r\n" + +da_ret_t http_msg_request_create(http_msg_request_t **http_msg_request); +void http_msg_request_destroy(http_msg_request_t **http_msg_request); +da_ret_t http_msg_request_set_url(http_msg_request_t *http_msg_request, const char *url); +da_ret_t http_msg_request_get_url(http_msg_request_t *http_msg_request, const char **url); +da_ret_t http_msg_request_add_field(http_msg_request_t *http_msg_request, const char *field, const char *value); + +da_ret_t http_msg_response_create(http_msg_response_t **http_msg_response); +void http_msg_response_destroy(http_msg_response_t **http_msg_response); +da_ret_t http_msg_response_add_field(http_msg_response_t *http_msg_response, const char *field, const char *value); +/* Caution! Caller must free memory for every "char** out_xxx" for followings */ +da_bool_t http_msg_response_get_content_type(http_msg_response_t *http_msg_response, char **out_type); +void http_msg_response_set_content_type(http_msg_response_t *http_msg_response, const char *in_type); + +da_bool_t http_msg_response_get_content_length(http_msg_response_t *http_msg_response, da_size_t *out_length); +da_bool_t http_msg_response_get_content_disposition(http_msg_response_t *http_msg_response, char **out_disposition, char **out_file_name); +da_bool_t http_msg_response_get_ETag(http_msg_response_t *http_msg_response, char **out_value); +da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response, char **out_value); +da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response, char **out_value); +#ifdef _RAF_SUPPORT +da_bool_t http_msg_response_get_RAF_mode(http_msg_response_t *http_msg_response, + char **out_value); +#endif +da_ret_t http_msg_request_get_iter(http_msg_request_t *http_msg_request, http_msg_iter_t *http_msg_iter); +da_ret_t http_msg_response_get_iter(http_msg_response_t *http_msg_response, http_msg_iter_t *http_msg_iter); +// should remove later +da_bool_t http_msg_get_field_with_iter(http_msg_iter_t *http_msg_iter, char **field, char **value); +da_bool_t http_msg_get_header_with_iter(http_msg_iter_t *http_msg_iter, char **out_field, http_header_t **out_header); +da_bool_t extract_attribute_from_header(char *szHeadStr, const char *szFindStr, char **ppRtnValue); +da_bool_t http_msg_request_get_if_range(http_msg_request_t *http_msg_request, char **out_value); +da_bool_t http_msg_request_get_range(http_msg_request_t *http_msg_request, char **out_value); + +#endif // _Download_Agent_Http_Msg_Handler_H diff --git a/agent/include/download-agent-interface.h b/agent/include/download-agent-interface.h new file mode 100755 index 0000000..f5ce653 --- /dev/null +++ b/agent/include/download-agent-interface.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2012 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 _DOWNLOAD_AGENT_INTERFACE_H +#define _DOWNLOAD_AGENT_INTERFACE_H + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "download-agent-defs.h" +#include <stdarg.h> + +typedef struct { + int download_id; + char *file_type; + unsigned long long file_size; + char *tmp_saved_path; + char *content_name; + char *etag; +} download_info_t; + +typedef struct { + int download_id; + char *saved_path; + char *etag; + int err; + int http_status; +} finished_info_t; + +typedef struct { + const char **request_header; + int request_header_count; + const char *install_path; + const char *file_name; + const char *temp_file_path; + const char *etag; + const char *pkg_name; + int network_bonding; + void *user_req_data; + void *user_client_data; +} req_data_t; + +typedef void (*da_paused_cb) (int download_id, + void *user_param1, void *user_param2); +typedef void (*da_progress_cb) (int download_id, + unsigned long long received_size, + void *user_param1, void *user_param2); +typedef void (*da_started_cb) (download_info_t *download_info, + void *user_param1, void *user_param2); +typedef void (*da_finished_cb) (finished_info_t *finished_info, + void *user_param1, void *user_param2); + +typedef struct { + da_started_cb download_info_cb; + da_progress_cb progress_cb; + da_finished_cb finished_cb; + da_paused_cb paused_cb; +} da_cb_t; + +EXPORT_API int da_init(); +EXPORT_API int da_deinit(); + +EXPORT_API int da_start_download(const char *url, req_data_t *ext_data, + da_cb_t *da_cb_data, int *download_id); +EXPORT_API int da_cancel_download(int download_id); +EXPORT_API int da_cancel_download_without_update(int download_id); +EXPORT_API int da_suspend_download(int download_id); +EXPORT_API int da_suspend_download_without_update(int download_id); +EXPORT_API int da_resume_download(int download_id); +EXPORT_API int da_is_valid_download_id(int download_id); + +#ifdef __cplusplus +} +#endif + +#endif //_DOWNLOAD_AGENT_INTERFACE_H + + diff --git a/agent/include/download-agent-mime-util.h b/agent/include/download-agent-mime-util.h new file mode 100755 index 0000000..7f57899 --- /dev/null +++ b/agent/include/download-agent-mime-util.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012 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 _Download_Agent_Mime_Table_H +#define _Download_Agent_Mime_Table_H + +#include "download-agent-type.h" + +#define NO_EXTENSION_NAME_STR "dat" + +#define DD_MIME_STR "application/vnd.oma.dd+xml" +#define DD_EXT_STR "*.dd" +#define DRM_MIME_MSG_STR "application/vnd.oma.drm.message" +#define DRM_EXT_STR "*.dm" +#define DRM_MIME_CONTENT_STR "application/vnd.oma.drm.content" + +typedef struct { + char *standard; + char *normal; +} Ext_translation_table; + +da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type); +da_bool_t da_get_extension_name_from_url(char *url, char **ext); +da_ret_t da_mime_get_ext_name(char *mime, char **ext); +da_bool_t da_get_file_name_from_url(char *url, char **name) ; +void delete_prohibited_char(char *szTarget, int str_len); +da_ret_t get_extension_from_mime_type(char *mime_type, char **extension); +#ifdef _ENABLE_OMA_DRM +da_bool_t is_content_drm_dcf(char *content_type); +da_bool_t is_content_drm_dm(char *content_type); +#endif + + + +#endif diff --git a/agent/include/download-agent-plugin-conf.h b/agent/include/download-agent-plugin-conf.h new file mode 100755 index 0000000..11e8095 --- /dev/null +++ b/agent/include/download-agent-plugin-conf.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012 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 _Download_Agent_Plugin_Conf_H +#define _Download_Agent_Plugin_Conf_H + +#include "download-agent-type.h" +#include "download-agent-interface.h" + +da_ret_t get_user_agent_string(char **uagent_str); +char *get_proxy_address(void); +#ifdef _RAF_SUPPORT +//test code +void get_smart_bonding_vconf(); +#endif + +#endif diff --git a/agent/include/download-agent-plugin-drm.h b/agent/include/download-agent-plugin-drm.h new file mode 100644 index 0000000..361f387 --- /dev/null +++ b/agent/include/download-agent-plugin-drm.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2012 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 _Download_Agent_Plugin_Drm_H +#define _Download_Agent_Plugin_Drm_H + +#include "download-agent-type.h" + +da_bool_t EDRM_convert(const char *in_file_path, char **out_file_path); +da_ret_t EDRM_wm_get_license(char *rights_url, char **out_content_url); + +#endif diff --git a/agent/include/download-agent-plugin-libcurl.h b/agent/include/download-agent-plugin-libcurl.h new file mode 100644 index 0000000..67a4c53 --- /dev/null +++ b/agent/include/download-agent-plugin-libcurl.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012 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 _Download_Agent_Plugin_Libcurl_H +#define _Download_Agent_Plugin_Libcrul_H + +#include "download-agent-type.h" +#include "download-agent-dl-info.h" + +#define MAX_SESSION_COUNT DA_MAX_DOWNLOAD_REQ_AT_ONCE +#define MAX_TIMEOUT DA_MAX_TIME_OUT + +da_ret_t PI_http_start(da_info_t *da_info); +da_ret_t PI_http_disconnect(http_info_t *info); +da_ret_t PI_http_cancel(http_info_t *info); +da_ret_t PI_http_pause(http_info_t *info); +da_ret_t PI_http_unpause(http_info_t *info); +#ifdef _RAF_SUPPORT +da_ret_t PI_http_set_file_name_to_curl(http_msg_t *http_msg, char *file_path); +#endif + +#endif diff --git a/agent/include/download-agent-pthread.h b/agent/include/download-agent-pthread.h new file mode 100755 index 0000000..2748581 --- /dev/null +++ b/agent/include/download-agent-pthread.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2012 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 _DOWNLOAD_AGENT_PTHREAD_H +#define _DOWNLOAD_AGENT_PTHREAD_H + +#include <pthread.h> +#include <errno.h> +#include <time.h> + +#include "download-agent-debug.h" + +#define DA_MUTEX_INIT(mutex_add, attr) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_init(mutex_add, attr);\ + if (0 == ret){\ + break;\ + }\ + else if (EINVAL == ret){\ + DA_LOGE("pthread_mutex_init FAIL with EINVAL.");\ + break;\ + }\ + else if (ENOMEM == ret){\ + DA_LOGE("pthread_mutex_init FAIL with ENOMEM.");\ + break;\ + }\ + else{\ + DA_LOGE("pthread_mutex_init FAIL with %d.", ret);\ + break;\ + }\ + } while(1);\ +} + +#define DA_COND_INIT(cond_add, attr) do {\ + if (0 != pthread_cond_init(cond_add, attr)){\ + DA_LOGE("pthread_cond_init FAIL");\ + }\ +} while(0) + +#define DA_MUTEX_LOCK(mutex_add) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_lock(mutex_add);\ + if (0 == ret){\ + break;\ + }\ + else if (EINVAL == ret){\ + DA_LOGE("pthread_mutex_lock FAIL with EINVAL.");\ + break;\ + }\ + else if (EDEADLK == ret){\ + DA_LOGE("pthread_mutex_lock FAIL with EDEADLK.");\ + break;\ + }\ + else{\ + DA_LOGE("pthread_mutex_lock FAIL with %d.", ret);\ + break;\ + }\ + } while(1);\ +} + +#define DA_MUTEX_UNLOCK(mutex_add) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_unlock(mutex_add);\ + if (0 == ret){\ + break;\ + }\ + else if (EINVAL == ret) {\ + DA_LOGE("pthread_mutex_unlock FAIL with EINVAL.");\ + break;\ + }\ + else if (EPERM == ret) {\ + DA_LOGE("pthread_mutex_unlock FAIL with EPERM.");\ + break;\ + }\ + else {\ + DA_LOGE("pthread_mutex_unlock FAIL with %d.", ret);\ + break;\ + }\ + } while(1);\ +} + +#define DA_COND_SIGNAL(cond_add) do {\ + if (0 != pthread_cond_signal(cond_add)) {\ + DA_LOGE("pthread_cond_signal FAIL");\ + }\ + } while(0) + +#define DA_COND_WAIT(cond_add, mutex_add) do {\ + if (0 != pthread_cond_wait(cond_add, mutex_add)){\ + DA_LOGE("pthread_cond_wait FAIL");\ + }\ + } while(0) + +#define DA_COND_TIMED_WAIT(cond_add, mutex_add, time) do {\ + if (0 != pthread_cond_timedwait(cond_add, mutex_add, time)){\ + DA_LOGE("pthread_cond_wait FAIL");\ + }\ + } while(0) + + +#define DA_COND_DESTROY(cond_add) do {\ + if (0 != pthread_cond_destroy(cond_add)){\ + DA_LOGE("pthread_cond_destroy FAIL");\ + }\ + } while(0) + +#define DA_MUTEX_DESTROY(mutex_add) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_destroy(mutex_add);\ + if (0 == ret){\ + break;\ + }\ + else if (EINVAL == ret){\ + DA_LOGE("pthread_mutex_destroy FAIL with EINVAL.");\ + break;\ + }\ + else if (EBUSY == ret){\ + DA_LOGE("pthread_mutex_destroy FAIL with EBUSY.");\ + break;\ + }\ + else {\ + DA_LOGE("pthread_mutex_destroy FAIL with %d.", ret);\ + break;\ + }\ + } while(1);\ +} +#endif diff --git a/agent/include/download-agent-type.h b/agent/include/download-agent-type.h new file mode 100755 index 0000000..e77c121 --- /dev/null +++ b/agent/include/download-agent-type.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012 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 _DOWNLOAD_AGENT_TYPE_H +#define _DOWNLOAD_AGENT_TYPE_H + +#include "download-agent-defs.h" + +typedef int da_ret_t; +typedef int da_bool_t; +typedef unsigned long long da_size_t; + +#define IS_NOT_VALID_ID(x) (x <= DA_INVALID_ID) + +#define DA_MAX_URI_LEN 1024 +#define DA_MAX_FULL_PATH_LEN 356 // need configuration +#define DA_MAX_FILE_PATH_LEN 256 // need configuration +#define DA_MAX_STR_LEN 256 +#define DA_MAX_MIME_STR_LEN 256 +#define DA_MAX_PROXY_ADDR_LEN 64 // e.g. 100.200.300.400:10000 + +#define SCHEME_HTTP "http://" + +#define DA_DEFAULT_INSTALL_PATH_FOR_PHONE "/opt/usr/media/Downloads" + +#define DA_MAX_ID DA_MAX_DOWNLOAD_REQ_AT_ONCE + +#define SAVE_FILE_BUFFERING_SIZE_50KB (50*1024) + +#define NULL_CHECK(DATA) {\ + if (!DATA) {\ + DA_LOGE("NULL CHECK!:%s",(#DATA));\ + return;\ + }\ +} + +#define NULL_CHECK_RET(DATA) {\ + if (!DATA) {\ + DA_LOGE("NULL CHECK!:%s",(#DATA));\ + return DA_ERR_INVALID_ARGUMENT;\ + }\ +} + +#define NULL_CHECK_GOTO(DATA) {\ + if (!DATA) {\ + DA_LOGE("NULL CHECK!:%s",(#DATA));\ + ret = DA_ERR_INVALID_ARGUMENT;\ + goto ERR;\ + }\ +} + +#define NULL_CHECK_RET_OPT(DATA, RET_DATA) {\ + if (!DATA) {\ + DA_LOGE("NULL CHECK!:%s",(#DATA));\ + return RET_DATA;\ + }\ +} + +#endif + @@ -0,0 +1,16 @@ +#!/bin/bash + +gbs build -A armv7l --include-all + +sdb root on +sdb shell change-booting-mode.sh --update + +sdb -d push /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/RPMS/org.tizen.browser* + +#sdb shell rpm -e --nodeps org.tizen.browser +#sdb shell pkgcmd -i -t rpm -p /root/org.tizen.browser-4* +#sdb shell sync +#sdb shell reboot + + + diff --git a/blog.txt b/blog.txt new file mode 100644 index 0000000..3dbb519 --- /dev/null +++ b/blog.txt @@ -0,0 +1,1758 @@ +info: generate repositories ... +info: build conf has been downloaded at: + /var/tmp/youngj-gbs/tizen.conf +[32minfo: [0mstart building packages from: /home/youngj/dev/spin/tizen_2_4_download-provider/download-provider (git) +2015-05-14 18:49 +0900 +gbs 0.23 +[32minfo: [0mprepare sources... +[32minfo: [0mstart export source from: /home/youngj/dev/spin/tizen_2_4_download-provider/download-provider ... +info: the following untracked files would be included: + .cproject + .project + agent/download-agent-plugin-libcurl.c~ + bi.sh + blog.txt + download-provider-w.manifest~ + download-provider.manifest~ + i.sh + packaging/download-provider.spec~ + refresh.sh +warning: Deprecated option '--git-export-only', please use '--no-build' instead! +info: Creating (native) source archive download-provider-2.1.23.tar.gz from '6faf3bf06df44cba1e07da17e7bfae625ac6cb29' +info: package files have been exported to: + /home/youngj/GBS-ROOT/local/sources/tizen/download-provider-2.1.23-0 +[32minfo: [0mretrieving repo metadata... +[32minfo: [0mparsing package data... +[32minfo: [0mbuilding repo metadata ... +[32minfo: [0mresolving skipped packages ... +[32minfo: [0mpackage dependency resolving ... +[32minfo: [0mnext pass: +download-provider +[32minfo: [0m*** [1/1] building download-provider-2.1.23-0 armv7l tizen (worker: 0) *** +VM_IMAGE: , VM_SWAP: +--repository /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/RPMS --repository http://168.219.209.55/download/snapshots/2.4-mobile/common/latest/repos/target/packages +logging output to /home/youngj/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.0/.build.log... +[ 0s] Memory limit set to 6608244KB +[ 0s] Using BUILD_ROOT=/home/youngj/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.0 +[ 0s] Using BUILD_ARCH=armv7l:armv7el:armv6l:armv5tejl:armv5tel:armv5l:armv4tl:armv4l:armv3l:noarch +[ 0s] +[ 0s] +[ 0s] santafe started "build download-provider.spec" at Thu May 14 09:49:49 UTC 2015. +[ 0s] +[ 0s] +[ 0s] processing specfile /home/youngj/GBS-ROOT/local/sources/tizen/download-provider-2.1.23-0/download-provider.spec ... +[ 0s] init_buildsystem --configdir /usr/lib/build/configs --cachedir /home/youngj/GBS-ROOT/local/cache --repository /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/RPMS --repository http://168.219.209.55/download/snapshots/2.4-mobile/common/latest/repos/target/packages --use-system-qemu /home/youngj/GBS-ROOT/local/sources/tizen/download-provider-2.1.23-0/download-provider.spec ... +[ 0s] initializing /home/youngj/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.0/.srcfiles.cache ... +[ 0s] /usr/lib/build/createrpmdeps /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/RPMS +[ 1s] /usr/lib/build/createrepomddeps --cachedir=/home/youngj/GBS-ROOT/local/cache http://168.219.209.55/download/snapshots/2.4-mobile/common/latest/repos/target/packages +[ 1s] expanding package dependencies... +[ 2s] copying qemu +[ 2s] +[ 2s] registering binfmt handlers for VM +[ 2s] warning: /usr/lib/build/qemu-reg: line 7: interpreter '/usr/bin/qemu-arm64-binfmt' not found +[ 2s] write: Invalid argument +[ 2s] /proc/sys/fs/binfmt_misc/register: write failed +[ 2s] /usr/lib/build/qemu-reg: line 7: write failed. Content: :aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-arm64-binfmt:P +[ 2s] +[ 2s] /.build/qemu-reg: No such file or directory +[ 2s] /.build/qemu-reg: failed. Trying alternate binfmt file +[ 2s] warning: /usr/lib/build/qemu-reg: line 7: interpreter '/usr/bin/qemu-arm64-binfmt' not found +[ 2s] write: Invalid argument +[ 2s] /proc/sys/fs/binfmt_misc/register: write failed +[ 2s] /usr/lib/build/qemu-reg: line 7: write failed. Content: :aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-arm64-binfmt:P +[ 2s] +[ 2s] /usr/lib/build/qemu-reg: binfmt registration failed +[ 9s] [1/4] downloading http://168.219.209.55/download/snapshots/2.4-mobile/common/latest/repos/target/packages/armv7l/capi-network-wifi-direct-devel-1.2.31-6.7.armv7l.rpm ... +[ 10s] [2/4] downloading http://168.219.209.55/download/snapshots/2.4-mobile/common/latest/repos/target/packages/armv7l/libresourced-devel-0.2.86-7.11.armv7l.rpm ... +[ 10s] [3/4] downloading http://168.219.209.55/download/snapshots/2.4-mobile/common/latest/repos/target/packages/noarch/model-build-features-0.4-7.1.noarch.rpm ... +[ 10s] [4/4] downloading http://168.219.209.55/download/snapshots/2.4-mobile/common/latest/repos/target/packages/armv7l/smack-devel-1.0+s14-3.13.armv7l.rpm ... +[ 10s] +[ 11s] reordering...cycle: gcc49-locale -> gcc49 +[ 11s] breaking dependency gcc49 -> gcc49-locale +[ 11s] cycle: coreutils -> pam +[ 11s] breaking dependency pam -> coreutils +[ 11s] cycle: gio-branding-upstream -> libgio +[ 11s] breaking dependency libgio -> gio-branding-upstream +[ 11s] cycle: dbus-libs -> dbus +[ 11s] breaking dependency dbus-libs -> dbus +[ 11s] cycle: efl -> eina +[ 11s] breaking dependency eina -> efl +[ 11s] cycle: efl -> eo +[ 11s] breaking dependency eo -> efl +[ 11s] cycle: ecore -> eldbus +[ 11s] breaking dependency ecore -> eldbus +[ 11s] cycle: ecore -> evas +[ 11s] breaking dependency ecore -> evas +[ 11s] cycle: pulseaudio-libs -> pulseaudio +[ 11s] breaking dependency pulseaudio -> pulseaudio-libs +[ 11s] cycle: pkgmgr-info -> pkgmgr-info-parser +[ 11s] breaking dependency pkgmgr-info -> pkgmgr-info-parser +[ 11s] cycle: pkgmgr-client -> pkgmgr-installer -> pkgmgr +[ 11s] breaking dependency pkgmgr-client -> pkgmgr-installer +[ 11s] cycle: pkgmgr-client -> pkgmgr +[ 11s] breaking dependency pkgmgr -> pkgmgr-client +[ 11s] cycle: pkgmgr -> pkgmgr-installer +[ 11s] breaking dependency pkgmgr -> pkgmgr-installer +[ 11s] cycle: libalarm -> alarm-server +[ 11s] breaking dependency alarm-server -> libalarm +[ 11s] cycle: libsensord -> sensord +[ 11s] breaking dependency sensord -> libsensord +[ 11s] cycle: libsoftokn3 -> nss +[ 11s] breaking dependency nss -> libsoftokn3 +[ 11s] cycle: rpm -> rpm-libs +[ 11s] breaking dependency rpm-libs -> rpm +[ 11s] done +[ 12s] deleting download-provider +[ 12s] deleting download-provider-devel +[ 13s] [1/326] [2/326] [3/326] [4/326] installing model-build-features-0.4-7.1 +[ 13s] [5/326] [6/326] [7/326] [8/326] [9/326] [10/326] [11/326] [12/326] [13/326] [14/326] [15/326] [16/326] [17/326] [18/326] [19/326] [20/326] [21/326] [22/326] [23/326] [24/326] [25/326] [26/326] [27/326] [28/326] [29/326] [30/326] [31/326] [32/326] [33/326] [34/326] [35/326] [36/326] [37/326] [38/326] [39/326] [40/326] [41/326] [42/326] [43/326] [44/326] [45/326] [46/326] [47/326] [48/326] [49/326] [50/326] [51/326] [52/326] [53/326] [54/326] [55/326] [56/326] [57/326] [58/326] [59/326] [60/326] [61/326] [62/326] [63/326] [64/326] [65/326] [66/326] [67/326] [68/326] [69/326] [70/326] [71/326] [72/326] [73/326] [74/326] [75/326] [76/326] [77/326] [78/326] [79/326] [80/326] [81/326] [82/326] installing fribidi-devel-0.19.6-2.2 +[ 13s] [83/326] installing openssl-devel-1.0.1m-4.8 +[ 15s] [84/326] installing smack-devel-1.0+s14-3.13 +[ 16s] [85/326] [86/326] [87/326] [88/326] [89/326] [90/326] [91/326] [92/326] [93/326] [94/326] [95/326] [96/326] [97/326] [98/326] [99/326] [100/326] [101/326] [102/326] [103/326] [104/326] installing libwayland-server-1.6.0-1.19 +[ 16s] [105/326] [106/326] [107/326] [108/326] [109/326] [110/326] [111/326] installing gettext-runtime-0.18.3.2-2.18 +[ 17s] [112/326] [113/326] [114/326] [115/326] [116/326] [117/326] [118/326] [119/326] [120/326] [121/326] [122/326] [123/326] [124/326] installing libicu-devel-51-1.270 +[ 17s] [125/326] [126/326] [127/326] [128/326] installing lua-5.1.4-2.16 +[ 18s] [129/326] [130/326] [131/326] [132/326] [133/326] [134/326] [135/326] [136/326] [137/326] [138/326] installing libwayland-cursor-1.6.0-1.19 +[ 18s] [139/326] [140/326] [141/326] [142/326] [143/326] [144/326] [145/326] [146/326] [147/326] installing libsndfile-devel-1.0.28-3.5 +[ 19s] [148/326] [149/326] [150/326] [151/326] [152/326] [153/326] [154/326] [155/326] [156/326] [157/326] [158/326] [159/326] installing lua-devel-5.1.4-2.16 +[ 19s] [160/326] [161/326] [162/326] [163/326] [164/326] [165/326] installing gettext-tools-0.18.3.2-2.18 +[ 21s] [166/326] [167/326] [168/326] [169/326] [170/326] installing wayland-devel-1.6.0-1.19 +[ 21s] [171/326] [172/326] [173/326] [174/326] [175/326] installing harfbuzz-devel-0.9.40-3.3 +[ 22s] [176/326] [177/326] [178/326] [179/326] [180/326] [181/326] [182/326] [183/326] [184/326] [185/326] [186/326] [187/326] [188/326] [189/326] [190/326] [191/326] [192/326] [193/326] [194/326] [195/326] [196/326] [197/326] [198/326] [199/326] [200/326] [201/326] [202/326] [203/326] [204/326] [205/326] [206/326] [207/326] [208/326] [209/326] installing dbus-devel-1.8.16-2.15 +[ 22s] [210/326] [211/326] [212/326] [213/326] [214/326] [215/326] [216/326] [217/326] [218/326] [219/326] [220/326] [221/326] installing systemd-devel-216-9.13 +[ 23s] [222/326] installing xdgmime-devel-0.0.12-1.48 +[ 23s] [223/326] [224/326] [225/326] [226/326] [227/326] [228/326] [229/326] [230/326] [231/326] [232/326] installing capi-content-mime-type-devel-0.0.3-1.49 +[ 23s] [233/326] installing libidn-devel-1.15-1.258 +[ 24s] [234/326] [235/326] installing eina-devel-1.13.0-39.8 +[ 24s] [236/326] installing sqlite-devel-3.7.14-6.5 +[ 24s] [237/326] installing vconf-internal-keys-0.0.152-15.1 +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-rcs-keys.sh +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-ail-keys.sh +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key db/ail+ail_info +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-desktop-mode-keys.sh +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-factory-keys.sh +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-webkit-keys.sh +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key db/webkit+user_agent +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-dailybriefing-keys.sh +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-aircommand-keys.sh +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-filemanager-keys.sh +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/filemanager+Mmc +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key db/filemanager+dbupdate +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-security-mdpp-keys.sh +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-ise-keys.sh +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key db/ise+keysound +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-sysman-keys.sh +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+added_usb_storage +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+removed_usb_storage +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+charger_status +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+charge_now +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+battery_status_low +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+battery_capacity +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+battery_level_status +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+usb_status +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+earjack +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+low_memory +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+sliding_keyboard +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+mmc_mount +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+mmc_unmount +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+mmc_format +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+mmc_err_status +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key db/sysman+mmc_dev_changed +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+hdmi +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+stime_changed +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+power_off +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sysman+mmc_format_progress +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/deviced+boot_power_on +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-kies-via-wifi-keys.sh +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-cloud-pdm-keys.sh +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-group-play-keys.sh +[ 27s] running ---------------------------------------------------- /opt/usr/vconf-internal-email-keys.sh +[ 27s] Key already exist. Use -f option to force update +[ 27s] Error! create key memory/sync+email +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-popsync-keys.sh +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-ode-keys.sh +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-system-keys.sh +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/system+timechanged +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key db/system+timechange +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key db/system+timechange_external +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-fmm-keys.sh +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-appservice-keys.sh +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-crash-keys.sh +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-idle-lock-keys.sh +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key db/idle_lock+bgset +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-quicksetting-keys.sh +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-pkgmgr-keys.sh +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/pkgmgr+status +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-keepit-keys.sh +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key db/keepit+screen_capture_destination +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-contacts-svc-keys.sh +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key db/contacts-svc+name_display_order +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key db/contacts-svc+name_sorting_order +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key db/contacts-svc+phonenumber_min_match_digit +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-pm-keys.sh +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/pm+state +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/pm+custom_brightness_status +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/pm+camera_status +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/pm+battery_timetoempty +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/pm+battery_timetofull +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/pm+brt_changed_lpm +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/pm+lcdoff_source +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/pm+key_ignore +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/pm+current_brt +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/pm+sip_status +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-sound-keys.sh +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/Sound+SoundStatus +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/Sound+SoundCaptureStatus +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key memory/private+Sound+VoiceControlOn +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-radio-keys.sh +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-download-keys.sh +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-account-keys.sh +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key db/account+sync_all +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key db/account+auto_sync +[ 28s] Key already exist. Use -f option to force update +[ 28s] Error! create key db/account+msg +[ 28s] running ---------------------------------------------------- /opt/usr/vconf-internal-mobiletv-keys.sh +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-calendar-keys.sh +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-qc-keys.sh +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-debug-keys.sh +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-myfile-keys.sh +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-mobile-hotspot-keys.sh +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/mobile_hotspot+mode +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/mobile_hotspot+connected_device +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key db/mobile_hotspot+security +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key db/mobile_hotspot+hide +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-voicerecorder-keys.sh +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-voice-keys.sh +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key db/voice_input+language +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-facebook-keys.sh +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-setup-wizard-keys.sh +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-mobex-connector-keys.sh +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-miracast-keys.sh +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-fota-consumer.sh +[ 30s] running ---------------------------------------------------- /opt/usr/vconf-internal-telephony-keys.sh +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+daemon_load_count +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+nw_name +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+plmn +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+lac +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+cell_id +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+roam_icon_mode +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+svc_type +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+svc_cs +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+svc_ps +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+svc_roam +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+zone_type +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+sim_slot +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+sim_slot2 +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+sim_slot_count +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+pb_init +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+sim_status +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+sim_is_changed +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+cphs_operator_name_full +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+cphs_operator_name_short +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key memory/telephony+call_state +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key db/telephony+call_forward_state +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key db/telephony+call_forward_state2 +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key db/telephony+ss_cli_state +[ 30s] Key already exist. Use -f option to force update +[ 30s] Error! create key db/telephony+ss_cli_state2 +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+tapi_state +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+spn_disp_condition +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+spn +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+rssi +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+imei +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+ps_type +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/setting+3gEnabled +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+telephony_ready +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+nitz_gmt +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+nitz_event_gmt +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+nitz_zone +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/telephony+flight_mode +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+svc_act +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/telephony+sim_power_state1 +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/telephony+sim_power_state2 +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/telephony+dualsim+receive_incoming_call +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/telephony+modem_always_on +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/telephony+activation_completed +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+emergency_mode +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/telephony+mdn +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+call_alert_signal_type +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+call_alert_pitch_type +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/telephony+call_signal +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/telephony+dualsim+default_data_service +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/telephony+dualsim+preferred_voice_subscription +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/telephony+dualsim+default_subscription +[ 31s] running ---------------------------------------------------- /opt/usr/vconf-internal-location-keys.sh +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/location+setting+Usemylocation +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/location+setting+GpsEnabled +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/location+setting+AgpsEnabled +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/location+setting+NetworkEnabled +[ 31s] running ---------------------------------------------------- /opt/usr/vconf-internal-lockscreen-keys.sh +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/lockscreen+phone_lock_verification +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/lockscreen+wallpaper_type +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/lockscreen+security_auto_lock +[ 31s] running ---------------------------------------------------- /opt/usr/vconf-internal-eas-keys.sh +[ 31s] running ---------------------------------------------------- /opt/usr/vconf-internal-livebox-keys.sh +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/data-provider-master+started +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key db/data-provider-master+serveraddr +[ 31s] Key already exist. Use -f option to force update +[ 31s] Error! create key memory/private+data-provider-master+restart_count +[ 32s] running ---------------------------------------------------- /opt/usr/vconf-internal-nfc-keys.sh +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/nfc+feature +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/nfc+enable +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/nfc+sbeam +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/nfc+predefined_item_state +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/nfc+predefined_item +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/nfc+se_type +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/nfc+wallet_mode +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/nfc+state_by_flight +[ 32s] running ---------------------------------------------------- /opt/usr/vconf-internal-menuscreen-keys.sh +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/menuscreen+desktop +[ 32s] running ---------------------------------------------------- /opt/usr/vconf-internal-smemo-keys.sh +[ 32s] running ---------------------------------------------------- /opt/usr/vconf-internal-boot-animation-keys.sh +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key memory/boot_animation+finished +[ 32s] running ---------------------------------------------------- /opt/usr/vconf-internal-allshare-keys.sh +[ 32s] running ---------------------------------------------------- /opt/usr/vconf-internal-google-pim-sync-keys.sh +[ 32s] running ---------------------------------------------------- /opt/usr/vconf-internal-dr-keys.sh +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key memory/data_router+osp_serial_open +[ 32s] running ---------------------------------------------------- /opt/usr/vconf-internal-svoice-keys.sh +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/svoice+package_name +[ 32s] running ---------------------------------------------------- /opt/usr/vconf-internal-bt-keys.sh +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key memory/bluetooth+btsco +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key memory/bluetooth+sco_headset_name +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/bluetooth+lestatus +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key memory/bluetooth+dutmode +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key file/private+libug-setting-bluetooth-efl+visibility_time +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key file/private+bt-service+bt_off_due_to_timeout +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key file/private+bt-core+powersaving_mode_deactivated +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key file/private+bt-core+flight_mode_deactivated +[ 32s] running ---------------------------------------------------- /opt/usr/vconf-internal-video-player-keys.sh +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/private+org.tizen.videos+personal_no_ask_again +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/private+org.tizen.videos+backgroud_playing +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/private+org.tizen.videos+auto_search_subtitle_file +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/private+org.tizen.videos+show_subtitle +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/private+org.tizen.videos+subtitle_size +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/private+org.tizen.videos+subtitle_edge +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/private+org.tizen.videos+subtitle_font +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/private+org.tizen.videos+subtitle_font_color +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/private+org.tizen.videos+subtitle_alignment +[ 32s] Key already exist. Use -f option to force update +[ 32s] Error! create key db/private+org.tizen.videos+subtitle_font_color_hex +[ 32s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+subtitle_bg_color +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+subtitle_bg_color_hex +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+subtitle_caption_win_color_hex +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+display_color_tone_type +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+outdoor_visibility +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+preview_url_videos +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+preview_url_records +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+preview_audio_track +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+show_indicator +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+show_border +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+repeat_mode +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+screen_mode +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+sound_alive +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+motion_asked +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+storage_type +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+sort_type +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+view_as_type +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+capture_on +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+tag_active +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+tag_weather +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+tag_location +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+tag_edit_weather +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key memory/private+org.tizen.videos+allow_dock_connect +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key memory/private+org.tizen.videos+extern_mode +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+multi_play +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/private+org.tizen.videos+main_display_tab +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key memory/private+org.tizen.videos+mirroring_warning +[ 33s] running ---------------------------------------------------- /opt/usr/vconf-internal-shot-tizen-keys.sh +[ 33s] running ---------------------------------------------------- /opt/usr/vconf-internal-music-keys.sh +[ 33s] running ---------------------------------------------------- /opt/usr/vconf-internal-wifi-keys.sh +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key memory/wifi+state +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key memory/wifi+transfer_state +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key memory/wifi+strength +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key memory/wifi+wifi_qs_exit +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/wifi+enable_quick_start +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key memory/wifi+connected_ap_name +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key memory/wifi+ug_run_state +[ 33s] Key already exist. Use -f option to force update +[ 33s] Error! create key db/wifi+bssid_address +[ 33s] running ---------------------------------------------------- /opt/usr/vconf-internal-chatonv-keys.sh +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-testmode-keys.sh +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/testmode+fast_dormancy +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/testmode+fast_dormancy2 +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-starter-keys.sh +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/starter+sequence +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/starter+use_volume_key +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key db/starter+is_fallback +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key db/starter+fallback_pkg +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-camera-keys.sh +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/camera+state +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key file/camera+shutter_sound_policy +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/recorder+state +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/camera+pid +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/camera+flash_state +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/recorder+pid +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-ready-to-share-keys.sh +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-oma-ds-keys.sh +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-browser-keys.sh +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-memo-keys.sh +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-call-keys.sh +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key db/call+vol_level +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-idle-screen-keys.sh +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/idle-screen+safemode +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-gallery-setting-keys.sh +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-image-viewer-keys.sh +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-isf-keys.sh +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key db/isf+input_language +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key db/isf+input_keyboard_uuid +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/isf+input_panel_state +[ 35s] running ---------------------------------------------------- /opt/usr/vconf-internal-dnet-keys.sh +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/dnet+status +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/dnet+network_config +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/dnet+ip +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/dnet+proxy +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/dnet+wifi +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/dnet+cellular +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/dnet+state +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/dnet+state2 +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key memory/dnet+packet_state +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key db/dnet+statistics+cellular+totalrcv +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key db/dnet+statistics+cellular+totalrcv2 +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key db/dnet+statistics+cellular+totalsnt +[ 35s] Key already exist. Use -f option to force update +[ 35s] Error! create key db/dnet+statistics+cellular+totalsnt2 +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/dnet+statistics+cellular+lastrcv +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/dnet+statistics+cellular+lastrcv2 +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/dnet+statistics+cellular+lastsnt +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/dnet+statistics+cellular+lastsnt2 +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/dnet+statistics+wifi+totalrcv +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/dnet+statistics+wifi+totalsnt +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/dnet+statistics+wifi+lastrcv +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/dnet+statistics+wifi+lastsnt +[ 36s] running ---------------------------------------------------- /opt/usr/vconf-internal-mobex-engine-keys.sh +[ 36s] running ---------------------------------------------------- /opt/usr/vconf-internal-dock-keys.sh +[ 36s] running ---------------------------------------------------- /opt/usr/vconf-internal-syncml-keys.sh +[ 36s] running ---------------------------------------------------- /opt/usr/vconf-internal-admin-keys.sh +[ 36s] running ---------------------------------------------------- /opt/usr/vconf-internal-baby-crying-detector-keys.sh +[ 36s] running ---------------------------------------------------- /opt/usr/vconf-internal-csc-keys.sh +[ 36s] running ---------------------------------------------------- /opt/usr/vconf-internal-msg-keys.sh +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key memory/msg+ready +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/msg+recv_sms +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/msg+recv_mms +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/msg+network_mode +[ 36s] running ---------------------------------------------------- /opt/usr/vconf-internal-ciss-keys.sh +[ 36s] running ---------------------------------------------------- /opt/usr/vconf-internal-alarm-keys.sh +[ 36s] running ---------------------------------------------------- /opt/usr/vconf-internal-setting-keys.sh +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+call+vibration_pattern_path +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+touch_sounds +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+button_sounds +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+sound_lock +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+media+sound_volume +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+Brightness +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+automatic_brightness_level +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+auto_display_adjustment +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+lcd_backlight_normal +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+call+ringtone_sound_volume +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+call+ringtone_path +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+call+ringtone_path_with_time +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+call+ringtone_default_path +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+call+vibration_level +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+call+vibration_type +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+noti+sound_volume +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+noti+msg_alert_rep_type +[ 36s] Key already exist. Use -f option to force update +[ 36s] Error! create key db/setting+sound+noti+msg_ringtone_path +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+sound+noti+ringtone_default_path +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+sound+noti+email_alert_rep_type +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+sound+noti+email_ringtone_path +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+sound+noti+vibration_level +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+sound+touch_feedback+sound_volume +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+sound+touch_feedback+vibration_level_bak +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+sound+touch_feedback+vibration_level +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key memory/setting+usb_in_mode_change +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key memory/setting+usb_mode +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key memory/setting+usb_sel_mode +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+debug_mode +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+select_network +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+network_mode +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+power_on_lock +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+phone_lock_attempts_left +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+phone_lock_timestamp +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+sim_lock_timestamp +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+simple_password +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+screen_lock_type +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+3rd_lock_pkg_name +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+font_size +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+font_type +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+brightness_automatic +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+automatic_time_update +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+date_format +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+cityname_id +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+weekofday_format +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+lang +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+ticker_noti+twitter +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+accessibility+font_size +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+accessibility+font_name +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key memory/setting+accessibility+torch_light +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+accessibility+rapid_key_input +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+accessibility+assistive_light_reminder +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+accessibility+turn_off_all_sounds +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+sound+sound_on_bak +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+sound+touch_sounds_bak +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+sound+sound_lock_bak +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+accessibility+accept_call +[ 38s] Key already exist. Use -f option to force update +[ 38s] Error! create key db/setting+accessibility+enable_auto_answer +[ 38s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+accessibility+auto_answer +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+accessibility+powerkey_end_calls +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+accessibility+led_notify +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+accessibility+lock_time +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+accessibility+power_key_hold +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+accessibility+easy_touch_mode +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+accessibility+tts +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+accessibility+speech_rate +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+system_mode+status +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+status +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+wifi +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+bt +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+gps +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+data_sync +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+hotspot +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+brt+status +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+brt+auto+status +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+brt+value +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+backlight+time +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+system_mode+reminder +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+at +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+cpu +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+display +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+bg_color +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+pwrsv+custom_mode+screen_vib +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+fmm+sim_change_alert +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+fmm+recipients +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+fmm+sender +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+fmm+alert_message +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+fmm+remote_control +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+fmm+location_consent +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/menu_widget+language +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/menu_widget+regionformat +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+menuscreen+package_name +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+homescreen+package_name +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+transaction_tracking +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+expiry_reminder +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+roaming_network +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+default_memory+download +[ 39s] Key already exist. Use -f option to force update +[ 39s] Error! create key db/setting+default_memory+download_contents +[ 39s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+default_memory+download_application +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+default_memory+install_applications +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+default_memory+wifi_direct +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+default_memory+bluetooth +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+default_memory+camera +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+default_memory+voice_recorder +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+battery_percentage +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+accessibility+screen_zoom +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+timezone_id +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+timezone +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+rotate_lock +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+auto_rotate_screen +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+accessibility+mono_audio +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+accessibility+led_playing_path +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/menu_widget+regionformat_time1224 +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+sim_lock_attempts_left +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key memoroy/setting+font_changed +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+device_name +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+sound+sound_on +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+sound+vibration_on +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+sound+vibrate_when_ringing +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+sound+vibrate_when_notification +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+sound+haptic_feedback_on +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+data_roaming +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+motion_active +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+use_tilt +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+use_tilt_scroll +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+tilt_scroll_sensitivity +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+use_panning +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+use_panning_browser +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+panning_sensitivity +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+panning_browser_sensitivity +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+use_double_tap +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+use_turn_over +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+use_pick_up +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+use_pick_up_call +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+use_shake +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+use_mute_pause +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+motion+palm_motion +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+motion+palm_touch_mute +[ 40s] Key already exist. Use -f option to force update +[ 40s] Error! create key db/setting+motion+palm_swipe_capture +[ 40s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+motion+palm_swipe_tryit +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/menu_widget+bgset +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+devoption+bgprocess +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+default_rendering_engine +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+most_recently_setting +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+data_limit +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+select_network_act +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+lang_automatic +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+data_usage_cycle +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+data_usage_roaming_status +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+set_data_usage_limit +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+accessibility+taphold_delay +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+accessibility+speak_passwd +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+accessibility+sound_balance +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+selected_num +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+screenmode+selected_name +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+lcd_timeout_normal_backup +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+led_indicator+charging +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+led_indicator+low_batt +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+led_indicator+notifications +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+led_indicator+voice_rec +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key memory/setting+rotate_hold +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key memory/setting+tmp_font_name +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+psmode +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+mmc_encryption+status +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+mmc_encryption+is_encrypting_flag +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+display+touchkey_light_duration +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+display+screen_capture_destination +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+display+edit_after_screen_capture +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+network_restrict_mode +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+lcd_freq_control +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+display+dynamic_status_bar +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+network+mobile_data_on_reminder +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+network+mobile_data_off_reminder +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+usb_otg +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+psmode_shortcut +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+handsfree_sound_reminder +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+firewall +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key memory/setting+personal +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+personal_unlock_method +[ 42s] Key already exist. Use -f option to force update +[ 42s] Error! create key db/setting+personal_off_popup_do_not_show_flag +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+personal_attempts +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+personal_timestamp +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+developer_option_state +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+firewall_net_interface +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+change_ui+theme +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+change_ui+color_theme_wallpaper_set +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+win_gray +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+win_fps +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+open_via_multi +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+verify_samsung_account +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+fingerprint_no_disclaimer +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+upsm_no_disclaimer +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+emergency+mode +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/setting+emergency_no_disclaimer +[ 43s] running ---------------------------------------------------- /opt/usr/vconf-internal-usb-keys.sh +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key memory/usb+cur_mode +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/usb+sel_mode +[ 43s] running ---------------------------------------------------- /opt/usr/vconf-internal-wms-keys.sh +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+preview_message +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+safety_enable +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key memory/wms+safety_message_trigger +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+smart_relay_support +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+smart_search_support +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+wakeup_by_gesture_setting +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+application_shortcuts_down_package_class +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+application_shortcuts_up_package_class +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+clocks_set_idle +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+favorites_reorder +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+noti_setting_setconnected_active_path +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+package_exist_emailminiapp +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+powerkey_double_pressing +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+safety_cam_disable +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key memory/wms+shortcut_clock +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+watch_pkgname +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key memory/wms+watchapps_reorder_data +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key memory/wms+watchapps_reorder_viewtype +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+contacts_settings +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key memory/wms+gm_setupwizard_data_receiving_finished +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+gm_setupwizard_eula_finished +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key memory/wms+gm_setupwizard_restore_finished +[ 43s] Key already exist. Use -f option to force update +[ 43s] Error! create key db/wms+is_initialed_watch +[ 43s] Key already exist. Use -f option to force update +[ 44s] Error! create key db/wms+is_master_reset +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key db/wms+restore_start +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key db/wms+smart_relay +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key db/wms+sync_contacts +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key db/wms+sync_logs +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key db/wms+wakeup_by_gesture_enable +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key memory/wms+wmanager_connected +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key db/wms+wearable_status_xml +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key db/wms+host_status_xml +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key db/wms+shake_gesture_enable +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key db/wms+palm_over_enable +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key db/wms+palm_swipe_enable +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key db/wms+summary_panel +[ 44s] running ---------------------------------------------------- /opt/usr/vconf-internal-player-keys.sh +[ 44s] Key already exist. Use -f option to force update +[ 44s] Error! create key memory/Player+XvStateInfo +[ 44s] running ---------------------------------------------------- /opt/usr/vconf-internal-mdm-keys.sh +[ 44s] running ---------------------------------------------------- /opt/usr/vconf-internal-pwlock-keys.sh +[ 44s] [238/326] [239/326] [240/326] [241/326] [242/326] [243/326] [244/326] [245/326] [246/326] [247/326] [248/326] [249/326] [250/326] installing libstorage-devel-0.1.0-3.28 +[ 44s] [251/326] installing pkgmgr-info-devel-0.0.230-23.5 +[ 44s] [252/326] installing capi-network-wifi-direct-devel-1.2.31-6.7 +[ 45s] [253/326] installing eo-devel-1.13.0-39.8 +[ 45s] [254/326] [255/326] installing vconf-internal-keys-devel-0.0.152-15.1 +[ 45s] [256/326] installing libcurl-devel-7.40.1_1-6.6 +[ 46s] [257/326] installing libpng-devel-1.2.50-2.1 +[ 46s] [258/326] [259/326] [260/326] [261/326] [262/326] [263/326] [264/326] [265/326] [266/326] [267/326] [268/326] installing vconf-keys-devel-0.2.84-6.15 +[ 46s] [269/326] installing capi-network-connection-devel-1.0.57-11.1 +[ 47s] [270/326] installing efl-devel-1.13.0-39.8 +[ 47s] [271/326] [272/326] installing eet-devel-1.13.0-39.8 +[ 48s] [273/326] installing freetype-devel-2.5.5-2.42 +[ 48s] [274/326] [275/326] [276/326] [277/326] installing fontconfig-devel-2.11.92-4.6 +[ 48s] [278/326] installing pulseaudio-libs-devel-4.0.181-18.1 +[ 49s] [279/326] installing ector-devel-1.13.0-39.8 +[ 49s] [280/326] [281/326] [282/326] [283/326] [284/326] [285/326] installing vconf-devel-0.2.84-6.15 +[ 49s] [286/326] [287/326] [288/326] [289/326] [290/326] [291/326] [292/326] [293/326] [294/326] installing evas-devel-1.13.0-39.8 +[ 50s] [295/326] [296/326] [297/326] [298/326] [299/326] installing ecore-devel-1.13.0-39.8 +[ 50s] [300/326] [301/326] [302/326] [303/326] installing edbus-devel-1.6.0+svn.76526slp2+build10-1.159 +[ 51s] [304/326] [305/326] installing libresourced-devel-0.2.86-7.11 +[ 51s] [306/326] [307/326] [308/326] [309/326] installing aul-devel-0.2.3.0-21.2 +[ 51s] [310/326] [311/326] [312/326] [313/326] [314/326] installing app-svc-devel-0.1.78-7.72 +[ 52s] [315/326] [316/326] [317/326] [318/326] [319/326] [320/326] [321/326] [322/326] [323/326] [324/326] [325/326] [326/326] installing notification-devel-0.2.31-4.4 +[ 52s] removing nis flags from /home/youngj/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.0/etc/nsswitch.conf... +[ 52s] now finalizing build dir... +[ 52s] qemu: Unsupported syscall: 311 +[ 53s] ----------------------------------------------------------------- +[ 53s] ----- building download-provider.spec (user abuild) +[ 53s] ----------------------------------------------------------------- +[ 53s] ----------------------------------------------------------------- +[ 53s] qemu: Unsupported syscall: 311 +[ 53s] + exec rpmbuild --define '_srcdefattr (-,root,root)' --nosignature --target=armv7l-tizen-linux --define '_build_create_debug 1' -ba /home/abuild/rpmbuild/SOURCES/download-provider.spec +[ 53s] Building target platforms: armv7l-tizen-linux +[ 53s] Building for target armv7l-tizen-linux +[ 53s] Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.fmaEg6 +[ 53s] + umask 022 +[ 53s] + cd /home/abuild/rpmbuild/BUILD +[ 53s] + cd /home/abuild/rpmbuild/BUILD +[ 53s] + rm -rf download-provider-2.1.23 +[ 53s] + /bin/gzip -dc /home/abuild/rpmbuild/SOURCES/download-provider-2.1.23.tar.gz +[ 53s] + /bin/tar -xf - +[ 53s] + STATUS=0 +[ 53s] + '[' 0 -ne 0 ']' +[ 53s] + cd download-provider-2.1.23 +[ 53s] + /bin/chmod -Rf a+rX,u+w,g-w,o-w . +[ 53s] + exit 0 +[ 53s] Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.Uc0Ko6 +[ 53s] + umask 022 +[ 53s] + cd /home/abuild/rpmbuild/BUILD +[ 53s] + cd download-provider-2.1.23 +[ 53s] + LANG=C +[ 53s] + export LANG +[ 53s] + unset DISPLAY +[ 53s] + CFLAGS='-O2 -g2 -feliminate-unused-debug-types -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -fdiagnostics-color=never -Wl,--as-needed -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=neon -mfloat-abi=softfp -Wp,-D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb -g' +[ 53s] + export CFLAGS +[ 53s] + CXXFLAGS='-O2 -g2 -feliminate-unused-debug-types -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -fdiagnostics-color=never -Wl,--as-needed -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=neon -mfloat-abi=softfp -Wp,-D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb -g' +[ 53s] + export CXXFLAGS +[ 53s] + FFLAGS='-O2 -g2 -feliminate-unused-debug-types -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -fdiagnostics-color=never -Wl,--as-needed -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=neon -mfloat-abi=softfp -Wp,-D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb -g -I%_fmoddir' +[ 53s] + export FFLAGS +[ 53s] + LD_AS_NEEDED=1 +[ 53s] + export LD_AS_NEEDED +[ 53s] + export 'CFLAGS=-O2 -g2 -feliminate-unused-debug-types -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -fdiagnostics-color=never -Wl,--as-needed -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=neon -mfloat-abi=softfp -Wp,-D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb -g -DTIZEN_DEBUG_ENABLE' +[ 53s] + CFLAGS='-O2 -g2 -feliminate-unused-debug-types -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -fdiagnostics-color=never -Wl,--as-needed -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=neon -mfloat-abi=softfp -Wp,-D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb -g -DTIZEN_DEBUG_ENABLE' +[ 53s] + export 'CXXFLAGS=-O2 -g2 -feliminate-unused-debug-types -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -fdiagnostics-color=never -Wl,--as-needed -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=neon -mfloat-abi=softfp -Wp,-D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb -g -DTIZEN_DEBUG_ENABLE' +[ 53s] + CXXFLAGS='-O2 -g2 -feliminate-unused-debug-types -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -fdiagnostics-color=never -Wl,--as-needed -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=neon -mfloat-abi=softfp -Wp,-D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb -g -DTIZEN_DEBUG_ENABLE' +[ 53s] + export 'FFLAGS=-O2 -g2 -feliminate-unused-debug-types -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -fdiagnostics-color=never -Wl,--as-needed -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=neon -mfloat-abi=softfp -Wp,-D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb -g -I%_fmoddir -DTIZEN_DEBUG_ENABLE' +[ 53s] + FFLAGS='-O2 -g2 -feliminate-unused-debug-types -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -fdiagnostics-color=never -Wl,--as-needed -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=neon -mfloat-abi=softfp -Wp,-D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb -g -I%_fmoddir -DTIZEN_DEBUG_ENABLE' +[ 53s] + CFLAGS='-O2 -g2 -feliminate-unused-debug-types -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -fdiagnostics-color=never -Wl,--as-needed -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=neon -mfloat-abi=softfp -Wp,-D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb -g -DTIZEN_DEBUG_ENABLE -fPIC -D_REENTRANT -fvisibility=hidden' +[ 53s] + export CFLAGS +[ 53s] + FFLAGS='-O2 -g2 -feliminate-unused-debug-types -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -fdiagnostics-color=never -Wl,--as-needed -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=neon -mfloat-abi=softfp -Wp,-D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb -g -I%_fmoddir -DTIZEN_DEBUG_ENABLE -fPIC -fvisibility=hidden' +[ 53s] + export FFLAGS +[ 53s] + LDFLAGS+=' -Wl,--as-needed -Wl,--hash-style=both' +[ 53s] + export LDFLAGS +[ 53s] + /usr/bin/cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr -DBIN_INSTALL_DIR:PATH=/usr/bin -DLIB_INSTALL_DIR:PATH=/usr/lib -DINCLUDE_INSTALL_DIR:PATH=/usr/include -DPKG_NAME=download-provider -DPKG_VERSION=2.1.23 -DPKG_RELEASE=0 -DIPC_SOCKET:PATH=/opt/data/download-provider/download-provider.sock -DPROVIDER_DIR:PATH=/opt/usr/data/download-provider -DNOTIFY_DIR:PATH=/opt/usr/data/download-provider/notify -DDATABASE_DIR:PATH=/opt/usr/data/download-provider/database -DDATABASE_CLIENT_DIR:PATH=/opt/usr/data/download-provider/database/clients -DIMAGE_DIR:PATH=/usr/share/download-provider/images -DLOCALE_DIR:PATH=/usr/share/download-provider/locales -DLICENSE_DIR:PATH=/usr/share/license -DSUPPORT_WIFI_DIRECT:BOOL=ON -DSUPPORT_SYS_RESOURCE:BOOL=OFF -DSUPPORT_DOWNLOAD_BOOSTER:BOOL=OFF -DSUPPORT_NOTIFICATION:BOOL=ON -DSUPPORT_LOG_MESSAGE:BOOL=ON -DSUPPORT_OMA_DRM:BOOL=OFF -DSUPPORT_SECURITY_PRIVILEGE:BOOL=OFF -DSUPPORT_COMPANION_MODE:BOOL=OFF -DSUPPORT_KNOX:BOOL=ON -DTIZEN_2_3_UX:BOOL=ON -DCMAKE_LOG_DUMP_SCRIPT_DIR=/opt/etc/dump.d/module.d -DHTTP_LIB=libcurl -DCMAKE_SKIP_RPATH:BOOL=ON -DBUILD_SHARED_LIBS:BOOL=ON . +[ 53s] PROJECT : download-provider +[ 53s] VERSION : 2.1.23-0 +[ 53s] SUPPORT_WIFI_DIRECT: ON +[ 53s] SUPPORT_LOG_MESSAGE: ON +[ 53s] SUPPORT_SECURITY_PRIVILEGE: OFF +[ 53s] SUPPORT_COMPANION_MODE: OFF +[ 53s] TIZEN_2_3_UX:On +[ 53s] SUPPORT_KNOX: ON +[ 54s] -- The C compiler identification is GNU 4.9.2 +[ 54s] -- Check for working C compiler: /bin/cc +[ 54s] -- Check for working C compiler: /bin/cc -- works +[ 54s] -- Detecting C compiler ABI info +[ 55s] -- Detecting C compiler ABI info - done +[ 55s] -- Found PkgConfig: /bin/pkg-config (found version "0.28") +[ 55s] SUPPORT_SYS_RESOURCE: OFF +[ 55s] -- checking for modules 'xdgmime;vconf;capi-network-connection;dlog;storage' +[ 55s] -- found xdgmime, version 1.1.0 +[ 55s] -- found vconf, version 0.2.45 +[ 55s] -- found capi-network-connection, version +[ 55s] -- found dlog, version 1.0 +[ 55s] -- found storage, version 0.1 +[ 55s] HTTP_LIB: libcurl +[ 55s] -- checking for module 'libcurl' +[ 55s] -- found libcurl, version 7.40.1-DEV +[ 55s] Build type: Debug +[ 55s] -- checking for module 'glib-2.0 gobject-2.0 dlog capi-base-common capi-appfw-app-manager capi-appfw-application bundle' +[ 55s] -- found glib-2.0 gobject-2.0 dlog capi-base-common capi-appfw-app-manager capi-appfw-application bundle, version 2.43.1;2.43.1;1.0;0.2.0;0.1.22 +[ 55s] Build type: Debug +[ 55s] -- checking for modules 'glib-2.0;gobject-2.0;sqlite3;capi-appfw-app-manager;capi-network-connection;capi-content-mime-type;appsvc;bundle;libsmack;dlog;libsystemd-daemon;vconf' +[ 55s] -- found glib-2.0, version 2.43.1 +[ 56s] -- found gobject-2.0, version 2.43.1 +[ 56s] -- found sqlite3, version 3.7.14 +[ 56s] -- found capi-appfw-app-manager, version +[ 56s] -- found capi-network-connection, version +[ 56s] -- found capi-content-mime-type, version +[ 56s] -- found appsvc, version 0.1.0 +[ 56s] -- found bundle, version 0.1.22 +[ 56s] -- found libsmack, version 1.0 +[ 56s] -- found dlog, version 1.0 +[ 56s] -- found libsystemd-daemon, version 216 +[ 56s] -- found vconf, version 0.2.45 +[ 56s] WIFI direct:On +[ 56s] -- checking for module 'capi-network-wifi-direct' +[ 56s] -- found capi-network-wifi-direct, version 0.0 +[ 56s] Notification:On +[ 56s] -- checking for module 'notification' +[ 56s] -- found notification, version 0.1.0 +[ 56s] Companion:Off +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ar.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/az.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/bg.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ca.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/cs.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/da.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/de.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/el_GR.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/en.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/en_PH.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/en_US.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/es_ES.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/es_US.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/et.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/eu.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/fi.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/fr.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/fr_CA.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ga.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/gl.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/hi.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/hr.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/hu.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/hy.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/is.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/it_IT.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ja_JP.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ka.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/kk.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ko_KR.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/lt.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/lv.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/mk.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/nb.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/nl.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/pl.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/pt_BR.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/pt_PT.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ro.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ru_RU.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/sk.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/sl.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/sr.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/sv.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/tr_TR.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/uk.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/uz.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/zh_CN.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/zh_HK.po +[ 56s] PO: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/zh_TW.po +[ 56s] .mo files: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ar.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/az.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/bg.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ca.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/cs.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/da.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/de.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/el_GR.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/en.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/en_PH.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/en_US.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/es_ES.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/es_US.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/et.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/eu.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/fi.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/fr.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/fr_CA.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ga.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/gl.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/hi.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/hr.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/hu.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/hy.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/is.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/it_IT.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ja_JP.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ka.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/kk.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ko_KR.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/lt.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/lv.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/mk.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/nb.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/nl.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/pl.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/pt_BR.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/pt_PT.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ro.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/ru_RU.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/sk.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/sl.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/sr.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/sv.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/tr_TR.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/uk.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/uz.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/zh_CN.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/zh_HK.mo;/home/abuild/rpmbuild/BUILD/download-provider-2.1.23/po/tizen2.3/zh_TW.mo +[ 56s] INSTALL download-provider.res +[ 56s] -- Configuring done +[ 56s] -- Generating done +[ 56s] -- Build files have been written to: /home/abuild/rpmbuild/BUILD/download-provider-2.1.23 +[ 56s] + make -j16 +[ 56s] Scanning dependencies of target po +[ 56s] Scanning dependencies of target download-provider-interface +[ 56s] [ 1%] [ 2%] [ 3%] [ 5%] Scanning dependencies of target downloadagent2 +[ 56s] [ 7%] [ 7%] Generating ar.mo +[ 56s] Building C object provider-interface/CMakeFiles/download-provider-interface.dir/__/provider/download-provider-ipc.c.o +[ 56s] Building C object provider-interface/CMakeFiles/download-provider-interface.dir/__/provider/download-provider-utils.c.o +[ 56s] Building C object provider-interface/CMakeFiles/download-provider-interface.dir/__/provider/download-provider-pthread.c.o +[ 56s] [ 8%] [ 10%] [ 11%] Generating bg.mo +[ 56s] Scanning dependencies of target download-provider +[ 56s] [ 12%] Generating az.mo +[ 56s] [ 13%] [ 15%] [ 16%] Generating ca.mo +[ 56s] Generating cs.mo +[ 56s] [ 17%] Building C object provider-interface/CMakeFiles/download-provider-interface.dir/download-provider-interface.c.o +[ 56s] [ 18%] Building C object agent/CMakeFiles/downloadagent2.dir/download-agent-interface.c.o +[ 56s] Building C object agent/CMakeFiles/downloadagent2.dir/download-agent-client-mgr.c.o +[ 56s] Building C object agent/CMakeFiles/downloadagent2.dir/download-agent-dl-mgr.c.o +[ 56s] [ 20%] Building C object agent/CMakeFiles/downloadagent2.dir/download-agent-dl-info.c.o +[ 56s] Generating da.mo +[ 56s] Building C object agent/CMakeFiles/downloadagent2.dir/download-agent-http-mgr.c.o +[ 56s] Building C object provider/CMakeFiles/download-provider.dir/download-provider-pthread.c.o +[ 56s] [ 21%] [ 22%] [ 23%] [ 25%] [ 26%] [ 27%] Building C object agent/CMakeFiles/downloadagent2.dir/download-agent-encoding.c.o +[ 56s] In file included from /usr/include/unistd.h:25:0, +[ 56s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-pthread.c:17: +[ 56s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 56s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 56s] ^ +[ 56s] In file included from /usr/include/unistd.h:25:0, +[ 56s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-pthread.c:17: +[ 56s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 56s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 56s] ^ +[ 56s] Building C object provider/CMakeFiles/download-provider.dir/download-provider-utils.c.o +[ 56s] In file included from /usr/include/stdio.h:27:0, +[ 56s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-utils.c:17: +[ 56s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 56s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 56s] ^ +[ 56s] Generating de.mo +[ 56s] In file included from /usr/include/stdio.h:27:0, +[ 56s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-ipc.c:17: +[ 56s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 56s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 56s] ^ +[ 56s] Building C object provider/CMakeFiles/download-provider.dir/download-provider-ipc.c.o +[ 56s] Building C object agent/CMakeFiles/downloadagent2.dir/download-agent-http-msg-handler.c.o +[ 56s] In file included from /usr/include/stdio.h:27:0, +[ 56s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider-interface/download-provider-interface.c:17: +[ 56s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 56s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 56s] ^ +[ 57s] In file included from /usr/include/stdio.h:27:0, +[ 57s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-utils.c:17: +[ 57s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 57s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 57s] ^ +[ 57s] In file included from /usr/include/stdio.h:27:0, +[ 57s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-ipc.c:17: +[ 57s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 57s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 57s] ^ +[ 57s] Generating el_GR.mo +[ 57s] [ 28%] [ 30%] [ 32%] [ 33%] [ 33%] [ 35%] [ 36%] [ 37%] Linking C shared library libdownload-provider-interface.so +[ 57s] [ 38%] [ 40%] [ 41%] Generating en.mo +[ 57s] Generating en_PH.mo +[ 57s] Building C object provider/CMakeFiles/download-provider.dir/download-provider-notify.c.o +[ 57s] Generating en_US.mo +[ 57s] Building C object agent/CMakeFiles/downloadagent2.dir/download-agent-file.c.o +[ 57s] Building C object agent/CMakeFiles/downloadagent2.dir/download-agent-plugin-conf.c.o +[ 57s] Building C object agent/CMakeFiles/downloadagent2.dir/download-agent-mime-util.c.o +[ 57s] Building C object agent/CMakeFiles/downloadagent2.dir/download-agent-plugin-libcurl.c.o +[ 57s] Building C object provider/CMakeFiles/download-provider.dir/download-provider-smack.c.o +[ 57s] Building C object provider/CMakeFiles/download-provider.dir/download-provider-network.c.o +[ 57s] Building C object provider/CMakeFiles/download-provider.dir/download-provider-db.c.o +[ 57s] [ 42%] [ 43%] [ 45%] [ 46%] Generating es_ES.mo +[ 57s] Building C object provider/CMakeFiles/download-provider.dir/download-provider-plugin-download-agent.c.o +[ 57s] Generating es_US.mo +[ 57s] Generating et.mo +[ 57s] In file included from /usr/include/stdlib.h:24:0, +[ 57s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-smack.c:17: +[ 57s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 57s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 57s] ^ +[ 57s] [ 47%] [ 48%] In file included from /usr/include/stdio.h:27:0, +[ 57s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-db.c:19: +[ 57s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 57s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 57s] ^ +[ 57s] [ 50%] Building C object provider/CMakeFiles/download-provider.dir/download-provider-queue.c.o +[ 57s] Generating eu.mo +[ 57s] In file included from /usr/include/stdio.h:27:0, +[ 57s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-notify.c:17: +[ 57s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 57s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 57s] ^ +[ 57s] Generating fi.mo +[ 57s] In file included from /usr/include/stdio.h:27:0, +[ 57s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-plugin-download-agent.c:17: +[ 57s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 57s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 57s] ^ +[ 57s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/agent/download-agent-http-msg-handler.c: In function '__get_http_header_for_field': +[ 57s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/agent/download-agent-http-msg-handler.c:376:23: warning: 'http_msg_iter' may be used uninitialized in this function [-Wmaybe-uninitialized] +[ 57s] *http_msg_iter = cur->next; +[ 57s] ^ +[ 57s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/agent/download-agent-http-msg-handler.c:620:18: note: 'http_msg_iter' was declared here +[ 57s] http_msg_iter_t http_msg_iter; +[ 57s] ^ +[ 57s] In file included from /usr/include/unistd.h:25:0, +[ 57s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/include/download-provider.h:103, +[ 57s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-network.c:17: +[ 57s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 57s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 57s] ^ +[ 57s] [ 51%] [ 52%] Generating fr.mo +[ 57s] Building C object provider/CMakeFiles/download-provider.dir/download-provider-queue-manager.c.o +[ 57s] [ 53%] [ 55%] In file included from /usr/include/stdlib.h:24:0, +[ 57s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-queue.c:17: +[ 57s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 57s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 57s] ^ +[ 57s] Generating ga.mo +[ 58s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/agent/download-agent-http-msg-handler.c: In function '__get_http_req_header_for_field': +[ 58s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/agent/download-agent-http-msg-handler.c:376:23: warning: 'http_msg_iter' may be used uninitialized in this function [-Wmaybe-uninitialized] +[ 58s] *http_msg_iter = cur->next; +[ 58s] ^ +[ 58s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/agent/download-agent-http-msg-handler.c:641:18: note: 'http_msg_iter' was declared here +[ 58s] http_msg_iter_t http_msg_iter; +[ 58s] ^ +[ 58s] Generating fr_CA.mo +[ 58s] [ 56%] Building C object provider/CMakeFiles/download-provider.dir/download-provider-client.c.o +[ 58s] [ 57%] Generating gl.mo +[ 58s] [ 58%] Generating hi.mo +[ 58s] [ 60%] Generating hr.mo +[ 58s] [ 61%] Generating hu.mo +[ 58s] [ 62%] Generating hy.mo +[ 58s] [ 63%] Generating is.mo +[ 58s] [ 63%] [ 65%] Built target download-provider-interface +[ 58s] [ 66%] Generating it_IT.mo +[ 58s] Generating ja_JP.mo +[ 58s] [ 67%] [ 68%] Building C object provider/CMakeFiles/download-provider.dir/download-provider-client-manager.c.o +[ 58s] Generating ka.mo +[ 58s] [ 70%] Generating kk.mo +[ 58s] [ 71%] Generating ko_KR.mo +[ 58s] [ 72%] Generating lt.mo +[ 58s] [ 73%] Generating lv.mo +[ 58s] [ 75%] Generating mk.mo +[ 58s] [ 76%] Generating nb.mo +[ 58s] [ 77%] Generating nl.mo +[ 58s] [ 78%] Generating pl.mo +[ 58s] [ 80%] Generating pt_BR.mo +[ 58s] [ 81%] [ 82%] [ 83%] [ 85%] [ 86%] [ 87%] [ 88%] Building C object provider/CMakeFiles/download-provider.dir/download-provider-notification.c.o +[ 58s] Generating pt_PT.mo +[ 58s] Generating ro.mo +[ 58s] [ 90%] Building C object provider/CMakeFiles/download-provider.dir/download-provider-notification-manager.c.o +[ 58s] Generating ru_RU.mo +[ 58s] Building C object provider/CMakeFiles/download-provider.dir/download-provider-main.c.o +[ 58s] Generating sl.mo +[ 58s] [ 91%] Generating sk.mo +[ 58s] [ 92%] Generating sr.mo +[ 58s] Generating sv.mo +[ 58s] [ 93%] [ 95%] [ 96%] Generating tr_TR.mo +[ 58s] [ 98%] [ 98%] Generating uz.mo +[ 58s] Generating uk.mo +[ 58s] [100%] Generating zh_CN.mo +[ 58s] Generating zh_HK.mo +[ 58s] Generating zh_TW.mo +[ 58s] [100%] Built target po +[ 59s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/agent/download-agent-file.c: In function 'check_drm_convert': +[ 59s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/agent/download-agent-file.c:819:12: warning: unused variable 'ret_b' [-Wunused-variable] +[ 59s] da_bool_t ret_b = DA_TRUE; +[ 59s] ^ +[ 59s] In file included from /usr/include/stdlib.h:24:0, +[ 59s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-queue-manager.c:17: +[ 59s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 59s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 59s] ^ +[ 59s] In file included from /usr/include/stdlib.h:24:0, +[ 59s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-notification-manager.c:18: +[ 59s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 59s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 59s] ^ +[ 59s] In file included from /usr/include/stdio.h:27:0, +[ 59s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-main.c:17: +[ 59s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 59s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 59s] ^ +[ 59s] In file included from /usr/include/sys/time.h:21:0, +[ 59s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-client.c:16: +[ 59s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 59s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 59s] ^ +[ 59s] In file included from /usr/include/stdio.h:27:0, +[ 59s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-client-manager.c:17: +[ 59s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 59s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 59s] ^ +[ 59s] In file included from /usr/include/time.h:27:0, +[ 59s] from /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-notification.c:18: +[ 59s] /usr/include/features.h:328:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp] +[ 59s] # warning _FORTIFY_SOURCE requires compiling with optimization (-O) +[ 59s] ^ +[ 59s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-queue-manager.c: In function '__dp_queue_manager': +[ 59s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-queue-manager.c:257:3: warning: implicit declaration of function 'gettimeofday' [-Wimplicit-function-declaration] +[ 59s] gettimeofday(&now, NULL); +[ 59s] ^ +[ 59s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-main.c: In function 'main': +[ 59s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-main.c:38:2: warning: 'g_type_init' is deprecated (declared at /usr/include/glib-2.0/gobject/gtype.h:681) [-Wdeprecated-declarations] +[ 59s] g_type_init(); +[ 59s] ^ +[ 59s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-notification.c: In function 'dp_notification_new': +[ 59s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-notification.c:429:2: warning: implicit declaration of function 'notification_set_text_domain' [-Wimplicit-function-declaration] +[ 59s] err = notification_set_text_domain(noti_handle, DP_DOMAIN, DP_LOCALEDIR); +[ 59s] ^ +[ 59s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-client-manager.c: In function '__dp_client_new': +[ 59s] /home/abuild/rpmbuild/BUILD/download-provider-2.1.23/provider/download-provider-client-manager.c:383:2: warning: implicit declaration of function 'app_manager_get_package' [-Wimplicit-function-declaration] +[ 59s] if (app_manager_get_package(credential.pid, &pkgname) != +[ 59s] ^ +[ 59s] Linking C shared library libdownloadagent2.so +[ 59s] Linking C executable download-provider +[ 59s] [100%] Built target downloadagent2 +[ 60s] [100%] Built target download-provider +[ 60s] + exit 0 +[ 60s] Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.2D3HEr +[ 60s] + umask 022 +[ 60s] + cd /home/abuild/rpmbuild/BUILD +[ 60s] + cd download-provider-2.1.23 +[ 60s] + LANG=C +[ 60s] + export LANG +[ 60s] + unset DISPLAY +[ 60s] + rm -rf /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm +[ 60s] + mkdir -p /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm +[ 60s] + rm -rf /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm +[ 60s] + /bin/make DESTDIR=/home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm INSTALL_ROOT=/home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm install +[ 60s] [ 13%] Built target downloadagent2 +[ 60s] [ 18%] Built target download-provider-interface +[ 60s] [ 37%] Built target download-provider +[ 60s] [100%] Built target po +[ 60s] Install the project... +[ 60s] -- Install configuration: "" +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/pkgconfig/download-provider.pc +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/systemd/system/download-provider.service +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/systemd/system/download-provider.socket +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_img.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_unknown.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_tpk.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_swf.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_word.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/B03_Processing_download_failed.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_text.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_drm.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/B03_Processing_download_complete.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_html.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_ppt.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_movie.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_pdf.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_xls.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_music.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/images/download_manager_icon_date.png +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/license/download-provider +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/opt/etc/dump.d/module.d/dump-download-provider.sh +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/download-provider.res +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/libdownloadagent2.so.0.1.0 +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/libdownloadagent2.so +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/libdownload-provider-interface.so.2.1.23 +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/libdownload-provider-interface.so.0 +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/libdownload-provider-interface.so +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/include/download-provider/download-provider-interface.h +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/pkgconfig/download-provider-interface.pc +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/bin/download-provider +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/include/download-provider/download-provider.h +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/ar/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/az/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/bg/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/ca/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/cs/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/da/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/de/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/el_GR/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/en/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/en_PH/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/en_US/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/es_ES/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/es_US/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/et/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/eu/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/fi/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/fr/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/fr_CA/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/ga/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/gl/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/hi/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/hr/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/hu/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/hy/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/is/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/it_IT/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/ja_JP/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/ka/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/kk/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/ko_KR/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/lt/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/lv/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/mk/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/nb/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/nl/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/pl/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/pt_BR/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/pt_PT/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/ro/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/ru_RU/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/sk/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/sl/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/sr/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/sv/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/tr_TR/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/uk/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/uz/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/zh_CN/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/zh_HK/LC_MESSAGES/download-provider.mo +[ 60s] -- Installing: /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/locales/zh_TW/LC_MESSAGES/download-provider.mo +[ 60s] + rm -f /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/info/dir +[ 60s] + find /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm -regex '.*\.la$' +[ 60s] + xargs rm -f -- +[ 60s] + find /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm -regex '.*\.a$' +[ 60s] + xargs rm -f -- +[ 60s] + mkdir -p /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/etc/vasum/vsmzone.resource/ +[ 60s] + mv /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/download-provider/download-provider.res /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/etc/vasum/vsmzone.resource/ +[ 60s] + mkdir -p /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/share/license +[ 60s] + mkdir -p /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/systemd/system/graphical.target.wants +[ 60s] + mkdir -p /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/systemd/system/sockets.target.wants +[ 60s] + ln -s ../download-provider.service /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/systemd/system/graphical.target.wants/ +[ 60s] + ln -s ../download-provider.socket /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/systemd/system/sockets.target.wants/ +[ 60s] + /usr/lib/rpm/find-debuginfo.sh --strict-build-id /home/abuild/rpmbuild/BUILD/download-provider-2.1.23 +[ 61s] extracting debug info from /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/libdownload-provider-interface.so.2.1.23 +[ 61s] extracting debug info from /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/lib/libdownloadagent2.so.0.1.0 +[ 62s] extracting debug info from /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm/usr/bin/download-provider +[ 62s] symlinked /usr/lib/debug/usr/lib/libdownload-provider-interface.so.2.1.23.debug to /usr/lib/debug/usr/lib/libdownload-provider-interface.so.debug +[ 62s] symlinked /usr/lib/debug/usr/lib/libdownload-provider-interface.so.2.1.23.debug to /usr/lib/debug/usr/lib/libdownload-provider-interface.so.0.debug +[ 62s] symlinked /usr/lib/debug/usr/lib/libdownloadagent2.so.0.1.0.debug to /usr/lib/debug/usr/lib/libdownloadagent2.so.debug +[ 63s] cpio: gcc-4.9.2/libgcc/config/arm/ieee754-df.S: Cannot stat: No such file or directory +[ 63s] cpio: gcc-4.9.2/obj-armv7l-tizen-linux-gnueabi/armv7l-tizen-linux-gnueabi/libgcc: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/bits/types.h: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/csu: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/csu/elf-init.c: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/csu/init.c: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/io: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/io/fstat.c: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/io/lstat.c: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/io/stat.c: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/io/sys/stat.h: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/sysdeps/arm/crti.S: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/sysdeps/arm/crtn.S: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/sysdeps/arm/start.S: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/sysdeps/unix/sysv/linux/bits/stat.h: Cannot stat: No such file or directory +[ 63s] cpio: glibc-2.21/time/time.h: Cannot stat: No such file or directory +[ 63s] 977 blocks +[ 63s] + /usr/lib/rpm/check-buildroot +[ 63s] + /usr/lib/rpm/brp-compress +[ 63s] + /usr/lib/rpm/brp-tizen +[ 63s] + /usr/lib/rpm/tizen/find-docs.sh /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm +[ 63s] Processing files: download-provider-2.1.23-0.armv7l +[ 63s] Aptk: PG1hbmlmZXN0PgoJPGRlZmluZT4KCQk8ZG9tYWluIG5hbWU9ImRvd25sb2FkLXBy +[ 63s] b3ZpZGVyIiAvPgoJCTxwcm92aWRlPgoJCQk8bGFiZWwgbmFtZT0iZG93bmxvYWQt +[ 63s] cHJvdmlkZXI6OmRiIiAvPgoJCTwvcHJvdmlkZT4KCQk8cmVxdWVzdD4KCQkJPHNt +[ 63s] YWNrIHJlcXVlc3Q9ImRvd25sb2FkLXByb3ZpZGVyOjpkYiIgdHlwZT0icnciIC8+ +[ 63s] CgkJCTxzbWFjayByZXF1ZXN0PSJzeXN0ZW06OnVzZV9pbnRlcm5ldCIgdHlwZT0i +[ 63s] dyIgLz4KCQkJPHNtYWNrIHJlcXVlc3Q9InN5cy1hc3NlcnQ6OmNvcmUiIHR5cGU9 +[ 63s] InJ3eGF0IiAvPgoJCQk8c21hY2sgcmVxdWVzdD0iZGV2aWNlOjpzeXNfbG9nZ2lu +[ 63s] ZyIgdHlwZT0idyIgLz4KCQkJPHNtYWNrIHJlcXVlc3Q9InN5c3RlbTo6ZXh0X3N0 +[ 63s] b3JhZ2UiIHR5cGU9ImFyd3h0IiAvPgoJCQk8c21hY2sgcmVxdWVzdD0ic3lzdGVt +[ 63s] OjpleHRfbWVkaWEiIHR5cGU9ImFyd3h0IiAvPgoJCQk8c21hY2sgcmVxdWVzdD0i +[ 63s] c3lzdGVtOjptZWRpYSIgdHlwZT0icnd4YXQiIC8+CgkJCTxzbWFjayByZXF1ZXN0 +[ 63s] PSJzeXN0ZW06Om1lZGlhOjpyb290IiB0eXBlPSJyd3hhdCIgLz4KCQkJPHNtYWNr +[ 63s] IHJlcXVlc3Q9ImNvbm5tYW4iIHR5cGU9InJ3IiAvPgoJCQk8c21hY2sgcmVxdWVz +[ 63s] dD0ibmV0LWNvbmZpZyIgdHlwZT0icnciIC8+CgkJCTxzbWFjayByZXF1ZXN0PSJ3 +[ 63s] aWZpLWRpcmVjdDo6aW5mbyIgdHlwZT0iciIgLz4KCQkJPHNtYWNrIHJlcXVlc3Q9 +[ 63s] ImNvbm5tYW46OmdldCIgdHlwZT0icnciIC8+CgkJCTxzbWFjayByZXF1ZXN0PSJ0 +[ 63s] ZWxlcGhvbnlfZnJhbWV3b3JrOjphcGlfcHNfcHVibGljIiB0eXBlPSJydyIgLz4K +[ 63s] CQk8L3JlcXVlc3Q+CgkJPHBlcm1pdD4KCQkJPHNtYWNrIHBlcm1pdD0ic3lzdGVt +[ 63s] Ojp1c2VfaW50ZXJuZXQiIHR5cGU9InciIC8+CgkJPC9wZXJtaXQ+Cgk8L2RlZmlu +[ 63s] ZT4KCTxyZXF1ZXN0PgoJCTxkb21haW4gbmFtZT0iZG93bmxvYWQtcHJvdmlkZXIi +[ 63s] IC8+Cgk8L3JlcXVlc3Q+Cgk8YXNzaWduPgoJCTxmaWxlc3lzdGVtIHBhdGg9Ii91 +[ 63s] c3Ivc2hhcmUvZG93bmxvYWQtcHJvdmlkZXIqIiBsYWJlbD0iXyIgLz4KCQk8Zmls +[ 63s] ZXN5c3RlbSBwYXRoPSIvdXNyL2xpYi9saWJkb3dubG9hZC1wcm92aWRlci1pbnRl +[ 63s] cmZhY2Uuc28qIiBsYWJlbD0iXyIgZXhlY19sYWJlbD0ibm9uZSIgLz4KCQk8Zmls +[ 63s] ZXN5c3RlbSBwYXRoPSIvdXNyL2xpYi9saWJkb3dubG9hZGFnZW50Mi5zbyoiIGxh +[ 63s] YmVsPSJfIiBleGVjX2xhYmVsPSJub25lIiAvPgoJCTxmaWxlc3lzdGVtIHBhdGg9 +[ 63s] Ii91c3IvbGliL3N5c3RlbWQvc3lzdGVtL2Rvd25sb2FkLXByb3ZpZGVyLnNlcnZp +[ 63s] Y2UiIGxhYmVsPSJfIiBleGVjX2xhYmVsPSJub25lIiAvPgoJCTxmaWxlc3lzdGVt +[ 63s] IHBhdGg9Ii91c3IvbGliL3N5c3RlbWQvc3lzdGVtL2dyYXBoaWNhbC50YXJnZXQu +[ 63s] d2FudHMvZG93bmxvYWQtcHJvdmlkZXIuc2VydmljZSIgbGFiZWw9Il8iIGV4ZWNf +[ 63s] bGFiZWw9Im5vbmUiIC8+CgkJPGZpbGVzeXN0ZW0gcGF0aD0iL3Vzci9saWIvc3lz +[ 63s] dGVtZC9zeXN0ZW0vZG93bmxvYWQtcHJvdmlkZXIuc29ja2V0IiBsYWJlbD0iXyIg +[ 63s] ZXhlY19sYWJlbD0ibm9uZSIgLz4KCQk8ZmlsZXN5c3RlbSBwYXRoPSIvdXNyL2xp +[ 63s] Yi9zeXN0ZW1kL3N5c3RlbS9zb2NrZXRzLnRhcmdldC53YW50cy9kb3dubG9hZC1w +[ 63s] cm92aWRlci5zb2NrZXQiIGxhYmVsPSJfIiBleGVjX2xhYmVsPSJub25lIiAvPgoJ +[ 63s] CTxmaWxlc3lzdGVtIHBhdGg9Ii9vcHQvZXRjL2R1bXAuZC9tb2R1bGUuZC9kdW1w +[ 63s] LWRvd25sb2FkLXByb3ZpZGVyLnNoIiBsYWJlbD0iXyIgZXhlY19sYWJlbD0ibm9u +[ 63s] ZSIgLz4KIAkJPGZpbGVzeXN0ZW0gcGF0aD0iL3Vzci9zaGFyZS9kb3dubG9hZC1w +[ 63s] cm92aWRlci9kb3dubG9hZC1wcm92aWRlci5yZXMiIGxhYmVsPSJfIiAvPgoJPC9h +[ 63s] c3NpZ24+CjwvbWFuaWZlc3Q+Cg== +[ 63s] +[ 63s] Provides: libdownload-provider-interface.so.0 libdownloadagent2.so.0.1.0 +[ 63s] Requires(interp): /bin/sh +[ 63s] Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +[ 63s] Requires(post): /bin/sh connman libdevice-node sqlite sys-assert +[ 63s] Requires: ld-linux.so.3 ld-linux.so.3(GLIBC_2.4) libappsvc.so.0 libbundle.so.0 libc.so.6 libc.so.6(GLIBC_2.4) libc.so.6(GLIBC_2.7) libcapi-appfw-app-control.so.0 libcapi-appfw-app-manager.so.0 libcapi-content-mime-type.so.0 libcapi-network-connection.so.1 libcurl.so.4 libcurl.so.4(CURL_OPENSSL_4) libdl.so.2 libdl.so.2(GLIBC_2.4) libdlog.so.0 libdownloadagent2.so.0.1.0 libgcc_s.so.1 libgcc_s.so.1(GCC_3.0) libgcc_s.so.1(GCC_3.3.1) libgcc_s.so.1(GCC_3.5) libglib-2.0.so.0 libgobject-2.0.so.0 libnotification.so.0 libpthread.so.0 libpthread.so.0(GLIBC_2.4) libsmack.so.1 libsmack.so.1(LIBSMACK) libsqlite3.so.0 libstorage.so.0.1 libsystemd.so.0 libsystemd.so.0(LIBSYSTEMD_209) libvconf.so.0 libwifi-direct.so.0 libxdgmime.so.1 +[ 63s] Processing files: download-provider-debuginfo-2.1.23-0.armv7l +[ 63s] Processing files: download-provider-debugsource-2.1.23-0.armv7l +[ 63s] Processing files: download-provider-devel-2.1.23-0.armv7l +[ 64s] Provides: libdownloadagent2.so.0.1.0 pkgconfig(download-provider) = 2.1.23-0 pkgconfig(download-provider-interface) = 2.1.23-0 +[ 64s] Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +[ 64s] Requires: /usr/bin/pkg-config ld-linux.so.3 ld-linux.so.3(GLIBC_2.4) libappsvc.so.0 libbundle.so.0 libc.so.6 libc.so.6(GLIBC_2.4) libc.so.6(GLIBC_2.7) libcapi-appfw-app-manager.so.0 libcapi-content-mime-type.so.0 libcapi-network-connection.so.1 libcurl.so.4 libcurl.so.4(CURL_OPENSSL_4) libdl.so.2 libdl.so.2(GLIBC_2.4) libdlog.so.0 libdownload-provider-interface.so.0 libdownloadagent2.so.0.1.0 libgcc_s.so.1 libgcc_s.so.1(GCC_3.0) libgcc_s.so.1(GCC_3.3.1) libgcc_s.so.1(GCC_3.5) libglib-2.0.so.0 libgobject-2.0.so.0 libnotification.so.0 libpthread.so.0 libpthread.so.0(GLIBC_2.4) libsmack.so.1 libsmack.so.1(LIBSMACK) libsqlite3.so.0 libstorage.so.0.1 libsystemd.so.0 libsystemd.so.0(LIBSYSTEMD_209) libvconf.so.0 libwifi-direct.so.0 libxdgmime.so.1 pkgconfig(bundle) pkgconfig(capi-appfw-app-manager) pkgconfig(capi-appfw-application) pkgconfig(capi-base-common) pkgconfig(dlog) pkgconfig(glib-2.0) pkgconfig(gobject-2.0) +[ 64s] Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm +[ 64s] warning: Could not canonicalize hostname: santafe +[ 64s] Wrote: /home/abuild/rpmbuild/SRPMS/download-provider-2.1.23-0.src.rpm +[ 64s] Wrote: /home/abuild/rpmbuild/RPMS/armv7l/download-provider-2.1.23-0.armv7l.rpm +[ 64s] Wrote: /home/abuild/rpmbuild/RPMS/armv7l/download-provider-debuginfo-2.1.23-0.armv7l.rpm +[ 64s] Wrote: /home/abuild/rpmbuild/RPMS/armv7l/download-provider-debugsource-2.1.23-0.armv7l.rpm +[ 64s] Wrote: /home/abuild/rpmbuild/RPMS/armv7l/download-provider-devel-2.1.23-0.armv7l.rpm +[ 64s] Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.u6ZuHj +[ 64s] + umask 022 +[ 64s] + cd /home/abuild/rpmbuild/BUILD +[ 64s] + cd download-provider-2.1.23 +[ 64s] + /bin/rm -rf /home/abuild/rpmbuild/BUILDROOT/download-provider-2.1.23-0.arm +[ 64s] + exit 0 +[ 64s] ... checking for files with abuild user/group +[ 65s] +[ 65s] santafe finished "build download-provider.spec" at Thu May 14 09:50:54 UTC 2015. +[ 65s] +[32minfo: [0mfinished building download-provider +[32minfo: [0mupdating local repo +[32minfo: [0m*** Build Status Summary *** +=== Total succeeded built packages: (1) === +[32minfo: [0mgenerated html format report: + /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/index.html +[32minfo: [0mgenerated RPM packages can be found from local repo: + /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/RPMS +[32minfo: [0mgenerated source RPM packages can be found from local repo: + /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/SRPMS +[32minfo: [0mbuild logs can be found in: + /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/logs +[32minfo: [0mbuild roots located in: + /home/youngj/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.* +info: Done +-l: change-booting-mode.sh: command not found
diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..7c5ce45 --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +gbs -c gbs.conf build -P tzm -A aarch64 --include-all $@ diff --git a/download-provider-w.manifest b/download-provider-w.manifest new file mode 100644 index 0000000..b200805 --- /dev/null +++ b/download-provider-w.manifest @@ -0,0 +1,38 @@ +<manifest> + <define> + <domain name="download-provider" /> + <provide> + <label name="download-provider::db" /> + </provide> + <request> + <smack request="download-provider::db" type="rw" /> + <smack request="system::use_internet" type="w" /> + <smack request="sys-assert::core" type="rwxat" /> + <smack request="device::sys_logging" type="w" /> + <smack request="system::media" type="arwxt" /> + <smack request="system::ext_media" type="arwxt" /> + <smack request="connman" type="rw" /> + <smack request="net-config" type="rw" /> + <smack request="wifi-direct::info" type="r" /> + <smack request="connman::get" type="rw" /> + <smack request="telephony_framework::api_ps_public" type="rw" /> + <smack request="system::vconf" type="rwxat" /> + </request> + <permit> + <smack permit="system::use_internet" type="w" /> + </permit> + </define> + <request> + <domain name="download-provider" /> + </request> + <assign> + <filesystem path="/usr/lib/libdownload-provider-interface.so*" label="_" exec_label="none" /> + <filesystem path="/usr/lib/libdownloadagent2.so*" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/download-provider.service" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/graphical.target.wants/download-provider.service" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/sockets.target.wants/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/opt/etc/dump.d/module.d/dump-download-provider.sh" label="_" exec_label="none" /> + <filesystem path="/usr/share/download-provider/download-provider.res" label="_" /> + </assign> +</manifest> diff --git a/download-provider-w.manifest~ b/download-provider-w.manifest~ new file mode 100644 index 0000000..2f8cba8 --- /dev/null +++ b/download-provider-w.manifest~ @@ -0,0 +1,37 @@ +<manifest> + <define> + <domain name="download-provider" /> + <provide> + <label name="download-provider::db" /> + </provide> + <request> + <smack request="download-provider::db" type="rw" /> + <smack request="system::use_internet" type="w" /> + <smack request="sys-assert::core" type="rwxat" /> + <smack request="device::sys_logging" type="w" /> + <smack request="system::media" type="arwxt" /> + <smack request="system::ext_media" type="arwxt" /> + <smack request="connman" type="rw" /> + <smack request="net-config" type="rw" /> + <smack request="wifi-direct::info" type="r" /> + <smack request="connman::get" type="rw" /> + <smack request="telephony_framework::api_ps_public" type="rw" /> + </request> + <permit> + <smack permit="system::use_internet" type="w" /> + </permit> + </define> + <request> + <domain name="download-provider" /> + </request> + <assign> + <filesystem path="/usr/lib/libdownload-provider-interface.so*" label="_" exec_label="none" /> + <filesystem path="/usr/lib/libdownloadagent2.so*" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/download-provider.service" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/graphical.target.wants/download-provider.service" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/sockets.target.wants/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/opt/etc/dump.d/module.d/dump-download-provider.sh" label="_" exec_label="none" /> + <filesystem path="/usr/share/download-provider/download-provider.res" label="_" /> + </assign> +</manifest> diff --git a/download-provider.manifest b/download-provider.manifest new file mode 100644 index 0000000..dabcc72 --- /dev/null +++ b/download-provider.manifest @@ -0,0 +1,41 @@ +<manifest> + <define> + <domain name="download-provider" /> + <provide> + <label name="download-provider::db" /> + </provide> + <request> + <smack request="download-provider::db" type="rw" /> + <smack request="system::use_internet" type="w" /> + <smack request="sys-assert::core" type="rwxat" /> + <smack request="device::sys_logging" type="w" /> + <smack request="system::ext_storage" type="arwxt" /> + <smack request="system::ext_media" type="arwxt" /> + <smack request="system::media" type="rwxat" /> + <smack request="system::media::root" type="rwxat" /> + <smack request="connman" type="rw" /> + <smack request="net-config" type="rw" /> + <smack request="wifi-direct::info" type="r" /> + <smack request="connman::get" type="rw" /> + <smack request="telephony_framework::api_ps_public" type="rw" /> + <smack request="system::vconf" type="rwxat" /> + </request> + <permit> + <smack permit="system::use_internet" type="w" /> + </permit> + </define> + <request> + <domain name="download-provider" /> + </request> + <assign> + <filesystem path="/usr/share/download-provider*" label="_" /> + <filesystem path="/usr/lib/libdownload-provider-interface.so*" label="_" exec_label="none" /> + <filesystem path="/usr/lib/libdownloadagent2.so*" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/download-provider.service" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/graphical.target.wants/download-provider.service" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/sockets.target.wants/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/opt/etc/dump.d/module.d/dump-download-provider.sh" label="_" exec_label="none" /> + <filesystem path="/usr/share/download-provider/download-provider.res" label="_" /> + </assign> +</manifest> diff --git a/download-provider.manifest~ b/download-provider.manifest~ new file mode 100644 index 0000000..2261820 --- /dev/null +++ b/download-provider.manifest~ @@ -0,0 +1,40 @@ +<manifest> + <define> + <domain name="download-provider" /> + <provide> + <label name="download-provider::db" /> + </provide> + <request> + <smack request="download-provider::db" type="rw" /> + <smack request="system::use_internet" type="w" /> + <smack request="sys-assert::core" type="rwxat" /> + <smack request="device::sys_logging" type="w" /> + <smack request="system::ext_storage" type="arwxt" /> + <smack request="system::ext_media" type="arwxt" /> + <smack request="system::media" type="rwxat" /> + <smack request="system::media::root" type="rwxat" /> + <smack request="connman" type="rw" /> + <smack request="net-config" type="rw" /> + <smack request="wifi-direct::info" type="r" /> + <smack request="connman::get" type="rw" /> + <smack request="telephony_framework::api_ps_public" type="rw" /> + </request> + <permit> + <smack permit="system::use_internet" type="w" /> + </permit> + </define> + <request> + <domain name="download-provider" /> + </request> + <assign> + <filesystem path="/usr/share/download-provider*" label="_" /> + <filesystem path="/usr/lib/libdownload-provider-interface.so*" label="_" exec_label="none" /> + <filesystem path="/usr/lib/libdownloadagent2.so*" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/download-provider.service" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/graphical.target.wants/download-provider.service" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/usr/lib/systemd/system/sockets.target.wants/download-provider.socket" label="_" exec_label="none" /> + <filesystem path="/opt/etc/dump.d/module.d/dump-download-provider.sh" label="_" exec_label="none" /> + <filesystem path="/usr/share/download-provider/download-provider.res" label="_" /> + </assign> +</manifest> diff --git a/download-provider.pc.in b/download-provider.pc.in new file mode 100644 index 0000000..72ea9e5 --- /dev/null +++ b/download-provider.pc.in @@ -0,0 +1,6 @@ +# Package Information + +Name: @PROJECT_NAME@ +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Cflags: -I/usr/include/download-provider diff --git a/download-provider.res b/download-provider.res new file mode 100644 index 0000000..fa78a82 --- /dev/null +++ b/download-provider.res @@ -0,0 +1 @@ +LINK=["/opt/data/download-provider/download-provider.sock,/opt/data/download-provider/download-provider.sock"] diff --git a/dump-download-provider.sh b/dump-download-provider.sh new file mode 100644 index 0000000..e639496 --- /dev/null +++ b/dump-download-provider.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +PKG_NAME=download-provider + +DUMP_DIR=$1/$PKG_NAME +/bin/mkdir -p $DUMP_DIR + +# Download DB +DB_DIR=/opt/usr/data/download-provider/database +if [ "$DB_DIR" ] +then + /bin/echo "copy download DB ..." + /bin/cp -rf ${DB_DIR}* $DUMP_DIR +fi diff --git a/gbs.conf b/gbs.conf new file mode 100644 index 0000000..399db56 --- /dev/null +++ b/gbs.conf @@ -0,0 +1,285 @@ +############################################### +# +# Tizen v2.4 for mobile +# +[profile.tizenmb_v2.4] +obs = obs.tizenmb +# The order is IMPORTANT! +repos = repo.tizenmb_base_v2.4_obs +buildroot = ~/GBS-ROOT-2.4-DEV + +[repo.tizenmb_base_v2.4_obs] +url = http://168.219.209.55/download/snapshots/2.4-mobile/common/latest/repos/target/packages + +############################################### +# +# Tizen v2.4 for emulator(i586) +# +[profile.tizen_emulator_v2.4] +obs = obs.tizenmb +# The order is IMPORTANT! +repos = repo.tizen_emulator_base_v2.4_obs +buildroot = ~/GBS-ROOT-2.4-DEV + +[repo.tizen_emulator_base_v2.4_obs] +url = http://168.219.209.55/download/snapshots/2.4-mobile/common/latest/repos/emulator/packages + +############################################### +# +# Tizen v2.3 for mobile +# +[profile.tizenmb_v2.3] +obs = obs.tizenmb +# The order is IMPORTANT! +repos = repo.tizenmb_supplement_v2.3, repo.tizenmb_supplement_chromium_v2.3, repo.tizenmb_base_v2.3 +buildroot = ~/GBS-ROOT-2.3-DEV + +[repo.tizenmb_supplement_v2.3] +url = http://10.251.52.177/tizenrepo/eur-open/supplement_v2.3 + +[repo.tizenmb_base_v2.3] +url = http://10.251.52.177/tizenrepo/eur-open/PtnZ910FXX_20141020.002 + +# Supplementary repo for chromium +[repo.tizenmb_supplement_chromium_v2.3] +url = http://10.251.52.177/tizenrepo/eur-open/supplement_mobile_chromium_orange_v2.3_1 + +############################################### +# +# Tizen v2.1 for mobile +# +[profile.tizenmb_v2.1] +passwdx = +obs = obs.tizenmb +# The order is IMPORTANT! +repos = repo.tizenmb_supplement, repo.tizenmb_base +buildroot = ~/GBS-ROOT + +[obs.tizenmb] +url = http://slp-build.sec.samsung.net:81 + +# base repo +[repo.tizenmb_base] +url = http://10.251.52.177/tizenrepo/jpn-dcm/Redwood8974JPNDCM_20131218.006 + +# Supplementary repo for additional rpms packages required in gbs build +[repo.tizenmb_supplement] +url = http://10.251.52.177/tizenrepo/jpn-dcm/supplement + +############################################### +# +# Tizen v2.2.1 for tv (GolfP Platform Binary) +# +[profile.tztv_v2.2.1_golfp] +repos = repo.tztv_2.2.1_golfp_supplement, repo.tztv_2.2.1_golfp_product, repo.tztv_2.2.1_golfp_profile, repo.tztv_2.2.1_golfp_product_i586, repo.tztv_2.2.1_golfp_profile_i586, repo.tztv_2.2.1_golfp_base +buildroot = ~/GBS-TV-2.2.1-GOLFP + +[repo.tztv_2.2.1_golfp_product] +url = http://10.251.52.177/tizenrepo/tv_repo/snapshots/tztv-2.2.1/product/tztv-2.2.1_20140807.3/repos/product/armv7l/packages/ + +[repo.tztv_2.2.1_golfp_profile] +url = http://10.251.52.177/tizenrepo/tv_repo/snapshots/tztv-2.2.1/product/tztv-2.2.1_20140807.3/repos/profile/armv7l/packages/ + +[repo.tztv_2.2.1_golfp_product_i586] +url = http://10.251.52.177/tizenrepo/tv_repo/snapshots/tztv-2.2.1/product/tztv-2.2.1_20140807.3/repos/product/ia32/packages/ + +[repo.tztv_2.2.1_golfp_profile_i586] +url = http://10.251.52.177/tizenrepo/tv_repo/snapshots/tztv-2.2.1/product/tztv-2.2.1_20140807.3/repos/profile/ia32/packages/ + +[repo.tztv_2.2.1_golfp_base] +url = http://10.251.52.177/tizenrepo/tv_repo/tizen-rsa/tizen-2.2.1 + +# Supplementary repo for additional rpms packages required in gbs build +[repo.tztv_2.2.1_golfp_supplement] +url = http://10.251.52.177/tizenrepo/tv_repo/supplement_tv + +############################################### +# +# Tizen v2.2.1 for tv (Prehawk Platform Binary) +# +[profile.tztv_v2.2.1_prehawk] +repos = repo.tztv_2.2.1_prehawk_supplement, repo.tztv_2.2.1_prehawk_product, repo.tztv_2.2.1_prehawk_profile, repo.tztv_2.2.1_prehawk_base +buildroot = ~/GBS-TV-2.2.1-PREHAWK + +[repo.tztv_2.2.1_prehawk_product] +url = http://10.251.52.177/tizenrepo/tv_repo/Prehawk_atsc_20141018.5/repos/product/armv7l/packages/ + +[repo.tztv_2.2.1_prehawk_profile] +url = http://10.251.52.177/tizenrepo/tv_repo/Prehawk_atsc_20141018.5/repos/profile/armv7l/packages/ + +[repo.tztv_2.2.1_prehawk_base] +url = http://10.251.52.177/tizenrepo/tv_repo/tizen-2.2.1-vd-4.8_20140822.1 + +# Supplementary repo for additional rpms packages required in gbs build +[repo.tztv_2.2.1_prehawk_supplement] +# This supplement is temporary repository for capi-media-player package +# which added new API (player_get_content_video_size). +# If this package will be merged, I'll change this codes +url = http://10.251.52.177/tizenrepo/tv_repo/supplement_tv_prehawk_player + +############################################### +# +# Tizen v3.0 for TV (arm-x11) +# +[obs.tizen] +url = https://api.tizen.org + +[profile.tztv_v3.0] +obs = obs.tizen +repos = repo.tv_arm-x11 +buildroot = ~/GBS-ROOT-3.0-TV + +[repo.tv_arm-x11] +url = http://download.tizen.org/snapshots/tizen/tv/latest/repos/arm-x11/packages/ +#url = http://download.tizen.org/snapshots/tizen/mobile/latest/repos/arm64-wayland/packages/ + +############################################### +# +# Tizen v3.0 for tv (emulator32-x11) +# +[obs.tizentv] +url = https://api.tizen.org + +[profile.tztv_v3.0_emulator] +obs = obs.tizentv +repos = repo.tztv_v3.0_emul +buildroot = ~/GBS-ROOT-3.0-TV-EMUL + +[repo.tztv_v3.0_emul] +url = http://download.tizen.org/snapshots/tizen/tv/latest/repos/emulator32-x11/packages/ + +############################################### +# +# Tizen v3.0 for tv (arm64-x11) +# +[obs.tizentv] +url = https://api.tizen.org + +[profile.tztv_v3.0_arm64-x11] +obs = obs.tizentv +repos = repo.tztv_v3.0_arm64-x11 +buildroot = ~/GBS-ROOT-3.0-TV-arm64-x11 + +[repo.tztv_v3.0_arm64-x11] +url = http://download.tizen.org/snapshots/tizen/tv/latest/repos/arm64-x11/packages/ + +############################################### +# +# Tizen v3.0 for tv (ia32-x11) +# +[obs.tizentv] +url = https://api.tizen.org + +[profile.tztv_v3.0_ia32-x11] +obs = obs.tizentv +repos = repo.tztv_v3.0_ia32-x11 +buildroot = ~/GBS-ROOT-3.0-TV-ia32-x11 + +[repo.tztv_v3.0_ia32-x11] +url = http://download.tizen.org/snapshots/tizen/tv/latest/repos/ia32-x11/packages/ + +############################################### +# +# Tizen v3.0 for tv (x86_64-x11) +# +[obs.tizentv] +url = https://api.tizen.org + +[profile.tztv_v3.0_x86_64-x11] +obs = obs.tizentv +repos = repo.tztv_v3.0_x86_64-x11 +buildroot = ~/GBS-ROOT-3.0-TV-x86_64-x11 + +[repo.tztv_v3.0_x86_64-x11] +url = http://download.tizen.org/snapshots/tizen/tv/latest/repos/x86_64-x11/packages/ + +############################################### +# +# Tizen v3.0 for TV (arm-wayland) +# +[obs.tizen] +url = https://api.tizen.org + +[profile.tztv_v3.0-wayland] +obs = obs.tizen +repos = repo.tv_arm-wayland +buildroot = ~/GBS-ROOT-3.0-TV-wayland + +[repo.tv_arm-wayland] +url = http://download.tizen.org/snapshots/tizen/tv/latest/repos/arm-wayland/packages/ + +############################################### +# +# Tizen v3.0 for tv (emulator32-wayland) +# +[obs.tizentv] +url = https://api.tizen.org + +[profile.tztv_v3.0_emulator-wayland] +obs = obs.tizentv +repos = repo.tztv_v3.0_emul-wayland +buildroot = ~/GBS-ROOT-3.0-TV-EMUL-wayland + +[repo.tztv_v3.0_emul-wayland] +url = http://download.tizen.org/snapshots/tizen/tv/latest/repos/emulator32-wayland/packages/ + +############################################### +# +# Tizen v3.0 for tv (arm64-wayland) +# +[obs.tizentv] +url = https://api.tizen.org + +[profile.tztv_v3.0_arm64-wayland] +obs = obs.tizentv +repos = repo.tztv_v3.0_arm64-wayland +buildroot = ~/GBS-ROOT-3.0-TV-arm64-wayland + +[repo.tztv_v3.0_arm64-wayland] +url = http://download.tizen.org/snapshots/tizen/tv/latest/repos/arm64-wayland/packages/ +#url = http://download.tizen.org/snapshots/tizen/mobile/latest/repos/arm64-wayland/packages/ + +############################################### +# +# Tizen v3.0 for tv (ia32-wayland) +# +[obs.tizentv] +url = https://api.tizen.org + +[profile.tztv_v3.0_ia32-wayland] +obs = obs.tizentv +repos = repo.tztv_v3.0_ia32-wayland +buildroot = ~/GBS-ROOT-3.0-TV-ia32-wayland + +[repo.tztv_v3.0_ia32-wayland] +url = http://download.tizen.org/snapshots/tizen/tv/latest/repos/ia32-wayland/packages/ + +############################################### +# +# Tizen v3.0 for tv (x86_64-wayland) +# +[obs.tizentv] +url = https://api.tizen.org + +[profile.tztv_v3.0_x86_64-wayland] +obs = obs.tizentv +repos = repo.tztv_v3.0_x86_64-wayland +buildroot = ~/GBS-ROOT-3.0-TV-x86_64-wayland + +[repo.tztv_v3.0_x86_64-wayland] +url = http://download.tizen.org/snapshots/tizen/tv/latest/repos/x86_64-wayland/packages/ + +############################################### +# +# Tizen v3.0 for Mobile (arm64-wayland) +# +[obs.tizen] +url = https://api.tizen.org + +[profile.tzm] +obs = obs.tizen +repos = repo.arm64-wayland +buildroot = ~/GBS-ROOT-3.0-Mobile-wayland64 + +[repo.arm64-wayland] +url = http://download.tizen.org/snapshots/tizen/mobile/latest/repos/arm64-wayland/packages/
\ No newline at end of file @@ -0,0 +1,10 @@ +#!/bin/bash + +sdb root on +sdb shell change-booting-mode.sh --update + +sdb -d push /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/RPMS/org.tizen.browser* /root + +sdb shell rpm -e --nodeps org.tizen.browser +sdb shell pkgcmd -i -t rpm -p /root/org.tizen.browser-4* + diff --git a/packaging/download-provider.spec b/packaging/download-provider.spec new file mode 100644 index 0000000..06b893c --- /dev/null +++ b/packaging/download-provider.spec @@ -0,0 +1,215 @@ +%define _ux_define tizen2.3 +Name: download-provider +Summary: Download the contents in background +Version: 2.1.23 +Release: 0 +Group: Development/Libraries +License: Apache License, Version 2.0 +Source0: %{name}-%{version}.tar.gz +Requires(post): sys-assert +Requires(post): libdevice-node +Requires(post): sqlite +Requires(post): connman +BuildRequires: cmake +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(gobject-2.0) +BuildRequires: pkgconfig(xdgmime) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(bundle) +BuildRequires: pkgconfig(capi-base-common) +BuildRequires: pkgconfig(capi-appfw-app-manager) +BuildRequires: pkgconfig(capi-appfw-application) +BuildRequires: pkgconfig(capi-network-connection) +BuildRequires: pkgconfig(appsvc) +BuildRequires: pkgconfig(libcurl) +BuildRequires: pkgconfig(capi-content-mime-type) +BuildRequires: pkgconfig(libsmack) +BuildRequires: gettext-devel +BuildRequires: pkgconfig(libsystemd-daemon) +BuildRequires: pkgconfig(capi-network-wifi-direct) +BuildRequires: pkgconfig(libresourced) +#BuildRequires: model-build-features T30 +BuildRequires: pkgconfig(storage) +%if "%{?tizen_profile_name}" == "wearable" +BuildRequires: pkgconfig(security-server) +%else if "%{?tizen_profile_name}" == "mobile" +BuildRequires: pkgconfig(notification) +%endif + +%description +Description: Download the contents in background + +%package devel +Summary: download-provider +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +Description: Download the contents in background (development files) + +%prep +%setup -q + +%define _data_install_path /opt/usr/data/%{name} +%define _resource_install_path /usr/share/%{name} +%define _imagedir %{_resource_install_path}/images +%define _localedir %{_resource_install_path}/locales +%define _databasedir %{_data_install_path}/database +%define _database_client_dir %{_databasedir}/clients +%define _notifydir %{_data_install_path}/notify +%define _ipc_socket /opt/data/%{name}/%{name}.sock +%define _licensedir /usr/share/license +%define _logdump_script_dir /opt/etc/dump.d/module.d +%define _http_lib libcurl + +%define download_booster OFF +%define sys_resource OFF +%define support_oma_drm OFF +%define wifi_direct ON +%define support_security_privilege OFF +%define support_companion_mode OFF +%define support_notification ON +%define support_knox ON +%define _manifest_name %{name}.manifest + +%if 0%{?model_build_feature_wlan_p2p_disable } +%define wifi_direct OFF +%endif +%if "%{?tizen_profile_name}" == "wearable" +%define download_booster OFF +%define support_notification OFF +%define _manifest_name %{name}-w.manifest +%endif +%if 0%{?sec_product_feature_container_enable} +%define support_knox ON +%endif + +%define cmake \ + CFLAGS="${CFLAGS:-%optflags} -fPIC -D_REENTRANT -fvisibility=hidden"; export CFLAGS \ + FFLAGS="${FFLAGS:-%optflags} -fPIC -fvisibility=hidden"; export FFLAGS \ + LDFLAGS+=" -Wl,--as-needed -Wl,--hash-style=both"; export LDFLAGS \ + %__cmake \\\ + -DCMAKE_INSTALL_PREFIX:PATH=%{_prefix} \\\ + -DBIN_INSTALL_DIR:PATH=%{_bindir} \\\ + -DLIB_INSTALL_DIR:PATH=%{_libdir} \\\ + -DINCLUDE_INSTALL_DIR:PATH=%{_includedir} \\\ + -DPKG_NAME=%{name} \\\ + -DPKG_VERSION=%{version} \\\ + -DPKG_RELEASE=%{release} \\\ + -DIPC_SOCKET:PATH=%{_ipc_socket} \\\ + -DPROVIDER_DIR:PATH=%{_data_install_path} \\\ + -DNOTIFY_DIR:PATH=%{_notifydir} \\\ + -DDATABASE_DIR:PATH=%{_databasedir} \\\ + -DDATABASE_CLIENT_DIR:PATH=%{_database_client_dir} \\\ + -DIMAGE_DIR:PATH=%{_imagedir} \\\ + -DLOCALE_DIR:PATH=%{_localedir} \\\ + -DLICENSE_DIR:PATH=%{_licensedir} \\\ + -DSUPPORT_WIFI_DIRECT:BOOL=OFF \\\ + %if "%{?sys_resource}" == "ON" \ + -DSUPPORT_SYS_RESOURCE:BOOL=ON \\\ + %else \ + -DSUPPORT_SYS_RESOURCE:BOOL=OFF \\\ + %endif \ + %if "%{?download_booster}" == "ON" \ + -DSUPPORT_DOWNLOAD_BOOSTER:BOOL=ON \\\ + %else \ + -DSUPPORT_DOWNLOAD_BOOSTER:BOOL=OFF \\\ + %endif \ + %if "%{?support_notification}" == "ON" \ + -DSUPPORT_NOTIFICATION:BOOL=ON \\\ + %else \ + -DSUPPORT_NOTIFICATION:BOOL=OFF \\\ + %endif \ + -DSUPPORT_LOG_MESSAGE:BOOL=ON \\\ + %if "%{?support_oma_drm}" == "ON" \ + -DSUPPORT_OMA_DRM:BOOL=ON \\\ + %else \ + -DSUPPORT_OMA_DRM:BOOL=OFF \\\ + %endif \ + %if "%{?support_security_privilege}" == "ON" \ + -DSUPPORT_SECURITY_PRIVILEGE:BOOL=ON \\\ + %else \ + -DSUPPORT_SECURITY_PRIVILEGE:BOOL=OFF \\\ + %endif \ + %if "%{?support_companion_mode}" == "ON" \ + -DSUPPORT_COMPANION_MODE:BOOL=ON \\\ + %else \ + -DSUPPORT_COMPANION_MODE:BOOL=OFF \\\ + %endif \ + %if "%{?support_knox}" == "ON" \ + -DSUPPORT_KNOX:BOOL=ON \\\ + %else \ + -DSUPPORT_KNOX:BOOL=OFF \\\ + %endif \ + %if "%{?_ux_define}" == "tizen2.3" \ + -DTIZEN_2_3_UX:BOOL=ON \\\ + %endif \ + -DCMAKE_LOG_DUMP_SCRIPT_DIR=%{_logdump_script_dir} \\\ + -DHTTP_LIB=%{_http_lib} \\\ + %if "%{?_lib}" == "lib64" \ + %{?_cmake_lib_suffix64} \\\ + %endif \ + %{?_cmake_skip_rpath} \\\ + -DBUILD_SHARED_LIBS:BOOL=ON + +%build +export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE" +export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" +export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" +%cmake . +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +#%if 0%{?sec_product_feature_container_enable} +mkdir -p %{buildroot}/etc/vasum/vsmzone.resource/ +mv %{buildroot}/usr/share/download-provider/download-provider.res %{buildroot}/etc/vasum/vsmzone.resource/ +#%endif + +mkdir -p %{buildroot}%{_licensedir} +mkdir -p %{buildroot}%{_libdir}/systemd/system/graphical.target.wants +mkdir -p %{buildroot}%{_libdir}/systemd/system/sockets.target.wants +ln -s ../download-provider.service %{buildroot}%{_libdir}/systemd/system/graphical.target.wants/ +ln -s ../download-provider.socket %{buildroot}%{_libdir}/systemd/system/sockets.target.wants/ + +%post +#make notify dir in post section for smack +mkdir -p %{_notifydir} +mkdir -p --mode=0700 %{_databasedir} +chsmack -a 'download-provider' %{_databasedir} +mkdir -p --mode=0700 %{_database_client_dir} +chsmack -a 'download-provider' %{_database_client_dir} + +%files +%defattr(-,root,root,-) +%manifest %{_manifest_name} +%{_imagedir}/*.png +%{_localedir}/*/*/download-provider.mo +%{_libdir}/libdownloadagent2.so.0.1.0 +%{_libdir}/libdownloadagent2.so +%{_libdir}/systemd/system/download-provider.service +%{_libdir}/systemd/system/graphical.target.wants/download-provider.service +%{_libdir}/systemd/system/download-provider.socket +%{_libdir}/systemd/system/sockets.target.wants/download-provider.socket +%{_libdir}/libdownload-provider-interface.so.%{version} +%{_libdir}/libdownload-provider-interface.so.0 +%{_bindir}/%{name} +%{_licensedir}/%{name} +%attr(0544,root,root) %{_logdump_script_dir}/dump-%{name}.sh +#%if 0%{?sec_product_feature_container_enable} +%attr(0644,root,root) /etc/vasum/vsmzone.resource/download-provider.res +#%endif + +%files devel +%defattr(-,root,root,-) +%{_libdir}/libdownloadagent2.so.0.1.0 +%{_libdir}/libdownloadagent2.so +%{_libdir}/libdownload-provider-interface.so +%{_includedir}/download-provider/download-provider.h +%{_includedir}/download-provider/download-provider-interface.h +%{_bindir}/%{name} +%{_libdir}/pkgconfig/download-provider.pc +%{_libdir}/pkgconfig/download-provider-interface.pc diff --git a/packaging/download-provider.spec~ b/packaging/download-provider.spec~ new file mode 100644 index 0000000..ac0ab57 --- /dev/null +++ b/packaging/download-provider.spec~ @@ -0,0 +1,219 @@ +%define _ux_define tizen2.3 +Name: download-provider +Summary: Download the contents in background +Version: 2.1.23 +Release: 0 +Group: Development/Libraries +License: Apache License, Version 2.0 +Source0: %{name}-%{version}.tar.gz +Requires(post): sys-assert +Requires(post): libdevice-node +Requires(post): sqlite +Requires(post): connman +BuildRequires: cmake +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(gobject-2.0) +BuildRequires: pkgconfig(xdgmime) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(bundle) +BuildRequires: pkgconfig(capi-base-common) +BuildRequires: pkgconfig(capi-appfw-app-manager) +BuildRequires: pkgconfig(capi-appfw-application) +BuildRequires: pkgconfig(capi-network-connection) +BuildRequires: pkgconfig(appsvc) +BuildRequires: pkgconfig(libcurl) +BuildRequires: pkgconfig(capi-content-mime-type) +BuildRequires: pkgconfig(libsmack) +BuildRequires: gettext-devel +BuildRequires: pkgconfig(libsystemd-daemon) +BuildRequires: pkgconfig(capi-network-wifi-direct) +BuildRequires: pkgconfig(libresourced) +BuildRequires: model-build-features +BuildRequires: pkgconfig(storage) +%if "%{?tizen_profile_name}" == "wearable" +BuildRequires: pkgconfig(security-server) +%else if "%{?tizen_profile_name}" == "mobile" +BuildRequires: pkgconfig(notification) +%endif + +%description +Description: Download the contents in background + +%package devel +Summary: download-provider +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +Description: Download the contents in background (development files) + +%prep +%setup -q + +%define _data_install_path /opt/usr/data/%{name} +%define _resource_install_path /usr/share/%{name} +%define _imagedir %{_resource_install_path}/images +%define _localedir %{_resource_install_path}/locales +%define _databasedir %{_data_install_path}/database +%define _database_client_dir %{_databasedir}/clients +%define _notifydir %{_data_install_path}/notify +%define _ipc_socket /opt/data/%{name}/%{name}.sock +%define _licensedir /usr/share/license +%define _logdump_script_dir /opt/etc/dump.d/module.d +%define _http_lib libcurl + +%define download_booster OFF +%define sys_resource OFF +%define support_oma_drm OFF +%define wifi_direct ON +%define support_security_privilege OFF +%define support_companion_mode OFF +%define support_notification ON +%define support_knox ON +%define _manifest_name %{name}.manifest + +%if 0%{?model_build_feature_wlan_p2p_disable } +%define wifi_direct OFF +%endif +%if "%{?tizen_profile_name}" == "wearable" +%define download_booster OFF +%define support_notification OFF +%define _manifest_name %{name}-w.manifest +%endif +%if 0%{?sec_product_feature_container_enable} +%define support_knox ON +%endif + +%define cmake \ + CFLAGS="${CFLAGS:-%optflags} -fPIC -D_REENTRANT -fvisibility=hidden"; export CFLAGS \ + FFLAGS="${FFLAGS:-%optflags} -fPIC -fvisibility=hidden"; export FFLAGS \ + LDFLAGS+=" -Wl,--as-needed -Wl,--hash-style=both"; export LDFLAGS \ + %__cmake \\\ + -DCMAKE_INSTALL_PREFIX:PATH=%{_prefix} \\\ + -DBIN_INSTALL_DIR:PATH=%{_bindir} \\\ + -DLIB_INSTALL_DIR:PATH=%{_libdir} \\\ + -DINCLUDE_INSTALL_DIR:PATH=%{_includedir} \\\ + -DPKG_NAME=%{name} \\\ + -DPKG_VERSION=%{version} \\\ + -DPKG_RELEASE=%{release} \\\ + -DIPC_SOCKET:PATH=%{_ipc_socket} \\\ + -DPROVIDER_DIR:PATH=%{_data_install_path} \\\ + -DNOTIFY_DIR:PATH=%{_notifydir} \\\ + -DDATABASE_DIR:PATH=%{_databasedir} \\\ + -DDATABASE_CLIENT_DIR:PATH=%{_database_client_dir} \\\ + -DIMAGE_DIR:PATH=%{_imagedir} \\\ + -DLOCALE_DIR:PATH=%{_localedir} \\\ + -DLICENSE_DIR:PATH=%{_licensedir} \\\ + %if "%{?wifi_direct}" == "ON" \ + -DSUPPORT_WIFI_DIRECT:BOOL=ON \\\ + %else \ + -DSUPPORT_WIFI_DIRECT:BOOL=OFF \\\ + %endif \ + %if "%{?sys_resource}" == "ON" \ + -DSUPPORT_SYS_RESOURCE:BOOL=ON \\\ + %else \ + -DSUPPORT_SYS_RESOURCE:BOOL=OFF \\\ + %endif \ + %if "%{?download_booster}" == "ON" \ + -DSUPPORT_DOWNLOAD_BOOSTER:BOOL=ON \\\ + %else \ + -DSUPPORT_DOWNLOAD_BOOSTER:BOOL=OFF \\\ + %endif \ + %if "%{?support_notification}" == "ON" \ + -DSUPPORT_NOTIFICATION:BOOL=ON \\\ + %else \ + -DSUPPORT_NOTIFICATION:BOOL=OFF \\\ + %endif \ + -DSUPPORT_LOG_MESSAGE:BOOL=ON \\\ + %if "%{?support_oma_drm}" == "ON" \ + -DSUPPORT_OMA_DRM:BOOL=ON \\\ + %else \ + -DSUPPORT_OMA_DRM:BOOL=OFF \\\ + %endif \ + %if "%{?support_security_privilege}" == "ON" \ + -DSUPPORT_SECURITY_PRIVILEGE:BOOL=ON \\\ + %else \ + -DSUPPORT_SECURITY_PRIVILEGE:BOOL=OFF \\\ + %endif \ + %if "%{?support_companion_mode}" == "ON" \ + -DSUPPORT_COMPANION_MODE:BOOL=ON \\\ + %else \ + -DSUPPORT_COMPANION_MODE:BOOL=OFF \\\ + %endif \ + %if "%{?support_knox}" == "ON" \ + -DSUPPORT_KNOX:BOOL=ON \\\ + %else \ + -DSUPPORT_KNOX:BOOL=OFF \\\ + %endif \ + %if "%{?_ux_define}" == "tizen2.3" \ + -DTIZEN_2_3_UX:BOOL=ON \\\ + %endif \ + -DCMAKE_LOG_DUMP_SCRIPT_DIR=%{_logdump_script_dir} \\\ + -DHTTP_LIB=%{_http_lib} \\\ + %if "%{?_lib}" == "lib64" \ + %{?_cmake_lib_suffix64} \\\ + %endif \ + %{?_cmake_skip_rpath} \\\ + -DBUILD_SHARED_LIBS:BOOL=ON + +%build +export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE" +export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" +export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" +%cmake . +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +%if 0%{?sec_product_feature_container_enable} +mkdir -p %{buildroot}/etc/vasum/vsmzone.resource/ +mv %{buildroot}/usr/share/download-provider/download-provider.res %{buildroot}/etc/vasum/vsmzone.resource/ +%endif + +mkdir -p %{buildroot}%{_licensedir} +mkdir -p %{buildroot}%{_libdir}/systemd/system/graphical.target.wants +mkdir -p %{buildroot}%{_libdir}/systemd/system/sockets.target.wants +ln -s ../download-provider.service %{buildroot}%{_libdir}/systemd/system/graphical.target.wants/ +ln -s ../download-provider.socket %{buildroot}%{_libdir}/systemd/system/sockets.target.wants/ + +%post +#make notify dir in post section for smack +mkdir -p %{_notifydir} +mkdir -p --mode=0700 %{_databasedir} +chsmack -a 'download-provider' %{_databasedir} +mkdir -p --mode=0700 %{_database_client_dir} +chsmack -a 'download-provider' %{_database_client_dir} + +%files +%defattr(-,root,root,-) +%manifest %{_manifest_name} +%{_imagedir}/*.png +%{_localedir}/*/*/download-provider.mo +%{_libdir}/libdownloadagent2.so.0.1.0 +%{_libdir}/libdownloadagent2.so +%{_libdir}/systemd/system/download-provider.service +%{_libdir}/systemd/system/graphical.target.wants/download-provider.service +%{_libdir}/systemd/system/download-provider.socket +%{_libdir}/systemd/system/sockets.target.wants/download-provider.socket +%{_libdir}/libdownload-provider-interface.so.%{version} +%{_libdir}/libdownload-provider-interface.so.0 +%{_bindir}/%{name} +%{_licensedir}/%{name} +%attr(0544,root,root) %{_logdump_script_dir}/dump-%{name}.sh +%if 0%{?sec_product_feature_container_enable} +%attr(0644,root,root) /etc/vasum/vsmzone.resource/download-provider.res +%endif + +%files devel +%defattr(-,root,root,-) +%{_libdir}/libdownloadagent2.so.0.1.0 +%{_libdir}/libdownloadagent2.so +%{_libdir}/libdownload-provider-interface.so +%{_includedir}/download-provider/download-provider.h +%{_includedir}/download-provider/download-provider-interface.h +%{_bindir}/%{name} +%{_libdir}/pkgconfig/download-provider.pc +%{_libdir}/pkgconfig/download-provider-interface.pc diff --git a/po/redwood/CMakeLists.txt b/po/redwood/CMakeLists.txt new file mode 100644 index 0000000..706d725 --- /dev/null +++ b/po/redwood/CMakeLists.txt @@ -0,0 +1,27 @@ +# for i18n + +SET(POFILES az.po bg.po ca.po cs.po da.po de.po el_GR.po en.po en_US.po es_ES.po + es_US.po et.po eu.po fi.po fr_CA.po fr.po gl.po hr.po hu.po hy.po is.po + it_IT.po ka.po kk.po ko_KR.po lt.po lv.po mn_MN.po nb.po nl.po pl.po + pt_BR.po pt_PT.po ro.po ru_RU.po sk.po sl.po sr.po sv.po tr_TR.po uk.po uz.po) + +SET(MSGFMT "/usr/bin/msgfmt") + +FOREACH(pofile ${POFILES}) + SET(pofile ${CMAKE_CURRENT_SOURCE_DIR}/${pofile}) + MESSAGE("PO: ${pofile}") + GET_FILENAME_COMPONENT(absPofile ${pofile} ABSOLUTE) + GET_FILENAME_COMPONENT(lang ${absPofile} NAME_WE) + SET(moFile ${CMAKE_CURRENT_BINARY_DIR}/${lang}.mo) + ADD_CUSTOM_COMMAND( + OUTPUT ${moFile} + COMMAND ${MSGFMT} -o ${moFile} ${absPofile} + DEPENDS ${absPofile} + ) + INSTALL(FILES ${moFile} + DESTINATION ${LOCALE_DIR}/${lang}/LC_MESSAGES RENAME ${PKG_NAME}.mo) + SET(moFiles ${moFiles} ${moFile}) +ENDFOREACH(pofile) + +MESSAGE(".mo files: ${moFiles}") +ADD_CUSTOM_TARGET(po ALL DEPENDS ${moFiles}) diff --git a/po/redwood/az.po b/po/redwood/az.po new file mode 100644 index 0000000..f8d4868 --- /dev/null +++ b/po/redwood/az.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Yükləmə tamamlandı" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Yükləmə alınmadı" + diff --git a/po/redwood/bg.po b/po/redwood/bg.po new file mode 100644 index 0000000..4b2b9cb --- /dev/null +++ b/po/redwood/bg.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Изтеглянето завършено" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Изтеглянето неуспешно" + diff --git a/po/redwood/ca.po b/po/redwood/ca.po new file mode 100644 index 0000000..e4cb32e --- /dev/null +++ b/po/redwood/ca.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descàrrega completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Descàrrega fallida" + diff --git a/po/redwood/cs.po b/po/redwood/cs.po new file mode 100644 index 0000000..7c33b8b --- /dev/null +++ b/po/redwood/cs.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Stahování dokončeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Stažení se nezdařilo" + diff --git a/po/redwood/da.po b/po/redwood/da.po new file mode 100644 index 0000000..1cbbbec --- /dev/null +++ b/po/redwood/da.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Overførsel fuldført" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Overførsel mislykkedes" + diff --git a/po/redwood/de.po b/po/redwood/de.po new file mode 100644 index 0000000..8301d76 --- /dev/null +++ b/po/redwood/de.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download beendet" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download fehlgeschlagen" + diff --git a/po/redwood/el_GR.po b/po/redwood/el_GR.po new file mode 100644 index 0000000..f96c0a1 --- /dev/null +++ b/po/redwood/el_GR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Η λήψη ολοκληρώθηκε" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Αποτυχία λήψης" + diff --git a/po/redwood/en.po b/po/redwood/en.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/redwood/en.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/redwood/en_US.po b/po/redwood/en_US.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/redwood/en_US.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/redwood/es_ES.po b/po/redwood/es_ES.po new file mode 100644 index 0000000..300e275 --- /dev/null +++ b/po/redwood/es_ES.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Error de descarga" + diff --git a/po/redwood/es_US.po b/po/redwood/es_US.po new file mode 100644 index 0000000..6be685a --- /dev/null +++ b/po/redwood/es_US.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Error al descargar" + diff --git a/po/redwood/et.po b/po/redwood/et.po new file mode 100644 index 0000000..6ffe386 --- /dev/null +++ b/po/redwood/et.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Allalaadimine on lõpule viidud" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Allalaadimine nurjus" + diff --git a/po/redwood/eu.po b/po/redwood/eu.po new file mode 100644 index 0000000..b9db71f --- /dev/null +++ b/po/redwood/eu.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Deskarga osatuta" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Deskargak huts egin du" + diff --git a/po/redwood/fi.po b/po/redwood/fi.po new file mode 100644 index 0000000..7929571 --- /dev/null +++ b/po/redwood/fi.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Lataus valmis" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Lataus epäonnistui" + diff --git a/po/redwood/fr.po b/po/redwood/fr.po new file mode 100644 index 0000000..f1e8884 --- /dev/null +++ b/po/redwood/fr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Téléchargement terminé" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Echec du téléchargement" + diff --git a/po/redwood/fr_CA.po b/po/redwood/fr_CA.po new file mode 100644 index 0000000..608ae3d --- /dev/null +++ b/po/redwood/fr_CA.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Téléchargement terminé" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Échec du téléchargement" + diff --git a/po/redwood/gl.po b/po/redwood/gl.po new file mode 100644 index 0000000..8527d75 --- /dev/null +++ b/po/redwood/gl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Erro na descarga" + diff --git a/po/redwood/hr.po b/po/redwood/hr.po new file mode 100644 index 0000000..0f225a4 --- /dev/null +++ b/po/redwood/hr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Skidanje dovršeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Skidanje neuspješno" + diff --git a/po/redwood/hu.po b/po/redwood/hu.po new file mode 100644 index 0000000..847e5af --- /dev/null +++ b/po/redwood/hu.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "A letöltés befejeződött" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Sikertelen letöltés" + diff --git a/po/redwood/hy.po b/po/redwood/hy.po new file mode 100644 index 0000000..8636b2b --- /dev/null +++ b/po/redwood/hy.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Ներբեռնումն ավարտվեց" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Ներբեռնումը ձախողվեց" + diff --git a/po/redwood/is.po b/po/redwood/is.po new file mode 100644 index 0000000..3bb7f29 --- /dev/null +++ b/po/redwood/is.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Niðurhali lokið" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Niðurhal mistókst" + diff --git a/po/redwood/it_IT.po b/po/redwood/it_IT.po new file mode 100644 index 0000000..51a407e --- /dev/null +++ b/po/redwood/it_IT.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download completato" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download non riuscito" + diff --git a/po/redwood/ka.po b/po/redwood/ka.po new file mode 100644 index 0000000..83aea79 --- /dev/null +++ b/po/redwood/ka.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "ჩამოტვირთვა დასრულდა" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "ვერ ჩამოიტვირთა" + diff --git a/po/redwood/kk.po b/po/redwood/kk.po new file mode 100644 index 0000000..bd25ab4 --- /dev/null +++ b/po/redwood/kk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Жүктеу аяқталды" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Жүктеу орындалмады" + diff --git a/po/redwood/ko_KR.po b/po/redwood/ko_KR.po new file mode 100644 index 0000000..80d1e37 --- /dev/null +++ b/po/redwood/ko_KR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "다운로드 완료" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "다운로드 안 됨" + diff --git a/po/redwood/lt.po b/po/redwood/lt.po new file mode 100644 index 0000000..d08e1d5 --- /dev/null +++ b/po/redwood/lt.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Atsisiuntimas baigtas" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Atsisiųsti nepavyko" + diff --git a/po/redwood/lv.po b/po/redwood/lv.po new file mode 100644 index 0000000..323c609 --- /dev/null +++ b/po/redwood/lv.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Lejupielāde pabeigta" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Lejupielāde neizdevās" + diff --git a/po/redwood/mn_MN.po b/po/redwood/mn_MN.po new file mode 100644 index 0000000..7060f68 --- /dev/null +++ b/po/redwood/mn_MN.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Татан авалт дууссан" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Татаж авч чадсангүй" + diff --git a/po/redwood/nb.po b/po/redwood/nb.po new file mode 100644 index 0000000..49448f5 --- /dev/null +++ b/po/redwood/nb.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Nedlasting fullført" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Nedlastingen mislyktes" + diff --git a/po/redwood/nl.po b/po/redwood/nl.po new file mode 100644 index 0000000..1195f04 --- /dev/null +++ b/po/redwood/nl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Downloaden voltooid" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Downloaden mislukt" + diff --git a/po/redwood/pl.po b/po/redwood/pl.po new file mode 100644 index 0000000..9e52a17 --- /dev/null +++ b/po/redwood/pl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Pobieranie zakończone" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Pobieranie nie powiodło się" + diff --git a/po/redwood/pt_BR.po b/po/redwood/pt_BR.po new file mode 100644 index 0000000..0fdce74 --- /dev/null +++ b/po/redwood/pt_BR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download concluído" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Falha no download" + diff --git a/po/redwood/pt_PT.po b/po/redwood/pt_PT.po new file mode 100644 index 0000000..c934937 --- /dev/null +++ b/po/redwood/pt_PT.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Transferência concluída" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "A transferência falhou" + diff --git a/po/redwood/ro.po b/po/redwood/ro.po new file mode 100644 index 0000000..820ab33 --- /dev/null +++ b/po/redwood/ro.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descărcare finalizată" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Descărcarea nu a reuşit" + diff --git a/po/redwood/ru_RU.po b/po/redwood/ru_RU.po new file mode 100644 index 0000000..e3cb63a --- /dev/null +++ b/po/redwood/ru_RU.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Загрузка завершена" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Сбой загрузки" + diff --git a/po/redwood/sk.po b/po/redwood/sk.po new file mode 100644 index 0000000..6d92c75 --- /dev/null +++ b/po/redwood/sk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Sťahovanie je dokončené" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Sťahovanie zlyhalo" + diff --git a/po/redwood/sl.po b/po/redwood/sl.po new file mode 100644 index 0000000..1c256ab --- /dev/null +++ b/po/redwood/sl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Prenos je končan" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Prenos ni uspel" + diff --git a/po/redwood/sr.po b/po/redwood/sr.po new file mode 100644 index 0000000..2e6331a --- /dev/null +++ b/po/redwood/sr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Preuzimanje završeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Neuspešno preuzimanje" + diff --git a/po/redwood/sv.po b/po/redwood/sv.po new file mode 100644 index 0000000..e792e63 --- /dev/null +++ b/po/redwood/sv.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Hämtningen är klar" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Hämtningen misslyckades" + diff --git a/po/redwood/tr_TR.po b/po/redwood/tr_TR.po new file mode 100644 index 0000000..73277df --- /dev/null +++ b/po/redwood/tr_TR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "İndirme tamamlandı" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "İndirme başarısız" + diff --git a/po/redwood/uk.po b/po/redwood/uk.po new file mode 100644 index 0000000..ad32cd3 --- /dev/null +++ b/po/redwood/uk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Завантаження завершено" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Збій завантаження" + diff --git a/po/redwood/uz.po b/po/redwood/uz.po new file mode 100644 index 0000000..ff9b724 --- /dev/null +++ b/po/redwood/uz.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Yuklab olish yakunlandi" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Yuklab olib bo‘lmadi" + diff --git a/po/tizen2.3/CMakeLists.txt b/po/tizen2.3/CMakeLists.txt new file mode 100644 index 0000000..1ff1ce8 --- /dev/null +++ b/po/tizen2.3/CMakeLists.txt @@ -0,0 +1,30 @@ +# for i18n + +SET(POFILES + ar.po az.po bg.po ca.po cs.po da.po de.po el_GR.po en.po + en_PH.po en_US.po es_ES.po es_US.po et.po eu.po fi.po fr.po + fr_CA.po ga.po gl.po hi.po hr.po hu.po hy.po is.po it_IT.po + ja_JP.po ka.po kk.po ko_KR.po lt.po lv.po mk.po nb.po nl.po + pl.po pt_BR.po pt_PT.po ro.po ru_RU.po sk.po sl.po sr.po sv.po + tr_TR.po uk.po uz.po zh_CN.po zh_HK.po zh_TW.po) + +SET(MSGFMT "/usr/bin/msgfmt") + +FOREACH(pofile ${POFILES}) + SET(pofile ${CMAKE_CURRENT_SOURCE_DIR}/${pofile}) + MESSAGE("PO: ${pofile}") + GET_FILENAME_COMPONENT(absPofile ${pofile} ABSOLUTE) + GET_FILENAME_COMPONENT(lang ${absPofile} NAME_WE) + SET(moFile ${CMAKE_CURRENT_BINARY_DIR}/${lang}.mo) + ADD_CUSTOM_COMMAND( + OUTPUT ${moFile} + COMMAND ${MSGFMT} -o ${moFile} ${absPofile} + DEPENDS ${absPofile} + ) + INSTALL(FILES ${moFile} + DESTINATION ${LOCALE_DIR}/${lang}/LC_MESSAGES RENAME ${PKG_NAME}.mo) + SET(moFiles ${moFiles} ${moFile}) +ENDFOREACH(pofile) + +MESSAGE(".mo files: ${moFiles}") +ADD_CUSTOM_TARGET(po ALL DEPENDS ${moFiles}) diff --git a/po/tizen2.3/ar.po b/po/tizen2.3/ar.po new file mode 100644 index 0000000..1bf0a3c --- /dev/null +++ b/po/tizen2.3/ar.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "تم التنزيل" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "فشل التنزيل" + diff --git a/po/tizen2.3/az.po b/po/tizen2.3/az.po new file mode 100644 index 0000000..f8d4868 --- /dev/null +++ b/po/tizen2.3/az.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Yükləmə tamamlandı" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Yükləmə alınmadı" + diff --git a/po/tizen2.3/bg.po b/po/tizen2.3/bg.po new file mode 100644 index 0000000..4b2b9cb --- /dev/null +++ b/po/tizen2.3/bg.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Изтеглянето завършено" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Изтеглянето неуспешно" + diff --git a/po/tizen2.3/ca.po b/po/tizen2.3/ca.po new file mode 100644 index 0000000..e4cb32e --- /dev/null +++ b/po/tizen2.3/ca.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descàrrega completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Descàrrega fallida" + diff --git a/po/tizen2.3/cs.po b/po/tizen2.3/cs.po new file mode 100644 index 0000000..7c33b8b --- /dev/null +++ b/po/tizen2.3/cs.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Stahování dokončeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Stažení se nezdařilo" + diff --git a/po/tizen2.3/da.po b/po/tizen2.3/da.po new file mode 100644 index 0000000..1cbbbec --- /dev/null +++ b/po/tizen2.3/da.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Overførsel fuldført" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Overførsel mislykkedes" + diff --git a/po/tizen2.3/de.po b/po/tizen2.3/de.po new file mode 100644 index 0000000..8301d76 --- /dev/null +++ b/po/tizen2.3/de.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download beendet" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download fehlgeschlagen" + diff --git a/po/tizen2.3/el_GR.po b/po/tizen2.3/el_GR.po new file mode 100644 index 0000000..f96c0a1 --- /dev/null +++ b/po/tizen2.3/el_GR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Η λήψη ολοκληρώθηκε" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Αποτυχία λήψης" + diff --git a/po/tizen2.3/en.po b/po/tizen2.3/en.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/tizen2.3/en.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/tizen2.3/en_PH.po b/po/tizen2.3/en_PH.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/tizen2.3/en_PH.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/tizen2.3/en_US.po b/po/tizen2.3/en_US.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/tizen2.3/en_US.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/tizen2.3/es_ES.po b/po/tizen2.3/es_ES.po new file mode 100644 index 0000000..300e275 --- /dev/null +++ b/po/tizen2.3/es_ES.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Error de descarga" + diff --git a/po/tizen2.3/es_US.po b/po/tizen2.3/es_US.po new file mode 100644 index 0000000..6be685a --- /dev/null +++ b/po/tizen2.3/es_US.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Error al descargar" + diff --git a/po/tizen2.3/et.po b/po/tizen2.3/et.po new file mode 100644 index 0000000..6ffe386 --- /dev/null +++ b/po/tizen2.3/et.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Allalaadimine on lõpule viidud" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Allalaadimine nurjus" + diff --git a/po/tizen2.3/eu.po b/po/tizen2.3/eu.po new file mode 100644 index 0000000..b9db71f --- /dev/null +++ b/po/tizen2.3/eu.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Deskarga osatuta" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Deskargak huts egin du" + diff --git a/po/tizen2.3/fi.po b/po/tizen2.3/fi.po new file mode 100644 index 0000000..7929571 --- /dev/null +++ b/po/tizen2.3/fi.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Lataus valmis" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Lataus epäonnistui" + diff --git a/po/tizen2.3/fr.po b/po/tizen2.3/fr.po new file mode 100644 index 0000000..f1e8884 --- /dev/null +++ b/po/tizen2.3/fr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Téléchargement terminé" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Echec du téléchargement" + diff --git a/po/tizen2.3/fr_CA.po b/po/tizen2.3/fr_CA.po new file mode 100644 index 0000000..608ae3d --- /dev/null +++ b/po/tizen2.3/fr_CA.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Téléchargement terminé" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Échec du téléchargement" + diff --git a/po/tizen2.3/ga.po b/po/tizen2.3/ga.po new file mode 100644 index 0000000..f8651ef --- /dev/null +++ b/po/tizen2.3/ga.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Íoslódáilte" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Theip ar íoslódáil" + diff --git a/po/tizen2.3/gl.po b/po/tizen2.3/gl.po new file mode 100644 index 0000000..8527d75 --- /dev/null +++ b/po/tizen2.3/gl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Erro na descarga" + diff --git a/po/tizen2.3/hi.po b/po/tizen2.3/hi.po new file mode 100644 index 0000000..36382aa --- /dev/null +++ b/po/tizen2.3/hi.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "डाउनलोड पूर्ण" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "डाउनलोड विफल" + diff --git a/po/tizen2.3/hr.po b/po/tizen2.3/hr.po new file mode 100644 index 0000000..0f225a4 --- /dev/null +++ b/po/tizen2.3/hr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Skidanje dovršeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Skidanje neuspješno" + diff --git a/po/tizen2.3/hu.po b/po/tizen2.3/hu.po new file mode 100644 index 0000000..847e5af --- /dev/null +++ b/po/tizen2.3/hu.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "A letöltés befejeződött" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Sikertelen letöltés" + diff --git a/po/tizen2.3/hy.po b/po/tizen2.3/hy.po new file mode 100644 index 0000000..8636b2b --- /dev/null +++ b/po/tizen2.3/hy.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Ներբեռնումն ավարտվեց" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Ներբեռնումը ձախողվեց" + diff --git a/po/tizen2.3/is.po b/po/tizen2.3/is.po new file mode 100644 index 0000000..3bb7f29 --- /dev/null +++ b/po/tizen2.3/is.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Niðurhali lokið" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Niðurhal mistókst" + diff --git a/po/tizen2.3/it_IT.po b/po/tizen2.3/it_IT.po new file mode 100644 index 0000000..51a407e --- /dev/null +++ b/po/tizen2.3/it_IT.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download completato" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download non riuscito" + diff --git a/po/tizen2.3/ja_JP.po b/po/tizen2.3/ja_JP.po new file mode 100644 index 0000000..b466c9b --- /dev/null +++ b/po/tizen2.3/ja_JP.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "ダウンロード完了" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "ダウンロード失敗" + diff --git a/po/tizen2.3/ka.po b/po/tizen2.3/ka.po new file mode 100644 index 0000000..83aea79 --- /dev/null +++ b/po/tizen2.3/ka.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "ჩამოტვირთვა დასრულდა" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "ვერ ჩამოიტვირთა" + diff --git a/po/tizen2.3/kk.po b/po/tizen2.3/kk.po new file mode 100644 index 0000000..bd25ab4 --- /dev/null +++ b/po/tizen2.3/kk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Жүктеу аяқталды" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Жүктеу орындалмады" + diff --git a/po/tizen2.3/ko_KR.po b/po/tizen2.3/ko_KR.po new file mode 100644 index 0000000..80d1e37 --- /dev/null +++ b/po/tizen2.3/ko_KR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "다운로드 완료" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "다운로드 안 됨" + diff --git a/po/tizen2.3/lt.po b/po/tizen2.3/lt.po new file mode 100644 index 0000000..d08e1d5 --- /dev/null +++ b/po/tizen2.3/lt.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Atsisiuntimas baigtas" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Atsisiųsti nepavyko" + diff --git a/po/tizen2.3/lv.po b/po/tizen2.3/lv.po new file mode 100644 index 0000000..323c609 --- /dev/null +++ b/po/tizen2.3/lv.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Lejupielāde pabeigta" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Lejupielāde neizdevās" + diff --git a/po/tizen2.3/mk.po b/po/tizen2.3/mk.po new file mode 100644 index 0000000..0ef6f04 --- /dev/null +++ b/po/tizen2.3/mk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Преземањето заврши" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Преземањето не успеа" + diff --git a/po/tizen2.3/nb.po b/po/tizen2.3/nb.po new file mode 100644 index 0000000..49448f5 --- /dev/null +++ b/po/tizen2.3/nb.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Nedlasting fullført" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Nedlastingen mislyktes" + diff --git a/po/tizen2.3/nl.po b/po/tizen2.3/nl.po new file mode 100644 index 0000000..1195f04 --- /dev/null +++ b/po/tizen2.3/nl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Downloaden voltooid" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Downloaden mislukt" + diff --git a/po/tizen2.3/pl.po b/po/tizen2.3/pl.po new file mode 100644 index 0000000..9e52a17 --- /dev/null +++ b/po/tizen2.3/pl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Pobieranie zakończone" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Pobieranie nie powiodło się" + diff --git a/po/tizen2.3/pt_BR.po b/po/tizen2.3/pt_BR.po new file mode 100644 index 0000000..0fdce74 --- /dev/null +++ b/po/tizen2.3/pt_BR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download concluído" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Falha no download" + diff --git a/po/tizen2.3/pt_PT.po b/po/tizen2.3/pt_PT.po new file mode 100644 index 0000000..c934937 --- /dev/null +++ b/po/tizen2.3/pt_PT.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Transferência concluída" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "A transferência falhou" + diff --git a/po/tizen2.3/ro.po b/po/tizen2.3/ro.po new file mode 100644 index 0000000..820ab33 --- /dev/null +++ b/po/tizen2.3/ro.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descărcare finalizată" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Descărcarea nu a reuşit" + diff --git a/po/tizen2.3/ru_RU.po b/po/tizen2.3/ru_RU.po new file mode 100644 index 0000000..e3cb63a --- /dev/null +++ b/po/tizen2.3/ru_RU.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Загрузка завершена" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Сбой загрузки" + diff --git a/po/tizen2.3/sk.po b/po/tizen2.3/sk.po new file mode 100644 index 0000000..6d92c75 --- /dev/null +++ b/po/tizen2.3/sk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Sťahovanie je dokončené" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Sťahovanie zlyhalo" + diff --git a/po/tizen2.3/sl.po b/po/tizen2.3/sl.po new file mode 100644 index 0000000..1c256ab --- /dev/null +++ b/po/tizen2.3/sl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Prenos je končan" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Prenos ni uspel" + diff --git a/po/tizen2.3/sr.po b/po/tizen2.3/sr.po new file mode 100644 index 0000000..2e6331a --- /dev/null +++ b/po/tizen2.3/sr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Preuzimanje završeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Neuspešno preuzimanje" + diff --git a/po/tizen2.3/sv.po b/po/tizen2.3/sv.po new file mode 100644 index 0000000..e792e63 --- /dev/null +++ b/po/tizen2.3/sv.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Hämtningen är klar" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Hämtningen misslyckades" + diff --git a/po/tizen2.3/tr_TR.po b/po/tizen2.3/tr_TR.po new file mode 100644 index 0000000..73277df --- /dev/null +++ b/po/tizen2.3/tr_TR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "İndirme tamamlandı" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "İndirme başarısız" + diff --git a/po/tizen2.3/uk.po b/po/tizen2.3/uk.po new file mode 100644 index 0000000..ad32cd3 --- /dev/null +++ b/po/tizen2.3/uk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Завантаження завершено" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Збій завантаження" + diff --git a/po/tizen2.3/uz.po b/po/tizen2.3/uz.po new file mode 100644 index 0000000..ff9b724 --- /dev/null +++ b/po/tizen2.3/uz.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Yuklab olish yakunlandi" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Yuklab olib bo‘lmadi" + diff --git a/po/tizen2.3/zh_CN.po b/po/tizen2.3/zh_CN.po new file mode 100644 index 0000000..f5e03c8 --- /dev/null +++ b/po/tizen2.3/zh_CN.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "下载完成" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "下载失败" + diff --git a/po/tizen2.3/zh_HK.po b/po/tizen2.3/zh_HK.po new file mode 100644 index 0000000..ef7afd3 --- /dev/null +++ b/po/tizen2.3/zh_HK.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "下載完成" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "下載失敗" + diff --git a/po/tizen2.3/zh_TW.po b/po/tizen2.3/zh_TW.po new file mode 100644 index 0000000..ef7afd3 --- /dev/null +++ b/po/tizen2.3/zh_TW.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "下載完成" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "下載失敗" + diff --git a/provider-interface/CMakeLists.txt b/provider-interface/CMakeLists.txt new file mode 100755 index 0000000..70792e7 --- /dev/null +++ b/provider-interface/CMakeLists.txt @@ -0,0 +1,49 @@ + +## PROJECT NAME +PROJECT(download-provider-interface C) +SET(PACKAGE_DESCRIPTION "Interface supported by download-provider") + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Debug") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +SET(PC_REQUIRED "glib-2.0 gobject-2.0 dlog capi-base-common capi-appfw-app-manager capi-appfw-application bundle") + +INCLUDE(FindPkgConfig) + +pkg_check_modules(provider_interface_pkgs REQUIRED ${PC_REQUIRED}) + +FOREACH(flag ${provider_interface_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +## INCLUDES +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/provider/include) + +SET(PROVIDER_INTERFACE_LINK_LIBRARIES + ${GLIB-2_LIBRARIES} + ${GOBJECT-2_LIBRARIES} + pthread + ) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -Wall") + +ADD_DEFINITIONS(-DDOWNLOAD_PROVIDER_LOG_TAG=\"DOWNLOAD_PROVIDER_INTERFACE\") + +ADD_LIBRARY(${PROJECT_NAME} SHARED + ${CMAKE_SOURCE_DIR}/provider/download-provider-utils.c + ${CMAKE_SOURCE_DIR}/provider/download-provider-ipc.c + ${CMAKE_SOURCE_DIR}/provider/download-provider-pthread.c + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.c ) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${provider_interface_pkgs_LDFLAGS} ${PROVIDER_INTERFACE_LINK_LIBRARIES}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${PKG_VERSION}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION 0) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/${PROJECT_NAME}.h DESTINATION ${INCLUDE_INSTALL_DIR}/${PKG_NAME}) +CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) diff --git a/provider-interface/download-provider-interface.c b/provider-interface/download-provider-interface.c new file mode 100755 index 0000000..b6c81a1 --- /dev/null +++ b/provider-interface/download-provider-interface.c @@ -0,0 +1,1563 @@ +/* + * Copyright (c) 2013 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 <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> + +#include <pthread.h> +#include <signal.h> + +#include <dlog.h> +#include <download-provider-interface.h> +#include <download-provider.h> +#include <download-provider-log.h> +#include <download-provider-pthread.h> +#include <download-provider-ipc.h> +#include <download-provider-utils.h> + +#include <bundle.h> // for notification bundle +#ifdef T30 +#include <bundle_internal.h> +#endif +#include <app_control.h> +#include <app_control_internal.h> + +#ifdef SUPPORT_CHECK_IPC +#include <sys/ioctl.h> +#endif + +#define DP_CHECK_CONNECTION do {\ + int dp_errorcode = __check_connections();\ + if (dp_errorcode != DP_ERROR_NONE) {\ + CLIENT_MUTEX_UNLOCK(&g_function_mutex);\ + return __dp_interface_convert_errorcode(dp_errorcode);\ + }\ +} while(0) + +#define DP_PRE_CHECK_ID do {\ + if (id <= 0) {\ + TRACE_ERROR("[CHECK ID] (%d)", id);\ + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER;\ + }\ +} while(0) + +// define type +typedef struct { + int channel; // query & response + int notify; // event from provider +} dp_interface_ipc; + +typedef struct { + int id; + dp_interface_state_changed_cb state; + void *state_data; + dp_interface_progress_cb progress; + void *progress_data; +} dp_interface_slot; + +// declare the variables +dp_interface_ipc *g_dp_client = NULL; +dp_interface_slot g_interface_slots[MAX_DOWNLOAD_HANDLE]; +static pthread_mutex_t g_function_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t g_clear_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_t g_dp_event_thread_id = 0; + +//////////// defines functions ///////////////// + + +static int __dp_interface_convert_state(int state) +{ + switch (state) { + case DP_STATE_READY: + TRACE_DEBUG("READY"); + return DOWNLOAD_ADPATOR_STATE_READY; + case DP_STATE_CONNECTING: + TRACE_DEBUG("CONNECTING/QUEUED"); + return DOWNLOAD_ADPATOR_STATE_QUEUED; + case DP_STATE_QUEUED: + TRACE_DEBUG("QUEUED"); + return DOWNLOAD_ADPATOR_STATE_QUEUED; + case DP_STATE_DOWNLOADING: + TRACE_DEBUG("DOWNLOADING"); + return DOWNLOAD_ADPATOR_STATE_DOWNLOADING; + case DP_STATE_PAUSED: + TRACE_DEBUG("PAUSED"); + return DOWNLOAD_ADPATOR_STATE_PAUSED; + case DP_STATE_COMPLETED: + TRACE_DEBUG("COMPLETED"); + return DOWNLOAD_ADPATOR_STATE_COMPLETED; + case DP_STATE_CANCELED: + TRACE_DEBUG("CANCELED"); + return DOWNLOAD_ADPATOR_STATE_CANCELED; + case DP_STATE_FAILED: + TRACE_DEBUG("FAILED"); + return DOWNLOAD_ADPATOR_STATE_FAILED; + default: + break; + } + return DOWNLOAD_ADPATOR_STATE_NONE; +} + +static int __dp_interface_convert_errorcode(int errorcode) +{ + switch (errorcode) { + case DP_ERROR_NONE: + return DOWNLOAD_ADAPTOR_ERROR_NONE; + case DP_ERROR_INVALID_PARAMETER: + TRACE_DEBUG("ERROR_INVALID_PARAMETER"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + case DP_ERROR_OUT_OF_MEMORY: + TRACE_DEBUG("ERROR_OUT_OF_MEMORY"); + return DOWNLOAD_ADAPTOR_ERROR_OUT_OF_MEMORY; + case DP_ERROR_IO_EAGAIN: + TRACE_DEBUG("ERROR_IO_ERROR(EAGAIN)"); + return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; + case DP_ERROR_IO_EINTR: + TRACE_DEBUG("ERROR_IO_ERROR(EINTR)"); + return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; + case DP_ERROR_IO_ERROR: + TRACE_DEBUG("ERROR_IO_ERROR"); + return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; + case DP_ERROR_NETWORK_UNREACHABLE: + TRACE_DEBUG("ERROR_NETWORK_UNREACHABLE"); + return DOWNLOAD_ADAPTOR_ERROR_NETWORK_UNREACHABLE; + case DP_ERROR_NO_SPACE: + TRACE_DEBUG("ERROR_NO_SPACE"); + return DOWNLOAD_ADAPTOR_ERROR_NO_SPACE; + case DP_ERROR_FIELD_NOT_FOUND: + TRACE_DEBUG("ERROR_FIELD_NOT_FOUND"); + return DOWNLOAD_ADAPTOR_ERROR_FIELD_NOT_FOUND; + case DP_ERROR_INVALID_STATE: + TRACE_DEBUG("ERROR_INVALID_STATE"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_STATE; + case DP_ERROR_CONNECTION_FAILED: + case DP_ERROR_NETWORK_ERROR: + TRACE_DEBUG("ERROR_CONNECTION_TIMED_OUT/CONNECTION_FAILED"); + return DOWNLOAD_ADAPTOR_ERROR_CONNECTION_TIMED_OUT; + case DP_ERROR_INVALID_URL: + TRACE_DEBUG("ERROR_INVALID_URL"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_URL; + case DP_ERROR_INVALID_DESTINATION: + TRACE_DEBUG("ERROR_INVALID_DESTINATION"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_DESTINATION; + case DP_ERROR_PERMISSION_DENIED: + TRACE_DEBUG("ERROR_PERMISSION_DENIED"); + return DOWNLOAD_ADAPTOR_ERROR_PERMISSION_DENIED; + case DP_ERROR_QUEUE_FULL: + TRACE_DEBUG("ERROR_QUEUE_FULL"); + return DOWNLOAD_ADAPTOR_ERROR_QUEUE_FULL; + case DP_ERROR_ALREADY_COMPLETED: + TRACE_DEBUG("ERROR_ALREADY_COMPLETED"); + return DOWNLOAD_ADAPTOR_ERROR_ALREADY_COMPLETED; + case DP_ERROR_FILE_ALREADY_EXISTS: + TRACE_DEBUG("ERROR_FILE_ALREADY_EXISTS"); + return DOWNLOAD_ADAPTOR_ERROR_FILE_ALREADY_EXISTS; + case DP_ERROR_TOO_MANY_DOWNLOADS: + TRACE_DEBUG("ERROR_TOO_MANY_DOWNLOADS"); + return DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; + case DP_ERROR_NO_DATA: + TRACE_DEBUG("ERROR_NO_DATA"); + return DOWNLOAD_ADAPTOR_ERROR_NO_DATA; + case DP_ERROR_UNHANDLED_HTTP_CODE: + TRACE_DEBUG("ERROR_UNHANDLED_HTTP_CODE"); + return DOWNLOAD_ADAPTOR_ERROR_UNHANDLED_HTTP_CODE; + case DP_ERROR_CANNOT_RESUME: + TRACE_DEBUG("ERROR_CANNOT_RESUME"); + return DOWNLOAD_ADAPTOR_ERROR_CANNOT_RESUME; + case DP_ERROR_ID_NOT_FOUND: + TRACE_DEBUG("ERROR_ID_NOT_FOUND"); + return DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND; + case DP_ERROR_UNKNOWN: + TRACE_DEBUG("ERROR_INVALID_STATE/UNKNOWN"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_STATE; + case DP_ERROR_INVALID_NETWORK_TYPE: + TRACE_DEBUG("ERROR_INVALID_NETWORK_TYPE"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_NETWORK_TYPE; + default: + break; + } + return DOWNLOAD_ADAPTOR_ERROR_NONE; +} + +static int __get_my_slot_index(int id) +{ + int i = 0; + // search same info in array. + for (; i < MAX_DOWNLOAD_HANDLE; i++) + if (g_interface_slots[i].id == id) + return i; + return -1; +} + +static int __get_empty_slot_index() +{ + int i = 0; + for (; i < MAX_DOWNLOAD_HANDLE; i++) + if (g_interface_slots[i].id <= 0) + return i; + return -1; +} + +static int __create_socket() +{ + int sockfd = -1; + struct sockaddr_un clientaddr; + + if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + TRACE_STRERROR("[CRITICAL] socket system error"); + return -1; + } + + bzero(&clientaddr, sizeof clientaddr); + clientaddr.sun_family = AF_UNIX; + memset(clientaddr.sun_path, 0x00, sizeof(clientaddr.sun_path)); + strncpy(clientaddr.sun_path, IPC_SOCKET, strlen(IPC_SOCKET)); + clientaddr.sun_path[strlen(IPC_SOCKET)] = '\0'; + if (connect(sockfd, + (struct sockaddr*)&clientaddr, sizeof(clientaddr)) < 0) { + close(sockfd); + if (errno == EACCES || errno == EPERM) { + TRACE_STRERROR("check permission"); + return -DP_ERROR_PERMISSION_DENIED; + } + return -1; + } + TRACE_DEBUG("sockfd [%d]", sockfd); + return sockfd; +} + +static void __clear_interface() +{ + TRACE_DEBUG(""); + CLIENT_MUTEX_LOCK(&g_clear_mutex); + if (g_dp_client != NULL) { + if (g_dp_client->channel >= 0) + close(g_dp_client->channel); + g_dp_client->channel= -1; + if (g_dp_client->notify >= 0) + close(g_dp_client->notify); + g_dp_client->notify = -1; + free(g_dp_client); + g_dp_client = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_clear_mutex); +} + +static int __bp_disconnect(const char *funcname) +{ + TRACE_DEBUG("%s", funcname); + if (g_dp_event_thread_id > 0 && + pthread_kill(g_dp_event_thread_id, 0) != ESRCH) { + if (pthread_cancel(g_dp_event_thread_id) != 0) { + TRACE_STRERROR("pthread:%d", (int)g_dp_event_thread_id); + } + g_dp_event_thread_id = 0; + } + __clear_interface(); + return DP_ERROR_NONE; +} + +// listen ASYNC state event, no timeout +static void *__dp_event_manager(void *arg) +{ + if (g_dp_client == NULL) { + TRACE_STRERROR("[CRITICAL] INTERFACE null"); + return 0; + } + + size_t path_size = sizeof(NOTIFY_DIR) + 11; + char notify_fifo[path_size]; + snprintf((char *)¬ify_fifo, path_size,"%s/%d", NOTIFY_DIR, getpid()); + TRACE_DEBUG("IPC ESTABILISH %s", notify_fifo); + g_dp_client->notify = open(notify_fifo, O_RDONLY, 0600); + if (g_dp_client->notify < 0) { + TRACE_STRERROR("[CRITICAL] failed to ESTABILISH IPC %s", notify_fifo); + g_dp_event_thread_id = 0; + CLIENT_MUTEX_LOCK(&g_function_mutex); + __clear_interface(); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return 0; + } + + // deferred wait to cancal until next function called. + // ex) function : select, read in this thread + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + + while(g_dp_client != NULL && g_dp_client->notify >= 0) { + + if (g_dp_event_thread_id <= 0 || + pthread_self() != g_dp_event_thread_id) { + TRACE_ERROR("competitive threads self:%0x global:%0x", + pthread_self(), g_dp_event_thread_id); + // another thread may work. just terminate + break; + } + + // blocking fifo. + dp_ipc_event_fmt eventinfo; + memset(&eventinfo, 0x00, sizeof(dp_ipc_event_fmt)); + if (dp_ipc_read(g_dp_client->notify, &eventinfo, + sizeof(dp_ipc_event_fmt), __FUNCTION__) <= 0 || + (eventinfo.id <= 0 && + eventinfo.errorcode == DP_ERROR_CLIENT_DOWN)) { + TRACE_INFO("expelled by provider"); + g_dp_event_thread_id = 0; + CLIENT_MUTEX_LOCK(&g_function_mutex); + __clear_interface(); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return 0; + } + + int index = -1; + if ((index = __get_my_slot_index(eventinfo.id)) < 0) { + TRACE_ERROR("[CRITICAL] not found slot id:%d", eventinfo.id); + continue; + } + + // begin protect callback sections & thread safe + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + if (eventinfo.state == DP_STATE_DOWNLOADING && + eventinfo.received_size > 0) { + if (eventinfo.id == g_interface_slots[index].id && + g_interface_slots[index].progress != NULL) { + // progress event + g_interface_slots[index].progress(eventinfo.id, + eventinfo.received_size, + g_interface_slots[index].progress_data); + } + } else { + if (eventinfo.id == g_interface_slots[index].id && + g_interface_slots[index].state != NULL) { + // state event + g_interface_slots[index].state(eventinfo.id, + __dp_interface_convert_state(eventinfo.state), + g_interface_slots[index].state_data); + } + } + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + } // while + + g_dp_event_thread_id = 0; // set 0 to not call pthread_cancel + TRACE_DEBUG("thread end by itself"); + return 0; +} + + + + + + +////////////////// new download-provider /////////////////////////////// +////////////////// created on 7 November, 2013 ///////////////////////// + +#define DP_CHECK_IPC_SOCK (g_dp_client == NULL ? -1 : g_dp_client->channel) + +static void __dp_ipc_clear_garbage(int sock, const size_t length) +{ + if (length > 0) { + char garbage[length]; + if (read(sock, &garbage, length) == 0) { + TRACE_ERROR("sock:%d closed peer", sock); + } + } +} + +static int __dp_ipc_response(int sock, int download_id, short section, + unsigned property, size_t *size) +{ + dp_ipc_fmt *ipc_info = dp_ipc_get_fmt(sock); + if (ipc_info == NULL || ipc_info->section != section || + ipc_info->property != property || + (download_id >= 0 && ipc_info->id != download_id)) { + TRACE_STRERROR("socket read ipcinfo"); + free(ipc_info); + return DP_ERROR_IO_ERROR; + } + int errorcode = ipc_info->errorcode; + if (size != NULL) + *size = ipc_info->size; + free(ipc_info); + return errorcode; +} + +static int __connect_to_provider() +{ + int errorcode = DP_ERROR_NONE; + + CLIENT_MUTEX_LOCK(&g_clear_mutex); + + if (g_dp_client == NULL) { + g_dp_client = + (dp_interface_ipc *)calloc(1, sizeof(dp_interface_ipc)); + + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { + TRACE_ERROR("failed to ignore SIGPIPE signal"); + } + } + + if (g_dp_client != NULL) { + + int connect_retry = 3; + g_dp_client->channel = -1; + while(g_dp_client->channel < 0 && connect_retry-- > 0) { + int ret = __create_socket(); + if (ret == -1) { + TRACE_STRERROR("failed to connect to provider(remains:%d)", connect_retry); + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 20000000; + nanosleep(&ts, NULL); + } else if (ret >= 0) { + struct timeval tv_timeo = { 1, 500000 }; // 1.5 second + g_dp_client->channel = ret; + if (setsockopt(g_dp_client->channel, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, sizeof(tv_timeo)) < 0) { + TRACE_STRERROR("[CRITICAL] setsockopt SO_RCVTIMEO"); + } + } else { + errorcode = -ret; + TRACE_STRERROR("check error:%d", errorcode); + goto EXIT_CONNECT; + } + } + if (g_dp_client->channel < 0) { + TRACE_STRERROR("[CRITICAL] connect system error"); + errorcode = DP_ERROR_IO_ERROR; + goto EXIT_CONNECT; + } + + if (dp_ipc_query(g_dp_client->channel, -1, DP_SEC_INIT, + DP_PROP_NONE, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + goto EXIT_CONNECT; + } +#ifndef SO_PEERCRED + dp_credential cred; + cred.pid = getpid(); + cred.uid = getuid(); + cred.gid = getgid(); + // send PID. Not support SO_PEERCRED + if (dp_ipc_write(g_dp_client->channel, + &cred, sizeof(dp_credential)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + goto EXIT_CONNECT; + } +#endif + + errorcode = __dp_ipc_response(g_dp_client->channel, + -1, DP_SEC_INIT, DP_PROP_NONE, NULL); + // Commented by justine.bang + // Above ipc_query call try to wake up download-provider. + // But, we can sometimes meet EINTR, EAGAIN or EINPROGRESS signal if systemd is slow. + // So, If meet EINTR ,EAGAIN or EINPROGRESS in this line, it's better to wait response from download-provider one more time. + if (errorcode == DP_ERROR_IO_ERROR && (errno == EINTR || errno == EAGAIN || errno == EINPROGRESS)) { + errorcode = __dp_ipc_response(g_dp_client->channel, + -1, DP_SEC_INIT, DP_PROP_NONE, NULL); + } + + if (errorcode == DP_ERROR_NONE && g_dp_event_thread_id <= 0) { + if (pthread_create(&g_dp_event_thread_id, NULL, + __dp_event_manager, g_dp_client) != 0) { + TRACE_STRERROR("failed to create event-manager"); + errorcode = DP_ERROR_IO_ERROR; + } else { + pthread_detach(g_dp_event_thread_id); + } + } + + } + +EXIT_CONNECT: + CLIENT_MUTEX_UNLOCK(&g_clear_mutex); + if (errorcode != DP_ERROR_NONE) + __bp_disconnect(__FUNCTION__); + + return errorcode; +} + +static dp_error_type __check_connections() +{ + int ret = 0; + + if (g_dp_client == NULL) + if ((ret = __connect_to_provider()) != DP_ERROR_NONE) + return ret; + + if (g_dp_client == NULL || g_dp_client->channel < 0) { + TRACE_ERROR("[CHECK IPC]"); + return DP_ERROR_IO_ERROR; + } + return DP_ERROR_NONE; +} + +static int __dp_ipc_set_binary(const int id, const unsigned property, + const bundle_raw *string, const size_t length, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + if (string == NULL || length <= 0) { + TRACE_ERROR("%s check binary (%d)", funcname, length); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_SET, property, DP_ERROR_NONE, length * sizeof(unsigned char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + if (dp_ipc_write(sock, (void*)string, length * sizeof(unsigned char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, DP_SEC_SET, property, NULL); + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +static int __dp_ipc_set_string(const int id, const short section, const unsigned property, + const char *string, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + size_t length = 0; + if (string == NULL || (length = strlen(string)) <= 0 || + length > DP_MAX_STR_LEN) { + TRACE_ERROR("%s check string (%d:%s)", funcname, length, string); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + if (dp_ipc_write(sock, (void*)string, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +static int __dp_ipc_get_string(const int id, const unsigned property, + char **string, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + + if (string == NULL) { + TRACE_ERROR("%s check buffer", funcname); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_GET, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + size_t string_length = 0; + *string = NULL; + errorcode = __dp_ipc_response(sock, id, DP_SEC_GET, property, &string_length); + if (errorcode == DP_ERROR_NONE) { + if (string_length > 0) { + char *recv_str = (char *)calloc((string_length + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("check memory length:%d", string_length); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, string_length); + } else { + if (dp_ipc_read(sock, recv_str, string_length, funcname) <= 0) { + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[string_length] = '\0'; + *string = recv_str; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +// send command and int & return errorcode +static int __dp_ipc_set_int(const int id, const unsigned section, const unsigned property, + const int value, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + if (dp_ipc_write(sock, (void *)&value, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +// send command & return errorcode and int +static int __dp_ipc_get_int(const int id, const unsigned property, + int *value, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + + if (value == NULL) { + TRACE_ERROR("%s check buffer", funcname); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_GET, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + size_t extra_size = 0; + errorcode = __dp_ipc_response(sock, id, DP_SEC_GET, property, &extra_size); + if (errorcode == DP_ERROR_NONE) { + if (extra_size == sizeof(int)) { + if (dp_ipc_read(sock, value, extra_size, funcname) < 0) + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +// send command & return errorcode. +int __dp_ipc_echo(const int id, const short section, + const unsigned property, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +/////////////////////// APIs ///////////////////////////////// + +int dp_interface_create(int *id) +{ + int errorcode = DP_ERROR_NONE; + int index = -1; + + if (id == NULL) { + TRACE_ERROR("[CHECK id variable]"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + CLIENT_MUTEX_LOCK(&g_function_mutex); + + if ((index = __get_empty_slot_index()) < 0) { + TRACE_ERROR + ("[ERROR] TOO_MANY_DOWNLOADS[%d]", MAX_DOWNLOAD_HANDLE); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; + } + + DP_CHECK_CONNECTION; + + dp_ipc_fmt *ipc_info = NULL; + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, -1, DP_SEC_CONTROL, DP_PROP_CREATE, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + } else { + ipc_info = dp_ipc_get_fmt(sock); + if (ipc_info == NULL) { + TRACE_ERROR("[ERROR] IPC INFO is NULL"); + errorcode = DP_ERROR_IO_ERROR; + } else if (ipc_info->section != DP_SEC_CONTROL || + ipc_info->property != DP_PROP_CREATE || + ipc_info->size != 0) { + TRACE_ERROR("sock:%d id:%d section:%d property:%d size:%d", + sock, ipc_info->id, ipc_info->section, ipc_info->property, + ipc_info->size); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_DEBUG("download_id:%d", ipc_info->id); + if (errorcode == DP_ERROR_NONE && ipc_info->id > 0) { + *id = ipc_info->id; + g_interface_slots[index].id = ipc_info->id; + g_interface_slots[index].state = NULL; + g_interface_slots[index].state_data = NULL; + g_interface_slots[index].progress = NULL; + g_interface_slots[index].progress_data = NULL; + } + } + } + free(ipc_info); + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_destroy(const int id) +{ + int index = -1; + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + if ((index = __get_my_slot_index(id)) >= 0) { + g_interface_slots[index].id = 0; + g_interface_slots[index].state = NULL; + g_interface_slots[index].state_data = NULL; + g_interface_slots[index].progress = NULL; + g_interface_slots[index].progress_data = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_DESTROY, __FUNCTION__); +} + +int dp_interface_start(const int id) +{ + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_START, __FUNCTION__); +} + +int dp_interface_pause(const int id) +{ + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_PAUSE, __FUNCTION__); +} + +int dp_interface_cancel(const int id) +{ + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_CANCEL, __FUNCTION__); +} + +int dp_interface_set_url(const int id, const char *url) +{ + if (url == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_URL, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_URL, url, __FUNCTION__); +} + +int dp_interface_get_url(const int id, char **url) +{ + return __dp_ipc_get_string(id, DP_PROP_URL, url, __FUNCTION__); +} + +int dp_interface_set_destination(const int id, const char *path) +{ + if (path == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_DESTINATION, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_DESTINATION, path, __FUNCTION__); +} + +int dp_interface_get_destination(const int id, char **path) +{ + return __dp_ipc_get_string(id, DP_PROP_DESTINATION, path, __FUNCTION__); +} + +int dp_interface_set_file_name(const int id, const char *file_name) +{ + if (file_name == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_FILENAME, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_FILENAME, file_name, __FUNCTION__); +} + +int dp_interface_get_file_name(const int id, char **file_name) +{ + return __dp_ipc_get_string(id, DP_PROP_FILENAME, file_name, __FUNCTION__); +} + +int dp_interface_get_downloaded_file_path(const int id, char **path) +{ + return __dp_ipc_get_string(id, DP_PROP_SAVED_PATH, path, __FUNCTION__); +} + +int dp_interface_get_temp_path(const int id, char **temp_path) +{ + return __dp_ipc_get_string(id, DP_PROP_TEMP_SAVED_PATH, temp_path, __FUNCTION__); +} + +int dp_interface_get_content_name(const int id, char **content_name) +{ + return __dp_ipc_get_string(id, DP_PROP_CONTENT_NAME, content_name, __FUNCTION__); +} + +int dp_interface_get_etag(const int id, char **etag) +{ + return __dp_ipc_get_string(id, DP_PROP_ETAG, etag, __FUNCTION__); +} + +int dp_interface_set_temp_file_path(const int id, const char *path) +{ + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_TEMP_SAVED_PATH, path, __FUNCTION__); +} + +int dp_interface_set_network_type(const int id, int net_type) +{ + return __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NETWORK_TYPE, + net_type, __FUNCTION__); +} + +int dp_interface_get_network_type(const int id, int *net_type) +{ + if (net_type == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_NETWORK_TYPE, net_type, __FUNCTION__); +} + +int dp_interface_get_network_bonding(const int id, int *enable) +{ + if (enable == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_NETWORK_BONDING, enable, __FUNCTION__); +} + +int dp_interface_set_network_bonding(const int id, int enable) +{ + return __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NETWORK_BONDING, + enable, __FUNCTION__); +} + +int dp_interface_set_state_changed_cb(const int id, + dp_interface_state_changed_cb callback, void *user_data) +{ + int errorcode = __dp_ipc_echo(id, DP_SEC_SET, DP_PROP_STATE_CALLBACK, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index < 0) { + index = __get_empty_slot_index(); + if (index >= 0) { + g_interface_slots[index].id = id; + } else { + TRACE_ERROR("too many download limit:%d", + MAX_DOWNLOAD_HANDLE); + errorcode = DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; + } + } + if (index >= 0) { + g_interface_slots[index].state = callback; + g_interface_slots[index].state_data = user_data; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + } + return errorcode; +} + +int dp_interface_unset_state_changed_cb(const int id) +{ + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index >= 0) { + g_interface_slots[index].state = NULL; + g_interface_slots[index].state_data = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + if (index < 0) + return DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND; + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_STATE_CALLBACK, __FUNCTION__); +} + +int dp_interface_set_progress_cb(const int id, + dp_interface_progress_cb callback, void *user_data) +{ + int errorcode = __dp_ipc_echo(id, DP_SEC_SET, DP_PROP_PROGRESS_CALLBACK, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index < 0) { + index = __get_empty_slot_index(); + if (index >= 0) { + g_interface_slots[index].id = id; + } else { + TRACE_ERROR("too many download limit:%d", + MAX_DOWNLOAD_HANDLE); + errorcode = DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; + } + } + if (index >= 0) { + g_interface_slots[index].progress = callback; + g_interface_slots[index].progress_data = user_data; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + } + return errorcode; +} + +int dp_interface_unset_progress_cb(const int id) +{ + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index >= 0) { + g_interface_slots[index].progress = NULL; + g_interface_slots[index].progress_data = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + if (index < 0) + return DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND; + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_PROGRESS_CALLBACK, __FUNCTION__); +} + +int dp_interface_get_state(const int id, int *state) +{ + if (state == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int dp_state = DP_STATE_NONE; + int errorcode = __dp_ipc_get_int(id, DP_PROP_STATE, &dp_state, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) + *state = __dp_interface_convert_state(dp_state); + return errorcode; +} + +int dp_interface_get_content_size(const int id, + unsigned long long *content_size) +{ + int errorcode = DP_ERROR_NONE; + + if (content_size == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_GET, DP_PROP_TOTAL_FILE_SIZE, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", __FUNCTION__, sock); + } else { + size_t extra_size = 0; + errorcode = __dp_ipc_response(sock, id, DP_SEC_GET, DP_PROP_TOTAL_FILE_SIZE, &extra_size); + if (errorcode == DP_ERROR_NONE) { + if (extra_size == sizeof(unsigned long long)) { + if (dp_ipc_read(sock, content_size, extra_size, __FUNCTION__) < 0) + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_get_mime_type(const int id, char **mime_type) +{ + if (mime_type == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_string(id, DP_PROP_MIME_TYPE, mime_type, + __FUNCTION__); +} + +int dp_interface_set_auto_download(const int id, int enable) +{ + short section = DP_SEC_SET; + if (enable <= 0) + section = DP_SEC_UNSET; + return __dp_ipc_echo(id, section, DP_PROP_AUTO_DOWNLOAD, __FUNCTION__); +} + +int dp_interface_get_auto_download(const int id, int *enable) +{ + if (enable == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_AUTO_DOWNLOAD, enable, __FUNCTION__); +} + +int dp_interface_get_error(const int id, int *error) +{ + if (error == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int errorcode = DP_ERROR_NONE; + int ret = __dp_ipc_get_int(id, DP_PROP_ERROR, &errorcode, __FUNCTION__); + if (ret == DOWNLOAD_ADAPTOR_ERROR_NONE) + *error = __dp_interface_convert_errorcode(errorcode); + return ret; +} + +int dp_interface_get_http_status(const int id, int *http_status) +{ + if (http_status == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_HTTP_STATUS, http_status, + __FUNCTION__); +} + +int dp_interface_set_notification_title(const int id, const char *title) +{ + if (title == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_SUBJECT, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_NOTIFICATION_SUBJECT, title, __FUNCTION__); +} + +int dp_interface_get_notification_title(const int id, char **title) +{ + if (title == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_string(id, DP_PROP_NOTIFICATION_SUBJECT, title, __FUNCTION__); +} + +int dp_interface_set_notification_description(const int id, const char *description) +{ + if (description == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_DESCRIPTION, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_NOTIFICATION_DESCRIPTION, description, __FUNCTION__); +} + +int dp_interface_get_notification_description(const int id, char **description) +{ + if (description == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_string(id, DP_PROP_NOTIFICATION_DESCRIPTION, description, __FUNCTION__); +} + +int dp_interface_set_notification_type(const int id, int type) +{ + if (type == DP_NOTIFICATION_TYPE_NONE) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_TYPE, __FUNCTION__); + return __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NOTIFICATION_TYPE, type, __FUNCTION__); +} + +int dp_interface_get_notification_type(const int id, int *type) +{ + if (type == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_NOTIFICATION_TYPE, type, __FUNCTION__); +} + +int dp_interface_set_notification_bundle(const int id, const int type, void *bundle_param) +{ + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_BUNDLE_TYPE_ONGOING && + type != DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE && + type != DP_NOTIFICATION_BUNDLE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + if (bundle_param == NULL) { // unset + return __dp_ipc_set_int(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + } else { // set + int length = 0; + bundle_raw *raw_buffer = NULL; + int result = bundle_encode_raw(bundle_param, &raw_buffer, &length); + if (result == 0 && length > 0) { + errorcode = __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + errorcode = __dp_ipc_set_binary(id, DP_PROP_NOTIFICATION_RAW, raw_buffer, (size_t)length, __FUNCTION__); + } + } else { + TRACE_ERROR("failed to encode raws error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (raw_buffer != NULL) + bundle_free_encoded_rawdata(&raw_buffer); + } + return errorcode; +} + +int dp_interface_get_notification_bundle(const int id, const int type, void **bundle_param) +{ + if (bundle_param == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_BUNDLE_TYPE_ONGOING && + type != DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE && + type != DP_NOTIFICATION_BUNDLE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + + // send type, get errorcode with extra_size, get bundle binary + + errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + const unsigned section = DP_SEC_GET; + const unsigned property = DP_PROP_NOTIFICATION_RAW; + size_t extra_size = 0; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void *)&type, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, &extra_size); + } + } + if (errorcode == DP_ERROR_NONE && extra_size > 0) { + unsigned char *recv_raws = (unsigned char *)calloc(extra_size, sizeof(unsigned char)); + if (recv_raws == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", sock, extra_size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, extra_size); + } else { + if (dp_ipc_read(sock, recv_raws, extra_size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + errorcode = DP_ERROR_IO_ERROR; + free(recv_raws); + } else { + TRACE_DEBUG("sock:%d length:%d raws", sock, extra_size); + *bundle_param = bundle_decode_raw(recv_raws, extra_size); + free(recv_raws); + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_set_notification_service_handle(const int id, const int type, void *handle) +{ + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_SERVICE_TYPE_ONGOING && + type != DP_NOTIFICATION_SERVICE_TYPE_COMPLETE && + type != DP_NOTIFICATION_SERVICE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + if (handle == NULL) { // unset + return __dp_ipc_set_int(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + } else { // set + int length = 0; + bundle_raw *raw_buffer = NULL; + bundle *bundle_data = NULL; + int result = app_control_export_as_bundle((app_control_h) handle, &bundle_data); + if (result == APP_CONTROL_ERROR_NONE) { + result = bundle_encode_raw(bundle_data, &raw_buffer, &length); + if (result == 0 && length > 0) { + errorcode = __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + errorcode = __dp_ipc_set_binary(id, DP_PROP_NOTIFICATION_RAW, raw_buffer, (size_t)length, __FUNCTION__); + } + } else { + TRACE_ERROR("failed to encode raws error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + } else { + TRACE_ERROR("failed to encode service handle error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (raw_buffer != NULL) + bundle_free_encoded_rawdata(&raw_buffer); + if (bundle_data != NULL) + bundle_free(bundle_data); + } + return errorcode; +} + +int dp_interface_get_notification_service_handle(const int id, const int type, void **handle) +{ + bundle *bundle_data = NULL; + if (handle == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_SERVICE_TYPE_ONGOING && + type != DP_NOTIFICATION_SERVICE_TYPE_COMPLETE && + type != DP_NOTIFICATION_SERVICE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + + // send type, get errorcode with extra_size, get bundle binary + + errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + const unsigned section = DP_SEC_GET; + const unsigned property = DP_PROP_NOTIFICATION_RAW; + size_t extra_size = 0; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void *)&type, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, &extra_size); + } + } + if (errorcode == DP_ERROR_NONE && extra_size > 0) { + unsigned char *recv_raws = (unsigned char *)calloc(extra_size, sizeof(unsigned char)); + if (recv_raws == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", sock, extra_size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, extra_size); + } else { + if (dp_ipc_read(sock, recv_raws, extra_size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + errorcode = DP_ERROR_IO_ERROR; + free(recv_raws); + } else { + TRACE_DEBUG("sock:%d length:%d raws", sock, extra_size); + + bundle_data = bundle_decode_raw(recv_raws, extra_size); + if (bundle_data) { + int result = 0; + result = app_control_create((app_control_h *)handle); + if (result == APP_CONTROL_ERROR_NONE) { + result = app_control_import_from_bundle((app_control_h)*handle, bundle_data); + if (result != APP_CONTROL_ERROR_NONE) { + TRACE_ERROR("failed to import service handle error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + } else { + TRACE_ERROR("failed to create service handle error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + bundle_free(bundle_data); + } + free(recv_raws); + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_add_http_header_field(const int id, const char *field, + const char *value) +{ + // cmd + field string + value string + // wait response + int errorcode = DP_ERROR_NONE; + size_t field_length = 0; + size_t value_length = 0; + if (field == NULL || (field_length = strlen(field)) <= 0 || + field_length > DP_MAX_STR_LEN) { + TRACE_ERROR("check field (%d:%s)", field_length, field); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (value == NULL || (value_length = strlen(value)) <= 0 || + value_length > DP_MAX_STR_LEN) { + TRACE_ERROR("check value (%d:%s)", value_length, value); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + short section = DP_SEC_SET; + unsigned property = DP_PROP_HTTP_HEADER; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, field_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void*)field, field_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + if (errorcode == DP_ERROR_NONE) { + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, value_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void*)value, value_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + } + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_get_http_header_field(const int id, const char *field, + char **value) +{ + // cmd + field string + // wait response + value string + int errorcode = DP_ERROR_NONE; + size_t length = 0; + if (field == NULL || (length = strlen(field)) <= 0 || + length > DP_MAX_STR_LEN) { + TRACE_ERROR("check field (%d:%s)", length, field); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (value == NULL) { + TRACE_ERROR("check pointer for value"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + short section = DP_SEC_GET; + unsigned property = DP_PROP_HTTP_HEADER; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void*)field, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + size_t string_length = 0; + *value = NULL; + errorcode = __dp_ipc_response(sock, id, section, property, &string_length); + if (errorcode == DP_ERROR_NONE) { + if (string_length > 0) { + char *recv_str = (char *)calloc((string_length + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("check memory length:%d", string_length); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, string_length); + } else { + if (dp_ipc_read(sock, recv_str, string_length, __FUNCTION__) <= 0) { + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[string_length] = '\0'; + *value = recv_str; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_get_http_header_field_list(const int id, char ***fields, + int *length) +{ + // cmd + // wait response + // wait size + // wait strings + int errorcode = DP_ERROR_NONE; + if (fields == NULL) { + TRACE_ERROR("check pointer for fields"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (length == NULL) { + TRACE_ERROR("check pointer for length"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + short section = DP_SEC_GET; + unsigned property = DP_PROP_HTTP_HEADERS; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + + int array_size = 0; + size_t extra_size = 0; + errorcode = __dp_ipc_response(sock, id, section, property, &extra_size); + if (errorcode == DP_ERROR_NONE) { + if (extra_size == sizeof(int)) { + if (dp_ipc_read(sock, &array_size, extra_size, __FUNCTION__) < 0) { + errorcode = DP_ERROR_IO_ERROR; + } else { + if (array_size <= 0) { + errorcode = DP_ERROR_NO_DATA; + *length = 0; + } else { + int i = 0; + char **recv_strings = NULL; + recv_strings = (char **)calloc(array_size, sizeof(char *)); + if (recv_strings == NULL) { + TRACE_STRERROR("check memory size:%d", array_size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + *length = 0; + } else { + // get strings. + for (; i < array_size; i++) { + size_t string_length = 0; + errorcode = __dp_ipc_response(sock, id, section, property, &string_length); + recv_strings[i] = NULL; + if (errorcode == DP_ERROR_NONE && string_length > 0) { + char *recv_str = (char *)calloc((string_length + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("check memory length:%d", string_length * sizeof(char)); + errorcode = DP_ERROR_OUT_OF_MEMORY; + break; + } else { + if (dp_ipc_read(sock, recv_str, string_length, __FUNCTION__) <= 0) { + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[string_length] = '\0'; + recv_strings[i] = recv_str; + } + } + } + } + *fields = recv_strings; + } + if (errorcode != DP_ERROR_NONE) { // if error, free all allocated memories + int j = 0; + for (; j < i; j++) { + free(recv_strings[j]); + } + free(recv_strings); + *length = 0; + *fields = NULL; + if (errorcode != DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); // clear IPC, can not expect the size of futher packets + } + *length = i; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + + + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_remove_http_header_field(const int id, + const char *field) +{ + return __dp_ipc_set_string(id, DP_SEC_UNSET, DP_PROP_HTTP_HEADER, field, __FUNCTION__); +} diff --git a/provider-interface/download-provider-interface.pc.in b/provider-interface/download-provider-interface.pc.in new file mode 100644 index 0000000..35e1cc9 --- /dev/null +++ b/provider-interface/download-provider-interface.pc.in @@ -0,0 +1,8 @@ +# Package Information + +Name: @PROJECT_NAME@ +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_REQUIRED@ +Libs: -L/usr/lib -l@PROJECT_NAME@ +Cflags: -I/usr/include/@PKG_NAME@ diff --git a/provider-interface/include/download-provider-interface.h b/provider-interface/include/download-provider-interface.h new file mode 100755 index 0000000..e9d3d59 --- /dev/null +++ b/provider-interface/include/download-provider-interface.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2013 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 __DOWNLOAD_PROVIDER_INTERFACE_H__ +#define __DOWNLOAD_PROVIDER_INTERFACE_H__ + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#include <tizen.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +// sync with url-download +typedef enum +{ + DOWNLOAD_ADPATOR_STATE_NONE, + DOWNLOAD_ADPATOR_STATE_READY, + DOWNLOAD_ADPATOR_STATE_QUEUED, + DOWNLOAD_ADPATOR_STATE_DOWNLOADING, + DOWNLOAD_ADPATOR_STATE_PAUSED, + DOWNLOAD_ADPATOR_STATE_COMPLETED, + DOWNLOAD_ADPATOR_STATE_FAILED, + DOWNLOAD_ADPATOR_STATE_CANCELED, +} download_adaptor_state_e; + +typedef enum +{ + DOWNLOAD_ADAPTOR_NETWORK_DATA_NETWORK, + DOWNLOAD_ADAPTOR_NETWORK_WIFI, + DOWNLOAD_ADAPTOR_NETWORK_WIFI_DIRECT, + DOWNLOAD_ADAPTOR_NETWORK_ALL +} download_adaptor_network_type_e ; + +typedef enum +{ + DOWNLOAD_ADAPTOR_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ + DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + DOWNLOAD_ADAPTOR_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ + DOWNLOAD_ADAPTOR_ERROR_NETWORK_UNREACHABLE = TIZEN_ERROR_NETWORK_UNREACHABLE, /**< Network is unreachable */ + DOWNLOAD_ADAPTOR_ERROR_CONNECTION_TIMED_OUT = TIZEN_ERROR_CONNECTION_TIME_OUT, /**< Http session time-out */ + DOWNLOAD_ADAPTOR_ERROR_NO_SPACE = TIZEN_ERROR_FILE_NO_SPACE_ON_DEVICE, /**< No space left on device */ + DOWNLOAD_ADAPTOR_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */ + DOWNLOAD_ADAPTOR_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */ + DOWNLOAD_ADAPTOR_ERROR_INVALID_STATE = TIZEN_ERROR_DOWNLOAD | 0x21, /**< Invalid state */ + DOWNLOAD_ADAPTOR_ERROR_CONNECTION_FAILED = TIZEN_ERROR_DOWNLOAD | 0x22, /**< Connection failed */ + DOWNLOAD_ADAPTOR_ERROR_INVALID_URL = TIZEN_ERROR_DOWNLOAD | 0x24, /**< Invalid URL */ + DOWNLOAD_ADAPTOR_ERROR_INVALID_DESTINATION = TIZEN_ERROR_DOWNLOAD | 0x25, /**< Invalid destination */ + DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS = TIZEN_ERROR_DOWNLOAD | 0x26, /**< Full of available simultaneous downloads */ + DOWNLOAD_ADAPTOR_ERROR_QUEUE_FULL = TIZEN_ERROR_DOWNLOAD | 0x27, /**< Full of available downloading items from server*/ + DOWNLOAD_ADAPTOR_ERROR_ALREADY_COMPLETED = TIZEN_ERROR_DOWNLOAD | 0x28, /**< The download is already completed */ + DOWNLOAD_ADAPTOR_ERROR_FILE_ALREADY_EXISTS = TIZEN_ERROR_DOWNLOAD | 0x29, /**< It is failed to rename the downloaded file */ + DOWNLOAD_ADAPTOR_ERROR_CANNOT_RESUME = TIZEN_ERROR_DOWNLOAD | 0x2a, /**< It cannot resume */ + DOWNLOAD_ADAPTOR_ERROR_FIELD_NOT_FOUND = TIZEN_ERROR_DOWNLOAD | 0x2b, /**< Specified field not found */ + DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_REDIRECTS = TIZEN_ERROR_DOWNLOAD | 0x30, /**< In case of too may redirects from http response header*/ + DOWNLOAD_ADAPTOR_ERROR_UNHANDLED_HTTP_CODE = TIZEN_ERROR_DOWNLOAD | 0x31, /**< The download cannot handle the http status value */ + DOWNLOAD_ADAPTOR_ERROR_REQUEST_TIMEOUT = TIZEN_ERROR_DOWNLOAD | 0x32, /**< There are no action after client create a download id*/ + DOWNLOAD_ADAPTOR_ERROR_RESPONSE_TIMEOUT = TIZEN_ERROR_DOWNLOAD | 0x33, /**< It does not call start API in some time although the download is created*/ + DOWNLOAD_ADAPTOR_ERROR_SYSTEM_DOWN = TIZEN_ERROR_DOWNLOAD | 0x34, /**< There are no response from client after rebooting download daemon*/ + DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND = TIZEN_ERROR_DOWNLOAD | 0x35, /**< The download id is not existed in download service module*/ + DOWNLOAD_ADAPTOR_ERROR_INVALID_NETWORK_TYPE = TIZEN_ERROR_DOWNLOAD | 0x36, /**< error when setting network bonding and network all is not set */ + DOWNLOAD_ADAPTOR_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA, /**< No data because the set API is not called */ + DOWNLOAD_ADAPTOR_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR /**< Internal I/O error */ +} download_adaptor_error_e; + +// sync types with url-download.. +typedef void (*dp_interface_state_changed_cb) (int id, int state, void *user_data); +typedef void (*dp_interface_progress_cb) (int id, unsigned long long received, void *user_data); + +EXPORT_API int dp_interface_set_state_changed_cb + (const int id, dp_interface_state_changed_cb callback, void *user_data); +EXPORT_API int dp_interface_unset_state_changed_cb(int id); +EXPORT_API int dp_interface_set_progress_cb + (const int id, dp_interface_progress_cb callback, void *user_data); +EXPORT_API int dp_interface_unset_progress_cb(const int id); + +EXPORT_API int dp_interface_create(int *id); +EXPORT_API int dp_interface_destroy(const int id); + +EXPORT_API int dp_interface_start(const int id); +EXPORT_API int dp_interface_pause(const int id); +EXPORT_API int dp_interface_cancel(const int id); + +EXPORT_API int dp_interface_set_url(const int id, const char *url); +EXPORT_API int dp_interface_set_destination(const int id, const char *path); +EXPORT_API int dp_interface_set_file_name(const int id, const char *file_name); +EXPORT_API int dp_interface_set_network_type(const int id, int net_type); +EXPORT_API int dp_interface_set_network_bonding(const int id, int enable); +EXPORT_API int dp_interface_set_auto_download(const int id, int enable); +EXPORT_API int dp_interface_get_url(const int id, char **url); +EXPORT_API int dp_interface_get_network_type(const int id, int *net_type); +EXPORT_API int dp_interface_get_network_bonding(const int id, int *enable); +EXPORT_API int dp_interface_get_destination(const int id, char **path); +EXPORT_API int dp_interface_get_file_name(const int id, char **file_name); +EXPORT_API int dp_interface_get_downloaded_file_path(const int id, char **path); +EXPORT_API int dp_interface_get_mime_type(const int id, char **mime_type); +EXPORT_API int dp_interface_get_auto_download(const int id, int *enable); +EXPORT_API int dp_interface_get_state(const int id, int *state); +EXPORT_API int dp_interface_get_temp_path(const int id, char **temp_path); +EXPORT_API int dp_interface_get_content_name(const int id, char **content_name); +EXPORT_API int dp_interface_get_content_size(const int id, unsigned long long *content_size); +EXPORT_API int dp_interface_get_error(const int id, int *error); +EXPORT_API int dp_interface_get_http_status(const int id, int *http_status); +EXPORT_API int dp_interface_get_etag(const int id, char **etag); +EXPORT_API int dp_interface_set_temp_file_path(const int id, const char *path); + +EXPORT_API int dp_interface_add_http_header_field(const int id, const char *field, const char *value); +EXPORT_API int dp_interface_get_http_header_field(const int id, const char *field, char **value); +EXPORT_API int dp_interface_get_http_header_field_list(const int id, char ***fields, int *length); +EXPORT_API int dp_interface_remove_http_header_field(const int id, const char *field); + +EXPORT_API int dp_interface_set_notification_bundle(const int id, const int type, void *bundle_param); +EXPORT_API int dp_interface_get_notification_bundle(const int id, const int type, void **bundle_param); +EXPORT_API int dp_interface_set_notification_service_handle(const int id, const int type, void *handle); +EXPORT_API int dp_interface_get_notification_service_handle(const int id, const int type, void **handle); +EXPORT_API int dp_interface_set_notification_title(const int id, const char *title); +EXPORT_API int dp_interface_get_notification_title(const int id, char **title); +EXPORT_API int dp_interface_set_notification_description(const int id, const char *description); +EXPORT_API int dp_interface_get_notification_description(const int id, char **description); +EXPORT_API int dp_interface_set_notification_type(const int id, int type); +EXPORT_API int dp_interface_get_notification_type(const int id, int *type); +#ifdef __cplusplus +} +#endif + +#endif /* __DOWNLOAD_PROVIDER_INTERFACE_H__ */ diff --git a/provider/CMakeLists.txt b/provider/CMakeLists.txt new file mode 100755 index 0000000..43862ef --- /dev/null +++ b/provider/CMakeLists.txt @@ -0,0 +1,123 @@ + +## PROJECT NAME +PROJECT(${PKG_NAME} C) + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Debug") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +INCLUDE(FindPkgConfig) + +pkg_check_modules(dp2_pkgs REQUIRED glib-2.0 + gobject-2.0 + sqlite3 + capi-appfw-app-manager + capi-network-connection + capi-content-mime-type + appsvc + bundle + libsmack + dlog + libsystemd-daemon + vconf) + +FOREACH(flag ${dp2_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +IF(SUPPORT_WIFI_DIRECT) +MESSAGE("WIFI direct:On") +pkg_check_modules(dp2_wifi_direct_pkgs REQUIRED + capi-network-wifi-direct) +FOREACH(flag ${dp2_wifi_direct_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +ELSE (SUPPORT_WIFI_DIRECT) +MESSAGE("WIFI direct:Off") +ENDIF(SUPPORT_WIFI_DIRECT) + +IF(SUPPORT_SECURITY_PRIVILEGE) +pkg_check_modules(dp2_security_privilege_pkgs REQUIRED security-server) +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${dp2_security_privilege_pkgs_CFLAGS}") +ENDIF(SUPPORT_SECURITY_PRIVILEGE) + +IF(SUPPORT_NOTIFICATION) +MESSAGE("Notification:On") +pkg_check_modules(dp2_noti_pkgs REQUIRED + notification) +FOREACH(flag ${dp2_noti_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +ADD_DEFINITIONS(-DSUPPORT_NOTIFICATION) +ELSE (SUPPORT_NOTIFICATION) +MESSAGE("Notification:Off") +ENDIF(SUPPORT_NOTIFICATION) + +IF(SUPPORT_COMPANION_MODE) +MESSAGE("Companion:On") +pkg_check_modules(dp2_companion_pkgs REQUIRED + sap-client-stub-api) +FOREACH(flag ${dp2_companion_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +ADD_DEFINITIONS(-DSUPPORT_COMPANION_MODE) +ELSE (SUPPORT_COMPANION_MODE) +MESSAGE("Companion:Off") +ENDIF(SUPPORT_COMPANION_MODE) + +## INCLUDES +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/agent/include) + +set(DP2_LINK_LIBRARIES ${GLIB-2_LIBRARIES} + ${GOBJECT-2_LIBRARIES} + pthread + capi-appfw-app-manager + ) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -Wall -fPIE") + +IF(DEFINED IMAGE_DIR) + ADD_DEFINITIONS(-DIMAGE_DIR=\"${IMAGE_DIR}\") +ENDIF(DEFINED IMAGE_DIR) + +IF(DEFINED PROVIDER_DIR) + ADD_DEFINITIONS(-DPROVIDER_DIR=\"${PROVIDER_DIR}\") +ENDIF(DEFINED PROVIDER_DIR) + +IF(DEFINED DATABASE_CLIENT_DIR) + ADD_DEFINITIONS(-DDATABASE_CLIENT_DIR=\"${DATABASE_CLIENT_DIR}\") +ENDIF(DEFINED DATABASE_CLIENT_DIR) + +IF(DEFINED DATABASE_DIR) + ADD_DEFINITIONS(-DDATABASE_DIR=\"${DATABASE_DIR}\") +ENDIF(DEFINED DATABASE_DIR) + +IF(DEFINED LOCALE_DIR) + ADD_DEFINITIONS(-DPKG_NAME=\"${PKG_NAME}\") + ADD_DEFINITIONS(-DLOCALE_DIR=\"${LOCALE_DIR}\") +ENDIF(DEFINED LOCALE_DIR) + +ADD_DEFINITIONS(-DDOWNLOAD_PROVIDER_LOG_TAG=\"DOWNLOAD_PROVIDER\") + +ADD_EXECUTABLE(${PROJECT_NAME} + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-pthread.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-ipc.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-utils.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-notify.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-smack.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-network.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-db.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-plugin-download-agent.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-queue.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-queue-manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-client.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-client-manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-notification.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-notification-manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-main.c ) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${dp2_pkgs_LDFLAGS} ${DP2_LINK_LIBRARIES} ${dp2_noti_pkgs_LDFLAGS} ${dp2_companion_pkgs_LDFLAGS} ${dp2_wifi_direct_pkgs_LDFLAGS} ${dp2_security_privilege_pkgs_LDFLAGS} -ldl -pie) +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BIN_INSTALL_DIR}) + +INSTALL(FILES include/download-provider.h DESTINATION ${INCLUDE_INSTALL_DIR}/${PKG_NAME}) diff --git a/provider/download-provider-client-manager.c b/provider/download-provider-client-manager.c new file mode 100644 index 0000000..28ecaf3 --- /dev/null +++ b/provider/download-provider-client-manager.c @@ -0,0 +1,741 @@ +/* + * Copyright (c) 2013 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 <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <signal.h> + +#include <app_manager.h> +#include <systemd/sd-daemon.h> +#include <glib-object.h> + +#include <download-provider.h> +#include <download-provider-log.h> +#include <download-provider-config.h> +#include <download-provider-pthread.h> +#include <download-provider-smack.h> +#include <download-provider-client.h> +#include <download-provider-notification.h> +#include <download-provider-notification-manager.h> +#include <download-provider-utils.h> +#include <download-provider-ipc.h> +#include <download-provider-notify.h> +#include <download-provider-db-defs.h> +#include <download-provider-db.h> +#include <download-provider-queue-manager.h> +#include <download-provider-client-manager.h> +#include <download-provider-plugin-download-agent.h> +#include <download-provider-network.h> + +int g_dp_sock = -1; +dp_client_slots_fmt *g_dp_client_slots = NULL; +static void *g_db_handle = 0; +static pthread_mutex_t g_db_mutex = PTHREAD_MUTEX_INITIALIZER; + +void dp_terminate(int signo) +{ + TRACE_DEBUG("Received SIGTERM:%d", signo); + close(g_dp_sock); + g_dp_sock = -1; +} + +void dp_broadcast_signal() +{ + TRACE_INFO("broadcast"); + // announce to all thread for clients + // signo 10 : ip changed + if (g_dp_client_slots != NULL) { + int i = 0; + for (; i < DP_MAX_CLIENTS; i++) { + if (g_dp_client_slots[i].thread > 0 && + pthread_kill(g_dp_client_slots[i].thread, 0) != ESRCH) + pthread_kill(g_dp_client_slots[i].thread, SIGUSR1); + } + } + +} + +char *dp_db_get_client_smack_label(const char *pkgname) +{ + char *smack_label = NULL; + unsigned length = 0; + int errorcode = DP_ERROR_NONE; + + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (dp_db_get_client_property_string(g_db_handle, pkgname, DP_DB_COL_SMACK_LABEL, (unsigned char **)&smack_label, &length, &errorcode) < 0) { + TRACE_SECURE_ERROR("failed to get smack label for %s", pkgname); + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + + return smack_label; +} + +static int __dp_db_open_client_manager() +{ + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (dp_db_open_client_manager(&g_db_handle) < 0) { + TRACE_ERROR("[CRITICAL] can not open SQL"); + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + return -1; + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + return 0; +} + +static void __dp_db_free_client_manager() +{ + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (g_db_handle != 0) { + TRACE_SECURE_DEBUG("TRY to close [%s]", DP_DBFILE_CLIENTS); + dp_db_close(g_db_handle); + g_db_handle = 0; + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); +} + +static int __dp_accept_socket_new() +{ + int fd_base, listen_fds = sd_listen_fds(1); + TRACE_DEBUG("sd_listen_fds:%d", listen_fds); + for (fd_base = 0 ; fd_base < listen_fds; fd_base++) { + if (sd_is_socket_unix(fd_base + SD_LISTEN_FDS_START, SOCK_STREAM, 1, IPC_SOCKET, 0) >= 0) { + TRACE_INFO("listen systemd socket:%d", fd_base + SD_LISTEN_FDS_START); + return fd_base + SD_LISTEN_FDS_START; + } + } + return -1; +} + +int dp_client_slot_free(dp_client_slots_fmt *slot) +{ + if (slot->client.channel >= 0) { + close(slot->client.channel); + slot->client.channel = -1; + } + if (slot->client.dbhandle != 0) { + dp_db_close(slot->client.dbhandle); + slot->client.dbhandle = 0; + } + // free all requests + // remove notify fifo + if (slot->client.notify >= 0) { + close(slot->client.notify); + slot->client.notify = -1; + } + dp_notify_deinit(slot->credential.pid); + // kill thread + if (slot->thread != 0) + pthread_cancel(slot->thread); + slot->thread = 0; + if (slot->pkgname != NULL) { + TRACE_SECURE_DEBUG("TRY to close [%s]", slot->pkgname); + free(slot->pkgname); + slot->pkgname = NULL; + } + return 0; +} + +// precondition : all slots are empty +static int __dp_manage_client_requests(dp_client_slots_fmt *clients) +{ + int errorcode = DP_ERROR_NONE; + int i = 0; + int slot_index = 0; + + dp_notification_manager_kill(); + dp_queue_manager_kill(); + + // get all clients info from clients database. + + int *ids = (int *)calloc(DP_MAX_CLIENTS, sizeof(int)); + if (ids == NULL) { + TRACE_ERROR("failed to allocate the clients"); + return -1; + } + // getting ids of clients + int rows_count = dp_db_get_ids(g_db_handle, DP_TABLE_CLIENTS, NULL, ids, NULL, DP_MAX_CLIENTS, DP_DB_COL_ACCESS_TIME, "ASC", &errorcode); + for (; i < rows_count; i++) { + char *pkgname = NULL; + unsigned length = 0; + errorcode = DP_ERROR_NONE; + if (dp_db_get_property_string(g_db_handle, ids[i], DP_TABLE_CLIENTS, DP_DB_COL_PACKAGE, (unsigned char **)&pkgname, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get pkgname for id:%d", ids[i]); + continue; + } + + if (pkgname != NULL) { + if (dp_db_remove_database(pkgname, time(NULL), DP_CARE_CLIENT_INFO_PERIOD * 3600) == 0) { // old database + // remove info from client database; + if (dp_db_delete(g_db_handle, ids[i], DP_TABLE_CLIENTS, &errorcode) == 0) { + TRACE_SECURE_ERROR("clear info for %s", pkgname); + // remove database file + } + TRACE_SECURE_INFO("remove database for %s", pkgname); + free(pkgname); + continue; + } + + dp_credential credential; + credential.pid = 0; + if (dp_db_get_property_int(g_db_handle, ids[i], DP_TABLE_CLIENTS, DP_DB_COL_UID, &credential.uid, &errorcode) < 0 || + dp_db_get_property_int(g_db_handle, ids[i], DP_TABLE_CLIENTS, DP_DB_COL_GID, &credential.gid, &errorcode) < 0) { + TRACE_SECURE_ERROR("failed to get credential for %s", pkgname); + free(pkgname); + continue; + } + if (dp_mutex_init(&clients[slot_index].mutex, NULL) != 0) { + TRACE_SECURE_ERROR("failed to initialize mutex for %s", pkgname); + free(pkgname); + continue; + } + // open database of a clients + if (dp_db_open_client_v2(&clients[slot_index].client.dbhandle, pkgname) < 0) { + TRACE_SECURE_ERROR("failed to open database for %s", pkgname); + // remove this client from clients database + if (dp_db_delete(g_db_handle, ids[i], DP_TABLE_CLIENTS, &errorcode) == 0) { + TRACE_SECURE_ERROR("clear info for %s", pkgname); + // remove database file + if (dp_db_remove_database(pkgname, time(NULL), 0) == 0) { + TRACE_SECURE_INFO("remove database for %s", pkgname); + } else { + TRACE_SECURE_ERROR("failed to remove database for %s", pkgname); + } + } + free(pkgname); + continue; + } + + // get ids if state is QUEUED, CONNECTING or DOWNLOADING with auto_download + int *request_ids = (int *)calloc(DP_MAX_REQUEST, sizeof(int)); + if (request_ids == NULL) { + TRACE_SECURE_ERROR("failed to allocate the requests for %s", pkgname); + free(pkgname); + continue; + } + int request_count = dp_db_get_crashed_ids(clients[slot_index].client.dbhandle, DP_TABLE_LOGGING, request_ids, DP_MAX_REQUEST, &errorcode); + TRACE_DEBUG("client: %s requests:%d", pkgname, request_count); + int ids_i = 0; + if (request_count > 0) { + clients[slot_index].pkgname = pkgname; + clients[slot_index].client.channel = -1; + clients[slot_index].client.notify = -1; + clients[slot_index].credential.pid = credential.pid; + clients[slot_index].credential.uid = credential.uid; + clients[slot_index].credential.gid = credential.gid; + for (ids_i = 0; ids_i < request_count; ids_i++) { + // loading requests from client's database... attach to client.requests + dp_request_fmt *request = (dp_request_fmt *) calloc(1, sizeof(dp_request_fmt)); + if (request == NULL) { + TRACE_ERROR("check memory download-id:%d", request_ids[ids_i]); + break; + } + request->id = request_ids[ids_i]; + request->agent_id = -1; + request->state = DP_STATE_QUEUED; + request->error = DP_ERROR_NONE; + if (dp_db_get_property_int(clients[slot_index].client.dbhandle, request->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, &request->network_type, &errorcode) < 0) { + TRACE_ERROR("failed to get network type for id:%d", request->id); + request->network_type = DP_NETWORK_WIFI; + } + request->access_time = (int)time(NULL); + request->state_cb = 0; + request->progress_cb = 0; + if (dp_db_get_property_int(clients[slot_index].client.dbhandle, request->id, DP_TABLE_LOGGING, DP_DB_COL_STARTCOUNT, &request->startcount, &errorcode) < 0) { + TRACE_ERROR("failed to get start count for id:%d", request->id); + request->startcount = 0; + } + request->startcount++; + request->noti_type = DP_NOTIFICATION_TYPE_NONE; + if (dp_db_get_property_int(clients[slot_index].client.dbhandle, request->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, &request->noti_type, &errorcode) < 0) { + TRACE_ERROR("failed to get notification type for id:%d", request->id); + } + if (request->noti_type == DP_NOTIFICATION_TYPE_NONE) { + TRACE_INFO("enable notification for id:%d", request->id); + request->noti_type = DP_NOTIFICATION_TYPE_COMPLETE_ONLY; + } + request->progress_lasttime = 0; + request->received_size = 0; // ? + request->content_type = DP_CONTENT_UNKNOWN; + request->file_size = 0; // ? + if (dp_db_get_property_int(clients[slot_index].client.dbhandle, request->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, &request->noti_priv_id, &errorcode) < 0) { + TRACE_ERROR("failed to get notification noti_priv_id for id:%d", request->id); + request->noti_priv_id = -1; + } + + dp_request_create(&clients[slot_index].client, request); + + if (dp_db_update_logging(clients[slot_index].client.dbhandle, request->id, DP_STATE_QUEUED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log download-id:%d", request->id); + errorcode = DP_ERROR_DISK_BUSY; + break; + } + if (dp_queue_manager_push_queue((void *)&clients[slot_index], (void *)request) < 0) { + errorcode = DP_ERROR_QUEUE_FULL; + TRACE_INFO("failed to push to queue for id:%d", request->id); + dp_request_destroy(&(clients[slot_index].client), NULL, request); + break; + } + // notification + if (dp_notification_manager_push_notification((void *)&clients[slot_index], (void *)request, DP_NOTIFICATION_ONGOING) < 0) { + TRACE_ERROR("failed to register notification for id:%d", request->id); + } + + } + + slot_index++; + + } else { + free(pkgname); + } + free(request_ids); + } + } + free(ids); + TRACE_DEBUG("slot_index:%d", slot_index); + if (slot_index > 0) + dp_queue_manager_wake_up(); + return slot_index; +} + +static int __dp_client_run(int clientfd, dp_client_slots_fmt *slot, + dp_credential credential) +{ + int errorcode = DP_ERROR_NONE; + // make notify fifo + slot->client.notify = dp_notify_init(credential.pid); + if (slot->client.notify < 0) { + TRACE_STRERROR("failed to open fifo slot:%d", clientfd); + errorcode = DP_ERROR_IO_ERROR; + } else { + char *smack_label = NULL; + if (dp_smack_is_mounted() == 1) { + smack_label = dp_smack_get_label_from_socket(clientfd); + if (smack_label == NULL) { + TRACE_SECURE_ERROR("smack_new_label_from_socket"); + } + } + // save client info to database + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (dp_db_update_client_info(g_db_handle, + slot->pkgname, smack_label, + credential.uid, credential.gid, &errorcode) < 0) { + TRACE_ERROR("check error:%s", dp_print_errorcode(errorcode)); + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + free(smack_label); + } + if (errorcode == DP_ERROR_NONE) { + + // create a thread for client + if (pthread_create(&slot->thread, NULL, + dp_client_request_thread, (void *)slot) != 0) { + TRACE_ERROR("failed to create client thread slot:%d", clientfd); + errorcode = DP_ERROR_OUT_OF_MEMORY; + slot->thread = 0; + dp_client_slot_free(slot); // => make pkgname as NULL + } else { + pthread_detach(slot->thread); + TRACE_SECURE_INFO("accept client[%s] pid:%d sock:%d", + slot->pkgname, credential.pid, clientfd); + slot->client.channel = clientfd; + slot->credential.pid = credential.pid; + slot->credential.uid = credential.uid; + slot->credential.gid = credential.gid; + } + } + return errorcode; +} + + +static int __dp_client_new(int clientfd, dp_client_slots_fmt *clients, + dp_credential credential) +{ + // search in clients list. + // if same pkgname. update it. + // search same pkg or pid in clients + int errorcode = DP_ERROR_NONE; + int i = 0; + int pkg_len = 0; + char *pkgname = NULL; + + // getting the package name via pid + if (app_manager_get_package(credential.pid, &pkgname) != + APP_MANAGER_ERROR_NONE) + TRACE_ERROR("[CRITICAL] app_manager_get_package"); + + //// TEST CODE ... to allow sample client ( no package name ). + if (pkgname == NULL) { + //pkgname = dp_strdup("unknown_app"); + char *temp_pkgname = (char *)calloc(41, sizeof(char)); + if (temp_pkgname == NULL || + snprintf(temp_pkgname, 41,"unknown_app_%d", credential.pid) < 0) { + pkgname = dp_strdup("unknown_app"); + } else { + pkgname = temp_pkgname; + } + } + + if (pkgname == NULL) { + TRACE_ERROR("[CRITICAL] app_manager_get_package"); + return DP_ERROR_INVALID_PARAMETER; + } + if ((pkg_len = strlen(pkgname)) <= 0) { + TRACE_ERROR("[CRITICAL] pkgname:%s", pkgname); + free(pkgname); + return DP_ERROR_INVALID_PARAMETER; + } + +#ifdef SUPPORT_SECURITY_PRIVILEGE + int result = security_server_check_privilege_by_sockfd(clientfd, SECURITY_PRIVILEGE_INTERNET, "w"); + if (result != SECURITY_SERVER_API_SUCCESS) { + TRACE_ERROR("check privilege permission:%d", result); + return DP_ERROR_PERMISSION_DENIED; + } +#endif + + // EINVAL: empty slot + // EBUSY : occupied slot + // locked & thread == 0 : downloading without client <= check target + // thread == 0, requests == NULL : clear target + + // Have this client ever been connected before ? + for (i = 0; i < DP_MAX_CLIENTS; i++) { + + int locked = CLIENT_MUTEX_TRYLOCK(&clients[i].mutex); + if (locked != 0) { // empty or used by other thread. it would be same client, but it's busy + continue; + } + TRACE_DEBUG("locked slot:%d", i); + if (locked == 0 && clients[i].thread == 0) { // this slot has run without the client + if (clients[i].pkgname != NULL) { + // check package name. + TRACE_DEBUG("check client[%s] slot:%d", clients[i].pkgname, i); + int cname_len = strlen(clients[i].pkgname); + if (pkg_len == cname_len && + strncmp(clients[i].pkgname, pkgname, pkg_len) == 0) { + TRACE_SECURE_INFO("update client[%s] slot:%d pid:%d sock:%d", + pkgname, i, credential.pid, clientfd); + if (clients[i].client.channel >= 0 && + clients[i].client.channel != clientfd) { + dp_ipc_socket_free(clients[i].client.channel); + if (clients[i].client.notify >= 0) + close(clients[i].client.notify); + dp_notify_deinit(clients[i].credential.pid); + } + errorcode = __dp_client_run(clientfd, &clients[i], credential); + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + if (errorcode != DP_ERROR_NONE) + dp_mutex_destroy(&clients[i].mutex); + free(pkgname); + return errorcode; + } + } + if (clients[i].client.requests == NULL) { // clear + dp_client_slot_free(&clients[i]); + dp_mutex_destroy(&clients[i].mutex); + continue; + } + } + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + } + + TRACE_DEBUG("search empty client[%s] slot:%d", pkgname, i); + // search empty slot + for (i = 0; i < DP_MAX_CLIENTS; i++) { + int locked = CLIENT_MUTEX_TRYLOCK(&clients[i].mutex); + if (locked == EINVAL) { + if (dp_mutex_init(&clients[i].mutex, NULL) == 0) { + CLIENT_MUTEX_LOCK(&clients[i].mutex); + TRACE_DEBUG("found empty client[%s] slot:%d", pkgname, i); + clients[i].pkgname = pkgname; + clients[i].client.dbhandle = 0; + clients[i].client.requests = NULL; + errorcode = __dp_client_run(clientfd, &clients[i], credential); + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + if (errorcode != DP_ERROR_NONE) + dp_mutex_destroy(&clients[i].mutex); + return errorcode; + } + } + if (locked == 0) + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + } + + TRACE_SECURE_INFO("busy client[%s] pid:%d sock:%d", pkgname, + credential.pid, clientfd); + free(pkgname); + return DP_ERROR_TOO_MANY_DOWNLOADS; +} + +void *dp_client_manager(void *arg) +{ + fd_set rset, eset, listen_fdset, except_fdset; + struct timeval timeout; // for timeout of select + socklen_t clientlen; + struct sockaddr_un clientaddr; + dp_credential credential; + unsigned i; + int errorcode = DP_ERROR_NONE; + GMainLoop *event_loop = (GMainLoop *)arg; + + g_dp_sock = __dp_accept_socket_new(); + if (g_dp_sock < 0) { + TRACE_STRERROR("failed to open listen socket"); + g_main_loop_quit(event_loop); + return 0; + } + + if (signal(SIGTERM, dp_terminate) == SIG_ERR || + signal(SIGPIPE, SIG_IGN) == SIG_ERR || + signal(SIGINT, dp_terminate) == SIG_ERR) { + TRACE_ERROR("failed to register signal callback"); + g_main_loop_quit(event_loop); + return 0; + } + + dp_notification_clear_ongoings(); + +#ifdef PROVIDER_DIR + dp_rebuild_dir(PROVIDER_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); +#endif +#ifdef DATABASE_DIR + dp_rebuild_dir(DATABASE_DIR, S_IRWXU); +#endif +#ifdef DATABASE_CLIENT_DIR + dp_rebuild_dir(DATABASE_CLIENT_DIR, S_IRWXU); +#endif +#ifdef NOTIFY_DIR + dp_rebuild_dir(NOTIFY_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); +#endif + + if (__dp_db_open_client_manager() < 0) { + TRACE_STRERROR("failed to open database for client-manager"); + g_main_loop_quit(event_loop); + return 0; + } + + dp_client_slots_fmt *clients = + (dp_client_slots_fmt *)calloc(DP_MAX_CLIENTS, + sizeof(dp_client_slots_fmt)); + if (clients == NULL) { + TRACE_ERROR("failed to allocate client slots"); + g_main_loop_quit(event_loop); + return 0; + } + g_dp_client_slots = clients; + for (i = 0; i < DP_MAX_CLIENTS; i++) { + dp_mutex_destroy(&clients[i].mutex); // clear mutex init + } + + int maxfd = g_dp_sock; + FD_ZERO(&listen_fdset); + FD_ZERO(&except_fdset); + FD_SET(g_dp_sock, &listen_fdset); + FD_SET(g_dp_sock, &except_fdset); + + while (g_dp_sock >= 0) { + + int clientfd = -1; + + // initialize timeout structure for calling timeout exactly + memset(&timeout, 0x00, sizeof(struct timeval)); + timeout.tv_sec = DP_CARE_CLIENT_MANAGER_INTERVAL; + credential.pid = -1; + credential.uid = -1; + credential.gid = -1; + + rset = listen_fdset; + eset = except_fdset; + + if (select((maxfd + 1), &rset, 0, &eset, &timeout) < 0) { + TRACE_STRERROR("interrupted by terminating"); + break; + } + + if (g_dp_sock < 0) { + TRACE_DEBUG("queue-manager is closed by other thread"); + break; + } + + if (FD_ISSET(g_dp_sock, &eset) > 0) { + TRACE_STRERROR("exception of socket"); + break; + } else if (FD_ISSET(g_dp_sock, &rset) > 0) { + + // Anyway accept client. + clientlen = sizeof(clientaddr); + clientfd = accept(g_dp_sock, (struct sockaddr *)&clientaddr, + &clientlen); + if (clientfd < 0) { + TRACE_STRERROR("too many client ? accept failure"); + // provider need the time of refresh. + break; + } + + // blocking & timeout to prevent the lockup by client. + struct timeval tv_timeo = {1, 500000}; // 1.5 sec + if (setsockopt(clientfd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, + sizeof(tv_timeo)) < 0) { + TRACE_ERROR("failed to set timeout in blocking socket"); + close(clientfd); + continue; + } + + dp_ipc_fmt ipc_info; + memset(&ipc_info, 0x00, sizeof(dp_ipc_fmt)); + if (read(clientfd, &ipc_info, sizeof(dp_ipc_fmt)) <= 0 || + ipc_info.section == DP_SEC_NONE || + ipc_info.property != DP_PROP_NONE || + ipc_info.id != -1 || + ipc_info.size != 0) { + TRACE_ERROR("peer terminate ? ignore this connection"); + close(clientfd); + continue; + } + +#ifdef SO_PEERCRED // getting the info of client + socklen_t cr_len = sizeof(credential); + if (getsockopt(clientfd, SOL_SOCKET, SO_PEERCRED, + &credential, &cr_len) < 0) { + TRACE_ERROR("failed to cred from sock:%d", clientfd); + close(clientfd); + continue; + } +#else // In case of not supported SO_PEERCRED + if (read(clientfd, &credential, sizeof(dp_credential)) <= 0) { + TRACE_ERROR("failed to cred from client:%d", clientfd); + close(clientfd); + continue; + } +#endif + + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (dp_db_check_connection(g_db_handle) < 0) { + TRACE_ERROR("check database, provider can't work anymore"); + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + close(clientfd); + break; + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + + if (ipc_info.section == DP_SEC_INIT) { + + // new client + errorcode = __dp_client_new(clientfd, clients, credential); + + } else { + errorcode = DP_ERROR_INVALID_PARAMETER; + } + if (dp_ipc_query(clientfd, -1, DP_SEC_INIT, DP_PROP_NONE, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", clientfd); + } + if (errorcode == DP_ERROR_NONE) { + // write client info into database + + } else { + TRACE_ERROR("sock:%d id:%d section:%s property:%s errorcode:%s size:%d", + clientfd, ipc_info.id, + dp_print_section(ipc_info.section), + dp_print_property(ipc_info.property), + dp_print_errorcode(ipc_info.errorcode), + ipc_info.size); + close(clientfd); // ban this client + } + + } else { + + // take care zombie client, slots + unsigned connected_clients = 0; + int i = 0; + for (; i < DP_MAX_CLIENTS; i++) { + + int locked = CLIENT_MUTEX_TRYLOCK(&clients[i].mutex); + if (locked == EINVAL) { // not initialized + continue; + } else if (locked == EBUSY) { // already locked + connected_clients++; + continue; + } + + if (locked == 0) { // locked + + // if no client thread, requests should be checked here + // if no queued, connecting or downloading, close the slot + if (clients[i].pkgname != NULL) { + if (clients[i].thread == 0) { + dp_client_clear_requests(&clients[i]); + if (clients[i].client.requests == NULL) { + dp_client_slot_free(&clients[i]); + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + dp_mutex_destroy(&clients[i].mutex); + continue; + } + } + connected_clients++; + } + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + } + } + TRACE_DEBUG("%d clients are active now", connected_clients); + // terminating download-provider if no clients. + if (connected_clients == 0) { + if (__dp_manage_client_requests(clients) <= 0) // if no crashed job + break; + } else { + dp_queue_manager_wake_up(); + dp_notification_manager_wake_up(); + } + } + + } + if (g_dp_sock >= 0) + close(g_dp_sock); + g_dp_sock = -1; + + dp_queue_manager_kill(); + dp_notification_clear_ongoings(); + dp_notification_manager_kill(); + + __dp_db_free_client_manager(); + + // kill other clients + TRACE_DEBUG("try to deallocate the resources for all clients"); + for (i = 0; i < DP_MAX_CLIENTS; i++) { + int locked = CLIENT_MUTEX_TRYLOCK(&clients[i].mutex); + if (locked == EBUSY) { // already locked + CLIENT_MUTEX_LOCK(&clients[i].mutex); + } else if (locked == EINVAL) { // not initialized, empty slot + continue; + } + dp_client_slot_free(&clients[i]); + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + dp_mutex_destroy(&clients[i].mutex); + } + free(clients); + // free all resources + + TRACE_INFO("client-manager's working is done"); + g_main_loop_quit(event_loop); + return 0; +} diff --git a/provider/download-provider-client.c b/provider/download-provider-client.c new file mode 100644 index 0000000..53c5909 --- /dev/null +++ b/provider/download-provider-client.c @@ -0,0 +1,2110 @@ +/* + * Copyright (c) 2013 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 <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <signal.h> + +#include <download-provider-log.h> +#include <download-provider-config.h> +#include <download-provider-ipc.h> +#include <download-provider-network.h> +#include <download-provider-client.h> +#include <download-provider-pthread.h> +#include <download-provider-notify.h> +#include <download-provider-notification-manager.h> +#include <download-provider-queue-manager.h> +#include <download-provider-client-manager.h> +#include <download-provider-db-defs.h> +#include <download-provider-db.h> +#include <download-provider-plugin-download-agent.h> +#include <download-provider-smack.h> + +char *dp_print_state(int state) +{ + switch(state) + { + case DP_STATE_NONE : + return "NONE"; + case DP_STATE_READY : + return "READY"; + case DP_STATE_QUEUED : + return "QUEUED"; + case DP_STATE_CONNECTING : + return "CONNECTING"; + case DP_STATE_DOWNLOADING : + return "DOWNLOADING"; + case DP_STATE_PAUSED : + return "PAUSED"; + case DP_STATE_COMPLETED : + return "COMPLETED"; + case DP_STATE_CANCELED : + return "CANCELED"; + case DP_STATE_FAILED : + return "FAILED"; + default : + break; + } + return "UNKNOWN"; +} + +char *dp_print_errorcode(int errorcode) +{ + switch(errorcode) + { + case DP_ERROR_NONE : + return "NONE"; + case DP_ERROR_INVALID_PARAMETER : + return "INVALID_PARAMETER"; + case DP_ERROR_OUT_OF_MEMORY : + return "OUT_OF_MEMORY"; + case DP_ERROR_IO_ERROR : + return "IO_ERROR"; + case DP_ERROR_NETWORK_UNREACHABLE : + return "NETWORK_UNREACHABLE"; + case DP_ERROR_CONNECTION_TIMED_OUT : + return "CONNECTION_TIMED_OUT"; + case DP_ERROR_NO_SPACE : + return "NO_SPACE"; + case DP_ERROR_FIELD_NOT_FOUND : + return "FIELD_NOT_FOUND"; + case DP_ERROR_INVALID_STATE : + return "INVALID_STATE"; + case DP_ERROR_CONNECTION_FAILED : + return "CONNECTION_FAILED"; + case DP_ERROR_INVALID_URL : + return "INVALID_URL"; + case DP_ERROR_INVALID_DESTINATION : + return "INVALID_DESTINATION"; + case DP_ERROR_QUEUE_FULL : + return "QUEUE_FULL"; + case DP_ERROR_ALREADY_COMPLETED : + return "ALREADY_COMPLETED"; + case DP_ERROR_FILE_ALREADY_EXISTS : + return "FILE_ALREADY_EXISTS"; + case DP_ERROR_TOO_MANY_DOWNLOADS : + return "TOO_MANY_DOWNLOADS"; + case DP_ERROR_NO_DATA : + return "NO_DATA"; + case DP_ERROR_UNHANDLED_HTTP_CODE : + return "UNHANDLED_HTTP_CODE"; + case DP_ERROR_CANNOT_RESUME : + return "CANNOT_RESUME"; + case DP_ERROR_PERMISSION_DENIED : + return "PERMISSION_DENIED"; + case DP_ERROR_RESPONSE_TIMEOUT : + return "RESPONSE_TIMEOUT"; + case DP_ERROR_REQUEST_TIMEOUT : + return "REQUEST_TIMEOUT"; + case DP_ERROR_SYSTEM_DOWN : + return "SYSTEM_DOWN"; + case DP_ERROR_CLIENT_DOWN : + return "CLIENT_DOWN"; + case DP_ERROR_DISK_BUSY: + return "DISK_BUSY"; + case DP_ERROR_ID_NOT_FOUND : + return "ID_NOT_FOUND"; + default : + break; + } + return "UNKNOWN"; +} + +char *dp_print_section(short section) +{ + switch (section) { + case DP_SEC_NONE: + return "NONE"; + case DP_SEC_INIT: + return "INIT"; + case DP_SEC_DEINIT: + return "DEINIT"; + case DP_SEC_CONTROL: + return "CONTROL"; + case DP_SEC_GET: + return "GET"; + case DP_SEC_SET: + return "SET"; + case DP_SEC_UNSET: + return "UNSET"; + default: + break; + } + return "UNKNOWN"; +} + +char *dp_print_property(unsigned property) +{ + switch (property) { + case DP_PROP_NONE: + return "NONE"; + case DP_PROP_CREATE: + return "CREATE"; + case DP_PROP_START: + return "START"; + case DP_PROP_PAUSE: + return "PAUSE"; + case DP_PROP_CANCEL: + return "CANCEL"; + case DP_PROP_DESTROY: + return "DESTROY"; + case DP_PROP_URL: + return "URL"; + case DP_PROP_DESTINATION: + return "DESTINATION"; + case DP_PROP_FILENAME: + return "FILENAME"; + case DP_PROP_STATE_CALLBACK: + return "STATE_CB"; + case DP_PROP_PROGRESS_CALLBACK: + return "PROGRESS_CB"; + case DP_PROP_AUTO_DOWNLOAD: + return "AUTO_DOWNLOAD"; + case DP_PROP_NETWORK_TYPE: + return "NETWORK_TYPE"; + case DP_PROP_NETWORK_BONDING: + return "NETWORK_BONDING"; + case DP_PROP_SAVED_PATH: + return "SAVED_PATH"; + case DP_PROP_TEMP_SAVED_PATH: + return "TEMP_SAVED_PATH"; + case DP_PROP_MIME_TYPE: + return "MIME_TYPE"; + case DP_PROP_RECEIVED_SIZE: + return "RECEIVED_SIZE"; + case DP_PROP_TOTAL_FILE_SIZE: + return "TOTAL_FILE_SIZE"; + case DP_PROP_CONTENT_NAME: + return "CONTENT_NAME"; + case DP_PROP_HTTP_STATUS: + return "HTTP_STATUS"; + case DP_PROP_ETAG: + return "ETAG"; + case DP_PROP_STATE: + return "STATE"; + case DP_PROP_ERROR: + return "ERROR"; + case DP_PROP_NOTIFICATION_RAW: + return "NOTIFICATION_RAW"; + case DP_PROP_NOTIFICATION_SUBJECT: + return "NOTIFICATION_SUBJECT"; + case DP_PROP_NOTIFICATION_DESCRIPTION: + return "NOTIFICATION_DESCRIPTION"; + case DP_PROP_NOTIFICATION_TYPE: + return "NOTIFICATION_TYPE"; + case DP_PROP_HTTP_HEADERS: + return "HTTP_HEADERS"; + case DP_PROP_HTTP_HEADER: + return "HTTP_HEADER"; + default: + break; + } + return "UNKNOWN"; +} + +static int __dp_get_download_id(dp_client_fmt *client) +{ + int download_id = -1; + static int last_download_id = 0; + int check_duplicate = 0; + int errorcode = DP_ERROR_NONE; + + do { + do { + struct timeval tval; + int cipher = 1; + int c = 0; + + download_id = -1; + gettimeofday(&tval, NULL); + + int usec = tval.tv_usec; + for (c = 0; ; c++, cipher++) { + if ((usec /= 10) <= 0) + break; + } + if (tval.tv_usec == 0) + tval.tv_usec = (tval.tv_sec & 0x0fff); + int disit_unit = 10; + for (c = 0; c < cipher - 3; c++) + disit_unit = disit_unit * 10; + download_id = tval.tv_sec + ((tval.tv_usec << 2) * 100) + + ((tval.tv_usec >> (cipher - 1)) * disit_unit) + + ((tval.tv_usec + (tval.tv_usec % 10)) & 0x0fff); + } while (last_download_id == download_id); + last_download_id = download_id; + check_duplicate = dp_db_check_duplicated_int(client->dbhandle, + DP_TABLE_LOGGING, DP_DB_COL_ID, download_id, &errorcode); + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("ERROR [%d]", errorcode); + } + } while (check_duplicate != 0); // means duplicated id + return download_id; +} + +void dp_request_create(dp_client_fmt *client, dp_request_fmt *request) +{ + // new request + // find the tail of linked list & check limitation + int i = 0; + dp_request_fmt *tailp = client->requests; + dp_request_fmt *prevp = NULL; + for (; i < MAX_DOWNLOAD_HANDLE; i++) { + if (tailp == NULL) + break; + TRACE_DEBUG("link %d info: id:%d access-time:%d", i, tailp->id, tailp->access_time); + prevp = tailp; + tailp = tailp->next; + } + request->next = NULL; + if (prevp == NULL) // it's first link + client->requests = request; + else + prevp->next = request; // attach at the tail + + TRACE_DEBUG("sock:%d download-id:%d", client->channel, request->id); +} + +static int __dp_request_create(dp_client_fmt *client, dp_ipc_fmt *ipc_info) +{ + int errorcode = DP_ERROR_NONE; + + int download_id = __dp_get_download_id(client); + + // allocation new request. + dp_request_fmt *request = (dp_request_fmt *) calloc(1, sizeof(dp_request_fmt)); + if (request == NULL) { + TRACE_ERROR("check memory sock:%d download-id:%d", client->channel, download_id); + return DP_ERROR_OUT_OF_MEMORY; + } + + if (dp_db_new_logging(client->dbhandle, download_id, DP_STATE_READY, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("new log sock:%d download-id:%d", client->channel, download_id); + free(request); + return DP_ERROR_DISK_BUSY; + } + + request->id = download_id; + request->agent_id = -1; + request->state = DP_STATE_READY; + request->error = DP_ERROR_NONE; + request->network_type = DP_NETWORK_ALL; + request->access_time = (int)time(NULL); + request->state_cb = 0; + request->progress_cb = 0; + request->startcount = 0; + request->noti_type = DP_NOTIFICATION_TYPE_NONE; + request->progress_lasttime = 0; + request->received_size = 0; + request->content_type = DP_CONTENT_UNKNOWN; + request->file_size = 0; + request->noti_priv_id = -1; + + dp_request_create(client, request); + ipc_info->id = download_id; + return errorcode; +} + +void dp_request_free(dp_request_fmt *request) +{ + // free notification handle here + TRACE_DEBUG("destory id:%d", request->id); + free(request); +} + +void dp_client_clear_requests(void *slotp) +{ + dp_client_slots_fmt *slot = (dp_client_slots_fmt *)slotp; + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return ; + } + dp_client_fmt *client = &slot->client; + if (client == NULL) { + TRACE_ERROR("check client memory"); + return ; + } + + int now_time = (int)time(NULL); + int i = 0; + unsigned queued_count = 0; + unsigned ongoing_count = 0; + dp_request_fmt *tailp = client->requests; + dp_request_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + + unsigned can_unload = 0; + if (tailp->id <= 0 || tailp->state == DP_STATE_NONE) { + TRACE_ERROR("id:%d unexpected request (%ld/%ld)", tailp->id, tailp->access_time, now_time); + can_unload = 1; + } else if (tailp->access_time > 0 && + (now_time - tailp->access_time) > DP_CARE_CLIENT_CLEAR_INTERVAL) { + // check accesstime. if difference is bigger than DP_CARE_CLIENT_CLEAR_INTERVAL, clear. + + if (tailp->state == DP_STATE_READY || + tailp->state == DP_STATE_COMPLETED || + tailp->state == DP_STATE_CANCELED || + tailp->state == DP_STATE_FAILED) { + can_unload = 1; + } else if (tailp->state == DP_STATE_CONNECTING) { // it take 120 sec over to connect. it means zombie. + TRACE_ERROR("id:%d connection timeout (%ld/%ld)", tailp->id, tailp->access_time, now_time); + if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id); + } + tailp->state = DP_STATE_FAILED; + tailp->error = DP_ERROR_CONNECTION_TIMED_OUT; + if (tailp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + tailp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, tailp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", tailp->id); + } + } + } + } else if (tailp->state == DP_STATE_PAUSED && + dp_is_alive_download(tailp->agent_id) == 0) { + // paused & agent_id not exist.... unload from memory. + TRACE_ERROR("id:%d hanged as paused (%ld/%ld)", tailp->id, tailp->access_time, now_time); + can_unload = 1; + } + + if (can_unload == 1) { + dp_request_fmt *removep = tailp; + if (prevp == NULL) // first request. + client->requests = tailp->next; + else + prevp->next = tailp->next; + tailp = tailp->next; + TRACE_DEBUG("request %d clear: id:%d state:%s", i, removep->id, dp_print_state(removep->state)); + dp_request_free(removep); + continue; + } else { + ongoing_count++; + } + + if (tailp->state == DP_STATE_QUEUED) + queued_count++; + + prevp = tailp; + tailp = tailp->next; + } + TRACE_DEBUG("info requests:%d queued:%d", ongoing_count, queued_count); + if (queued_count > 0) + dp_queue_manager_wake_up(); +} + +int dp_request_destroy(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + int errorcode = DP_ERROR_NONE; + + if (requestp != NULL && client->requests != NULL) { + if (requestp == client->requests) { + // cancel downloading ... after checking status + client->requests = requestp->next; + dp_request_free(requestp); + } else { + int i = 1; + dp_request_fmt *prevp = client->requests; + dp_request_fmt *removep = client->requests->next; + for (; i < MAX_DOWNLOAD_HANDLE; i++) { + if (removep == NULL) { + errorcode = DP_ERROR_ID_NOT_FOUND; + break; + } + if (removep == requestp) { + // cancel downloading ... after checking status + prevp->next = removep->next; + dp_request_free(removep); + break; + } + prevp = removep; + removep = removep->next; + } + } + } + + TRACE_DEBUG("sock:%d id:%d errorcode:%s", client->channel, + (ipc_info) ? ipc_info->id : -1, dp_print_errorcode(errorcode)); + + return errorcode; +} + +static int __dp_request_read_int(int sock, dp_ipc_fmt *ipc_info, int *value) +{ + int errorcode = DP_ERROR_NONE; + if (ipc_info->size == sizeof(int)) { + if (dp_ipc_read(sock, value, ipc_info->size, __FUNCTION__) < 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, ipc_info->size); + errorcode = DP_ERROR_IO_ERROR; + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + return errorcode; +} + +static int __dp_request_feedback_string(int sock, dp_ipc_fmt *ipc_info, void *string, size_t length, int errorvalue) +{ + int errorcode = DP_ERROR_NONE; + + if (length == 0 && errorvalue == DP_ERROR_NONE) + errorvalue = DP_ERROR_NO_DATA; + + if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, length); + } + if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) { + if (dp_ipc_write(sock, string, sizeof(char) * length) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, length); + } + } + return errorcode; +} + +static int __dp_request_read_string(int sock, dp_ipc_fmt *ipc_info, char **string) +{ + int errorcode = DP_ERROR_NONE; + if (ipc_info->size > 0) { + char *recv_str = (char *)calloc((ipc_info->size + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", sock, ipc_info->size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } else { + if (dp_ipc_read(sock, recv_str, ipc_info->size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, ipc_info->size); + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[ipc_info->size] = '\0'; + TRACE_DEBUG("sock:%d length:%d string:%s", sock, ipc_info->size, recv_str); + *string = recv_str; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + return errorcode; +} + +static int __dp_request_feedback_int(int sock, dp_ipc_fmt *ipc_info, void *value, int errorvalue, size_t extra_size) +{ + int errorcode = DP_ERROR_NONE; + if (errorvalue != DP_ERROR_NONE) + extra_size = 0; + if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, extra_size) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + } + if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) { + if (dp_ipc_write(sock, value, extra_size) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + } + } + return errorcode; +} + +static int __dp_request_get_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + int errorcode = DP_ERROR_NONE; + switch (ipc_info->property) { + case DP_PROP_URL: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_DESTINATION: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_FILENAME: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_STATE_CALLBACK: + { + int callback = 0; + if (requestp != NULL) { + callback = requestp->state_cb; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, &callback, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&callback, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_PROGRESS_CALLBACK: + { + int callback = 0; + if (requestp != NULL) { + callback = requestp->progress_cb; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, &callback, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&callback, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_AUTO_DOWNLOAD: + { + int autodownload = 0; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, &autodownload, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&autodownload, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NETWORK_TYPE: + { + int network = 0; + if (requestp != NULL) { + network = requestp->network_type; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, &network, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&network, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NETWORK_BONDING: + { + int network_bonding = 0; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, &network_bonding, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&network_bonding, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_SAVED_PATH: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_TEMP_SAVED_PATH: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_TMP_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_MIME_TYPE: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_MIMETYPE, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_RECEIVED_SIZE: + { + unsigned long long recv_size = 0; + if (requestp != NULL) { + recv_size = requestp->received_size; + } else { + errorcode = DP_ERROR_INVALID_STATE; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&recv_size, errorcode, sizeof(unsigned long long)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_TOTAL_FILE_SIZE: + { + unsigned long long file_size = 0; + if (requestp != NULL) { + file_size = requestp->file_size; + } else { + // load content_size(INT64) from database; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_SIZE, &file_size, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&file_size, errorcode, sizeof(unsigned long long)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_CONTENT_NAME: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_HTTP_STATUS: + { + int httpstatus = 0; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_HTTP_STATUS, &httpstatus, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&httpstatus, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_ETAG: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_ETAG, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_STATE: + { + int state = DP_STATE_NONE; + if (requestp != NULL) { + state = requestp->state; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &state, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&state, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_ERROR: + { + int errorvalue = DP_ERROR_NONE; + if (requestp != NULL) { + errorvalue = requestp->error; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_ERRORCODE, &errorvalue, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&errorvalue, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NOTIFICATION_TYPE: + { + int noti_type = 0; + if (requestp != NULL) { + noti_type = requestp->noti_type; + // if already notification, unregister from notification bar. + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, ¬i_type, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)¬i_type, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NOTIFICATION_SUBJECT: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_NOTIFICATION_DESCRIPTION: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_NOTIFICATION_RAW: // read type, send raw binary for type + { + int bundle_type = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type); + TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type); + char *raw_column = NULL; + if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING) + raw_column = DP_DB_COL_NOTI_RAW_ONGOING; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE) + raw_column = DP_DB_COL_NOTI_RAW_COMPLETE; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED) + raw_column = DP_DB_COL_NOTI_RAW_FAIL; + + if (raw_column == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + TRACE_ERROR("invalid type %d type:%d", dp_print_property(ipc_info->property), bundle_type); + if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section, ipc_info->property, errorcode, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + } + if (errorcode == DP_ERROR_NONE) { + unsigned char *raws_buffer = NULL; + unsigned length = 0; + // get blob binary from database by raw_column + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &raws_buffer, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, raws_buffer, (size_t)length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(raws_buffer); + } + break; + } + case DP_PROP_HTTP_HEADERS: + { + // 1. response + // 2. send the number of header fields by id + // 3. send response & field string for each fields + int field_count = dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ID, ipc_info->id, &errorcode); + if (field_count < 0 ) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + field_count = 0; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&field_count, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } else if (field_count > 0) { + // get fields from database. + int *ids = (int *)calloc(field_count, sizeof(int)); + if (ids == NULL) { + TRACE_ERROR("failed to allocate the clients"); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } else { + // getting ids of clients + int i = 0; + int rows_count = dp_db_get_cond_ids(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ROW_ID, DP_DB_COL_ID, ipc_info->id, ids, field_count, &errorcode); + for (; i < rows_count; i++) { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_cond_string(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ROW_ID, ids[i], DP_DB_COL_HEADER_FIELD, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + free(string); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + break; + } + } + } + } + + break; + } + case DP_PROP_HTTP_HEADER: + { + // 1. read field string + // 2. response with extra size + // 3. send string. + char *header_field = NULL; + char *string = NULL; + unsigned length = 0; + errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field); + if (errorcode == DP_ERROR_NONE && header_field != NULL) { + if (dp_db_get_header_value(client->dbhandle, ipc_info->id, header_field, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_field == NULL) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(header_field); + free(string); + break; + } + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + return errorcode; +} + +static int __dp_request_set_info(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return DP_ERROR_INVALID_PARAMETER; + } + dp_client_fmt *client = &slot->client; + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + // if completed or downloading, invalid state. + int download_state = DP_STATE_NONE; + if (requestp != NULL) { + download_state = requestp->state; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) { + TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; + } + } + // should the state be checked ? + TRACE_DEBUG("state:%s set property:%s", dp_print_state(download_state), dp_print_property(ipc_info->property)); + + switch (ipc_info->property) { + case DP_PROP_URL: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_DESTINATION: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + if (dp_smack_is_mounted() == 1) { + // check here destination is available. with checking smack + char *smack_label = dp_db_get_client_smack_label(slot->pkgname); + if (smack_label == NULL) { + TRACE_SECURE_ERROR("[SMACK][%d] no label", ipc_info->id); + errorcode = DP_ERROR_PERMISSION_DENIED; + } else if (dp_is_valid_dir(recv_str) != 0) { + errorcode = DP_ERROR_INVALID_DESTINATION; + } else if (dp_smack_is_valid_dir(slot->credential.uid, slot->credential.gid, smack_label, recv_str) != 0) { + errorcode = DP_ERROR_PERMISSION_DENIED; + } + free(smack_label); + } + if (errorcode == DP_ERROR_NONE && + dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_TEMP_SAVED_PATH: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_TEMP_FILE_PATH, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_FILENAME: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_STATE_CALLBACK: + { + // check state here + // DP_ERROR_INVALID_STATE if downloading or finished + // update database here + if (requestp != NULL) { + requestp->state_cb = 1; + } + int enable_cb = 1; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_PROGRESS_CALLBACK: + { + // check state here + // DP_ERROR_INVALID_STATE if downloading or finished + // update database here + if (requestp != NULL) { + requestp->progress_cb = 1; + } + int enable_cb = 1; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_AUTO_DOWNLOAD: + { + // update autodownload property as 1 in database + int enable_cb = 1; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NETWORK_TYPE: + { + int recv_int = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int); + if (recv_int <= DP_NETWORK_OFF || + recv_int > DP_NETWORK_ALL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // update in database + if (requestp != NULL) { + if (requestp->state == DP_STATE_QUEUED) { + dp_queue_manager_clear_queue(requestp); + } else { + requestp->network_type = recv_int; + if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + // pause & push queue + if (dp_pause_agent_download_without_update(requestp->agent_id) < 0) { + TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id); + } else { + requestp->state = DP_STATE_PAUSED; + requestp->error = DP_ERROR_NONE; + if (dp_queue_manager_push_queue(slot, requestp) < 0) { + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + } + requestp->state = DP_STATE_FAILED; + requestp->error = DP_ERROR_QUEUE_FULL; + errorcode = DP_ERROR_QUEUE_FULL; + } + } + } + } + } + int enable_cb = recv_int; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + break; + } + case DP_PROP_NETWORK_BONDING: + { + int recv_int = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int); + if (errorcode == DP_ERROR_NONE) { + if(requestp != NULL && requestp->network_type != DP_NETWORK_ALL) { + errorcode = DP_ERROR_INVALID_NETWORK_TYPE; + TRACE_ERROR("[ERROR] wrong network type"); + } else if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, (void *)&recv_int, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + break; + } + case DP_PROP_NOTIFICATION_TYPE: + { + int recv_int = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int); + if (recv_int == DP_NOTIFICATION_TYPE_NONE || + recv_int == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + recv_int == DP_NOTIFICATION_TYPE_ALL) { + // check state request->state == DP_STATE_COMPLETED + // DP_ERROR_INVALID_STATE + // update notificatio type in database + int noti_type = recv_int; + if (requestp != NULL) { + if (recv_int < requestp->noti_type) { + // if already notification, unregister from notification bar. + if (recv_int == DP_NOTIFICATION_TYPE_NONE) { + if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to clear notification %s", dp_print_property(ipc_info->property)); + } + } + if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0) { + TRACE_ERROR("failed to clear ongoing %s", dp_print_property(ipc_info->property)); + } + } + requestp->noti_type = recv_int; + } + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, (void *)¬i_type, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } else { + errorcode = DP_ERROR_INVALID_PARAMETER; + } + break; + } + case DP_PROP_NOTIFICATION_SUBJECT: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_NOTIFICATION_DESCRIPTION: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_NOTIFICATION_RAW: // bundle_type(db column) + bundle_binary + { + int bundle_type = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type); + TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type); + char *raw_column = NULL; + if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING) + raw_column = DP_DB_COL_NOTI_RAW_ONGOING; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE) + raw_column = DP_DB_COL_NOTI_RAW_COMPLETE; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED) + raw_column = DP_DB_COL_NOTI_RAW_FAIL; + else + errorcode = DP_ERROR_INVALID_PARAMETER; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } + if (errorcode == DP_ERROR_NONE) { + dp_ipc_fmt *raw_info = dp_ipc_get_fmt(client->channel); + if (raw_info == NULL || raw_info->section != ipc_info->section || + raw_info->property != ipc_info->property || + (raw_info->id != ipc_info->id)) { + TRACE_ERROR("there is a confusion waiting raw binary in %s section", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_IO_ERROR; + } + if (raw_info != NULL && raw_info->size > 0) { + unsigned char *recv_raws = (unsigned char *)calloc(raw_info->size, sizeof(unsigned char)); + if (recv_raws == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", client->channel, raw_info->size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } else { + if (dp_ipc_read(client->channel, recv_raws, raw_info->size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", client->channel, raw_info->size); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_DEBUG("sock:%d length:%d raws", client->channel, raw_info->size); + // save to database + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, (void *)recv_raws, raw_info->size, 3, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + free(recv_raws); + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + free(raw_info); + } + break; + } + case DP_PROP_HTTP_HEADER: // a request can have one or more fields, a fields can have only one value. + { + char *header_field = NULL; + char *header_value = NULL; + // 1. read field string + // 2. response after checking sql status + // 3. read query IPC for checking IPC + // 4. read value string + // 5. response + errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field); + if (errorcode == DP_ERROR_NONE && header_field != NULL) { + // check sql + int check_field = dp_db_check_duplicated_string(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, 0, header_field, &errorcode); + if (check_field < 0) { + errorcode = DP_ERROR_DISK_BUSY; + } else { + errorcode = DP_ERROR_NONE; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } else { + dp_ipc_fmt *header_ipc = dp_ipc_get_fmt(client->channel); + if (header_ipc == NULL || header_ipc->section != ipc_info->section || + header_ipc->property != ipc_info->property || + (header_ipc->id != ipc_info->id)) { + TRACE_ERROR("there is a confusion during waiting http string in %s section", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = __dp_request_read_string(client->channel, header_ipc, &header_value); + if (errorcode == DP_ERROR_NONE && header_value != NULL) { + if (check_field == 0) { // insert + if (dp_db_new_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } else { // update + if (dp_db_update_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_value == NULL) { + TRACE_ERROR("failed to set %s, do you want to run as unset?", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + } + free(header_ipc); + } + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_field == NULL) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + free(header_field); + free(header_value); + break; + } + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; +} + +static int __dp_request_unset_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + switch (ipc_info->property) { + case DP_PROP_URL: + // it would be run like cancel operation + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + case DP_PROP_DESTINATION: + // if downloading, change destination to da_agent + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + case DP_PROP_FILENAME: + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + case DP_PROP_STATE_CALLBACK: + { + if (requestp != NULL) { + requestp->state_cb = 0; + } + int enable_cb = 0; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, (void *)&enable_cb, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_PROGRESS_CALLBACK: + { + if (requestp != NULL) { + requestp->progress_cb = 0; + } + int enable_cb = 0; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, (void *)&enable_cb, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_AUTO_DOWNLOAD: + { + // update autodownload property as 0 in database + int enable_cb = 0; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, (void *)&enable_cb, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NETWORK_TYPE: + { + // check state here + // update database here + if (requestp != NULL) { + requestp->network_type = DP_NETWORK_OFF; + } + int enable_cb = DP_NETWORK_OFF; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NOTIFICATION_TYPE: + { + int noti_type = DP_NOTIFICATION_TYPE_NONE; + if (requestp != NULL) { + requestp->noti_type = noti_type; + } + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, (void *)¬i_type, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NOTIFICATION_SUBJECT: + { + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + } + case DP_PROP_NOTIFICATION_DESCRIPTION: + { + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + } + case DP_PROP_NOTIFICATION_RAW: + { + int bundle_type = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type); + TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type); + char *raw_column = NULL; + if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING) + raw_column = DP_DB_COL_NOTI_RAW_ONGOING; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE) + raw_column = DP_DB_COL_NOTI_RAW_COMPLETE; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED) + raw_column = DP_DB_COL_NOTI_RAW_FAIL; + if (raw_column != NULL) { + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + } else { + TRACE_ERROR("invalid param set: %s type:%d", dp_print_property(ipc_info->property), bundle_type); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + break; + } + case DP_PROP_HTTP_HEADER: // unset value by field + { + char *header_field = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field); + if (errorcode == DP_ERROR_NONE && header_field != NULL) { + int is_present = dp_db_check_duplicated_string(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, 0, header_field, &errorcode); + if (is_present < 0) + errorcode = DP_ERROR_DISK_BUSY; + else if (is_present == 0) + errorcode = DP_ERROR_FIELD_NOT_FOUND; + else if (dp_db_cond_delete(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, header_field, 2, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s for %s", dp_print_property(ipc_info->property), header_field); + errorcode = DP_ERROR_DISK_BUSY; + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_field == NULL) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + free(header_field); + break; + } + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_UNSET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; +} + +static int __dp_call_cancel_agent(dp_request_fmt *request) +{ + int ret = -1; + if (request != NULL) { + if (request->agent_id >= 0) { + TRACE_INFO("cancel download(%d) id: %d state:%s", request->agent_id, + request->id, dp_print_state(request->state)); + if (dp_cancel_agent_download_without_update(request->agent_id) == 0) + ret = 0; + } else { + TRACE_ERROR("invalid agent-id:%d id:%d", request->agent_id, + request->id); + } + } + return ret; +} + +static int __dp_request_controls(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return DP_ERROR_INVALID_PARAMETER; + } + dp_client_fmt *client = &slot->client; + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + if (ipc_info->property == DP_PROP_CREATE) { + // check packets again + if (ipc_info->size != 0 || ipc_info->id != -1) { + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = __dp_request_create(client, ipc_info); + } + } else { + + // get now state. + int download_state = DP_STATE_NONE; + if (requestp != NULL) { + download_state = requestp->state; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) { + TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; + } + } + TRACE_DEBUG("id:%d state:%s set property:%s", ipc_info->id, dp_print_state(download_state), dp_print_property(ipc_info->property)); + + if (ipc_info->property == DP_PROP_START) { + + if (download_state == DP_STATE_COMPLETED || + download_state == DP_STATE_DOWNLOADING) { + errorcode = DP_ERROR_INVALID_STATE; + } else { + + if (requestp == NULL) { // load from databse + // check state + // load and add new request to client->requests. + } + if (requestp == NULL) { + TRACE_ERROR("failed to load id:%d from database sock:%d", ipc_info->id, client->channel); + errorcode = DP_ERROR_DISK_BUSY; + } + if (errorcode == DP_ERROR_NONE) { + // update database + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_QUEUED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + errorcode = DP_ERROR_DISK_BUSY; + } else { + requestp->state = DP_STATE_QUEUED; + requestp->error = DP_ERROR_NONE; + // if it's the first request for this client-> push a request at the head of queue. + // check count queued, connecting.downloading in requets of client + // else push at the tail of queue. + // push to queue + if (dp_queue_manager_push_queue(slot, requestp) < 0) { + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + } + requestp->state = DP_STATE_FAILED; + requestp->error = DP_ERROR_QUEUE_FULL; + errorcode = DP_ERROR_QUEUE_FULL; + } else { // push ok + dp_queue_manager_wake_up(); + // notification + if (requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0) { + TRACE_ERROR("failed to register notification for id:%d", ipc_info->id); + } + } + } + } + } + TRACE_DEBUG("id:%d check start error:%s", ipc_info->id, dp_print_errorcode(errorcode)); + } + + } else if (ipc_info->property == DP_PROP_PAUSE) { + + if (download_state > DP_STATE_DOWNLOADING) { + errorcode = DP_ERROR_INVALID_STATE; + } else { // change state regardless it's on memory or not. + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_PAUSED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + errorcode = DP_ERROR_DISK_BUSY; + } else { + // call da_pause API + if (requestp != NULL) { + // pop from queue. if state is queued. + if (requestp->state == DP_STATE_QUEUED) { + dp_queue_manager_clear_queue(requestp); + } else if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + if (dp_pause_agent_download_without_update(requestp->agent_id) < 0) { + TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id); + } + } + requestp->state = DP_STATE_PAUSED; + requestp->error = DP_ERROR_NONE; + } + } + } + + } else if (ipc_info->property == DP_PROP_CANCEL) { + + if (download_state > DP_STATE_COMPLETED) { + errorcode = DP_ERROR_INVALID_STATE; + } else { // change state regardless it's on memory or not. + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + errorcode = DP_ERROR_DISK_BUSY; + } else { + // call da_cancel API + if (requestp != NULL) { + // pop from queue. if state is queued. + if (requestp->state == DP_STATE_QUEUED) { + dp_queue_manager_clear_queue(requestp); + } else if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + if (__dp_call_cancel_agent(requestp) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id); + } + } + requestp->agent_id = -1; + requestp->state = DP_STATE_CANCELED; + requestp->error = DP_ERROR_NONE; + if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", ipc_info->id); + } + } + } + } + } + + } else if (ipc_info->property == DP_PROP_DESTROY) { + + // check state + // pop from queue. if state is queued. + if (requestp != NULL) { + if (requestp->state == DP_STATE_QUEUED) + dp_queue_manager_clear_queue(requestp); + if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + // update state property database; + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + } else { + // call da_cancel API + if (__dp_call_cancel_agent(requestp) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id); + } + } + requestp->state = DP_STATE_CANCELED; + } + if (requestp->state == DP_STATE_QUEUED || requestp->state == DP_STATE_CANCELED) { + + if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", ipc_info->id); + } + } + } + requestp->agent_id = -1; + } + errorcode = dp_request_destroy(client, ipc_info, requestp); + + } else { + errorcode = DP_ERROR_INVALID_PARAMETER; + TRACE_ERROR("invalid param - id:%d set property:%s", ipc_info->id, dp_print_property(ipc_info->property)); + } + } + + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_CONTROL, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + + // workaround. client still request the feedback by cancelation + if (ipc_info->property == DP_PROP_CANCEL || + ipc_info->property == DP_PROP_PAUSE) { + if (requestp != NULL && requestp->state_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, ipc_info->id, requestp->state, errorcode, 0) < 0) { + TRACE_ERROR("id:%d disable state callback by IO_ERROR", ipc_info->id); + requestp->state_cb = 0; + } + } + } + + return errorcode; +} + +static int __dp_client_requests(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info) +{ + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return DP_ERROR_INVALID_PARAMETER; + } + dp_client_fmt *client = &slot->client; + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + // check id except create command /////////// DP_ERROR_ID_NOT_FOUND + dp_request_fmt *requestp = NULL; + if (ipc_info->section != DP_SEC_CONTROL || + ipc_info->property != DP_PROP_CREATE) { + // check on requests + int i = 0; + requestp = client->requests; + errorcode = DP_ERROR_ID_NOT_FOUND; + for (; i < MAX_DOWNLOAD_HANDLE; i++) { + if (requestp == NULL) + break; + //TRACE_DEBUG("link %d info: id:%d access-time:%d", i, requestp->id, requestp->access_time); + if (requestp->id == ipc_info->id) { + errorcode = DP_ERROR_NONE; + break; + } + requestp = requestp->next; + } + if (errorcode == DP_ERROR_ID_NOT_FOUND) { + // check in database + if (dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_LOGGING, DP_DB_COL_ID, ipc_info->id, &errorcode) > 0) { + //TRACE_DEBUG("found %d from database", ipc_info->id); + errorcode = DP_ERROR_NONE; + } + } + } + + // Check size for prevent + if (ipc_info->size > 4294967295U) { + TRACE_ERROR("Check socket. Invalid size value. sock:%d", client->channel); + return DP_ERROR_IO_ERROR; + } + if (errorcode != DP_ERROR_NONE) { // prechecking + TRACE_ERROR("precheck errorcode:%s sock:%d id:%d section:%s property:%s", + dp_print_errorcode(errorcode), + client->channel, ipc_info->id, + dp_print_section(ipc_info->section), + dp_print_property(ipc_info->property)); + + // clear followed packets. + if (ipc_info->size > 0) { + char garbage[ipc_info->size]; + if (read(client->channel, &garbage, ipc_info->size) == 0) { + TRACE_ERROR("sock:%d closed peer", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } + } + + if (dp_ipc_query(client->channel, ipc_info->id, + ipc_info->section, ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } + return errorcode; + } + + switch (ipc_info->section) { + case DP_SEC_CONTROL: + errorcode = __dp_request_controls(slot, ipc_info, requestp); + break; + case DP_SEC_GET: + errorcode = __dp_request_get_info(client, ipc_info, requestp); + break; + case DP_SEC_SET: + errorcode = __dp_request_set_info(slot, ipc_info, requestp); + break; + case DP_SEC_UNSET: + errorcode = __dp_request_unset_info(client, ipc_info, requestp); + break; + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + return errorcode; +} + +static void __dp_client_stop_all_requests(dp_client_slots_fmt *slot) +{ + unsigned push_count = 0; + int errorcode = DP_ERROR_NONE; + int i = 0; + dp_request_fmt *tailp = slot->client.requests; + for (; tailp != NULL; i++) { + TRACE_DEBUG("request %d stop id:%d state:%s", i, tailp->id, dp_print_state(tailp->state)); + int state = tailp->state; + if (state == DP_STATE_CONNECTING) { + if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id); + } + } else if (state == DP_STATE_DOWNLOADING) { + if (dp_pause_agent_download(tailp->agent_id) < 0) { + TRACE_ERROR("failed to pause download(%d) id:%d", tailp->agent_id, tailp->id); + } + } + if (state == DP_STATE_DOWNLOADING || state == DP_STATE_CONNECTING) { + tailp->state = DP_STATE_QUEUED; + // This is error code for checking the reason when changing ip configuration process + tailp->error = DP_ERROR_IO_EAGAIN; + // push to queue now + // in da callback, check DP_ERROR_IO_EAGAIN, then ignore. + if (dp_db_update_logging(slot->client.dbhandle, tailp->id, tailp->state, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", slot->client.channel, tailp->id); + } + if (dp_queue_manager_push_queue(slot, tailp) < 0) { + TRACE_ERROR("Fail to push queueg sock:%d download-id:%d", slot->client.channel, tailp->id); + // FIXME later : error case. How can handle this item? + } else { + push_count++; + } + } + tailp = tailp->next; + } + if (push_count > 0) + dp_queue_manager_wake_up(); +} + +void dp_client_sig_handler(int signo) +{ + TRACE_INFO("thread:%0x signal:%d", pthread_self(), signo); +} + +void *dp_client_request_thread(void *arg) +{ + dp_client_slots_fmt *slot = (dp_client_slots_fmt *)arg; + if (slot == NULL) { + TRACE_ERROR("slot null, can not launch the thread for client"); + return 0; + } + + // wait detaching thread + CLIENT_MUTEX_LOCK(&slot->mutex); + + TRACE_INFO("slot %p thread:%0x", slot, slot->thread); + + struct sigaction act = {{0},}; + sigset_t newmask; + sigemptyset(&newmask); + sigaddset(&newmask, SIGUSR1); + act.sa_handler = dp_client_sig_handler; + sigaction(SIGUSR1, &act, NULL); + + fd_set imask, emask; + int errorcode = DP_ERROR_NONE; + dp_client_fmt *client = &slot->client; + int client_sock = client->channel; + struct timeval timeout; // for timeout of select + + CLIENT_MUTEX_UNLOCK(&slot->mutex); + + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + + while (slot != NULL && client_sock >= 0 && + client_sock == slot->client.channel) { + + memset(&timeout, 0x00, sizeof(struct timeval)); + timeout.tv_sec = DP_CARE_CLIENT_REQUEST_INTERVAL; + FD_ZERO(&imask ); + FD_ZERO(&emask ); + FD_SET(client_sock, &imask); + FD_SET(client_sock, &emask); + if (select(client_sock + 1, &imask, 0, &emask, &timeout) < 0 ) { + if (slot != NULL && slot->client.channel >= 0) { + TRACE_INFO("broadcast by client-manager"); + CLIENT_MUTEX_LOCK(&slot->mutex); + // check all requests + __dp_client_stop_all_requests(slot); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + continue; + } else { + TRACE_STRERROR("interrupted by client-manager sock:%d", client_sock); + break; + } + } + if (FD_ISSET(client_sock, &imask) > 0) { + + CLIENT_MUTEX_LOCK(&slot->mutex); + + if (client->dbhandle == 0 || dp_db_check_connection(client->dbhandle) < 0) { + if (dp_db_open_client(&client->dbhandle, slot->pkgname) < 0) { + TRACE_ERROR("failed to open database for sock:%d", client_sock); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + break; + } + } + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + client->access_time = (int)time(NULL); + + // read ipc_fmt first. below func will deal followed packets + dp_ipc_fmt *ipc_info = dp_ipc_get_fmt(client_sock); + if (ipc_info == NULL) { + TRACE_STRERROR("sock:%d maybe closed", client_sock); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_DEBUG("sock:%d id:%d section:%s property:%s errorcode:%s size:%d", + client_sock, ipc_info->id, + dp_print_section(ipc_info->section), + dp_print_property(ipc_info->property), + dp_print_errorcode(ipc_info->errorcode), + ipc_info->size); + + // JOB + errorcode = __dp_client_requests(slot, ipc_info); + } + free(ipc_info); + + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + + if (errorcode == DP_ERROR_IO_ERROR || + errorcode == DP_ERROR_OUT_OF_MEMORY || + errorcode == DP_ERROR_INVALID_PARAMETER) { + TRACE_ERROR("disconnect client errorcode:%s sock:%d", + dp_print_errorcode(errorcode), client_sock); + break; + } + + } else if (FD_ISSET(client_sock, &emask) > 0) { + TRACE_ERROR("[EXCEPTION]"); + break; + } else { + + // timeout + if (CLIENT_MUTEX_TRYLOCK(&slot->mutex) == 0) { + // 1. clear zombie requests. clean requests finished. paused or ready for long time + dp_client_clear_requests(slot); + + int sql_errorcode = DP_ERROR_NONE; + + // 2. maintain only 1000 rows for each client + if (dp_db_limit_rows(client->dbhandle, DP_TABLE_LOGGING, DP_LOG_DB_LIMIT_ROWS, &sql_errorcode) < 0) { + TRACE_INFO("limit rows error:%s", dp_print_errorcode(sql_errorcode)); + } + // 3. maintain for 48 hours + if (dp_db_limit_time(client->dbhandle, DP_TABLE_LOGGING, DP_CARE_CLIENT_INFO_PERIOD, &sql_errorcode) < 0) { + TRACE_INFO("limit rows error:%s", dp_print_errorcode(sql_errorcode)); + } + // 4. if no requests, exit by itself. + if (slot->client.requests == NULL) { + TRACE_DEBUG("no requests"); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + break; + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + } + + FD_CLR(client_sock, &imask); + FD_CLR(client_sock, &emask); + + // if no requests, clear slot after disconnect with client. + CLIENT_MUTEX_LOCK(&slot->mutex); + + TRACE_INFO("thread done slot %p thread:%0x sock:%d", slot, slot->thread, client_sock); + + slot->thread = 0;// to prevent kill thread twice + + int i = 0; + dp_request_fmt *tailp = slot->client.requests; + dp_request_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + if (tailp->state != DP_STATE_QUEUED && + tailp->state != DP_STATE_CONNECTING && + tailp->state != DP_STATE_DOWNLOADING) { + dp_request_fmt *removep = tailp; + if (prevp == NULL) // first request. + client->requests = tailp->next; + else + prevp->next = tailp->next; + tailp = tailp->next; + TRACE_DEBUG("request %d remove: id:%d state:%s", i, removep->id, dp_print_state(removep->state)); + dp_request_free(removep); + continue; + } + TRACE_DEBUG("request %d remain: id:%d state:%s", i, tailp->id, dp_print_state(tailp->state)); + prevp = tailp; + tailp = tailp->next; + + } + // if no requests after clear finished requests. + if (slot->client.requests == NULL) { + dp_client_slot_free(slot); + } else { + if (slot->client.notify >= 0) + close(slot->client.notify); + dp_notify_deinit(slot->credential.pid); + slot->client.notify = -1; + if (slot->client.channel > 0) + close(slot->client.channel); + slot->client.channel = -1; + } + TRACE_INFO("thread done slot %p thread:%0x sock:%d", slot, slot->thread, client_sock); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return 0; +} + diff --git a/provider/download-provider-db.c b/provider/download-provider-db.c new file mode 100755 index 0000000..d05eabd --- /dev/null +++ b/provider/download-provider-db.c @@ -0,0 +1,1322 @@ +/* + * Copyright (c) 2013 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 <string.h> +//#include <errno.h> +#include <stdio.h> +#include <stdlib.h> // alloc +//#include <unistd.h> // unlink + +#include <sqlite3.h> + +#include "download-provider.h" +#include "download-provider-db-defs.h" +#include "download-provider-db.h" +#include "download-provider-log.h" +#include "download-provider-utils.h" + + +static void __basic_property(sqlite3 *handle) +{ + if (sqlite3_exec(handle, "PRAGMA journal_mode=PERSIST;", 0, 0, 0) != SQLITE_OK) + TRACE_ERROR("check property journal_mode:PERSIST"); + if (sqlite3_exec(handle, "PRAGMA foreign_keys=ON;", 0, 0, 0) != SQLITE_OK) + TRACE_ERROR("check property foreign_keys:ON"); +} + +static void __dp_finalize(sqlite3_stmt *stmt) +{ + if (stmt != 0) { + if (sqlite3_finalize(stmt) != SQLITE_OK) { + sqlite3 *handle = sqlite3_db_handle(stmt); + TRACE_ERROR("sqlite3_finalize:%s", sqlite3_errmsg(handle)); + } + } +} + +static int __check_table(sqlite3 *handle, char *table) +{ + sqlite3_stmt *stmt = NULL; + + if (handle == 0 || table == NULL) { + TRACE_ERROR("check handle or table:%s", table); + return -1; + } + + char *query = sqlite3_mprintf("SELECT name FROM sqlite_master WHERE type='table' AND name='%s'", table); + if (query == NULL) { + TRACE_ERROR("failed to make query statement"); + return -1; + } + int ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + int result = 0; + if (ret != SQLITE_OK) { + TRACE_ERROR("sqlite3_prepare:%s", sqlite3_errmsg(handle)); + result = -1; + } + if (result == 0 && sqlite3_step(stmt) != SQLITE_ROW) { + TRACE_DEBUG("not found table:%s", table); + result = -1; + } + __dp_finalize(stmt); + return result; +} + +static int __rebuild_client_tables(sqlite3 *handle) +{ + int ret = SQLITE_OK; + + if (__check_table(handle, DP_TABLE_LOGGING) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_LOGGING, 0, 0, 0); + if (ret == SQLITE_OK) { + ret = sqlite3_exec(handle, DP_SCHEMA_LOGGING_INDEX, 0, 0, 0); + } + } + if (ret == SQLITE_OK && __check_table(handle, DP_TABLE_DOWNLOAD) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_DOWNLOAD, 0, 0, 0); + } + if (ret == SQLITE_OK && __check_table(handle, DP_TABLE_REQUEST) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_REQUEST, 0, 0, 0); + } + if (ret == SQLITE_OK && __check_table(handle, DP_TABLE_HEADERS) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_HEADER, 0, 0, 0); + } + if (ret == SQLITE_OK && __check_table(handle, DP_TABLE_NOTIFICATION) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_NOTIFICATION, 0, 0, 0); + } + if (ret != SQLITE_OK) { + TRACE_ERROR("create tables:%d error:%s", ret, sqlite3_errmsg(handle)); + return -1; + } + return 0; +} + +static int __rebuild_client_manager_tables(sqlite3 *handle) +{ + int ret = SQLITE_OK; + if (__check_table(handle, DP_TABLE_CLIENTS) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_CLIENTS, 0, 0, 0); + } + if (ret != SQLITE_OK) { + TRACE_ERROR("create tables:%d error:%s", ret, sqlite3_errmsg(handle)); + return -1; + } + return 0; +} + +static int __db_open(sqlite3 **handle, char *database) +{ + if (sqlite3_open_v2(database, handle, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) { + int errorcode = sqlite3_errcode(*handle); + TRACE_ERROR("error(%d):%s", errorcode, sqlite3_errmsg(*handle)); + *handle = 0; + if (errorcode == SQLITE_CORRUPT) { // remove & re-create + TRACE_SECURE_INFO("unlink [%s]", database); + unlink(database); + errorcode = SQLITE_CANTOPEN; + } + if (errorcode == SQLITE_CANTOPEN) { + // create empty database + if (sqlite3_open(database, handle) != SQLITE_OK ) { + TRACE_SECURE_INFO("failed to connect:%s", database); + unlink(database); + *handle = 0; + return -1; + } + } else { + TRACE_ERROR("can not handle this error:%d", errorcode); + *handle = 0; + return -1; + } + } + __basic_property(*handle); + return 0; +} + +int dp_db_check_connection(void *handle) +{ + if (handle == 0) { + TRACE_ERROR("connection handler is null"); + return -1; + } + int phighwater = 0; + int pcur = 0; + int ret = sqlite3_db_status(handle, SQLITE_DBSTATUS_STMT_USED, &pcur, &phighwater, 0); + if (ret != SQLITE_OK) { + TRACE_INFO("sql(%p) error:%d, used memory:%d, highwater:%d", handle, ret, pcur, phighwater); + return -1; + } + return 0; +} + +int dp_db_open_client_manager(void **handle) +{ + if (*handle == 0) { + char *database = sqlite3_mprintf("%s/%s", DATABASE_DIR, DP_DBFILE_CLIENTS); + if (database == NULL) { + TRACE_ERROR("failed to make clients database file path"); + return -1; + } + if (__db_open((sqlite3 **)handle, database) < 0) { + TRACE_ERROR("failed to open %s", database); + *handle = 0; + } else { + // whenever open new handle, check all tables. it's simple + if (__rebuild_client_manager_tables(*handle) < 0) { + dp_db_close(*handle); + *handle = 0; + } + } + sqlite3_free(database); + } + return *handle ? 0 : -1; +} + +static char *__dp_db_get_client_db_path(char *pkgname) +{ + if (pkgname == NULL) + return NULL; + return sqlite3_mprintf("%s/clients/.%s", DATABASE_DIR, pkgname); +} + +// 0 : remove, -1: error or skip by diff_time +int dp_db_remove_database(char *pkgname, long now_time, long diff_time) +{ + // get file name + char *database = __dp_db_get_client_db_path(pkgname); + if (database == NULL) { + TRACE_ERROR("failed to make db file path"); + return -1; + } + int result = -1; + // get modified time of database file. + long modified_time = dp_get_file_modified_time(database); + if (modified_time >= now_time) { + TRACE_ERROR("check system timezone %ld vs %ld", modified_time, now_time); + } else if ((now_time - modified_time) > diff_time) { + char *database_journal = sqlite3_mprintf("%s-journal", database); + if (database_journal == NULL) { + TRACE_ERROR("failed to make db journal file path"); + } else { + if (dp_remove_file(database_journal) < 0) { + TRACE_ERROR("failed to remove db journal file path"); + } else { + if (dp_remove_file(database) < 0) { + TRACE_ERROR("failed to remove db file path"); + } else { + result = 0; + } + } + sqlite3_free(database_journal); + } + } + sqlite3_free(database); + return result; +} + +int dp_db_open_client_v2(void **handle, char *pkgname) +{ + char *database = __dp_db_get_client_db_path(pkgname); + if (database == NULL) { + TRACE_ERROR("failed to make db file path"); + return -1; + } + if (sqlite3_open_v2(database, (sqlite3 **)handle, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) { + int errorcode = sqlite3_errcode(*handle); + TRACE_ERROR("error(%d):%s", errorcode, sqlite3_errmsg(*handle)); + *handle = 0; + sqlite3_free(database); + return -1; + } + sqlite3_free(database); + __basic_property(*handle); + return 0; +} + +int dp_db_open_client(void **handle, char *pkgname) +{ + if (*handle == 0) { + char *database = __dp_db_get_client_db_path(pkgname); + if (database == NULL) { + TRACE_ERROR("failed to make db file path"); + return -1; + } + if (__db_open((sqlite3 **)handle, database) < 0) { + TRACE_SECURE_ERROR("failed to open %s", database); + *handle = 0; + } else { + // whenever open new handle, check all tables. it's simple + if (__rebuild_client_tables(*handle) < 0) { + dp_db_close(*handle); + *handle = 0; + } + } + sqlite3_free(database); + } + return *handle ? 0 : -1; +} + +void dp_db_close(void *handle) +{ + if (handle != 0) { + // remove empty page of db + //sqlite3_exec(handle, "VACUUM;", 0, 0, 0); + if (sqlite3_close((sqlite3 *)handle) != SQLITE_OK) + TRACE_ERROR("check sqlite close"); + } +} + +void dp_db_reset(void *stmt) +{ + if (stmt != 0) { + sqlite3_stmt *stmtp = stmt; + sqlite3_clear_bindings(stmtp); + if (sqlite3_reset(stmtp) != SQLITE_OK) { + sqlite3 *handle = sqlite3_db_handle(stmtp); + TRACE_ERROR("reset:%s", sqlite3_errmsg(handle)); + } + } +} + +void dp_db_finalize(void *stmt) +{ + __dp_finalize((sqlite3_stmt *)stmt); +} + +int dp_db_get_errorcode(void *handle) +{ + if (handle == 0) { + TRACE_ERROR("check connection handle"); + return DP_ERROR_DISK_BUSY; + } + int errorcode = sqlite3_errcode((sqlite3 *)handle); + if (errorcode == SQLITE_FULL) { + TRACE_ERROR("SQLITE_FULL-NO_SPACE"); + return DP_ERROR_NO_SPACE; + } else if (errorcode == SQLITE_TOOBIG || + errorcode == SQLITE_LOCKED || errorcode == SQLITE_BUSY) { + TRACE_ERROR("DISK_BUSY %s", sqlite3_errmsg((sqlite3 *)handle)); + return DP_ERROR_DISK_BUSY; + } + return DP_ERROR_NONE; +} + + +#define DP_DB_PARAM_NULL_CHECK do {\ + if (handle == 0) {\ + TRACE_ERROR("check connection handle");\ + return -1;\ + }\ +} while(0) + +#define DP_DB_BUFFER_NULL_CHECK(buffer) do {\ + if (buffer == NULL) {\ + TRACE_ERROR("check available memory");\ + return -1;\ + }\ +} while(0) + +#define DP_DB_BASIC_EXCEPTION_CHECK do {\ + if (errorcode != SQLITE_OK) {\ + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE)\ + *error = DP_ERROR_INVALID_PARAMETER;\ + __dp_finalize(stmt);\ + return -1;\ + }\ +} while(0) + +#define DP_DB_WRITE_STEP_EXCEPTION_CHECK do {\ + errorcode = sqlite3_step(stmt);\ + __dp_finalize(stmt);\ + if (errorcode != SQLITE_DONE) {\ + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE)\ + *error = DP_ERROR_INVALID_PARAMETER;\ + return -1;\ + }\ +} while(0) + +int dp_db_get_ids(void *handle, const char *table, char *idcolumn, int *ids, const char *where, const int limit, char *ordercolumn, char *ordering, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + int errorcode = SQLITE_OK; + int rows_count = 0; + sqlite3_stmt *stmt = NULL; + + char *order_query = NULL; + if (ordercolumn != NULL) + order_query = sqlite3_mprintf("ORDER BY %s %s", ordercolumn, ( ordering == NULL ? "ASC" : ordering )); + + if (idcolumn == NULL) + idcolumn = DP_DB_COL_ID; + + char *query = sqlite3_mprintf("SELECT %s FROM %s %s %s LIMIT ?", idcolumn, table, ( where == NULL ? "" : where ), ( order_query == NULL ? "" : order_query )); + DP_DB_BUFFER_NULL_CHECK(query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + //TRACE_DEBUG("debug query:%s", query); + sqlite3_free(query); + if (order_query != NULL) + sqlite3_free(order_query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, limit); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { + if (sqlite3_column_type(stmt, 0) == SQLITE_INTEGER) { + int columnvalue = sqlite3_column_int(stmt, 0); + //TRACE_DEBUG("id(%d):%d", rows_count, columnvalue); + ids[rows_count++] = columnvalue; + } + } + __dp_finalize(stmt); + return rows_count; +} + +int dp_db_get_crashed_ids(void *handle, const char *table, int *ids, const int limit, int *error) +{ + // make where. + //get ids if state is QUEUED, CONNECTING or DOWNLOADING with auto_download + char *where = sqlite3_mprintf("WHERE %s IS 1 AND (%s IS %d OR %s IS %d OR %s IS %d)", + DP_DB_COL_AUTO_DOWNLOAD, + DP_DB_COL_STATE, DP_STATE_DOWNLOADING, + DP_DB_COL_STATE, DP_STATE_CONNECTING, + DP_DB_COL_STATE, DP_STATE_QUEUED); + if (where != NULL) { + int rows_count = dp_db_get_ids(handle, table, DP_DB_COL_ID, ids, where, limit, NULL, NULL, error); + sqlite3_free(where); + return rows_count; + } + *error = DP_ERROR_OUT_OF_MEMORY; + return -1; +} + + +int dp_db_check_duplicated_int(void *handle, const char *table, const char *column, const int value, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + int errorcode = SQLITE_OK; + int count = 0; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT count(*) FROM %s WHERE %s IS ?", table, column); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, value); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_ROW) { + count = sqlite3_column_int(stmt, 0); + } else { + count = 0; + } + __dp_finalize(stmt); + return count; +} + +int dp_db_check_duplicated_string(void *handle, const int id, const char *table, const char *column, int is_like, const char *value, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + int errorcode = SQLITE_OK; + int count = 0; + sqlite3_stmt *stmt = NULL; + + char *id_check = NULL; + if (id >= 0) { + id_check = sqlite3_mprintf("AND %s IS ?", DP_DB_COL_ID); + } + char *query = NULL; + if (is_like > 0) + query = sqlite3_mprintf("SELECT count(*) FROM %s WHERE %s LIKE ? %s", table, column, (id_check == NULL ? "" : id_check)); + else + query = sqlite3_mprintf("SELECT count(*) FROM %s WHERE %s %s ? %s", table, column, (is_like == 0 ? "IS" : "IS NOT"), (id_check == NULL ? "" : id_check)); + if (id_check != NULL) + sqlite3_free(id_check); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_text(stmt, 1, value, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + if (id >= 0) { + errorcode = sqlite3_bind_int(stmt, 2, id); + DP_DB_BASIC_EXCEPTION_CHECK; + } + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_ROW) { + count = sqlite3_column_int(stmt, 0); + } else { + count = 0; + } + __dp_finalize(stmt); + return count; +} + +int dp_db_update_client_info(void *handle, const char *pkgname, const char *smack, const int uid, const int gid, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (pkgname == NULL) { + TRACE_ERROR("check pkgname"); + return -1; + } + + int is_update = dp_db_check_duplicated_string(handle, -1, DP_TABLE_CLIENTS, DP_DB_COL_PACKAGE, 0, pkgname, error); + if (is_update < 0) { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_DISK_BUSY; + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = NULL; + + if (is_update == 0) + query = sqlite3_mprintf( + "INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s) VALUES (?, ?, %d, %d, 0, DATETIME('NOW'), DATETIME('NOW'))", + DP_TABLE_CLIENTS, DP_DB_COL_SMACK_LABEL, DP_DB_COL_PACKAGE, DP_DB_COL_UID, + DP_DB_COL_GID, DP_DB_COL_REQUEST_COUNT, + DP_DB_COL_CREATE_TIME, DP_DB_COL_ACCESS_TIME, uid, gid); + else + query = sqlite3_mprintf("UPDATE %s SET %s = ?, %s = %d, %s = %d, %s = DATETIME('NOW') WHERE %s IS ?", + DP_TABLE_CLIENTS, DP_DB_COL_SMACK_LABEL, DP_DB_COL_UID, + uid, DP_DB_COL_GID, gid, DP_DB_COL_ACCESS_TIME, DP_DB_COL_PACKAGE); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + if (smack != NULL) { + errorcode = sqlite3_bind_text(stmt, 1, smack, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + } + errorcode = sqlite3_bind_text(stmt, 2, pkgname, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_get_client_property_string(void *handle, const char *pkgname, const char *column, unsigned char **value, unsigned *length, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (pkgname == NULL || column == NULL || value == NULL || length == NULL) { + TRACE_ERROR("check materials for query"); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s IS ? LIMIT 1", column, DP_TABLE_CLIENTS, DP_DB_COL_PACKAGE); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_text(stmt, 1, pkgname, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + *length = 0; + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_TEXT) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes + 1, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_text(stmt, 0), getbytes * sizeof(unsigned char)); + getstr[getbytes] = '\0'; + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + } else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else { + TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_ROW) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; + } + __dp_finalize(stmt); + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; +} + +int dp_db_new_logging(void *handle, const int id, const int state, const int errorvalue, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + + char *query = sqlite3_mprintf("INSERT INTO %s (%s, %s, %s, %s, %s) VALUES (?, ?, ?, DATETIME('now'), DATETIME('now'))", + DP_TABLE_LOGGING, DP_DB_COL_ID, DP_DB_COL_STATE, + DP_DB_COL_ERRORCODE, DP_DB_COL_CREATE_TIME, DP_DB_COL_ACCESS_TIME); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 2, state); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 3, errorvalue); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_update_logging(void *handle, const int id, const int state, const int errorvalue, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + + char *query = sqlite3_mprintf("UPDATE %s SET %s = ?, %s = ?, %s = DATETIME('now') WHERE %s = ?", + DP_TABLE_LOGGING, DP_DB_COL_STATE, DP_DB_COL_ERRORCODE, + DP_DB_COL_ACCESS_TIME, DP_DB_COL_ID); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, state); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 2, errorvalue); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 3, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +// 0:integer, 1:bigint, 2:string, 3:blob +int dp_db_replace_property(void *handle, const int id, const char *table, const char *column, const void *value, const unsigned length, const unsigned valuetype, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (table == NULL || column == NULL || value == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int is_update = dp_db_check_duplicated_int(handle, table, DP_DB_COL_ID, id, error); + if (is_update < 0) { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_DISK_BUSY; + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = NULL; + + if (is_update == 0) + query = sqlite3_mprintf("INSERT INTO %s (%s, %s) VALUES (?, ?)", table, column, DP_DB_COL_ID); + else + query = sqlite3_mprintf("UPDATE %s SET %s = ? WHERE %s IS ?", table, column, DP_DB_COL_ID); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + if (valuetype == 0) { + int *cast_value = (int *)value; + errorcode = sqlite3_bind_int(stmt, 1, *cast_value); + } else if (valuetype == 1) { + sqlite_int64 *cast_value = (sqlite_int64 *)value; + errorcode = sqlite3_bind_int64(stmt, 1, *cast_value); + } else if (valuetype == 2) { + errorcode = sqlite3_bind_text(stmt, 1, (char *)value, -1, SQLITE_STATIC); + } else if (valuetype == 3) { + errorcode = sqlite3_bind_blob(stmt, 1, value, (int)length, NULL); + } else { + TRACE_ERROR("invalid type:%d", valuetype); + __dp_finalize(stmt); + return -1; + } + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 2, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_get_property_string(void *handle, const int id, const char *table, const char *column, unsigned char **value, unsigned *length, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (table == NULL || column == NULL || value == NULL || length == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s = ? LIMIT 1", column, table, DP_DB_COL_ID); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + *length = 0; + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_TEXT) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes + 1, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_text(stmt, 0), getbytes * sizeof(unsigned char)); + getstr[getbytes] = '\0'; + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + } else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else if (data_type == SQLITE_BLOB) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_blob(stmt, 0), getbytes * sizeof(unsigned char)); + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + }else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else { + //TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_ROW) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; + } + __dp_finalize(stmt); + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; +} + +int dp_db_get_property_int(void *handle, const int id, const char *table, const char *column, void *value, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (table == NULL || column == NULL || value == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s = ? LIMIT 1", column, table, DP_DB_COL_ID); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_INTEGER) { + int recv_int = sqlite3_column_int(stmt, 0); + int *pvalue = value; + *pvalue = recv_int; + } else if (data_type == SQLITE_FLOAT) { + unsigned long long recv_int = sqlite3_column_int64(stmt, 0); + unsigned long long *pvalue = value; + *pvalue = recv_int; + } else { + TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_DONE) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; + } + __dp_finalize(stmt); + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; +} + +int dp_db_unset_property_string(void *handle, const int id, const char *table, const char *column, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (table == NULL || column == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int is_update = dp_db_check_duplicated_int(handle, table, DP_DB_COL_ID, id, error); + if (is_update < 0) { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_DISK_BUSY; + return -1; + } else if (is_update == 0) { + *error = DP_ERROR_ID_NOT_FOUND; + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("UPDATE %s SET %s = NULL WHERE %s IS ?", table, column, DP_DB_COL_ID); + + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +// "DELETE FROM %s WHERE %s NOT IN (SELECT %s FROM %s ORDER BY %s %s LIMIT %d)" +int dp_db_delete(void *handle, const int id, const char *table, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (table == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int is_update = dp_db_check_duplicated_int(handle, table, DP_DB_COL_ID, id, error); + if (is_update < 0) { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_DISK_BUSY; + return -1; + } else if (is_update == 0) { + *error = DP_ERROR_ID_NOT_FOUND; + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("DELETE FROM %s WHERE %s IS ?", table, DP_DB_COL_ID); + + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_new_header(void *handle, const int id, const char *field, const char *value, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (field == NULL) { + TRACE_ERROR("check field:%s", field); + return -1; + } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + + char *query = sqlite3_mprintf("INSERT INTO %s (%s, %s, %s) VALUES (?, ?, ?)", + DP_TABLE_HEADERS, DP_DB_COL_ID, DP_DB_COL_HEADER_FIELD, + DP_DB_COL_HEADER_DATA); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_text(stmt, 2, (char *)field, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_text(stmt, 3, (char *)value, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_update_header(void *handle, const int id, const char *field, const char *value, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + + char *query = sqlite3_mprintf("UPDATE %s SET %s = ? WHERE %s IS ? AND %s IS ?", + DP_TABLE_HEADERS, DP_DB_COL_HEADER_DATA, + DP_DB_COL_ID, DP_DB_COL_HEADER_FIELD); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_text(stmt, 1, (char *)value, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 2, id); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_text(stmt, 2, (char *)field, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_get_header_value(void *handle, const int id, const char *field, unsigned char **value, unsigned *length, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (field == NULL || value == NULL || length == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s IS ? AND %s IS ? LIMIT 1", DP_DB_COL_HEADER_DATA, DP_TABLE_HEADERS, DP_DB_COL_ID, DP_DB_COL_HEADER_FIELD); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_text(stmt, 2, (char *)field, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + *length = 0; + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_TEXT) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes + 1, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_text(stmt, 0), getbytes * sizeof(unsigned char)); + getstr[getbytes] = '\0'; + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + } else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else { + TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_ROW) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; + } + __dp_finalize(stmt); + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; +} + +// not supprot blob as column & value for additional condition +int dp_db_cond_delete(void *handle, const int id, const char *table, const char *column, const void *value, const unsigned valuetype, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (table == NULL || column == NULL || value == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("DELETE FROM %s WHERE %s IS ? AND %s IS ?", table, DP_DB_COL_ID, column); + + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + if (valuetype == 0) { + int *cast_value = (int *)value; + errorcode = sqlite3_bind_int(stmt, 2, *cast_value); + } else if (valuetype == 1) { + sqlite_int64 *cast_value = (sqlite_int64 *)value; + errorcode = sqlite3_bind_int64(stmt, 2, *cast_value); + } else if (valuetype == 2) { + errorcode = sqlite3_bind_text(stmt, 2, (char *)value, -1, SQLITE_STATIC); + } + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_get_cond_ids(void *handle, const char *table, const char *getcolumn, const char *column, const int value, int *ids, const int limit, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + int errorcode = SQLITE_OK; + int rows_count = 0; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s IS ?", getcolumn, table, column); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, value); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { + if (sqlite3_column_type(stmt, 0) == SQLITE_INTEGER) { + int columnvalue = sqlite3_column_int(stmt, 0); + //TRACE_DEBUG("id(%d):%d", rows_count, columnvalue); + ids[rows_count++] = columnvalue; + } + } + __dp_finalize(stmt); + return rows_count; +} + +int dp_db_get_cond_string(void *handle, const char *table, char *wherecolumn, const int wherevalue, const char *getcolumn, unsigned char **value, unsigned *length, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (table == NULL || getcolumn == NULL || value == NULL || length == NULL) { + TRACE_ERROR("check materials for query"); + return -1; + } + + if (wherecolumn == NULL) + wherecolumn = DP_DB_COL_ID; + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s = ? LIMIT 1", getcolumn, table, wherecolumn); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, wherevalue); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + *length = 0; + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_TEXT) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes + 1, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_text(stmt, 0), getbytes * sizeof(unsigned char)); + getstr[getbytes] = '\0'; + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + } else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else if (data_type == SQLITE_BLOB) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_blob(stmt, 0), getbytes * sizeof(unsigned char)); + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + }else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else { + TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_ROW) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; + } + __dp_finalize(stmt); + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; +} + +int dp_db_limit_rows(void *handle, const char *table, int limit, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (table == NULL) { + TRACE_ERROR("check materials for query"); + return -1; + } + if (limit < 0) { + TRACE_ERROR("check limitation:%d", limit); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("DELETE FROM %s WHERE %s NOT IN (SELECT %s FROM %s ORDER BY %s ASC LIMIT ?)", table, DP_DB_COL_ID, DP_DB_COL_ID, table, DP_DB_COL_CREATE_TIME); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, limit); + DP_DB_BASIC_EXCEPTION_CHECK; + + // apply "ON DELETE CASCADE" + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_limit_time(void *handle, const char *table, int hours, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (table == NULL) { + TRACE_ERROR("check materials for query"); + return -1; + } + if (hours <= 0) { + TRACE_ERROR("check limit time:%d", hours); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("DELETE FROM %s WHERE %s < DATETIME('now','-%d hours')", table, DP_DB_COL_CREATE_TIME, hours); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_get_http_headers_list(void *handle, int id, char **headers, int *error) +{ + int errorcode = SQLITE_OK; + int headers_index = 0; + sqlite3_stmt *stmt = NULL; + *error = DP_ERROR_NONE; + DP_DB_PARAM_NULL_CHECK; + + if (id <= 0) { + TRACE_ERROR("[CHECK ID]"); + *error = DP_ERROR_INVALID_PARAMETER; + return -1; + } + + errorcode = + sqlite3_prepare_v2(handle, + "SELECT header_field, header_data FROM header WHERE id = ?", + -1, &stmt, NULL); + + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + + DP_DB_BASIC_EXCEPTION_CHECK; + + while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { + int buffer_length = 0; + char *header_field = (char *)(sqlite3_column_text(stmt, 0)); + char *header_data = (char *)(sqlite3_column_text(stmt, 1)); + + // REF : http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 + buffer_length = strlen(header_field) + strlen(header_data) + 1; + char *headers_buffer = calloc(buffer_length + 1, sizeof(char)); + if (headers_buffer == NULL) { + TRACE_ERROR("[CALLOC] headers_buffer"); + continue; + } + int len = snprintf(headers_buffer, buffer_length + 1, + "%s:%s", header_field, header_data); + if (len <= 0) { + if (headers_buffer) + free(headers_buffer); + continue; + } else { + headers_buffer[len] = '\0'; + } + headers[headers_index++] = headers_buffer; + } + + __dp_finalize(stmt); + + return headers_index; +} + diff --git a/provider/download-provider-ipc.c b/provider/download-provider-ipc.c new file mode 100644 index 0000000..e79a6f7 --- /dev/null +++ b/provider/download-provider-ipc.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2013 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 <stdio.h> +#include <stdlib.h> + +#include <time.h> + +#include <sys/socket.h> // shutdown + +#include "download-provider-log.h" +#include "download-provider-ipc.h" + +int dp_ipc_check_stderr(int basecode) +{ + int errorcode = basecode; + if (errno == EPIPE) { + TRACE_STRERROR("[EPIPE:%d] Broken Pipe", errno); + errorcode = DP_ERROR_IO_ERROR; + } else if (errno == EAGAIN) { + TRACE_STRERROR("[EAGAIN:%d]", errno); + errorcode = DP_ERROR_IO_EAGAIN; + } else if (errno == EINTR) { + TRACE_STRERROR("[EINTR:%d]", errno); + errorcode = DP_ERROR_IO_EINTR; + } else if (errno == ENOENT) { + TRACE_STRERROR("[ENOENT:%d]", errno); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_STRERROR("[errno:%d]", errno); + } + return errorcode; +} + +int dp_ipc_write(int sock, void *value, size_t type_size) +{ + if (sock < 0) { + TRACE_ERROR("[ERROR] check sock:%d", sock); + return -1; + } else if (value == NULL) { + TRACE_ERROR("[ERROR] check buffer sock:%d", sock); + return -1; + } else if (write(sock, value, type_size) <= 0) { + TRACE_STRERROR("[IPC.Write] exception sock:%d", sock); + return -1; + } + return 0; +} + +ssize_t dp_ipc_read(int sock, void *value, size_t type_size, + const char *func) +{ + int errorcode = DP_ERROR_NONE; + ssize_t recv_bytes = 0; + + if (sock < 0) { + TRACE_ERROR("[ERROR] %s check sock:%d", func, sock); + return -1; + } + if (value == NULL) { + TRACE_ERROR("[ERROR] %s check buffer sock:%d", func, sock); + return -1; + } + + int tryagain = 3; + do { + errorcode = DP_ERROR_NONE; + recv_bytes = read(sock, value, type_size); + if (recv_bytes < 0) { + TRACE_ERROR("[IPC.Read] %s exception sock:%d", func, sock); + errorcode = dp_ipc_check_stderr(DP_ERROR_IO_ERROR); + } else if (recv_bytes == 0) { + TRACE_ERROR("[ERROR] %s closed peer sock:%d", func, sock); + errorcode = DP_ERROR_IO_ERROR; + } + } while (sock >= 0 && (errorcode == DP_ERROR_IO_EAGAIN || + errorcode == DP_ERROR_IO_EINTR) && (--tryagain > 0)); + return recv_bytes; +} + +dp_ipc_fmt *dp_ipc_get_fmt(int sock) +{ + dp_ipc_fmt *ipc_info = malloc(sizeof(dp_ipc_fmt)); + if (ipc_info == NULL) { + TRACE_ERROR("[ERROR] Fail to malloc"); + return NULL; + } + memset(ipc_info, 0x00, sizeof(dp_ipc_fmt)); + ssize_t recv_size = read(sock, ipc_info, sizeof(dp_ipc_fmt)); + if (recv_size <= 0 || recv_size != sizeof(dp_ipc_fmt)) { + TRACE_STRERROR("socket read ipcinfo read size:%d", recv_size); + free(ipc_info); + return NULL; + } + return ipc_info; +} + +int dp_ipc_query(int sock, int download_id, short section, + unsigned property, int error, size_t size) +{ + dp_ipc_fmt ipc_info; + memset(&ipc_info, 0x00, sizeof(dp_ipc_fmt)); + ipc_info.section = section; + ipc_info.property = property; + ipc_info.id = download_id; + ipc_info.errorcode = error; + ipc_info.size = size; + if (dp_ipc_write(sock, &ipc_info, sizeof(dp_ipc_fmt)) < 0) + return -1; + return 0; +} + +int dp_ipc_socket_free(int sockfd) +{ + if (sockfd < 0) + return -1; + close(sockfd); + return 0; +} diff --git a/provider/download-provider-main.c b/provider/download-provider-main.c new file mode 100755 index 0000000..ded45db --- /dev/null +++ b/provider/download-provider-main.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012 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 <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <pthread.h> + +#include <systemd/sd-daemon.h> +#include <glib-object.h> + +#include "download-provider-config.h" +#include "download-provider-log.h" +#include "download-provider-client-manager.h" +#include "download-provider-network.h" + +void *dp_client_manager(void *arg); + +int main(int argc, char **argv) +{ + GMainLoop *event_loop; + pthread_t tid; + TRACE_INFO("download-provider's working is started"); + + g_type_init(); + + event_loop = g_main_loop_new(NULL, FALSE); + if (!event_loop) { + TRACE_ERROR("Failed to create g main loop handle"); + return 0; + } + // check network status + if (dp_network_connection_init() < 0) { + TRACE_ERROR("failed to init network-manager"); + return 0; + } + // create a thread for main thread + if (pthread_create(&tid, NULL, dp_client_manager, (void *)event_loop) != 0) { + TRACE_ERROR("failed to create main thread"); + return 0; + } else { + pthread_detach(tid); + TRACE_INFO("download main thread is created[%lu]", tid); + } + + TRACE_INFO("g main loop is started"); + g_main_loop_run(event_loop); + dp_network_connection_destroy(); + g_main_loop_unref(event_loop); + + TRACE_INFO("download-provider's working is done"); + return 0; +} diff --git a/provider/download-provider-network.c b/provider/download-provider-network.c new file mode 100755 index 0000000..5fafe2c --- /dev/null +++ b/provider/download-provider-network.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2012 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 "download-provider.h" +#include "download-provider-log.h" +#include "download-provider-pthread.h" +#include "download-provider-network.h" +#include "download-provider-client-manager.h" + +#include <net_connection.h> + +#ifdef SUPPORT_WIFI_DIRECT +#include <wifi-direct.h> +#endif + +pthread_mutex_t g_dp_network_mutex = PTHREAD_MUTEX_INITIALIZER; +int g_network_status = DP_NETWORK_OFF; +connection_h g_network_connection = 0; +int g_network_is_wifi_direct = 0; + +#ifdef SUPPORT_COMPANION_MODE +// support B3 companion mode +#include "vconf.h" +#include "vconf-keys.h" +#include "SAPInterface.h" +#define VCONFKEY_SAP_CONNECTION_NOTIFICATION VCONFKEY_WMS_WMANAGER_CONNECTED +#define VCONFKEY_SAP_CONNECTION_TYPE "memory/private/sap/conn_type" +#endif + +static int __dp_network_is_companion_mode() +{ +#ifdef SUPPORT_COMPANION_MODE + int wms_connected = 0; + int companion_mode = 0; + vconf_get_int(VCONFKEY_SAP_CONNECTION_NOTIFICATION, &wms_connected); + vconf_get_int(VCONFKEY_SAP_CONNECTION_TYPE, &companion_mode); + TRACE_INFO("wms_connected:%d, companion_mode:%d", wms_connected, companion_mode); + if (wms_connected == 1 && (companion_mode & SAP_BT)) + return 1; + +#endif + return 0; +} + +#ifdef SUPPORT_WIFI_DIRECT + +static int __dp_network_wifi_direct_status() +{ + int is_connected = 0; + wifi_direct_state_e wifi_state = WIFI_DIRECT_STATE_DEACTIVATED; + if (wifi_direct_get_state(&wifi_state) == 0) { + if (wifi_state == WIFI_DIRECT_STATE_CONNECTED) { + TRACE_INFO("WIFI_DIRECT_STATE_CONNECTED"); + is_connected = 1; + } + } + return is_connected; +} + +// support WIFI-Direct +static void __dp_network_wifi_direct_changed_cb + (wifi_direct_error_e error_code, + wifi_direct_connection_state_e connection_state, + const char *mac_address, void *data) +{ + pthread_mutex_lock(&g_dp_network_mutex); + if (connection_state == WIFI_DIRECT_CONNECTION_RSP) { + TRACE_INFO("WIFI_DIRECT_CONNECTION_RSP"); + g_network_is_wifi_direct = __dp_network_wifi_direct_status(); + } else { + TRACE_INFO("WIFI_DIRECT_DISCONNECTION"); + g_network_is_wifi_direct = 0; + } + pthread_mutex_unlock(&g_dp_network_mutex); +} +#endif + +////////////////////////////////////////////////////////////////////////// +/// @brief check the status in more detail by connection type +/// @return dp_network_type +static int __dp_get_network_connection_status(connection_h connection, connection_type_e type) +{ + int network_type = DP_NETWORK_OFF; + if (__dp_network_is_companion_mode() == 1) { + network_type = DP_NETWORK_ALL; + TRACE_INFO("COMPANION MODE"); + } else if (type == CONNECTION_TYPE_WIFI) { + connection_wifi_state_e wifi_state; + wifi_state = CONNECTION_WIFI_STATE_DEACTIVATED; + if (connection_get_wifi_state(connection, &wifi_state) != + CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_get_wifi_state"); + } else { + if (wifi_state == CONNECTION_WIFI_STATE_CONNECTED) { + TRACE_INFO("WIFI CONNECTED"); + network_type = DP_NETWORK_WIFI; + } + } + } else if (type == CONNECTION_TYPE_CELLULAR) { + connection_cellular_state_e cellular_state; + cellular_state = CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE; + if (connection_get_cellular_state(connection, + &cellular_state) != CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_get_cellular_state"); + } else { + if (cellular_state == CONNECTION_CELLULAR_STATE_CONNECTED) { + TRACE_INFO("DATA NETWORK CONNECTED"); + network_type = DP_NETWORK_DATA_NETWORK; + } + } + } else if (type == CONNECTION_TYPE_ETHERNET) { + connection_ethernet_state_e ethernet_state; + ethernet_state = CONNECTION_ETHERNET_STATE_DISCONNECTED; + if (connection_get_ethernet_state(connection, + ðernet_state) != CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_get_ethernet_state"); + } else { + if (ethernet_state == CONNECTION_ETHERNET_STATE_CONNECTED) { + TRACE_INFO("ETHERNET CONNECTED"); + network_type = DP_NETWORK_WIFI; + } + } + } else { + TRACE_INFO("DISCONNECTED"); + network_type = DP_NETWORK_OFF; + } + g_network_status = network_type; + return network_type; +} + +////////////////////////////////////////////////////////////////////////// +/// @brief [callback] called whenever changed network status +/// @todo care requests by network status +static void __dp_network_connection_type_changed_cb(connection_type_e type, void *data) +{ + pthread_mutex_lock(&g_dp_network_mutex); + // this callback guarantee that already connected + if (__dp_network_is_companion_mode() == 1) { + TRACE_INFO("COMPANION MODE"); + g_network_status = DP_NETWORK_ALL; + } else if (type == CONNECTION_TYPE_WIFI) { + TRACE_INFO("WIFI CONNECTED"); + g_network_status = DP_NETWORK_WIFI; + } else if (type == CONNECTION_TYPE_CELLULAR) { + TRACE_INFO("DATA NETWORK CONNECTED"); + g_network_status = DP_NETWORK_DATA_NETWORK; + } else if (type == CONNECTION_TYPE_ETHERNET) { + TRACE_INFO("ETHERNET CONNECTED"); + g_network_status = DP_NETWORK_WIFI; + } else { + TRACE_INFO("DISCONNECTED"); + g_network_status = DP_NETWORK_OFF; + } + pthread_mutex_unlock(&g_dp_network_mutex); +} + +////////////////////////////////////////////////////////////////////////// +/// @brief [callback] called when changed network ip +/// @todo auto resume feature +static void __dp_network_connection_ip_changed_cb(const char *ip, const char *ipv6, void *data) +{ + if (dp_network_get_status() != DP_NETWORK_OFF) { + TRACE_DEBUG("[CONNECTION] IP CHANGED"); + // broadcast to all thread for clients + dp_broadcast_signal(); + } +} + +int dp_network_get_status() +{ + int status = DP_NETWORK_OFF; + pthread_mutex_lock(&g_dp_network_mutex); + status = g_network_status; + pthread_mutex_unlock(&g_dp_network_mutex); + return status; +} + +int dp_network_is_wifi_direct() +{ + pthread_mutex_lock(&g_dp_network_mutex); + int status = g_network_is_wifi_direct; + pthread_mutex_unlock(&g_dp_network_mutex); + return status; +} + +////////////////////////////////////////////////////////////////////////// +/// @brief create connection handle & regist callback +/// @return 0 : success -1 : failed +int dp_network_connection_init() +{ + int retcode = 0; + +#ifdef SUPPORT_WIFI_DIRECT + if (wifi_direct_initialize() == 0) { + wifi_direct_set_connection_state_changed_cb + (__dp_network_wifi_direct_changed_cb, NULL); + g_network_is_wifi_direct = __dp_network_wifi_direct_status(); + } +#endif + + if ((retcode = connection_create(&g_network_connection)) != + CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_create [%d]", retcode); + return -1; + } + if ((retcode = connection_set_type_changed_cb(g_network_connection, + __dp_network_connection_type_changed_cb, NULL)) != + CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_set_type_changed_cb [%d]", retcode); + connection_destroy(g_network_connection); + g_network_connection = 0; + return -1; + } + + if ((retcode = connection_set_ip_address_changed_cb + (g_network_connection, __dp_network_connection_ip_changed_cb, + NULL)) != CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed __dp_network_connection_ip_changed_cb [%d]", retcode); + connection_destroy(g_network_connection); + g_network_connection = 0; + return -1; + } + + connection_type_e type = CONNECTION_TYPE_DISCONNECTED; + if ((retcode = connection_get_type(g_network_connection, &type)) != + CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_get_type [%d]", retcode); + connection_destroy(g_network_connection); + g_network_connection = 0; + return -1; + } + g_network_status = + __dp_get_network_connection_status(g_network_connection, type); + return 0; +} + +////////////////////////////////////////////////////////////////////////// +/// @brief destroy connection handle +void dp_network_connection_destroy() +{ + pthread_mutex_lock(&g_dp_network_mutex); +#ifdef SUPPORT_WIFI_DIRECT + wifi_direct_unset_connection_state_changed_cb(); + wifi_direct_deinitialize(); +#endif + + if (g_network_connection != 0) { + connection_unset_type_changed_cb(g_network_connection); + connection_unset_ip_address_changed_cb(g_network_connection); + connection_destroy(g_network_connection); + } + g_network_connection = 0; + pthread_mutex_unlock(&g_dp_network_mutex); +} diff --git a/provider/download-provider-notification-manager.c b/provider/download-provider-notification-manager.c new file mode 100644 index 0000000..ea89c0c --- /dev/null +++ b/provider/download-provider-notification-manager.c @@ -0,0 +1,573 @@ +/* + * Copyright (c) 2013 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. + */ + +#ifdef SUPPORT_NOTIFICATION +#include <stdlib.h> +#include <signal.h> // pthread_kill +#include <errno.h> // ESRCH + +#include "download-provider-log.h" +#include "download-provider-pthread.h" +#include "download-provider-client.h" +#include "download-provider-client-manager.h" +#include "download-provider-notification.h" +#include "download-provider-db-defs.h" +#include "download-provider-db.h" +#endif +#include "download-provider-notification-manager.h" + +#ifdef SUPPORT_NOTIFICATION +typedef struct { // manage clients without mutex + int id; + int state; + int noti_priv_id; + double received_size; + double file_size; + dp_noti_type type; + void *slot; // client can not be NULL. it will exist in dummy + void *request; // this can be NULL after destroy + void *next; +} dp_notification_queue_fmt; + + +pthread_mutex_t g_dp_notification_manager_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t g_dp_notification_manager_cond = PTHREAD_COND_INITIALIZER; +pthread_t g_dp_notification_manager_tid = 0; + +static dp_notification_queue_fmt *g_dp_notification_clear = NULL; +static dp_notification_queue_fmt *g_dp_notification_ongoing = NULL; +static dp_notification_queue_fmt *g_dp_notification = NULL; + +pthread_mutex_t g_dp_notification_queue_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t g_dp_notification_queue_ongoing_mutex = PTHREAD_MUTEX_INITIALIZER; + +// normal . push at the tail of queue. +static int __dp_notification_queue_push(dp_notification_queue_fmt **queue, void *slot, void *request, const int id, const int state, const int noti_priv_id, const double received_size, const double file_size, const dp_noti_type type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL || request == NULL) { + TRACE_ERROR("check client and request memory address"); + return -1; + } else if (id <= 0) { + TRACE_ERROR("check slot or download id", id); + return -1; + } + + int ret = -1; + CLIENT_MUTEX_LOCK(&g_dp_notification_queue_mutex); + // search the tail of queue + int i = 0; + dp_notification_queue_fmt *tailp = *queue; + dp_notification_queue_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + prevp = tailp; + tailp = tailp->next; + } + dp_notification_queue_fmt *new_queue = (dp_notification_queue_fmt *)malloc(sizeof(dp_notification_queue_fmt)); + if (new_queue != NULL) { + new_queue->slot = slot; + new_queue->id = id; + new_queue->state = state; + new_queue->noti_priv_id = noti_priv_id; + new_queue->received_size = received_size; + new_queue->file_size = file_size; + new_queue->type = type; + new_queue->request = request; + new_queue->next = NULL; + if (prevp == NULL) + *queue = new_queue; + else + prevp->next = new_queue; + ret = 0; + } + //TRACE_DEBUG("queue push %d id:%d", i, id); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); + return ret; +} + +int __dp_notification_queue_pop(dp_notification_queue_fmt **queue, void **slot, void **request, int *id, int *state, int *noti_priv_id, double *received_size, double *file_size, dp_noti_type *type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL) { + TRACE_ERROR("check client memory address"); + return -1; + } + + int lock = CLIENT_MUTEX_TRYLOCK(&g_dp_notification_queue_mutex); + if (lock != 0) { + TRACE_DEBUG("skip queue is used by other thread"); + return 0; + } + if (queue == NULL || *queue == NULL) { + //TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); + return -1; + } + // get a head of queue + int ret = -1; + do { + dp_notification_queue_fmt *popp = *queue; + *queue = popp->next; + if (popp->slot == NULL) { + TRACE_DEBUG("queue error slot:%p id:%d", popp->slot, popp->id); + } else { + *slot = popp->slot; + if (request != NULL) { + *request = popp->request; + } + *id = popp->id; + *state = popp->state; + if (noti_priv_id != NULL) + *noti_priv_id = popp->noti_priv_id; + if (received_size != NULL) + *received_size = popp->received_size; + if (file_size != NULL) + *file_size = popp->file_size; + *type = popp->type; + ret = 0; + break; + } + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); + return ret; +} + +int __dp_notification_queue_ongoing_pop(dp_notification_queue_fmt **queue, void **slot, void **request, int *id, int *state, double *received_size, double *file_size, dp_noti_type *type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL) { + TRACE_ERROR("check client memory address"); + return -1; + } + + int lock = CLIENT_MUTEX_TRYLOCK(&g_dp_notification_queue_ongoing_mutex); + if (lock != 0) { + TRACE_DEBUG("skip queue is used by other thread"); + return 0; + } + if (queue == NULL || *queue == NULL) { + //TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return -1; + } + // get a head of queue + int ret = -1; + do { + dp_notification_queue_fmt *popp = *queue; + *queue = popp->next; + if (popp->slot == NULL) { + TRACE_DEBUG("queue error slot:%p id:%d", popp->slot, popp->id); + } else { + *slot = popp->slot; + if (request != NULL) { + *request = popp->request; + } + *id = popp->id; + *state = popp->state; + if (received_size != NULL) + *received_size = popp->received_size; + if (file_size != NULL) + *file_size = popp->file_size; + *type = popp->type; + ret = 0; + break; + } + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return ret; +} + +static int __dp_notification_queue_ongoing_push(dp_notification_queue_fmt **queue, void *slot, void *request, const int id, const int state, const double received_size, const double file_size, const dp_noti_type type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL || request == NULL) { + TRACE_ERROR("check client and request memory address"); + return -1; + } else if (id <= 0) { + TRACE_ERROR("check slot or download id", id); + return -1; + } + + int ret = -1; + CLIENT_MUTEX_LOCK(&g_dp_notification_queue_ongoing_mutex); + // search the tail of queue + int i = 0; + dp_notification_queue_fmt *tailp = *queue; + dp_notification_queue_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + if (tailp->slot == slot && tailp->request == request) { + if (tailp->id == id && tailp->state == state && tailp->type == type) { + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return 0; + } + } + prevp = tailp; + tailp = tailp->next; + } + dp_notification_queue_fmt *new_queue = (dp_notification_queue_fmt *)malloc(sizeof(dp_notification_queue_fmt)); + if (new_queue != NULL) { + new_queue->slot = slot; + new_queue->id = id; + new_queue->state = state; + new_queue->received_size = received_size; + new_queue->file_size = file_size; + new_queue->type = type; + new_queue->request = request; + new_queue->next = NULL; + if (prevp == NULL) + *queue = new_queue; + else + prevp->next = new_queue; + ret = 0; + } + //TRACE_DEBUG("queue push %d id:%d", i, id); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return ret; +} + +void __dp_notification_queue_clear(dp_notification_queue_fmt **queue, const int id) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return ; + } + CLIENT_MUTEX_LOCK(&g_dp_notification_queue_mutex); + int i = 0; + dp_notification_queue_fmt *tailp = *queue; + dp_notification_queue_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + if (tailp->id == id) { + // clear. + if (prevp == NULL) + *queue = tailp->next; + else + prevp->next = tailp->next; + TRACE_DEBUG("queue clear this %d id:%d", i, tailp->id); + free(tailp); + break; + } + prevp = tailp; + tailp = tailp->next; + } + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); +} + +int dp_notification_manager_clear_notification(void *slot, void *request, const dp_noti_type type) +{ + dp_request_fmt *requestp = request; + if (request == NULL) { + TRACE_DEBUG("check address request:%p id:%d", + request, (request == NULL ? 0 : requestp->id)); + return -1; + } + __dp_notification_queue_clear(&g_dp_notification, requestp->id); + TRACE_DEBUG("push clear id:%d noti_priv_id:%d", requestp->id, requestp->noti_priv_id); + if (__dp_notification_queue_push(&g_dp_notification_clear, slot, request, requestp->id, requestp->state, -1, 0, 0, type) < 0) { + TRACE_ERROR("failed to push to notification id:%d", requestp->id); + return -1; + } + dp_notification_manager_wake_up(); + return 0; +} + +int dp_notification_manager_push_notification(void *slot, void *request, const dp_noti_type type) +{ + dp_request_fmt *requestp = request; + if (slot == NULL || request == NULL) { + TRACE_DEBUG("check address client:%p request:%p id:%d", slot, + request, (request == NULL ? 0 : requestp->id)); + return -1; + } +// TRACE_DEBUG("push noti id:%d noti_priv_id:%d type:%d", requestp->id, requestp->noti_priv_id, type); + if (type == DP_NOTIFICATION) { + __dp_notification_queue_clear(&g_dp_notification_ongoing, requestp->id); + if (__dp_notification_queue_push(&g_dp_notification, slot, request, requestp->id, requestp->state, requestp->noti_priv_id, 0, (double)requestp->file_size, type) < 0) { + TRACE_ERROR("failed to push to notification id:%d", requestp->id); + return -1; + } + } else { + __dp_notification_queue_clear(&g_dp_notification, requestp->id); + if (__dp_notification_queue_ongoing_push(&g_dp_notification_ongoing, slot, request, requestp->id, requestp->state, (double)requestp->received_size, (double)requestp->file_size, type) < 0) { + TRACE_ERROR("failed to push to notification id:%d", requestp->id); + return -1; + } + } + dp_notification_manager_wake_up(); + return 0; +} + +static void __dp_notification_manager_check_notification() +{ + int pop_queue = 0; + do { + int errorcode = DP_ERROR_NONE; + int download_id = -1; + int state = -1; + dp_noti_type noti_type = -1; + dp_client_slots_fmt *slot = NULL; + dp_request_fmt *request = NULL; + pop_queue = 0; + if (__dp_notification_queue_pop(&g_dp_notification_clear, (void *)&slot, (void *)&request, &download_id, &state, NULL, NULL, NULL, ¬i_type) == 0) { + if (slot != NULL) { + int noti_priv_id = -1; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL && request->id == download_id && request->noti_priv_id >= 0) { + noti_priv_id = request->noti_priv_id; + request->noti_priv_id = -1; + if (dp_db_replace_property(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, (void *)&request->noti_priv_id, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + TRACE_DEBUG("clear ongoing id:%d noti_priv_id:%d type:%d", download_id, noti_priv_id, noti_type); + if (noti_priv_id >= 0) { + if (noti_type > DP_NOTIFICATION) + dp_notification_delete_ongoing(noti_priv_id); + else + dp_notification_delete(noti_priv_id); + } + } + pop_queue++; + continue; + } + int noti_priv_id = -1; + if (__dp_notification_queue_pop(&g_dp_notification, (void *)&slot, (void *)&request, &download_id, &state, ¬i_priv_id, NULL, NULL, ¬i_type) == 0) { + if (slot != NULL) { + __dp_notification_queue_clear(&g_dp_notification_ongoing, download_id); // prevent new ongoing + if (noti_priv_id >= 0) { + TRACE_DEBUG("clear ongoing(%d) id:%d type:%d state:%d", noti_priv_id, download_id, noti_type, state); + dp_notification_delete_ongoing(noti_priv_id); + noti_priv_id = -1; + } + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + TRACE_DEBUG("notification id:%d type:%d state:%d", download_id, noti_type, state); + if (request != NULL && request->id == download_id && request->noti_priv_id >= 0) { + dp_notification_delete_ongoing(request->noti_priv_id); + request->noti_priv_id = -1; + } + dp_content_type content_type = DP_CONTENT_UNKNOWN; + if (request != NULL) + content_type = request->content_type; + noti_priv_id = dp_notification_new(slot->client.dbhandle, download_id, state, content_type, slot->pkgname); // lazy API + TRACE_DEBUG("new notification(%d) id:%d type:%d state:%d", noti_priv_id, download_id, noti_type, state); + if (noti_priv_id < 0) { + TRACE_ERROR("failed to register notification for id:%d", download_id); + } else { + if (request != NULL && request->id == download_id) { + request->noti_priv_id = noti_priv_id; + } + if (dp_db_replace_property(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, (void *)¬i_priv_id, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + pop_queue++; + } + double received_size = 0; + double file_size = 0; + if (__dp_notification_queue_ongoing_pop(&g_dp_notification_ongoing, (void *)&slot, (void *)&request, &download_id, &state, &received_size, &file_size, ¬i_type) == 0) { + if (slot != NULL) { + int noti_priv_id = -1; + int request_id = -1; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL && request->id == download_id) { + request_id = download_id; + if (request->noti_priv_id >= 0) { + noti_priv_id = request->noti_priv_id; + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } else { + TRACE_ERROR("ongoing wrong address id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + continue; + } + + if (request_id < 0) { + TRACE_ERROR("ongoing wrong info id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + slot = NULL; + request = NULL; + continue; + } + if (noti_priv_id < 0 && noti_type > DP_NOTIFICATION_ONGOING) { + TRACE_DEBUG("ongoing precheck id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + noti_type = DP_NOTIFICATION_ONGOING; + } + + TRACE_DEBUG("ongoing id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + + char *subject = NULL; + if (noti_type == DP_NOTIFICATION || noti_type == DP_NOTIFICATION_ONGOING_UPDATE) { + unsigned length = 0; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL) { + if (dp_db_get_property_string(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (unsigned char **)&subject, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get subject id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } else if (subject == NULL && dp_db_get_property_string(slot->client.dbhandle, download_id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (unsigned char **)&subject, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get content_name id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + + if (noti_type > DP_NOTIFICATION_ONGOING) { // update + if (noti_priv_id >= 0 && dp_notification_ongoing_update(noti_priv_id, received_size, file_size, subject) < 0) { + TRACE_ERROR("failed to update ongoing for id:%d", download_id); + } + } else { // new ongoing + if (noti_priv_id >= 0) { + TRACE_DEBUG("clear ongoing id:%d noti_priv_id:%d", download_id, noti_priv_id); + dp_notification_delete(noti_priv_id); + dp_notification_delete_ongoing(noti_priv_id); + noti_priv_id = -1; + } + unsigned char *raws_buffer = NULL; + unsigned length = 0; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (dp_db_get_property_string(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_RAW_ONGOING, &raws_buffer, &length, &errorcode) < 0) { + TRACE_DEBUG("failed to get bundle raws id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + noti_priv_id = dp_notification_ongoing_new(slot->pkgname, subject, raws_buffer, length); + TRACE_DEBUG("new ongoing(%d) id:%d type:%d state:%d", noti_priv_id, download_id, noti_type, state); + free(raws_buffer); + if (noti_priv_id < 0) { + TRACE_ERROR("failed to update ongoing for id:%d", download_id); + } else { + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL) + request->noti_priv_id = noti_priv_id; + if (dp_db_replace_property(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, (void *)¬i_priv_id, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + } + free(subject); + } + pop_queue++; + } + } while (pop_queue > 0); +} + +static void *__dp_notification_manager(void *arg) +{ + pthread_cond_init(&g_dp_notification_manager_cond, NULL); + + dp_notification_set_locale(); + + while (g_dp_notification_manager_tid > 0) { + + if (g_dp_notification_manager_tid <= 0) { + TRACE_DEBUG("notification-manager is closed by other thread"); + break; + } + + // check wifi_direct first + __dp_notification_manager_check_notification(); + + CLIENT_MUTEX_LOCK(&g_dp_notification_manager_mutex); + pthread_cond_wait(&g_dp_notification_manager_cond, &g_dp_notification_manager_mutex); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_manager_mutex); + } + + TRACE_DEBUG("notification-manager's working is done"); + dp_notification_clear_locale(); + pthread_cond_destroy(&g_dp_notification_manager_cond); + pthread_exit(NULL); + return 0; +} + +static int __dp_notification_manager_start() +{ + if (g_dp_notification_manager_tid == 0 || + pthread_kill(g_dp_notification_manager_tid, 0) == ESRCH) { + TRACE_DEBUG("try to create notification-manager"); + if (pthread_create(&g_dp_notification_manager_tid, NULL, + __dp_notification_manager, NULL) != 0) { + TRACE_STRERROR("failed to create notification-manager"); + return -1; + } + } + return 0; +} + +void dp_notification_manager_wake_up() +{ + if (g_dp_notification_manager_tid > 0) { + int locked = CLIENT_MUTEX_TRYLOCK(&g_dp_notification_manager_mutex); + if (locked == 0) { + pthread_cond_signal(&g_dp_notification_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_manager_mutex); + } + } else { + __dp_notification_manager_start(); + } +} + +void dp_notification_manager_kill() +{ + if (g_dp_notification_manager_tid > 0 && + pthread_kill(g_dp_notification_manager_tid, 0) != ESRCH) { + //send signal to notification thread + g_dp_notification_manager_tid = 0; + CLIENT_MUTEX_LOCK(&g_dp_notification_manager_mutex); + pthread_cond_signal(&g_dp_notification_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_manager_mutex); + pthread_cancel(g_dp_notification_manager_tid); + int status; + pthread_join(g_dp_notification_manager_tid, (void **)&status); + } +} +#else + +int dp_notification_manager_clear_notification(void *slot, void *request, const dp_noti_type type) +{ + return 0; +} + +int dp_notification_manager_push_notification(void *slot, void *request, const dp_noti_type type) +{ + return 0; +} + +void dp_notification_manager_wake_up() +{ + return; +} + +void dp_notification_manager_kill() +{ + return; +} +#endif diff --git a/provider/download-provider-notification.c b/provider/download-provider-notification.c new file mode 100755 index 0000000..741fc62 --- /dev/null +++ b/provider/download-provider-notification.c @@ -0,0 +1,629 @@ +/* + * Copyright (c) 2013 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. + */ + +#ifdef SUPPORT_NOTIFICATION +#include <time.h> +#include <sys/time.h> +#include <stdlib.h> +#include <stdio.h> + +#include "download-provider.h" +#include "download-provider-notification.h" +#include "download-provider-db-defs.h" +#include "download-provider-db.h" +#include "download-provider-log.h" +#include "download-provider-client.h" +#include "download-provider-utils.h" + +#include <bundle.h> +#ifdef T30 +#include <bundle_internal.h> +#include <notification_internal.h> +#endif +#include <notification.h> + +#include <appsvc.h> + +#include <vconf.h> +#include <locale.h> +#include <libintl.h> +#define __(s) dgettext(PKG_NAME, s) + +#define DP_DOMAIN PKG_NAME +#define DP_LOCALEDIR LOCALE_DIR +#define DP_NOTIFICATION_NO_SUBJECT "No Name" + +#ifdef _TIZEN_2_3_UX +#define DP_NOTIFICATION_DRM_ICON_PATH IMAGE_DIR"/download_manager_icon_drm.png" +#define DP_NOTIFICATION_UNKNOWN_ICON_PATH IMAGE_DIR"/download_manager_icon_unknown.png" +#define DP_NOTIFICATION_EXCEL_ICON_PATH IMAGE_DIR"/download_manager_icon_xls.png" +#define DP_NOTIFICATION_HTML_ICON_PATH IMAGE_DIR"/download_manager_icon_html.png" +#define DP_NOTIFICATION_MUSIC_ICON_PATH IMAGE_DIR"/download_manager_icon_music.png" +#define DP_NOTIFICATION_PDF_ICON_PATH IMAGE_DIR"/download_manager_icon_pdf.png" +#define DP_NOTIFICATION_PPT_ICON_PATH IMAGE_DIR"/download_manager_icon_ppt.png" +#define DP_NOTIFICATION_TEXT_ICON_PATH IMAGE_DIR"/download_manager_icon_text.png" +#define DP_NOTIFICATION_WORD_ICON_PATH IMAGE_DIR"/download_manager_icon_word.png" +#define DP_NOTIFICATION_VIDEO_ICON_PATH IMAGE_DIR"/download_manager_icon_movie.png" +#define DP_NOTIFICATION_IMAGE_ICON_PATH IMAGE_DIR"/download_manager_icon_img.png" +#define DP_NOTIFICATION_FALSH_ICON_PATH IMAGE_DIR"/download_manager_icon_swf.png" +#define DP_NOTIFICATION_TPK_ICON_PATH IMAGE_DIR"/download_manager_icon_tpk.png" +#define DP_NOTIFICATION_VCAL_ICON_PATH IMAGE_DIR"/download_manager_icon_date.png" + +// base path +#define QP_PRELOAD_NOTI_ICON_PATH "/usr/apps/com.samsung.quickpanel/shared/res/noti_icons" +// each application path +#define QP_PRELOAD_COMMON_PATH QP_PRELOAD_NOTI_ICON_PATH"/Common" +#define DP_NOTIFICATION_COMPLETED_ICON_PATH QP_PRELOAD_COMMON_PATH"/noti_download_complete.png" +#define DP_NOTIFICATION_FAILED_ICON_PATH QP_PRELOAD_COMMON_PATH"/noti_download_failed.png" + +#define DP_NOTIFICATION_ONGOING_ICON_PATH "reserved://quickpanel/ani/downloading" +#define DP_NOTIFICATION_DOWNLOADING_ICON_PATH "reserved://indicator/ani/downloading" +#define DP_NOTIFICATION_FAILED_INDICATOR_ICON_PATH IMAGE_DIR"/B03_Processing_download_failed.png" +#define DP_NOTIFICATION_COMPLETED_INDICATOR_ICON_PATH IMAGE_DIR"/B03_Processing_download_complete.png" +#else +#define DP_NOTIFICATION_DRM_ICON_PATH IMAGE_DIR"/U01_icon_drm.png" +#define DP_NOTIFICATION_UNKNOWN_ICON_PATH IMAGE_DIR"/U01_icon_unkown.png" +#define DP_NOTIFICATION_EXCEL_ICON_PATH IMAGE_DIR"/U01_icon_excel.png" +#define DP_NOTIFICATION_HTML_ICON_PATH IMAGE_DIR"/U01_icon_html.png" +#define DP_NOTIFICATION_MUSIC_ICON_PATH IMAGE_DIR"/U01_list_icon_mp3.png" +#define DP_NOTIFICATION_PDF_ICON_PATH IMAGE_DIR"/U01_icon_pdf.png" +#define DP_NOTIFICATION_PPT_ICON_PATH IMAGE_DIR"/U01_icon_ppt.png" +#define DP_NOTIFICATION_TEXT_ICON_PATH IMAGE_DIR"/U01_icon_text.png" +#define DP_NOTIFICATION_WORD_ICON_PATH IMAGE_DIR"/U01_icon_word.png" +#define DP_NOTIFICATION_VIDEO_ICON_PATH IMAGE_DIR"/U01_list_icon_mp4.png" +#define DP_NOTIFICATION_IMAGE_ICON_PATH IMAGE_DIR"/U01_list_icon_image.png" +#define DP_NOTIFICATION_FALSH_ICON_PATH IMAGE_DIR"/U01_icon_swf.png" +#define DP_NOTIFICATION_TPK_ICON_PATH IMAGE_DIR"/U01_icon_tpk.png" +#define DP_NOTIFICATION_VCAL_ICON_PATH IMAGE_DIR"/U01_icon_vcs.png" + +#define DP_NOTIFICATION_FAILED_ICON_PATH IMAGE_DIR"/noti_download_failed.png" +#define DP_NOTIFICATION_COMPLETED_ICON_PATH IMAGE_DIR"/noti_download_complete.png" + +#define DP_NOTIFICATION_ONGOING_ICON_PATH "reserved://quickpanel/ani/downloading" +#define DP_NOTIFICATION_DOWNLOADING_ICON_PATH "reserved://indicator/ani/downloading" +#define DP_NOTIFICATION_FAILED_INDICATOR_ICON_PATH IMAGE_DIR"/B03_processing_download_fail.png" +#define DP_NOTIFICATION_COMPLETED_INDICATOR_ICON_PATH IMAGE_DIR"/B03_processing_download_complete.png" +#endif + +#define DP_MAX_ICONS_TABLE_COUNT 15 + +char *file_icons_table[DP_MAX_ICONS_TABLE_COUNT]={ + //unknown file type + DP_NOTIFICATION_UNKNOWN_ICON_PATH, + //image + DP_NOTIFICATION_IMAGE_ICON_PATH, + //video + DP_NOTIFICATION_VIDEO_ICON_PATH, + // audio /music + DP_NOTIFICATION_MUSIC_ICON_PATH, + // PDF + DP_NOTIFICATION_PDF_ICON_PATH, + // word + DP_NOTIFICATION_WORD_ICON_PATH, + // ppt + DP_NOTIFICATION_PPT_ICON_PATH, + // excel + DP_NOTIFICATION_EXCEL_ICON_PATH, + // html + DP_NOTIFICATION_HTML_ICON_PATH, + // txt + DP_NOTIFICATION_TEXT_ICON_PATH, + // DRM + DP_NOTIFICATION_DRM_ICON_PATH, + DP_NOTIFICATION_DRM_ICON_PATH, + DP_NOTIFICATION_FALSH_ICON_PATH, + DP_NOTIFICATION_TPK_ICON_PATH, + DP_NOTIFICATION_VCAL_ICON_PATH, +}; + +static const char *__dp_noti_error_str(int err) +{ + switch (err) { + case NOTIFICATION_ERROR_INVALID_PARAMETER: + return "NOTIFICATION_ERROR_INVALID_PARAMETER"; + case NOTIFICATION_ERROR_OUT_OF_MEMORY: + return "NOTIFICATION_ERROR_OUT_OF_MEMORY"; + case NOTIFICATION_ERROR_FROM_DB: + return "NOTIFICATION_ERROR_FROM_DB"; + case NOTIFICATION_ERROR_ALREADY_EXIST_ID: + return "NOTIFICATION_ERROR_ALREADY_EXIST_ID"; + case NOTIFICATION_ERROR_FROM_DBUS: + return "NOTIFICATION_ERROR_FROM_DBUS"; + case NOTIFICATION_ERROR_NOT_EXIST_ID: + return "NOTIFICATION_ERROR_NOT_EXIST_ID"; + default: + break; + } + return "Unknown error"; +} + +char *__dp_noti_get_sender(char *url) +{ + char *temp = NULL; + char *found = NULL; + char *found1 = NULL; + char *sender = NULL; + char *credential_sender = NULL; + + if (url == NULL) + return NULL; + + found = strstr(url, "://"); + if (found != NULL) { + temp = found + 3; + } else { + temp = url; + } + found = strchr(temp, '/'); + if (found != NULL) { + int len = 0; + len = found - temp; + sender = calloc(len + 1, sizeof(char)); + if (sender == NULL) + return NULL; + snprintf(sender, len + 1, "%s", temp); + } else { + sender = dp_strdup(temp); + } + + // For credential URL + found = strchr(sender, '@'); + found1 = strchr(sender, ':'); + if (found != NULL && found1 != NULL && found1 < found) { + int len = 0; + found = found + 1; + len = strlen(found); + credential_sender = calloc(len + 1, sizeof(char)); + if (credential_sender == NULL) { + free(sender); + return NULL; + } + snprintf(credential_sender, len + 1, "%s", found); + free(sender); + return credential_sender; + } else { + return sender; + } +} + +static char *__dp_noti_status(dp_state_type state) +{ + char *message = NULL; + switch (state) { + case DP_STATE_COMPLETED: + message = "IDS_DM_HEADER_DOWNLOAD_COMPLETE"; + break; + case DP_STATE_CANCELED: + case DP_STATE_FAILED: + message = "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB"; + break; + default: + break; + } + return message; +} + +void __lang_changed_cb(keynode_t *key, void* data) +{ + char *str = NULL; + str = vconf_get_str(VCONFKEY_LANGSET); + if (str != NULL) { + setlocale(LC_ALL, str); + bindtextdomain(PKG_NAME, LOCALE_DIR); + textdomain(PKG_NAME); + } + free(str); +} + +void dp_notification_set_locale() +{ + // move to notification.c + // locale + __lang_changed_cb(NULL, NULL); + if (vconf_notify_key_changed(VCONFKEY_LANGSET, __lang_changed_cb, NULL) != 0) + TRACE_ERROR("Fail to set language changed vconf callback"); +} + +void dp_notification_clear_locale() +{ + // move to notification.c + if (vconf_ignore_key_changed(VCONFKEY_LANGSET, __lang_changed_cb) != 0) + TRACE_ERROR("Fail to unset language changed vconf callback"); +} + +void dp_notification_clear_ongoings() +{ + int err = NOTIFICATION_ERROR_NONE; + err = notification_delete_all_by_type(NULL, NOTIFICATION_TYPE_ONGOING); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("[FAIL] clear noti [%s]", __dp_noti_error_str(err)); + } + return; +} + +int dp_notification_ongoing_new(const char *pkgname, const char *subject, unsigned char *raws_buffer, const int raws_length) +{ + int err = NOTIFICATION_ERROR_NONE; + notification_h noti_handle = NULL; + noti_handle = notification_create(NOTIFICATION_TYPE_ONGOING); + if (noti_handle == NULL) { + TRACE_ERROR("failed to create notification handle"); + return -1; + } + + if (subject != NULL) { + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, subject, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); + } else { + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, DP_NOTIFICATION_NO_SUBJECT, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); + } + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set subject error:%s", __dp_noti_error_str(err)); + } + + err = notification_set_image(noti_handle, + NOTIFICATION_IMAGE_TYPE_ICON, + DP_NOTIFICATION_ONGOING_ICON_PATH); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon error:%s", __dp_noti_error_str(err)); + } + + if (raws_buffer != NULL && raws_length > 0) { + bundle *b = NULL; + b = bundle_decode_raw((bundle_raw *)raws_buffer, raws_length); + if (b != NULL) { + err = notification_set_execute_option(noti_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } else { + b = bundle_create(); + if (b != NULL && pkgname != NULL) { + if (appsvc_set_pkgname(b, pkgname) != APPSVC_RET_OK) { + TRACE_ERROR("failed to set set pkgname"); + } else { + err = notification_set_execute_option(noti_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } + } else { + TRACE_ERROR("failed to create bundle"); + } + } + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set service error:%s", __dp_noti_error_str(err)); + } + if (b != NULL) + bundle_free(b); + } + + err = notification_set_property(noti_handle, + NOTIFICATION_PROP_DISABLE_TICKERNOTI); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set property error:%s", __dp_noti_error_str(err)); + notification_free(noti_handle); + return -1; + } + err = notification_set_image(noti_handle, + NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, + DP_NOTIFICATION_DOWNLOADING_ICON_PATH); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon indicator error:%s", __dp_noti_error_str(err)); + notification_free(noti_handle); + return -1; + } + err = notification_set_display_applist(noti_handle, + NOTIFICATION_DISPLAY_APP_ALL); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set display app all error:%s", __dp_noti_error_str(err)); + notification_free(noti_handle); + return -1; + } + + int priv_id = 0; + err = notification_insert(noti_handle, &priv_id); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set priv_id error:%s", __dp_noti_error_str(err)); + notification_free(noti_handle); + return -1; + } + + //TRACE_DEBUG("m_noti_id [%d]", priv_id); + notification_free(noti_handle); + + return priv_id; // store on memory for reuse it +} + + + +int dp_notification_ongoing_update(const int noti_priv_id, const double received_size, const double file_size, const char *subject) +{ + if (noti_priv_id > 0) { + int err = NOTIFICATION_ERROR_NONE; + if (file_size > 0) + err = notification_update_progress(NULL, noti_priv_id, (received_size / file_size)); + else + err = notification_update_size(NULL, noti_priv_id, received_size); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to update error:%s", __dp_noti_error_str(err)); + // return 0 because progress is called frequently + } + if (subject != NULL) { + notification_h noti_handle = NULL; + noti_handle = notification_load(NULL, noti_priv_id); + if (noti_handle != NULL) { + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, subject, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); + err = notification_update(noti_handle); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to update by priv_id:%d", noti_priv_id); + } + notification_free(noti_handle); + } else { + TRACE_ERROR("failed to load handle by priv_id:%d", noti_priv_id); + return -1; + } + } + } + return 0; +} + + +int dp_notification_delete_ongoing(const int noti_priv_id) +{ + int err = NOTIFICATION_ERROR_NONE; + err = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_ONGOING, noti_priv_id); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to delete notification by priv_id:%d error:%s", noti_priv_id, __dp_noti_error_str(err)); + } + return 0; +} + +int dp_notification_delete(const int noti_priv_id) +{ + int err = NOTIFICATION_ERROR_NONE; + err = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_NOTI, noti_priv_id); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to delete notification by priv_id:%d error:%s", noti_priv_id, __dp_noti_error_str(err)); + } + return 0; +} + + +int dp_notification_new(void *dbhandle, const int download_id, const int state, int content_type, const char *pkgname) +{ + int errorcode = DP_ERROR_NONE; + int err = NOTIFICATION_ERROR_NONE; + + if (state != DP_STATE_COMPLETED && + state != DP_STATE_CANCELED && + state != DP_STATE_FAILED) { + TRACE_ERROR("deny by invalid state:%d id:%d", state, download_id); + return -1; + } + + + notification_h noti_handle = NULL; + noti_handle = notification_create(NOTIFICATION_TYPE_NOTI); + if (noti_handle == NULL) { + TRACE_ERROR("failed to create notification handle"); + return -1; + } + + err = notification_set_layout(noti_handle, NOTIFICATION_LY_NOTI_EVENT_SINGLE); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("Fail to set notification layout [%d]", err); + notification_free(noti_handle); + return -1; + } + + err = notification_set_text_domain(noti_handle, DP_DOMAIN, DP_LOCALEDIR); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("Fail to set text domain [%d]", err); + notification_free(noti_handle); + return -1; + } + + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get description id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + if (string != NULL) { +#ifdef _TIZEN_2_3_UX + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_CONTENT, string, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); +#else + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, string, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); +#endif + free(string); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set state id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + } else { + string = __dp_noti_status(state); +#ifdef _TIZEN_2_3_UX + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_CONTENT, __(string), string, + NOTIFICATION_VARIABLE_TYPE_NONE); +#else + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, __(string), string, + NOTIFICATION_VARIABLE_TYPE_NONE); +#endif + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set state id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + } + + string = NULL; + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get subject id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + err = NOTIFICATION_ERROR_NONE; + if (string == NULL && dp_db_get_property_string(dbhandle, download_id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get content_name id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + if (string == NULL) + string = dp_strdup(DP_NOTIFICATION_NO_SUBJECT); + if (string != NULL) { +#ifdef _TIZEN_2_3_UX + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, string, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); +#else + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_CONTENT, string, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); +#endif + free(string); + string = NULL; + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set state id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + } + err = notification_set_time(noti_handle, time(NULL)); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set time id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + bundle *b = NULL; + bundle_raw *raws_buffer = NULL; + if (state == DP_STATE_COMPLETED) { + + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_RAW_COMPLETE, &raws_buffer, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get bundle raws id:%d", download_id); + } + if (raws_buffer != NULL) { + b = bundle_decode_raw(raws_buffer, length); + bundle_free_encoded_rawdata(&raws_buffer); + } + if (b != NULL) { + err = notification_set_execute_option(noti_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } else { + b = bundle_create(); + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_DOWNLOAD, DP_DB_COL_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get saved_path id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + if (b != NULL && string != NULL) { + if (appsvc_set_operation(b, APPSVC_OPERATION_VIEW) != APPSVC_RET_OK) { + TRACE_ERROR("failed to set service operation id:%d", download_id); + } else { + if (appsvc_set_uri(b, string) != APPSVC_RET_OK) { + TRACE_ERROR("failed to set service uri id:%d", download_id); + } else { + err = notification_set_execute_option(noti_handle, + NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } + } + } else { + TRACE_SECURE_ERROR("failed to create bundle id:%d path:%s", download_id, string); + } + free(string); + string = NULL; + } + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set service id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + char *file_type_icon = DP_NOTIFICATION_UNKNOWN_ICON_PATH; + if (content_type > 0 && content_type < DP_MAX_ICONS_TABLE_COUNT) + file_type_icon = file_icons_table[content_type]; + + err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, file_type_icon); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, + DP_NOTIFICATION_COMPLETED_INDICATOR_ICON_PATH); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + } else if (state == DP_STATE_CANCELED || state == DP_STATE_FAILED) { + + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_RAW_FAIL, &raws_buffer, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get bundle raws id:%d", download_id); + } + if (raws_buffer != NULL) { + b = bundle_decode_raw(raws_buffer, length); + bundle_free_encoded_rawdata(&raws_buffer); + } + if (b != NULL) { + err = notification_set_execute_option(noti_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } else { + b = bundle_create(); + if (b != NULL && pkgname != NULL) { + if (appsvc_set_pkgname(b, pkgname) != APPSVC_RET_OK) { + TRACE_ERROR("failed to set set pkgname id:%d", download_id); + } else { + err = notification_set_execute_option(noti_handle, + NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } + } else { + TRACE_ERROR("failed to create bundle id:%d", download_id); + } + } + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set service id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, + DP_NOTIFICATION_FAILED_ICON_PATH); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, + DP_NOTIFICATION_FAILED_INDICATOR_ICON_PATH); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + } + + if (b != NULL) + bundle_free(b); + + err = notification_set_property(noti_handle, + NOTIFICATION_PROP_DISABLE_TICKERNOTI); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set property id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + err = notification_set_display_applist(noti_handle, + NOTIFICATION_DISPLAY_APP_ALL ^ NOTIFICATION_DISPLAY_APP_INDICATOR); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set display app all id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + int priv_id = 0; + err = notification_insert(noti_handle, &priv_id); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + //TRACE_DEBUG("m_noti_id [%d]", priv_id); + notification_free(noti_handle); + + return priv_id; +} +#else +void dp_notification_clear_ongoings() +{ + return; +} +#endif diff --git a/provider/download-provider-notify.c b/provider/download-provider-notify.c new file mode 100644 index 0000000..3288fde --- /dev/null +++ b/provider/download-provider-notify.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013 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 <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <download-provider-log.h> +#include <download-provider-client.h> +#include <download-provider-client-manager.h> +#include <download-provider-ipc.h> + +static char *__dp_notify_get_path(pid_t pid) +{ + size_t path_size = sizeof(NOTIFY_DIR) + 21; + char *notify_fifo = (char *)calloc(path_size, sizeof(char)); + if (notify_fifo == NULL) { + TRACE_STRERROR("failed to alocalte fifo path pid:%d", (int)pid); + return NULL; + } + if (snprintf(notify_fifo, path_size,"%s/%d", NOTIFY_DIR, pid) < 0) { + TRACE_STRERROR("failed to make fifo path pid:%d", (int)pid); + free(notify_fifo); + return NULL; + } + return notify_fifo; +} + +int dp_notify_init(pid_t pid) +{ + char *notify_fifo = __dp_notify_get_path(pid); + if (notify_fifo == NULL) + return -1; + int notify_fd = -1; + struct stat fifo_state; + if (stat(notify_fifo, &fifo_state) == 0) // found + unlink(notify_fifo); + if (mkfifo(notify_fifo, 0644/*-rwrr*/) < 0) { + TRACE_STRERROR("failed to make fifo %s", notify_fifo); + } else { + notify_fd = open(notify_fifo, O_RDWR | O_NONBLOCK, 0644); + } + free(notify_fifo); + return notify_fd; +} + +void dp_notify_deinit(pid_t pid) +{ + char *notify_fifo = __dp_notify_get_path(pid); + if (notify_fifo == NULL) + return ; + struct stat fifo_state; + if (stat(notify_fifo, &fifo_state) == 0) // found + unlink(notify_fifo); + free(notify_fifo); +} + +static int __dp_notify_feedback(int sock, int id, int state, int errorcode, unsigned long long received_size) +{ + dp_ipc_event_fmt eventinfo; + memset(&eventinfo, 0x00, sizeof(dp_ipc_event_fmt)); + eventinfo.id = id; + eventinfo.state = state; + eventinfo.errorcode = errorcode; + eventinfo.received_size = received_size; + if (dp_ipc_write(sock, &eventinfo, sizeof(dp_ipc_event_fmt)) < 0) { + // failed to read from socket // ignore this status + return -1; + } + return 0; +} + +int dp_notify_feedback(int sock, void *slot, int id, int state, int errorcode, unsigned long long received_size) +{ + if (__dp_notify_feedback(sock, id, state, errorcode, received_size) < 0) { + TRACE_ERROR("notify failure by IO_ERROR"); + if (slot != NULL) { + dp_client_slots_fmt *base_slot = slot; + if (base_slot->client.notify >= 0) + close(base_slot->client.notify); + base_slot->client.notify = -1; + dp_notify_deinit(base_slot->credential.pid); + TRACE_ERROR("disable notify channel by IO_ERROR"); + } + return -1; + } + return 0; +} diff --git a/provider/download-provider-plugin-download-agent.c b/provider/download-provider-plugin-download-agent.c new file mode 100644 index 0000000..5522510 --- /dev/null +++ b/provider/download-provider-plugin-download-agent.c @@ -0,0 +1,989 @@ +/* + * Copyright (c) 2013 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 <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <time.h> +#include <sys/time.h> +#include <string.h> +#include <dlfcn.h> // dlopen +#include <fcntl.h> + +#include <download-provider.h> +#include <download-provider-log.h> +#include <download-provider-pthread.h> +#include <download-provider-ipc.h> +#include <download-provider-db-defs.h> +#include <download-provider-db.h> +#include <download-provider-utils.h> +#include <download-provider-notify.h> +#include <download-provider-smack.h> +#include <download-provider-client.h> +#include <download-provider-client-manager.h> +#include <download-provider-plugin-download-agent.h> +#include <download-provider-notification-manager.h> +#include <download-provider-queue-manager.h> + +#include <download-agent-defs.h> +#include <download-agent-interface.h> +#include "xdgmime.h" +#include "content/mime_type.h" + +#define DP_SDCARD_MNT_POINT "/opt/storage/sdcard" +#define DP_MAX_FILE_PATH_LEN 256 +#define DP_MAX_MIME_TABLE_NUM 15 + +typedef struct { + const char *mime; + int content_type; +}mime_table_type; + +const char *ambiguous_mime_type_list[] = { + "text/plain", + "application/octet-stream" +}; + +mime_table_type mime_table[]={ + // PDF + {"application/pdf",DP_CONTENT_PDF}, + // word + {"application/msword",DP_CONTENT_WORD}, + {"application/vnd.openxmlformats-officedocument.wordprocessingml.document",DP_CONTENT_WORD}, + // ppt + {"application/vnd.ms-powerpoint",DP_CONTENT_PPT}, + {"application/vnd.openxmlformats-officedocument.presentationml.presentation",DP_CONTENT_PPT}, + // excel + {"application/vnd.ms-excel",DP_CONTENT_EXCEL}, + {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",DP_CONTENT_EXCEL}, + // html + {"text/html",DP_CONTENT_HTML}, + // txt + {"text/txt",DP_CONTENT_TEXT}, + {"text/plain",DP_CONTENT_TEXT}, + // DRM + {"application/vnd.oma.drm.content",DP_CONTENT_SD_DRM}, + {"application/vnd.oma.drm.message",DP_CONTENT_DRM}, + {"application/x-shockwave-flash", DP_CONTENT_FLASH}, + {"application/vnd.tizen.package", DP_CONTENT_TPK}, + {"text/calendar",DP_CONTENT_VCAL}, +}; + +static void *g_da_handle = NULL; +static int (*download_agent_init)(void) = NULL; // int da_init(da_client_cb_t *da_client_callback); +static int (*download_agent_deinit)(void) = NULL; // int da_deinit(); +static int (*download_agent_is_alive)(int) = NULL; // int da_is_valid_download_id(int download_id); +static int (*download_agent_suspend)(int) = NULL; // int da_suspend_download(int download_id); +static int (*download_agent_resume)(int) = NULL; // int da_resume_download(int download_id); +static int (*download_agent_cancel)(int) = NULL; // int da_cancel_download(int download_id); +static int (*download_agent_suspend_without_update)(int) = NULL; // int da_suspend_download_without_update(int download_id); +static int (*download_agent_cancel_without_update)(int) = NULL; // int da_cancel_download_without_update(int download_id); +static int (*download_agent_start)(const char *url, req_data_t *ext_data, da_cb_t *da_cb_data, int *download_id) = NULL; // int da_start_download_with_extension(const char *url, extension_data_t *ext_data, int *download_id); +static dp_content_type __dp_get_content_type(const char *mime, const char *file_path); + +static int __change_error(int err) +{ + int ret = DP_ERROR_NONE; + switch (err) { + case DA_RESULT_OK: + ret = DP_ERROR_NONE; + break; + case DA_ERR_INVALID_ARGUMENT: + ret = DP_ERROR_INVALID_PARAMETER; + break; + case DA_ERR_FAIL_TO_MEMALLOC: + ret = DP_ERROR_OUT_OF_MEMORY; + break; + case DA_ERR_UNREACHABLE_SERVER: + ret = DP_ERROR_NETWORK_UNREACHABLE; + break; + case DA_ERR_HTTP_TIMEOUT: + ret = DP_ERROR_CONNECTION_TIMED_OUT; + break; + case DA_ERR_DISK_FULL: + ret = DP_ERROR_NO_SPACE; + break; + case DA_ERR_INVALID_STATE: + ret = DP_ERROR_INVALID_STATE; + break; + case DA_ERR_NETWORK_FAIL: + ret = DP_ERROR_NETWORK_ERROR; + break; + case DA_ERR_CONNECTION_FAIL: + case DA_ERR_NETWORK_UNAUTHORIZED: + ret = DP_ERROR_CONNECTION_FAILED; + break; + case DA_ERR_INVALID_URL: + ret = DP_ERROR_INVALID_URL; + break; + case DA_ERR_INVALID_INSTALL_PATH: + ret = DP_ERROR_INVALID_DESTINATION; + break; + case DA_ERR_ALREADY_MAX_DOWNLOAD: + ret = DP_ERROR_TOO_MANY_DOWNLOADS; + break; + case DA_ERR_FAIL_TO_CREATE_THREAD: + case DA_ERR_FAIL_TO_ACCESS_FILE: + default: + ret = DP_ERROR_IO_ERROR; + break; + } + return ret; +} + +static int __dp_da_state_feedback(dp_client_slots_fmt *slot, dp_request_fmt *request) +{ + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address"); + return -1; // try cancel + } + + TRACE_INFO("[INFO][%d] state:%s error:%s", request->id, + dp_print_state(request->state), dp_print_errorcode(request->error)); + + int errorcode = DP_ERROR_NONE; + if (dp_db_update_logging(slot->client.dbhandle, request->id, + request->state, request->error, &errorcode) < 0) { + TRACE_ERROR("logging failure id:%d error:%d", request->id, errorcode); + return -1; // try cancel + } + + request->access_time = (int)time(NULL); + + if (request->state_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, request->id, request->state, request->error, 0) < 0) { + TRACE_ERROR("id:%d disable state callback by IO_ERROR", request->id); + request->state_cb = 0; + } + } + + return 0; +} + +static int __precheck_request(dp_request_fmt *request, int agentid) +{ + if (request == NULL) { + TRACE_ERROR("null-check request req_id:%d", agentid); + return -1; + } + if (request->id < 0 || (request->agent_id != agentid)) { + TRACE_ERROR("id-check request_id:%d agent_id:%d req_id:%d", + request->id, request->agent_id, agentid); + return -1; + } + return 0; +} + +static int __set_file_permission_to_client(dp_client_slots_fmt *slot, dp_request_fmt *request, char *saved_path) +{ + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), (request == NULL ? 0 : request->agent_id)); + return DP_ERROR_INVALID_PARAMETER; + } else if (saved_path == NULL) { + TRACE_ERROR("check null saved path"); + return DP_ERROR_INVALID_PARAMETER; + } + + struct stat lstat_info; + struct stat fstat_info; + int fd; + int errorcode = DP_ERROR_NONE; + char *str = NULL; + str = strrchr(saved_path, '/'); + dp_credential cred = slot->credential; + if (lstat(saved_path, &lstat_info) != -1) { + fd = open (saved_path, O_RDONLY); + if (fd != -1) { + if (fstat(fd, &fstat_info) != -1) { + if (lstat_info.st_mode == fstat_info.st_mode && + lstat_info.st_ino == fstat_info.st_ino && + lstat_info.st_dev == fstat_info.st_dev) { + if ((fchown(fd, cred.uid, cred.gid) != 0) || + (fchmod(fd, S_IRUSR | S_IWUSR | + S_IRGRP | S_IROTH) != 0)) { + TRACE_STRERROR("[ERROR][%d] permission user:%d group:%d", + request->id, cred.uid, cred.gid); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + } else { + TRACE_STRERROR("fstat & lstat info have not matched"); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + } else { + TRACE_STRERROR("fstat call failed"); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + close(fd); + } else { + TRACE_SECURE_ERROR("open failed for file : %s", saved_path); + errorcode = DP_ERROR_IO_ERROR; + } + } else { + TRACE_STRERROR("lstat call failed"); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + if (errorcode == DP_ERROR_NONE && dp_smack_is_mounted() == 1) { + // get smack_label from sql + char *smack_label = dp_db_get_client_smack_label(slot->pkgname); + if (smack_label == NULL) { + TRACE_SECURE_ERROR("[SMACK][%d] no label", request->id); + errorcode = DP_ERROR_PERMISSION_DENIED; + } else { + size_t len = str - (saved_path); + char *dir_path = (char *)calloc(len + 1, sizeof(char)); + if (dir_path != NULL) { + strncpy(dir_path, saved_path, len); + errorcode = dp_smack_set_label(smack_label, dir_path, saved_path); + free(dir_path); + } else { + TRACE_STRERROR("[ERROR] calloc"); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } + free(smack_label); + } + } + return errorcode; +} + +static void __finished_cb(finished_info_t *info, void *user_req_data, + void *user_client_data) +{ + if (info == NULL) { + TRACE_ERROR("check download info address"); + return ; + } + dp_client_slots_fmt *slot = user_client_data; + dp_request_fmt *request = user_req_data; + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), info->download_id); + free(info->etag); + free(info->saved_path); + free(info); + return ; + } + CLIENT_MUTEX_LOCK(&slot->mutex); + if (__precheck_request(request, info->download_id) < 0) { + TRACE_ERROR("error request agent_id:%d", info->download_id); + if (dp_cancel_agent_download(info->download_id) < 0) + TRACE_ERROR("failed to call cancel_download(%d)", info->download_id); + free(info->etag); + free(info->saved_path); + free(info); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return ; + } + + int state = DP_STATE_NONE; + int errorcode = DP_ERROR_NONE; + + if (info->http_status > 0) { + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_HTTP_STATUS, (void *)&info->http_status, 0, 0, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set http_status(%d)", request->id, info->http_status); + } + } + + TRACE_SECURE_DEBUG("[FINISH][%d][%s]", request->id, info->saved_path); + if (info->err == DA_RESULT_OK) { + if (info->saved_path != NULL) { + if(strncmp(DP_SDCARD_MNT_POINT, info->saved_path, strlen(DP_SDCARD_MNT_POINT)) != 0) { + errorcode = __set_file_permission_to_client(slot, request, info->saved_path); + } + } else { + TRACE_ERROR("[ERROR][%d] No SavedPath", request->id); + errorcode = DP_ERROR_INVALID_DESTINATION; + } + if (errorcode == DP_ERROR_NONE) + state = DP_STATE_COMPLETED; + else + state = DP_STATE_FAILED; + } else { + if (info->err == DA_RESULT_USER_CANCELED) { + + TRACE_INFO("[CANCELED][%d]", request->id); + + // if state is canceled and error is DP_ERROR_IO_EAGAIN mean ip_changed + if (request->error == DP_ERROR_IO_EAGAIN) { + request->error = DP_ERROR_NONE; + } else { + state = DP_STATE_CANCELED; + errorcode = request->error; + } + + } else { + state = DP_STATE_FAILED; + errorcode = __change_error(info->err); + TRACE_ERROR("[FAILED][%d][%s] agent error:%d", request->id, + dp_print_errorcode(errorcode), info->err); + } + + } + + if (errorcode == DP_ERROR_NONE && info->saved_path != NULL) { + + char *content_name = NULL; + char *str = NULL; + str = strrchr(info->saved_path, '/'); + if (str != NULL) { + str++; + content_name = dp_strdup(str); + } + if (request->file_size == 0) {// missed in download_cb + request->file_size = request->received_size; + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_SIZE, (void *)&request->file_size, 0, 1, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set content_size(%ld)", request->id, request->file_size); + } + } + // update contentname, savedpath + if (content_name != NULL) { + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (void *)content_name, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set content_name", request->id); + } + } + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_SAVED_PATH, (void *)info->saved_path, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set saved_path", request->id); + } + free(content_name); + /* update the received file size. + * The last received file size cannot update + * because of reducing update algorithm*/ + if (request->progress_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, request->id, DP_STATE_DOWNLOADING, DP_ERROR_NONE, request->received_size) < 0) { + TRACE_ERROR("id:%d disable progress callback by IO_ERROR", request->id); + request->progress_cb = 0; + } + } + } + + request->state = state; + request->error = errorcode; + + if (__dp_da_state_feedback(slot, request) < 0) { + TRACE_ERROR("id:%d check notify channel", request->id); + if (dp_cancel_agent_download_without_update(request->agent_id) < 0) + TRACE_ERROR("[fail][%d]cancel_agent", request->id); + } + if (request->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + request->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, request, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", request->id); + } + } + free(info->etag); + free(info->saved_path); + free(info); + CLIENT_MUTEX_UNLOCK(&slot->mutex); +} + +static void __paused_cb(int download_id, void *user_req_data, void *user_client_data) +{ + dp_client_slots_fmt *slot = user_client_data; + dp_request_fmt *request = user_req_data; + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), download_id); + return ; + } + dp_queue_manager_wake_up(); +} + +static void __download_info_cb(download_info_t *info, void *user_req_data, void *user_client_data) +{ + if (info == NULL) { + TRACE_ERROR("check download info address"); + return ; + } + dp_client_slots_fmt *slot = user_client_data; + dp_request_fmt *request = user_req_data; + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), info->download_id); + free(info->content_name); + free(info->etag); + free(info->file_type); + free(info->tmp_saved_path); + free(info); + return ; + } + CLIENT_MUTEX_LOCK(&slot->mutex); + if (__precheck_request(request, info->download_id) < 0) { + TRACE_ERROR("error request agent_id:%d", info->download_id); + if (dp_cancel_agent_download(info->download_id) < 0) + TRACE_ERROR("failed to call cancel_download(%d)", info->download_id); + free(info->content_name); + free(info->etag); + free(info->file_type); + free(info->tmp_saved_path); + free(info); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return ; + } + + // update info before sending event + TRACE_SECURE_DEBUG("[DOWNLOAD][%d][%s]", request->id, info->tmp_saved_path); + if (info->tmp_saved_path != NULL) { + int errorcode = DP_ERROR_NONE; + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_MIMETYPE, (void *)info->file_type, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set mimetype", request->id); + } + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (void *)info->content_name, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set contentname", request->id); + } + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_TMP_SAVED_PATH, (void *)info->tmp_saved_path, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set tmp_saved_path", request->id); + } + if (info->file_size > 0 && dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_SIZE, (void *)&(info->file_size), 0, 1, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set file size", request->id); + } + if (info->etag && dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_ETAG, (void *)info->etag, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set etag", request->id); + } + if(strncmp(DP_SDCARD_MNT_POINT, info->tmp_saved_path, strlen(DP_SDCARD_MNT_POINT)) != 0) { + errorcode = __set_file_permission_to_client(slot, request, info->tmp_saved_path); + } + request->error = errorcode; + } else { + request->error = DP_ERROR_IO_ERROR; + } + + if (request->error != DP_ERROR_NONE) { + request->state = DP_STATE_FAILED; + TRACE_ERROR("id:%d try to cancel(%d)", request->id, info->download_id); + if (dp_cancel_agent_download(request->agent_id) < 0) { + TRACE_ERROR("[fail][%d] cancel_agent:%d", request->id, + info->download_id); + } + } else { + request->state = DP_STATE_DOWNLOADING; + request->file_size = info->file_size; // unsigned + TRACE_DEBUG("[STARTED] id:%d agentid:%d", request->id, info->download_id); + } + + if (__dp_da_state_feedback(slot, request) < 0) { + TRACE_ERROR("id:%d check notify channel", request->id); + if (dp_cancel_agent_download(request->agent_id) < 0) + TRACE_ERROR("[fail][%d]cancel_agent", request->id); + } + // notification + if (request->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, request, DP_NOTIFICATION_ONGOING_UPDATE) < 0) { + TRACE_ERROR("failed to register notification for id:%d", request->id); + } + } + //get the mime type for dp notification + if (request->noti_type > DP_NOTIFICATION_TYPE_NONE) { + request->content_type = __dp_get_content_type(info->file_type, info->tmp_saved_path); + } + free(info->content_name); + free(info->etag); + free(info->file_type); + free(info->tmp_saved_path); + free(info); + CLIENT_MUTEX_UNLOCK(&slot->mutex); +} + +static void __progress_cb(int download_id, unsigned long long received_size, + void *user_req_data, void *user_client_data) +{ + dp_client_slots_fmt *slot = user_client_data; + dp_request_fmt *request = user_req_data; + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), download_id); + return ; + } + CLIENT_MUTEX_LOCK(&slot->mutex); + /* + if (CLIENT_MUTEX_TRYLOCK(&slot->mutex) != 0) { + TRACE_ERROR("slot busy agent_id:%d", download_id); + return ; + } + */ + if (__precheck_request(request, download_id) < 0) { + TRACE_ERROR("error request agent_id:%d", download_id); + if (dp_cancel_agent_download(download_id) < 0) + TRACE_ERROR("failed to call cancel_download(%d)", download_id); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return ; + } + + // For resume case after pause, it change state from connecting to downloading + if (request->state == DP_STATE_CONNECTING) { + request->state = DP_STATE_DOWNLOADING; + if (__dp_da_state_feedback(slot, request) < 0) { + TRACE_ERROR("id:%d check notify channel", request->id); + if (dp_cancel_agent_download(request->agent_id) < 0) + TRACE_ERROR("[fail][%d]cancel_agent", request->id); + } + } + + if (request->state == DP_STATE_DOWNLOADING) { + request->received_size = received_size; + time_t tt = time(NULL); + struct tm *localTime = localtime(&tt); + // send event every 1 second. + if (request->progress_lasttime != localTime->tm_sec) { + request->progress_lasttime = localTime->tm_sec; + + if (request->progress_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, + request->id, DP_STATE_DOWNLOADING, DP_ERROR_NONE, received_size) < 0) { + // failed to read from socket // ignore this status + TRACE_ERROR("id:%d disable progress callback by IO_ERROR", request->id); + request->progress_cb = 0; + } + } + + if (request->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, request, DP_NOTIFICATION_ONGOING_PROGRESS) < 0) { + TRACE_ERROR("failed to register notification for id:%d", request->id); + } + } + + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); +} + +static int __dp_is_ambiguous_mime_type(const char *mime_type) +{ + if (mime_type == NULL) + return -1; + + int index = 0; + int listSize = sizeof(ambiguous_mime_type_list) / sizeof(const char *); + for (index = 0; index < listSize; index++) { + if (0 == strncmp(mime_type, ambiguous_mime_type_list[index], + strlen(ambiguous_mime_type_list[index]))) { + TRACE_DEBUG("It is ambiguous"); + return 0; + } + } + return -1; +} + +static dp_content_type __dp_get_content_type(const char *mime, const char *file_path) +{ + int i = 0; + int type = DP_CONTENT_UNKNOWN; + char *temp_mime = NULL; + if (mime == NULL || strlen(mime) < 1) + return DP_CONTENT_UNKNOWN; + + if ((file_path != NULL) && (strlen(file_path) > 0) && + (__dp_is_ambiguous_mime_type(mime) == 0)) { + const char *ext = strrchr(file_path, '.'); + if (ext == NULL) { + TRACE_ERROR("File Extension is NULL"); + return type; + } + mime_type_get_mime_type(ext + 1, &temp_mime); + } + if (temp_mime == NULL) { + temp_mime = (char *)calloc(1, DP_MAX_FILE_PATH_LEN); + if (temp_mime == NULL) { + TRACE_ERROR("Fail to call calloc"); + return type; + } + strncpy(temp_mime, mime, DP_MAX_FILE_PATH_LEN - 1); + } + TRACE_SECURE_DEBUG("mime type [%s]", temp_mime); + + /* Search a content type from mime table. */ + for (i = 0; i < DP_MAX_MIME_TABLE_NUM; i++) { + if (strncmp(mime_table[i].mime, temp_mime, strlen(temp_mime)) == 0){ + type = mime_table[i].content_type; + break; + } + } + if (type == DP_CONTENT_UNKNOWN) { + const char *unaliased_mime = NULL; + /* unaliased_mimetype means representative mime among similar types */ + unaliased_mime = xdg_mime_unalias_mime_type(temp_mime); + + if (unaliased_mime != NULL) { + TRACE_SECURE_DEBUG("unaliased mime type[%s]",unaliased_mime); + if (strstr(unaliased_mime,"video/") != NULL) + type = DP_CONTENT_VIDEO; + else if (strstr(unaliased_mime,"audio/") != NULL) + type = DP_CONTENT_MUSIC; + else if (strstr(unaliased_mime,"image/") != NULL) + type = DP_CONTENT_IMAGE; + } + } + free(temp_mime); + TRACE_DEBUG("type[%d]", type); + return type; +} + + +int dp_init_agent() +{ + + g_da_handle = dlopen("/usr/lib/libdownloadagent2.so", RTLD_LAZY | RTLD_GLOBAL); + if (!g_da_handle) { + TRACE_ERROR("[dlopen] %s", dlerror()); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + dlerror(); /* Clear any existing error */ + + *(void **) (&download_agent_init) = dlsym(g_da_handle, "da_init"); + if (download_agent_init == NULL ) { + TRACE_ERROR("[dlsym] da_init:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_deinit) = dlsym(g_da_handle, "da_deinit"); + if (download_agent_deinit == NULL ) { + TRACE_ERROR("[dlsym] da_deinit:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_is_alive) = + dlsym(g_da_handle, "da_is_valid_download_id"); + if (download_agent_is_alive == NULL ) { + TRACE_ERROR("[dlsym] da_is_valid_download_id:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_suspend) = + dlsym(g_da_handle, "da_suspend_download"); + if (download_agent_suspend == NULL ) { + TRACE_ERROR("[dlsym] da_suspend_download:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_resume) = + dlsym(g_da_handle, "da_resume_download"); + if (download_agent_resume == NULL) { + TRACE_ERROR("[dlsym] da_resume_download:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + +// *(void **) (&download_agent_cancel) = dlsym(g_da_handle, "da_cancel_download_without_update"); + *(void **) (&download_agent_cancel) = + dlsym(g_da_handle, "da_cancel_download"); + if (download_agent_cancel == NULL) { + TRACE_ERROR("[dlsym] da_cancel_download:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_start) = + dlsym(g_da_handle, "da_start_download"); + if (download_agent_start == NULL) { + TRACE_ERROR("[dlsym] da_start_download:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_cancel_without_update) = dlsym(g_da_handle, "da_cancel_download_without_update"); + if (download_agent_cancel_without_update == NULL) { + TRACE_ERROR("[dlsym] da_cancel_download_without_update:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_suspend_without_update) = dlsym(g_da_handle, "da_suspend_download_without_update"); + if (download_agent_suspend_without_update == NULL) { + TRACE_ERROR("[dlsym] da_suspend_download_without_update:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + int da_ret = -1; + da_ret = (*download_agent_init)(); + if (da_ret != DA_RESULT_OK) { + return DP_ERROR_OUT_OF_MEMORY; + } + return DP_ERROR_NONE; +} + +void dp_deinit_agent() +{ + if (g_da_handle != NULL) { + if (download_agent_deinit != NULL) + (*download_agent_deinit)(); + + dlclose(g_da_handle); + g_da_handle = NULL; + } +} + +// 1 : alive +// 0 : not alive +int dp_is_alive_download(int req_id) +{ + int da_ret = 0; + if (req_id < 0) + return 0; + if (download_agent_is_alive != NULL) + da_ret = (*download_agent_is_alive)(req_id); + return da_ret; +} + +// 0 : success +// -1 : failed +int dp_cancel_agent_download(int req_id) +{ + if (req_id < 0) { + TRACE_ERROR("[NULL-CHECK] req_id"); + return -1; + } + if (dp_is_alive_download(req_id) == 0) { + TRACE_ERROR("[CHECK agent-id:%d] dead request", req_id); + return -1; + } + if (download_agent_cancel != NULL) { + if ((*download_agent_cancel)(req_id) == DA_RESULT_OK) + return 0; + } + return -1; +} + +// 0 : success +// -1 : failed +int dp_pause_agent_download(int req_id) +{ + if (req_id < 0) { + TRACE_ERROR("[NULL-CHECK] req_id"); + return -1; + } + if (dp_is_alive_download(req_id) == 0) { + TRACE_ERROR("[CHECK agent-id:%d] dead request", req_id); + return -1; + } + if (download_agent_suspend != NULL) { + if ((*download_agent_suspend)(req_id) == DA_RESULT_OK) + return 0; + } + return -1; +} + + +// 0 : success +// -1 : failed +int dp_cancel_agent_download_without_update(int req_id) +{ + if (req_id < 0) { + TRACE_ERROR("[NULL-CHECK] req_id"); + return -1; + } + if (dp_is_alive_download(req_id) == 0) { + TRACE_ERROR("[CHECK agent-id:%d] dead request", req_id); + return -1; + } + if (download_agent_cancel_without_update != NULL) { + if ((*download_agent_cancel_without_update)(req_id) == DA_RESULT_OK) + return 0; + } + return -1; +} + +// 0 : success +// -1 : failed +int dp_pause_agent_download_without_update(int req_id) +{ + if (req_id < 0) { + TRACE_ERROR("[NULL-CHECK] req_id"); + return -1; + } + if (dp_is_alive_download(req_id) == 0) { + TRACE_ERROR("[CHECK agent-id:%d] dead request", req_id); + return -1; + } + if (download_agent_suspend_without_update != NULL) { + if ((*download_agent_suspend_without_update)(req_id) == DA_RESULT_OK) + return 0; + } + return -1; +} + +// 0 : success +// -1 : failed +// -2 : pended +int dp_start_agent_download(void *slot, void *request) +{ + int da_ret = -1; + int req_dl_id = -1; + req_data_t *req_data = NULL; + + dp_client_slots_fmt *base_slot = slot; + dp_request_fmt *base_req = request; + + if (slot == NULL || request == NULL) { + TRACE_ERROR("check slot or request address"); + return DP_ERROR_INVALID_PARAMETER; + } + + da_cb_t da_cb = { + __download_info_cb, + __progress_cb, + __finished_cb, + __paused_cb + }; + + req_data = (req_data_t *)calloc(1, sizeof(req_data_t)); + if (req_data == NULL) { + TRACE_ERROR("[ERROR] calloc"); + return DP_ERROR_OUT_OF_MEMORY; + } + + int errorcode = DP_ERROR_NONE; + unsigned length = 0; + char *url = NULL; + char *destination = NULL; + char *tmp_saved_path = NULL; + char *user_tmp_file_path = NULL; + char *filename = NULL; + char *etag = NULL; + int user_network_bonding = 0; + + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (unsigned char **)&url, &length, &errorcode) < 0 || + url == NULL) { + free(req_data); + if (errorcode == DP_ERROR_NO_DATA) { + TRACE_ERROR("url id:%d NO_DATA", base_req->id); + return DP_ERROR_INVALID_URL; + } else { + TRACE_ERROR("url id:%d DISK_BUSY", base_req->id); + return DP_ERROR_DISK_BUSY; + } + } + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_TEMP_FILE_PATH, (unsigned char **)&user_tmp_file_path, &length, &errorcode) < 0 || + user_tmp_file_path == NULL) { + TRACE_DEBUG("user_tmp_file_path id:%d NO_DATA", base_req->id); + } + + if (user_tmp_file_path != NULL) + req_data->temp_file_path = user_tmp_file_path; + else { + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (unsigned char **)&filename, &length, &errorcode) < 0 || + filename == NULL) { + TRACE_DEBUG("filename id:%d NO_DATA", base_req->id); + } else + req_data->file_name = filename; + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (unsigned char **)&destination, &length, &errorcode) < 0 || + destination == NULL) { + TRACE_DEBUG("destination id:%d NO_DATA", base_req->id); + } else + req_data->install_path = destination; + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_DOWNLOAD, DP_DB_COL_TMP_SAVED_PATH, (unsigned char **)&tmp_saved_path, &length, &errorcode) < 0 || + tmp_saved_path == NULL) { + TRACE_DEBUG("tmp_saved_path id:%d NO_DATA", base_req->id); + } + } + + if (tmp_saved_path != NULL) { + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_DOWNLOAD, DP_DB_COL_ETAG, (unsigned char **)&etag, &length, &errorcode) < 0 || + etag == NULL) { + TRACE_DEBUG("etag id:%d NO_DATA", base_req->id); + } + if (etag != NULL) { + TRACE_DEBUG("try to resume id:%d", base_req->id); + req_data->etag = etag; + req_data->temp_file_path = tmp_saved_path; + } else { + /* FIXME later : It is better to handle the unlink function in download agaent module + * or in upload the request data to memory after the download provider process is restarted */ + TRACE_SECURE_INFO("try to restart id:%d remove tmp file:%s", + base_req->id, tmp_saved_path); + if (dp_is_file_exist(tmp_saved_path) == 0) { + if (unlink(tmp_saved_path) != 0) + TRACE_STRERROR("failed to remove file id:%d", base_req->id); + } + } + } + if( dp_db_get_property_int(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, (int *)&user_network_bonding, &errorcode) < 0 || + user_network_bonding < 0) { + TRACE_DEBUG("unable to get network bonding value for id:%d", base_req->id); + } else + req_data->network_bonding = user_network_bonding; + + req_data->pkg_name = base_slot->pkgname; + + // get headers list from header table(DB) + int headers_count = dp_db_check_duplicated_int(base_slot->client.dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ID, base_req->id, &errorcode); + if (headers_count > 0) { + req_data->request_header = calloc(headers_count, sizeof(char *)); + if (req_data->request_header != NULL) { + headers_count = dp_db_get_http_headers_list(base_slot->client.dbhandle, base_req->id, (char **)req_data->request_header, &errorcode); + if (headers_count > 0) + req_data->request_header_count = headers_count; + } + } + + req_data->user_client_data = (void *)slot; + req_data->user_req_data = (void *)request; + + // call start API of agent lib + if (download_agent_start != NULL) + da_ret = (*download_agent_start)(url, req_data, &da_cb, &req_dl_id); + if (req_data->request_header_count > 0) { + int len = 0; + int i = 0; + len = req_data->request_header_count; + for (i = 0; i < len; i++) + free((void *)(req_data->request_header[i])); + free(req_data->request_header); + } + free(url); + free(destination); + free(tmp_saved_path); + free(user_tmp_file_path); + free(filename); + free(etag); + free(req_data); + + if (da_ret == DA_RESULT_OK) { + TRACE_DEBUG("request id :%d SUCCESS agent_id:%d", base_req->id, req_dl_id); + base_req->agent_id = req_dl_id; + } + return __change_error(da_ret); +} + +int dp_resume_agent_download(int req_id) +{ + int da_ret = -1; + if (req_id < 0) { + TRACE_ERROR("[NULL-CHECK] req_id"); + return DP_ERROR_INVALID_PARAMETER; + } + if (download_agent_resume != NULL) + da_ret = (*download_agent_resume)(req_id); + if (da_ret == DA_RESULT_OK) + return DP_ERROR_NONE; + else if (da_ret == DA_ERR_INVALID_STATE) + return DP_ERROR_INVALID_STATE; + return __change_error(da_ret); +} + diff --git a/provider/download-provider-pthread.c b/provider/download-provider-pthread.c new file mode 100644 index 0000000..3ef2816 --- /dev/null +++ b/provider/download-provider-pthread.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2012 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 <unistd.h> +#include <time.h> +#include <errno.h> + +#include "download-provider-log.h" +#include "download-provider-pthread.h" + +static char *__print_pthread_error(int code) +{ + switch(code) + { + case 0: + return "NONE"; + case EINVAL: + return "EINVAL"; + case ENOMEM: + return "ENOMEM"; + case EBUSY: + return "EBUSY"; + case EDEADLK: + return "EDEADLK"; + } + return "UNKNOWN"; +} + +int dp_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) +{ + int ret = pthread_mutex_init(mutex, attr); + if (0 == ret || EBUSY == ret) + return 0; + else + TRACE_STRERROR("error:%d.%s", ret, __print_pthread_error(ret)); + return -1; +} + +void dp_mutex_lock(pthread_mutex_t *mutex, const char *func, int line) +{ + int ret = pthread_mutex_lock(mutex); + if (ret != 0) + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); +} + +int dp_mutex_check_lock(pthread_mutex_t *mutex, const char *func, int line) +{ + int ret = pthread_mutex_lock(mutex); + if (ret != 0) + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); + return ret; +} + +int dp_mutex_trylock(pthread_mutex_t *mutex, const char *func, int line) +{ + int ret = pthread_mutex_trylock(mutex); + if (ret != 0 && ret != EINVAL) { + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); + } + return ret; +} + +int dp_mutex_timedlock(pthread_mutex_t *mutex, int sec, const char *func, int line) +{ + struct timespec deltatime; + deltatime.tv_sec = sec; + deltatime.tv_nsec = 0; + int ret = pthread_mutex_timedlock(mutex, &deltatime); + if (ret != 0) { + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); + } + return ret; +} + +void dp_mutex_unlock(pthread_mutex_t *mutex, const char *func, int line) +{ + int ret = pthread_mutex_unlock(mutex); + if (ret != 0) + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); +} + +void dp_mutex_destroy(pthread_mutex_t *mutex) +{ + int ret = pthread_mutex_destroy(mutex); + if (ret != 0) { + TRACE_STRERROR("error:%d.%s", ret, __print_pthread_error(ret)); + if(EBUSY == ret) { + if (pthread_mutex_unlock(mutex) == 0) + pthread_mutex_destroy(mutex); + } + } +} diff --git a/provider/download-provider-queue-manager.c b/provider/download-provider-queue-manager.c new file mode 100644 index 0000000..41f4a36 --- /dev/null +++ b/provider/download-provider-queue-manager.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2013 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 <stdlib.h> +#include <signal.h> // pthread_kill +#include <errno.h> // ESRCH + +#include <download-provider-log.h> +#include <download-provider-pthread.h> + +#include <download-provider-db-defs.h> +#include <download-provider-db.h> +#include <download-provider-queue.h> +#include <download-provider-network.h> +#include <download-provider-notify.h> +#include <download-provider-client.h> +#include <download-provider-client-manager.h> +#include <download-provider-plugin-download-agent.h> + +pthread_mutex_t g_dp_queue_manager_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t g_dp_queue_manager_cond = PTHREAD_COND_INITIALIZER; +pthread_t g_dp_queue_manager_tid = 0; + +static dp_queue_fmt *g_dp_queue_network_all = NULL; +static dp_queue_fmt *g_dp_queue_network_wifi = NULL; +static dp_queue_fmt *g_dp_queue_network_data_network = NULL; +static dp_queue_fmt *g_dp_queue_network_wifi_direct = NULL; + +static dp_queue_fmt **__dp_queue_manager_get_queue(int network) +{ + switch(network) { + case DP_NETWORK_ALL: + //TRACE_DEBUG("network all"); + return &g_dp_queue_network_all; + case DP_NETWORK_WIFI: + //TRACE_DEBUG("network wifi only"); + return &g_dp_queue_network_wifi; + case DP_NETWORK_DATA_NETWORK: + //TRACE_DEBUG("network data network only"); + return &g_dp_queue_network_data_network; + case DP_NETWORK_WIFI_DIRECT: + //TRACE_DEBUG("network wifi-direct"); + return &g_dp_queue_network_wifi_direct; + default: + break; + } + return NULL; +} +int dp_queue_manager_push_queue(void *slot, void *request) +{ + dp_request_fmt *requestp = request; + if (slot == NULL || request == NULL) { + TRACE_DEBUG("check address client:%p request:%p id:%d", slot, + request, (request == NULL ? 0 : requestp->id)); + return -1; + } + dp_queue_fmt **queue = __dp_queue_manager_get_queue(requestp->network_type); + if (requestp->state != DP_STATE_QUEUED) { + TRACE_ERROR("check id:%d state:%s", requestp->id, dp_print_state(requestp->state)); + return -1; + } + if (dp_queue_push(queue, slot, request) < 0) { + TRACE_ERROR("failed to push to queue id:%d", requestp->id); + return -1; + } + return 0; +} + +void dp_queue_manager_clear_queue(void *request) +{ + dp_request_fmt *requestp = request; + if (request == NULL) { + TRACE_DEBUG("check address request:%p id:%d", + request, (request == NULL ? 0 : requestp->id)); + return ; + } + dp_queue_fmt **queue = __dp_queue_manager_get_queue(requestp->network_type); + dp_queue_clear(queue, request); +} + +// if return negative, queue-manager try again. +static int __dp_queue_manager_try_download(dp_client_slots_fmt *slot, dp_request_fmt *request) +{ + int errorcode = DP_ERROR_NONE; + int result = 0; + + if (slot == NULL || request == NULL) { + TRACE_DEBUG("check address client:%p request:%p id:%d", slot, + request, (request == NULL ? 0 : request->id)); + // return 0 to ignore this call. + return 0; + } + + if (request->state != DP_STATE_QUEUED) { + TRACE_ERROR("check id %d state:%d", request->id, request->state); + return 0; + } + + // check startcount + + request->startcount++; + request->access_time = (int)time(NULL); + + if (dp_db_replace_property(slot->client.dbhandle, request->id, + DP_TABLE_LOGGING, DP_DB_COL_STARTCOUNT, + (void *)&request->startcount, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set startcount"); + return -1; + } + + errorcode = DP_ERROR_NONE; + + if (dp_is_alive_download(request->agent_id) > 0) + errorcode = dp_resume_agent_download(request->agent_id); + else + // call agent start function + errorcode = dp_start_agent_download(slot, request); + + if (errorcode == DP_ERROR_NONE) { + request->state = DP_STATE_CONNECTING; + } else if (errorcode == DP_ERROR_TOO_MANY_DOWNLOADS || + errorcode == DP_ERROR_DISK_BUSY || + errorcode == DP_ERROR_OUT_OF_MEMORY) { + TRACE_ERROR("push queue id:%d error:%s", request->id, dp_print_errorcode(errorcode)); + // PENDED + request->state = DP_STATE_QUEUED; + result = -1; // try again. + } else if (errorcode == DP_ERROR_INVALID_STATE) { // by resume + // ignore this request + result = -1; + TRACE_ERROR("failed to resume id:%d", request->id); + request->agent_id = -1; // workaround. da_agent will an object for this agent_id later + } else if (errorcode != DP_ERROR_NONE) { + request->state = DP_STATE_FAILED; + } + + request->error = errorcode; + + if (result == 0) { // it's not for retrying + int sqlerror = DP_ERROR_NONE; + if (dp_db_update_logging(slot->client.dbhandle, request->id, + request->state, request->error, &sqlerror) < 0) { + TRACE_ERROR("logging failure id:%d error:%d", request->id, sqlerror); + } + if (errorcode != DP_ERROR_NONE && request->state_cb == 1) { // announce state + + TRACE_ERROR("notify id:%d error:%s", request->id, dp_print_errorcode(errorcode)); + if (dp_notify_feedback(slot->client.notify, slot, + request->id, request->state, request->error, 0) < 0) { + TRACE_ERROR("disable state callback by IO_ERROR id:%d", request->id); + request->state_cb = 0; + } + } + } + + return result; + +} + +static int __dp_queue_manager_check_queue(dp_queue_fmt **queue) +{ + dp_client_slots_fmt *slot = NULL; + dp_request_fmt *request = NULL; + while (dp_queue_pop(queue, (void *)&slot, (void *)&request) == 0) { // pop a request from queue. + TRACE_DEBUG("queue-manager pop a request"); + if (slot == NULL || request == NULL) { + TRACE_DEBUG("queue error client:%p request:%p id:%d", slot, request, (request == NULL ? 0 : request->id)); + continue; + } + + CLIENT_MUTEX_LOCK(&slot->mutex); + + TRACE_DEBUG("queue info slot:%p request:%p id:%d", slot, request, (request == NULL ? 0 : request->id)); + + int errorcode = DP_ERROR_NONE; + int download_state = DP_STATE_NONE; + if (slot != NULL && request != NULL && + dp_db_get_property_int(slot->client.dbhandle, request->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) { + TRACE_ERROR("deny checking id:%d db state:%s memory:%s", request->id, dp_print_state(download_state), dp_print_state(request->state)); + errorcode = DP_ERROR_ID_NOT_FOUND; + } + + if (download_state == DP_STATE_QUEUED && __dp_queue_manager_try_download(slot, request) < 0) { + // if failed to start, push at the tail of queue. try again. + if (dp_queue_push(queue, slot, request) < 0) { + TRACE_ERROR("failed to push to queue id:%d", request->id); + int errorcode = DP_ERROR_NONE; + if (dp_db_update_logging(slot->client.dbhandle, request->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0) { + TRACE_ERROR("failed to update log id:%d", request->id); + } + request->state = DP_STATE_FAILED; + request->error = DP_ERROR_QUEUE_FULL; + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return -1; // return negative for taking a break + } + + CLIENT_MUTEX_UNLOCK(&slot->mutex); + + slot = NULL; + request = NULL; + } + return 0; +} + +static void *__dp_queue_manager(void *arg) +{ + pthread_cond_init(&g_dp_queue_manager_cond, NULL); + + if (dp_init_agent() != DP_ERROR_NONE) { + TRACE_ERROR("failed to init agent"); + pthread_cond_destroy(&g_dp_queue_manager_cond); + pthread_exit(NULL); + return 0; + } + + do { + + if (g_dp_queue_manager_tid <= 0) { + TRACE_INFO("queue-manager is closed by other thread"); + break; + } + + // check wifi_direct first + if (dp_network_is_wifi_direct() == 1 && __dp_queue_manager_check_queue(&g_dp_queue_network_wifi_direct) < 0) { + TRACE_ERROR("download-agent is busy, try again after 15 seconds"); + } else { // enter here if disable wifi-direct or download-agent is available + int network_status = dp_network_get_status(); + if (network_status != DP_NETWORK_OFF) { + TRACE_INFO("queue-manager try to check queue network:%d", network_status); + if (g_dp_queue_network_all != NULL && __dp_queue_manager_check_queue(&g_dp_queue_network_all) < 0) { + TRACE_ERROR("download-agent is busy, try again after 15 seconds"); + } else { + dp_queue_fmt **queue = __dp_queue_manager_get_queue(network_status); + if (__dp_queue_manager_check_queue(queue) < 0) { + TRACE_ERROR("download-agent is busy, try again after 15 seconds"); + } + } + } + } + + struct timeval now; + struct timespec ts; + gettimeofday(&now, NULL); + ts.tv_sec = now.tv_sec + 5; + ts.tv_nsec = now.tv_usec * 1000; + CLIENT_MUTEX_LOCK(&g_dp_queue_manager_mutex); + pthread_cond_timedwait(&g_dp_queue_manager_cond, &g_dp_queue_manager_mutex, &ts); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_manager_mutex); + + } while (g_dp_queue_manager_tid > 0); + + TRACE_DEBUG("queue-manager's working is done"); + dp_deinit_agent(); + dp_queue_clear_all(&g_dp_queue_network_all); + pthread_cond_destroy(&g_dp_queue_manager_cond); + pthread_exit(NULL); + return 0; +} + +static int __dp_queue_manager_start() +{ + if (g_dp_queue_manager_tid == 0 || + pthread_kill(g_dp_queue_manager_tid, 0) == ESRCH) { + TRACE_DEBUG("try to create queue-manager"); + if (pthread_create(&g_dp_queue_manager_tid, NULL, + __dp_queue_manager, NULL) != 0) { + TRACE_STRERROR("failed to create queue-manager"); + return -1; + } + } + return 0; +} + +void dp_queue_manager_wake_up() +{ + if (g_dp_queue_manager_tid > 0 && + pthread_kill(g_dp_queue_manager_tid, 0) != ESRCH) { + int locked = CLIENT_MUTEX_TRYLOCK(&g_dp_queue_manager_mutex); + if (locked == 0) { + pthread_cond_signal(&g_dp_queue_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_manager_mutex); + } + } else { + __dp_queue_manager_start(); + } +} + +void dp_queue_manager_kill() +{ + if (g_dp_queue_manager_tid > 0 && + pthread_kill(g_dp_queue_manager_tid, 0) != ESRCH) { + //send signal to queue thread + g_dp_queue_manager_tid = 0; + CLIENT_MUTEX_LOCK(&g_dp_queue_manager_mutex); + pthread_cond_signal(&g_dp_queue_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_manager_mutex); + pthread_cancel(g_dp_queue_manager_tid); + int status; + pthread_join(g_dp_queue_manager_tid, (void **)&status); + } +} diff --git a/provider/download-provider-queue.c b/provider/download-provider-queue.c new file mode 100644 index 0000000..ad038fd --- /dev/null +++ b/provider/download-provider-queue.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2013 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 <stdlib.h> + +#include <download-provider-queue.h> +#include <download-provider-log.h> +#include <download-provider-pthread.h> +#include <download-provider-client.h> +#include <download-provider-client-manager.h> + +/* queue + * 1. push : at the tail of linked list + * 2. pop : at the head of linked list + * 3. priority push : at the head of linked list + * 4. in pop, check client of slot, search request by download_id + */ + +//dp_queue_fmt *g_dp_queue = NULL; // head of linked list +pthread_mutex_t g_dp_queue_mutex = PTHREAD_MUTEX_INITIALIZER; + +// normal . push at the tail of queue. +int dp_queue_push(dp_queue_fmt **queue, void *slot, void *request) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + dp_client_slots_fmt *baseslot = slot; + dp_request_fmt *new_request = request; + if (slot == NULL || request == NULL || new_request->id <= 0) { + TRACE_ERROR("check client and request memory address"); + return -1; + } else if (new_request->id <= 0) { + TRACE_ERROR("check slot or download id", new_request->id); + return -1; + } else if (new_request->state != DP_STATE_QUEUED) { + TRACE_ERROR("check id:%d state:%s", new_request->id, dp_print_state(new_request->state)); + return -1; + } + + CLIENT_MUTEX_LOCK(&g_dp_queue_mutex); + // search the tail of queue + int i = 0; + dp_queue_fmt *tailp = *queue; + dp_queue_fmt *prevp = NULL; + TRACE_DEBUG("queue req slot:%p request:%p id:%d", slot, request, (request == NULL ? 0 : new_request->id)); + for (; tailp != NULL; i++) { + dp_request_fmt *qrequestp = tailp->request; + if (tailp->slot == NULL || tailp->request == NULL || + qrequestp->state != DP_STATE_QUEUED) { + TRACE_DEBUG("queue error %d slot:%p request:%p id:%d", i, tailp->slot, tailp->request, (tailp->request == NULL ? 0 : ((dp_request_fmt *)tailp->request)->id)); + } else if (tailp->slot == slot && tailp->request == request && qrequestp->id == new_request->id) { + TRACE_INFO("queue duplicte %d slot:%p request:%p id:%d", i, slot, request, new_request->id); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return 0; + } else { + TRACE_INFO("queue info %d slot:%p request:%p id:%d %s", i, tailp->slot, tailp->request, ((dp_request_fmt *)tailp->request)->id, ((dp_client_slots_fmt *)tailp->slot)->pkgname); + } + prevp = tailp; + tailp = tailp->next; + } + dp_queue_fmt *new_queue = (dp_queue_fmt *)malloc(sizeof(dp_queue_fmt)); + if (new_queue != NULL) { + new_queue->slot = slot; + new_queue->request = request; + new_queue->next = NULL; + if (prevp == NULL) + *queue = new_queue; + else + prevp->next = new_queue; + } else { + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return -1; + } + TRACE_DEBUG("queue push %d info:%s id:%d", i, baseslot->pkgname, new_request->id); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return 0; +} + +int dp_queue_pop(dp_queue_fmt **queue, void **slot, void **request) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL || request == NULL) { + TRACE_ERROR("check client and request memory address"); + return -1; + } + + int lock = CLIENT_MUTEX_TRYLOCK(&g_dp_queue_mutex); + if (lock != 0) { + TRACE_DEBUG("skip queue is used by other thread"); + return 0; + } + if (*queue == NULL) { + //TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return -1; + } + // get a head of queue + int ret = -1; + dp_queue_fmt *popp; + do { + popp = *queue; + *queue = popp->next; + dp_client_slots_fmt *slotp = popp->slot; + dp_request_fmt *requestp = popp->request; + if (slotp == NULL || requestp == NULL || + requestp->state != DP_STATE_QUEUED) { + TRACE_DEBUG("queue error slot:%p request:%p id:%d", popp->slot, popp->request, (requestp == NULL ? 0 : requestp->id)); + free(popp); + } else { + TRACE_INFO("queue pop slot:%p request:%p id:%d %s", popp->slot, popp->request, requestp->id, slotp->pkgname); + *slot = popp->slot; + *request = popp->request; + ret = 0; + free(popp); + break; + } + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return ret; +} + +void dp_queue_clear(dp_queue_fmt **queue, void *request) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return ; + } + if (request == NULL) { + TRACE_ERROR("check client and request memory address"); + return ; + } + CLIENT_MUTEX_LOCK(&g_dp_queue_mutex); + int i = 0; + dp_queue_fmt *tailp = *queue; + dp_queue_fmt *prevp = NULL; + TRACE_DEBUG("queue clear req request:%p id:%d", request, (request == NULL ? 0 : ((dp_request_fmt *)request)->id)); + for (; tailp != NULL; i++) { + dp_request_fmt *requestp = tailp->request; + TRACE_DEBUG("queue info %d request:%p id:%d", i, requestp, (requestp == NULL ? 0 : requestp->id)); + if (requestp == request) { + // clear. + if (prevp == NULL) + *queue = tailp->next; + else + prevp->next = tailp->next; + TRACE_DEBUG("queue clear this %d request:%p id:%d", i, requestp, (requestp == NULL ? 0 : requestp->id)); + free(tailp); + break; + } + prevp = tailp; + tailp = tailp->next; + } + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); +} + +void dp_queue_clear_all(dp_queue_fmt **queue) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return ; + } + CLIENT_MUTEX_LOCK(&g_dp_queue_mutex); + if (queue == NULL || *queue == NULL) { + TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return ; + } + // get a head of queue + do { + dp_queue_fmt *popp = *queue; + *queue = popp->next; + TRACE_DEBUG("queue clear slot:%p request:%p id:%d", popp->slot, popp->request, (popp->request == NULL ? 0 : ((dp_request_fmt *)popp->request)->id)); + free(popp); + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); +} diff --git a/provider/download-provider-smack.c b/provider/download-provider-smack.c new file mode 100644 index 0000000..5e89c45 --- /dev/null +++ b/provider/download-provider-smack.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2013 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 <stdlib.h> +#include <errno.h> +#include <sys/statfs.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <sys/smack.h> + +#include <download-provider.h> +#include <download-provider-log.h> +#include <download-provider-utils.h> + +#define SMACKFS_MAGIC 0x43415d53 +#define SMACKFS_MNT "/smack" + +static int __dp_smack_is_transmute(char *path) +{ + char *dir_label = NULL; + int ret = -1; + if (smack_getlabel(path, &dir_label, SMACK_LABEL_TRANSMUTE) == 0 && + dir_label != NULL) { + if (strncmp(dir_label, "TRUE", strlen(dir_label)) == 0) + ret = 0; + } + free(dir_label); + return ret; +} + +int dp_smack_is_mounted() +{ + struct statfs sfs; + int ret; + do { + ret = statfs(SMACKFS_MNT, &sfs); + } while (ret < 0 && errno == EINTR); + if (ret) { + TRACE_ERROR("[SMACK ERROR]"); + return -1; + } + if (sfs.f_type == SMACKFS_MAGIC) { + return 1; + } + TRACE_ERROR("[SMACK DISABLE]"); + return 0; +} + +int dp_smack_set_label(char *label, char *source, char *target) +{ + if (label == NULL || source == NULL || target == NULL) + return DP_ERROR_PERMISSION_DENIED; + + int is_setted_dir_label = 0; + int errorcode = DP_ERROR_NONE; + + if (__dp_smack_is_transmute(source) < 0) { + TRACE_SECURE_ERROR("[SMACK] no transmute:%s", source); + } else { + char *dir_label = NULL; + if (smack_getlabel(source, &dir_label, SMACK_LABEL_ACCESS) == 0) { + if (smack_have_access(label, dir_label, "t") > 0) { + if (smack_setlabel(target, dir_label, SMACK_LABEL_ACCESS) != 0) { + TRACE_SECURE_ERROR("[SMACK ERROR] label:%s", dir_label); + errorcode = DP_ERROR_PERMISSION_DENIED; + } else { + is_setted_dir_label = 1; + } + } else { + TRACE_SECURE_ERROR("[SMACK ERROR] access:%s/%s", label, dir_label); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + } else { + TRACE_SECURE_ERROR("[SMACK ERROR] no label:", source); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + free(dir_label); + } + if (is_setted_dir_label == 0 && + smack_setlabel(target, label, SMACK_LABEL_ACCESS) != 0) { + TRACE_SECURE_ERROR("[SMACK ERROR] label:%s", label); + errorcode = DP_ERROR_PERMISSION_DENIED; + // remove file. + if (dp_is_file_exist(target) == 0) + unlink(target); + } + return errorcode; +} + +char *dp_smack_get_label_from_socket(int sock) +{ + char *label = NULL; + if (smack_new_label_from_socket(sock, &label) != 0) { + free(label); + return NULL; + } + return label; +} + +int dp_smack_is_valid_dir(int uid, int gid, char *smack_label, char *dir) +{ + if (smack_label == NULL || dir == NULL) { + TRACE_ERROR("check parameter %s/%s", smack_label, dir); + return -1; + } + int ret = -1; + struct stat dstate; + if (stat(dir, &dstate) == 0) { + if ((dstate.st_uid == uid && (dstate.st_mode & (S_IRUSR | S_IWUSR)) == (S_IRUSR | S_IWUSR)) || + (dstate.st_gid == gid && (dstate.st_mode & (S_IRGRP | S_IWGRP)) == (S_IRGRP | S_IWGRP)) || + ((dstate.st_mode & (S_IROTH | S_IWOTH)) == (S_IROTH | S_IWOTH))) { + char *dir_label = NULL; + if (smack_getlabel(dir, &dir_label, SMACK_LABEL_ACCESS) == 0 && + smack_have_access(smack_label, dir_label, "rw") > 0) { + ret = 0; + } + free(dir_label); + } + } + return ret; +} + +int dp_is_valid_dir(const char *dirpath) +{ + struct stat dir_state; + int stat_ret; + if (dirpath == NULL) { + TRACE_ERROR("check path"); + return -1; + } + stat_ret = stat(dirpath, &dir_state); + if (stat_ret == 0 && S_ISDIR(dir_state.st_mode)) { + return 0; + } + return -1; +} + +void dp_rebuild_dir(const char *dirpath, mode_t mode) +{ + if (dp_is_valid_dir(dirpath) < 0) { + if (mkdir(dirpath, mode) == 0) { + TRACE_INFO("check directory:%s", dirpath); + if (smack_setlabel(dirpath, "_", SMACK_LABEL_ACCESS) != 0) { + TRACE_SECURE_ERROR("failed to set smack label:%s", dirpath); + } + } else { + TRACE_STRERROR("failed to create directory:%s", dirpath); + } + } +} diff --git a/provider/download-provider-utils.c b/provider/download-provider-utils.c new file mode 100644 index 0000000..a1fb736 --- /dev/null +++ b/provider/download-provider-utils.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/stat.h> +#include <sys/types.h> + +#include <sys/time.h> +#include <sys/statfs.h> +#include <unistd.h> + +#include "download-provider-log.h" + +char *dp_strdup(char *src) +{ + char *dest = NULL; + size_t src_len = 0; + + if (src == NULL) { + TRACE_ERROR("[CHECK PARAM]"); + return NULL; + } + + src_len = strlen(src); + if (src_len <= 0) { + TRACE_ERROR("[CHECK PARAM] len[%d]", src_len); + return NULL; + } + + dest = (char *)calloc(src_len + 1, sizeof(char)); + if (dest == NULL) { + TRACE_STRERROR("[CHECK] allocation"); + return NULL; + } + memcpy(dest, src, src_len * sizeof(char)); + dest[src_len] = '\0'; + + return dest; +} + +int dp_is_file_exist(const char *file_path) +{ + struct stat file_state; + int stat_ret; + + if (file_path == NULL) { + TRACE_ERROR("[NULL-CHECK] file path is NULL"); + return -1; + } + + stat_ret = stat(file_path, &file_state); + + if (stat_ret == 0) + if (file_state.st_mode & S_IFREG) + return 0; + + return -1; +} + +long dp_get_file_modified_time(const char *file_path) +{ + struct stat file_state; + int stat_ret; + + if (file_path == NULL) { + TRACE_ERROR("[NULL-CHECK] file path is NULL"); + return -1; + } + + stat_ret = stat(file_path, &file_state); + if (stat_ret == 0) + return file_state.st_mtime; + return -1; +} + +int dp_remove_file(const char *file_path) +{ + if ((file_path != NULL && strlen(file_path) > 0) && + dp_is_file_exist(file_path) == 0) { + if (unlink(file_path) != 0) { + TRACE_STRERROR("failed to remove file"); + return -1; + } + return 0; + } + return -1; +} diff --git a/provider/include/download-provider-client-manager.h b/provider/include/download-provider-client-manager.h new file mode 100644 index 0000000..0bb02ec --- /dev/null +++ b/provider/include/download-provider-client-manager.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 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 DOWNLOAD_PROVIDER_CLIENT_MANAGER_H +#define DOWNLOAD_PROVIDER_CLIENT_MANAGER_H + +#include <download-provider.h> +#include <download-provider-client.h> + +typedef struct { + dp_credential credential; + pthread_mutex_t mutex; // lock whenever access client variable + pthread_t thread; + char *pkgname; + dp_client_fmt client; +} dp_client_slots_fmt; + +int dp_client_slot_free(dp_client_slots_fmt *slot); +void dp_broadcast_signal(); +char *dp_db_get_client_smack_label(const char *pkgname); + +#endif diff --git a/provider/include/download-provider-client.h b/provider/include/download-provider-client.h new file mode 100644 index 0000000..6ce8d14 --- /dev/null +++ b/provider/include/download-provider-client.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013 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 DOWNLOAD_PROVIDER_CLIENT_H +#define DOWNLOAD_PROVIDER_CLIENT_H + +#include <pthread.h> +#include <download-provider.h> + +typedef struct { + int state; // downloading state, to prevent the crash, placed at the head of structure. + int id; // ID created in create request in requests thread. + int agent_id; + int error; + int network_type; + int access_time; + unsigned state_cb; // set : 1 unset : 0 + unsigned progress_cb; // set : 1 unset : 0 + unsigned startcount; + size_t progress_lasttime; + unsigned long long received_size; // progress + unsigned long long file_size; + dp_content_type content_type; + int noti_type; + int noti_priv_id; + void *next; +} dp_request_fmt; + +typedef struct { + int channel; // ipc , if negative means dummy client + int notify; // event + int access_time; + void *dbhandle; + dp_request_fmt *requests; +} dp_client_fmt; + +void *dp_client_request_thread(void *arg); +char *dp_print_state(int state); +char *dp_print_errorcode(int errorcode); +char *dp_print_section(short section); +char *dp_print_property(unsigned property); +void dp_request_create(dp_client_fmt *client, dp_request_fmt *request); +void dp_request_free(dp_request_fmt *request); +int dp_request_destroy(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp); +void dp_client_clear_requests(void *slotp); + +#endif diff --git a/provider/include/download-provider-config.h b/provider/include/download-provider-config.h new file mode 100755 index 0000000..5ab6bce --- /dev/null +++ b/provider/include/download-provider-config.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 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 DOWNLOAD_PROVIDER_CONFIG_H +#define DOWNLOAD_PROVIDER_CONFIG_H + +#include <download-provider.h> + +// client-manager +#define DP_MAX_CLIENTS 32 // the maximun number of slots +#define DP_CARE_CLIENT_MANAGER_INTERVAL 120 +#define DP_CARE_CLIENT_REQUEST_INTERVAL 120 +#define DP_CARE_CLIENT_CLEAR_INTERVAL 200 + +// database +#define DP_CARE_CLIENT_INFO_PERIOD 48 // hour + +// each client thread +#define DP_MAX_REQUEST MAX_DOWNLOAD_HANDLE +#define DP_LOG_DB_LIMIT_ROWS 1000 +#define DP_LOG_DB_CLEAR_LIMIT_ONE_TIME 100 + +// queue-manager +#define DP_MAX_DOWNLOAD_AT_ONCE 50 + +#endif diff --git a/provider/include/download-provider-db-defs.h b/provider/include/download-provider-db-defs.h new file mode 100644 index 0000000..6fd1a46 --- /dev/null +++ b/provider/include/download-provider-db-defs.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2012 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 DOWNLOAD_PROVIDER_DB_DEFS_H +#define DOWNLOAD_PROVIDER_DB_DEFS_H + +#define DP_DBFILE_CLIENTS ".download-provider-clients" + +// provider have a groups database file. +#define DP_TABLE_CLIENTS "clients" +// each client has a database file with below tables. file is named as pkgname. +#define DP_TABLE_LOGGING "logging" +#define DP_TABLE_REQUEST "request" +#define DP_TABLE_DOWNLOAD "download" +#define DP_TABLE_HEADERS "header" +#define DP_TABLE_NOTIFICATION "notification" + +// common +#define DP_DB_COL_ROW_ID "ROWID" +#define DP_DB_COL_ID "id" +#define DP_DB_COL_CREATE_TIME "createtime" +#define DP_DB_COL_ACCESS_TIME "accesstime" + +// clients table +#define DP_DB_COL_SMACK_LABEL "smack_label" +#define DP_DB_COL_PACKAGE "package" +#define DP_DB_COL_UID "uid" +#define DP_DB_COL_GID "gid" +#define DP_DB_COL_REQUEST_COUNT "requests" + +// logging table +#define DP_DB_COL_STATE "state" +#define DP_DB_COL_ERRORCODE "errorcode" +#define DP_DB_COL_AUTO_DOWNLOAD "auto_download" +#define DP_DB_COL_STARTCOUNT "startcount" + +// request table +#define DP_DB_COL_URL "url" +#define DP_DB_COL_DESTINATION "destination" +#define DP_DB_COL_FILENAME "filename" +#define DP_DB_COL_STATE_EVENT "state_event" +#define DP_DB_COL_PROGRESS_EVENT "progress_event" +#define DP_DB_COL_NETWORK_TYPE "network_type" +#define DP_DB_COL_NETWORK_BONDING "network_bonding" +#define DP_DB_COL_TEMP_FILE_PATH "temp_file_path" + +// download table +#define DP_DB_COL_SAVED_PATH "saved_path" +#define DP_DB_COL_TMP_SAVED_PATH "tmp_saved_path" +#define DP_DB_COL_MIMETYPE "mimetype" +#define DP_DB_COL_CONTENT_NAME "content_name" +#define DP_DB_COL_ETAG "etag" +#define DP_DB_COL_CONTENT_SIZE "content_size" +#define DP_DB_COL_HTTP_STATUS "http_status" + +// notification table +#define DP_DB_COL_NOTI_TYPE "type" +#define DP_DB_COL_NOTI_SUBJECT "subject" +#define DP_DB_COL_NOTI_DESCRIPTION "description" +#define DP_DB_COL_NOTI_PRIV_ID "priv_id" +#define DP_DB_COL_NOTI_RAW_ONGOING "raw_ongoing" +#define DP_DB_COL_NOTI_RAW_COMPLETE "raw_completed" +#define DP_DB_COL_NOTI_RAW_FAIL "raw_failed" + +// http headers table +#define DP_DB_COL_HEADER_FIELD "header_field" +#define DP_DB_COL_HEADER_DATA "header_data" + + + +// when a client is accepted, add +// when disconnected with no request, clear +// if exist, it's possible to be remain some requests +#define DP_SCHEMA_CLIENTS "CREATE TABLE IF NOT EXISTS clients(\ +id INTEGER UNIQUE PRIMARY KEY,\ +package TEXT UNIQUE NOT NULL,\ +smack_label TEXT DEFAULT NULL,\ +uid INTEGER DEFAULT 0,\ +gid INTEGER DEFAULT 0,\ +requests INTEGER DEFAULT 0,\ +createtime DATE,\ +accesstime DATE\ +)" + +// limitation : 1000 rows, 48 hours standard by createtime +#define DP_SCHEMA_LOGGING "CREATE TABLE IF NOT EXISTS logging(\ +id INTEGER UNIQUE PRIMARY KEY DESC NOT NULL,\ +state INTEGER DEFAULT 0,\ +errorcode INTEGER DEFAULT 0,\ +auto_download BOOLEAN DEFAULT 0,\ +startcount INTEGER DEFAULT 0,\ +createtime DATE,\ +accesstime DATE\ +)" + +#define DP_SCHEMA_REQUEST "CREATE TABLE IF NOT EXISTS request(\ +id INTEGER UNIQUE PRIMARY KEY,\ +state_event BOOLEAN DEFAULT 0,\ +progress_event BOOLEAN DEFAULT 0,\ +network_type TINYINT DEFAULT 3,\ +filename TEXT DEFAULT NULL,\ +destination TEXT DEFAULT NULL,\ +url TEXT DEFAULT NULL,\ +temp_file_path TEXT DEFAULT NULL,\ +network_bonding BOOLEAN DEFAULT 0,\ +FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE\ +)" + +#define DP_SCHEMA_DOWNLOAD "CREATE TABLE IF NOT EXISTS download(\ +id INTEGER UNIQUE PRIMARY KEY,\ +http_status INTEGER DEFAULT 0,\ +content_size UNSIGNED BIG INT DEFAULT 0,\ +mimetype VARCHAR(64) DEFAULT NULL,\ +content_name TEXT DEFAULT NULL,\ +saved_path TEXT DEFAULT NULL,\ +tmp_saved_path TEXT DEFAULT NULL,\ +etag TEXT DEFAULT NULL,\ +FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE\ +)" + +#define DP_SCHEMA_NOTIFICATION "CREATE TABLE IF NOT EXISTS notification(\ +id INTEGER UNIQUE PRIMARY KEY,\ +subject TEXT DEFAULT NULL,\ +description TEXT DEFAULT NULL,\ +type INTEGER DEFAULT 0,\ +priv_id INTEGER DEFAULT -1,\ +raw_completed BLOB DEFAULT NULL,\ +raw_failed BLOB DEFAULT NULL,\ +raw_ongoing BLOB DEFAULT NULL,\ +FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE\ +)" + +#define DP_SCHEMA_HEADER "CREATE TABLE IF NOT EXISTS header(\ +id INTEGER NOT NULL,\ +header_field TEXT DEFAULT NULL,\ +header_data TEXT DEFAULT NULL,\ +FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE\ +)" + +#define DP_SCHEMA_LOGGING_INDEX "CREATE UNIQUE INDEX IF NOT EXISTS requests_index ON logging (id, state, errorcode, createtime, accesstime)" + + + +#endif diff --git a/provider/include/download-provider-db.h b/provider/include/download-provider-db.h new file mode 100755 index 0000000..6f3a938 --- /dev/null +++ b/provider/include/download-provider-db.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 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 DOWNLOAD_PROVIDER_DB_H +#define DOWNLOAD_PROVIDER_DB_H + +int dp_db_check_connection(void *handle); +int dp_db_open_client_manager(void **handle); +int dp_db_open_client(void **handle, char *pkgname); +int dp_db_open_client_v2(void **handle, char *pkgname); +int dp_db_remove_database(char *pkgname, long now_time, long diff_time); +int dp_db_get_ids(void *handle, const char *table, char *idcolumn, int *ids, const char *where, const int limit, char *ordercolumn, char *ordering, int *error); +int dp_db_get_crashed_ids(void *handle, const char *table, int *ids, const int limit, int *error); +void dp_db_close(void *handle); +void dp_db_reset(void *stmt); +void dp_db_finalize(void *stmt); +int dp_db_get_errorcode(void *handle); + +int dp_db_check_duplicated_int(void *handle, const char *table, const char *column, const int value, int *error); +int dp_db_check_duplicated_string(void *handle, const int id, const char *table, const char *column, const int is_like, const char *value, int *error); +int dp_db_update_client_info(void *handle, const char *pkgname, const char *smack, const int uid, const int gid, int *error); +int dp_db_get_client_property_string(void *handle, const char *pkgname, const char *column, unsigned char **value, unsigned *length, int *error); +int dp_db_new_logging(void *handle, const int id, const int state, const int errorvalue, int *error); +int dp_db_update_logging(void *handle, const int id, const int state, const int errorvalue, int *error); +int dp_db_replace_property(void *handle, const int id, const char *table, const char *column, const void *value, const unsigned length, const unsigned valuetype, int *error); +int dp_db_get_property_string(void *handle, const int id, const char *table, const char *column, unsigned char **value, unsigned *length, int *error); +int dp_db_get_property_int(void *handle, const int id, const char *table, const char *column, void *value, int *error); +int dp_db_unset_property_string(void *handle, const int id, const char *table, const char *column, int *error); +int dp_db_delete(void *handle, const int id, const char *table, int *error); + + +int dp_db_new_header(void *handle, const int id, const char *field, const char *value, int *error); +int dp_db_update_header(void *handle, const int id, const char *field, const char *value, int *error); +int dp_db_get_header_value(void *handle, const int id, const char *field, unsigned char **value, unsigned *length, int *error); +int dp_db_cond_delete(void *handle, const int id, const char *table, const char *column, const void *value, const unsigned valuetype, int *error); +int dp_db_get_cond_ids(void *handle, const char *table, const char *getcolumn, const char *column, const int value, int *ids, const int limit, int *error); +int dp_db_get_cond_string(void *handle, const char *table, char *wherecolumn, const int wherevalue, const char *getcolumn, unsigned char **value, unsigned *length, int *error); +int dp_db_limit_rows(void *handle, const char *table, int limit, int *error); +int dp_db_limit_time(void *handle, const char *table, int hours, int *error); +int dp_db_get_http_headers_list(void *handle, int id, char **headers, int *error); + +#endif diff --git a/provider/include/download-provider-ipc.h b/provider/include/download-provider-ipc.h new file mode 100644 index 0000000..afddbe6 --- /dev/null +++ b/provider/include/download-provider-ipc.h @@ -0,0 +1,36 @@ + +/* + * Copyright (c) 2012 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 DOWNLOAD_PROVIDER_IPC_H +#define DOWNLOAD_PROVIDER_IPC_H + +#include "download-provider.h" + +int dp_ipc_check_stderr(int basecode); +int dp_ipc_write(int sock, void *value, size_t type_size); +ssize_t dp_ipc_read(int sock, void *value, size_t type_size, + const char *func); + + +dp_ipc_fmt *dp_ipc_get_fmt(int sock); +int dp_ipc_query(int sock, int download_id, short section, + unsigned property, int error, size_t size); + +int dp_ipc_socket_free(int sockfd); + +#endif + diff --git a/provider/include/download-provider-log.h b/provider/include/download-provider-log.h new file mode 100755 index 0000000..5b1b0cd --- /dev/null +++ b/provider/include/download-provider-log.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2012 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 DOWNLOAD_PROVIDER2_LOG_H +#define DOWNLOAD_PROVIDER2_LOG_H + +#ifdef SUPPORT_LOG_MESSAGE +#include <errno.h> +#include <dlog.h> +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG DOWNLOAD_PROVIDER_LOG_TAG +#if defined(LOGD) && defined(TIZEN_DEBUG_ENABLE) +#define TRACE_DEBUG(format, ARG...) LOGD(format, ##ARG) +#else +#define TRACE_DEBUG(...) do { } while(0) +#endif +#define TRACE_ERROR(format, ARG...) LOGE(format, ##ARG) +#define TRACE_STRERROR(format, ARG...) LOGE(format" [%s]", ##ARG, strerror(errno)) +#define TRACE_INFO(format, ARG...) LOGI(format, ##ARG) +#define TRACE_WARN(format, ARG...) LOGW(format, ##ARG) + +#if defined(SECURE_LOGD) && defined(TIZEN_DEBUG_ENABLE) +#define TRACE_SECURE_DEBUG(format, ARG...) SECURE_LOGD(format, ##ARG) +#else +#define TRACE_SECURE_DEBUG(...) do { } while(0) +#endif +#if defined(SECURE_LOGI) && defined(TIZEN_DEBUG_ENABLE) +#define TRACE_SECURE_INFO(format, ARG...) SECURE_LOGI(format, ##ARG) +#else +#define TRACE_SECURE_INFO(...) do { } while(0) +#endif +#if defined(SECURE_LOGE) && defined(TIZEN_DEBUG_ENABLE) +#define TRACE_SECURE_ERROR(format, ARG...) SECURE_LOGE(format, ##ARG) +#else +#define TRACE_SECURE_ERROR(...) do { } while(0) +#endif + +#else +#define TRACE_DEBUG(...) do { } while(0) +#define TRACE_ERROR(...) do { } while(0) +#define TRACE_STRERROR(...) do { } while(0) +#define TRACE_INFO(...) do { } while(0) +#define TRACE_WARN(...) do { } while(0) +#define TRACE_SECURE_DEBUG(...) do { } while(0) +#define TRACE_SECURE_INFO(...) do { } while(0) +#define TRACE_SECURE_ERROR(...) do { } while(0) +#endif + +#endif diff --git a/provider/include/download-provider-network.h b/provider/include/download-provider-network.h new file mode 100755 index 0000000..73fc12d --- /dev/null +++ b/provider/include/download-provider-network.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012 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 DOWNLOAD_PROVIDER_NETWORK_H +#define DOWNLOAD_PROVIDER_NETWORK_H + +#define DP_NETWORK_OFF -1 + +typedef enum { + DP_NETWORK_DATA_NETWORK = 0, + DP_NETWORK_WIFI = 1, + DP_NETWORK_WIFI_DIRECT = 2, + DP_NETWORK_ALL = 3 +} dp_network_defs; + +int dp_network_connection_init(); +void dp_network_connection_destroy(); +int dp_network_get_status(); +int dp_network_is_wifi_direct(); + +#endif diff --git a/provider/include/download-provider-notification-manager.h b/provider/include/download-provider-notification-manager.h new file mode 100644 index 0000000..0ffa740 --- /dev/null +++ b/provider/include/download-provider-notification-manager.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 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 DOWNLOAD_PROVIDER_NOTIFICATION_MANAGER_H +#define DOWNLOAD_PROVIDER_NOTIFICATION_MANAGER_H + +typedef enum { + DP_NOTIFICATION = 0, + DP_NOTIFICATION_ONGOING, + DP_NOTIFICATION_ONGOING_PROGRESS, + DP_NOTIFICATION_ONGOING_UPDATE, +} dp_noti_type; + +void dp_notification_manager_kill(); +void dp_notification_manager_wake_up(); +int dp_notification_manager_clear_notification(void *slot, void *request, const dp_noti_type type); +//int dp_notification_manager_push_notification_ongoing(void *slot, void *request, const dp_noti_type type); +int dp_notification_manager_push_notification(void *slot, void *request, const dp_noti_type type); + +#endif diff --git a/provider/include/download-provider-notification.h b/provider/include/download-provider-notification.h new file mode 100755 index 0000000..eb3f56e --- /dev/null +++ b/provider/include/download-provider-notification.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 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 DOWNLOAD_PROVIDER_NOTIFICATION_H +#define DOWNLOAD_PROVIDER_NOTIFICATION_H + +#ifdef SUPPORT_NOTIFICATION +void dp_notification_set_locale(void); +void dp_notification_clear_locale(void); +void dp_notification_clear_ongoings(void); +int dp_notification_delete_ongoing(const int noti_priv_id); +int dp_notification_delete(const int noti_priv_id); +int dp_notification_ongoing_new(const char *pkgname, const char *subject, unsigned char *raws_buffer, const int raws_length); +int dp_notification_ongoing_update(const int noti_priv_id, const double received_size, const double file_size, const char *subject); +int dp_notification_new(void *dbhandle, const int download_id, const int state, int content_type, const char *pkgname); +#else +void dp_notification_clear_ongoings(void); +#endif + +#endif diff --git a/provider/include/download-provider-notify.h b/provider/include/download-provider-notify.h new file mode 100644 index 0000000..80c21d9 --- /dev/null +++ b/provider/include/download-provider-notify.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 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 DOWNLOAD_PROVIDER_NOTIFY_H +#define DOWNLOAD_PROVIDER_NOTIFY_H + +int dp_notify_init(pid_t pid); +void dp_notify_deinit(pid_t pid); +int dp_notify_feedback(int sock, void *slot, int id, int state, int errorcode, unsigned long long received_size); + +#endif diff --git a/provider/include/download-provider-plugin-download-agent.h b/provider/include/download-provider-plugin-download-agent.h new file mode 100644 index 0000000..e3fb9c7 --- /dev/null +++ b/provider/include/download-provider-plugin-download-agent.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012 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 DOWNLOAD_PROVIDER_PLUGIN_DOWNLOAD_AGENT_H +#define DOWNLOAD_PROVIDER_PLUGIN_DOWNLOAD_AGENT_H + +int dp_is_file_exist(const char *file_path); +int dp_init_agent(); +void dp_deinit_agent(); +int dp_start_agent_download(void *slot, void *request); +int dp_resume_agent_download(int req_id); +int dp_pause_agent_download(int req_id); +int dp_cancel_agent_download(int req_id); +int dp_is_alive_download(int req_id); +int dp_cancel_agent_download_without_update(int req_id); +int dp_pause_agent_download_without_update(int req_id); + +#endif diff --git a/provider/include/download-provider-pthread.h b/provider/include/download-provider-pthread.h new file mode 100755 index 0000000..74e6036 --- /dev/null +++ b/provider/include/download-provider-pthread.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012 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 DOWNLOAD_PROVIDER_PTHREAD_H +#define DOWNLOAD_PROVIDER_PTHREAD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <pthread.h> + +// download-provider use default style mutex. +int dp_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); +void dp_mutex_lock(pthread_mutex_t *mutex, const char *func, int line); +int dp_mutex_check_lock(pthread_mutex_t *mutex, const char *func, int line); +int dp_mutex_trylock(pthread_mutex_t *mutex, const char *func, int line); +int dp_mutex_timedlock(pthread_mutex_t *mutex, int sec, const char *func, int line); +void dp_mutex_unlock(pthread_mutex_t *mutex, const char *func, int line); +void dp_mutex_destroy(pthread_mutex_t *mutex); + +#define CLIENT_MUTEX_LOCK(mutex) dp_mutex_lock(mutex, __FUNCTION__, __LINE__) +#define CLIENT_MUTEX_CHECKLOCK(mutex) dp_mutex_check_lock(mutex, __FUNCTION__, __LINE__) +#define CLIENT_MUTEX_TRYLOCK(mutex) dp_mutex_trylock(mutex, __FUNCTION__, __LINE__) +#define CLIENT_MUTEX_TIMEDLOCK(mutex, sec) dp_mutex_timedlock(mutex, sec, __FUNCTION__, __LINE__) +#define CLIENT_MUTEX_UNLOCK(mutex) dp_mutex_unlock(mutex, __FUNCTION__, __LINE__) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/provider/include/download-provider-queue-manager.h b/provider/include/download-provider-queue-manager.h new file mode 100644 index 0000000..ba7e641 --- /dev/null +++ b/provider/include/download-provider-queue-manager.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 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 DOWNLOAD_PROVIDER_QUEUE_MANAGER_H +#define DOWNLOAD_PROVIDER_QUEUE_MANAGER_H + +void dp_queue_manager_kill(); +void dp_queue_manager_wake_up(); +int dp_queue_manager_push_queue(void *slot, void *request); +void dp_queue_manager_clear_queue(void *request); + +#endif diff --git a/provider/include/download-provider-queue.h b/provider/include/download-provider-queue.h new file mode 100755 index 0000000..a8efcfa --- /dev/null +++ b/provider/include/download-provider-queue.h @@ -0,0 +1,31 @@ +/*
+ * Copyright (c) 2013 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 DOWNLOAD_PROVIDER_QUEUE_H
+#define DOWNLOAD_PROVIDER_QUEUE_H
+
+typedef struct { // manage clients without mutex
+ void *slot; // client can not be NULL. it will exist in dummy
+ void *request;
+ void *next;
+} dp_queue_fmt;
+
+int dp_queue_push(dp_queue_fmt **queue, void *slot, void *request);
+int dp_queue_pop(dp_queue_fmt **queue, void **slot, void **request);
+void dp_queue_clear(dp_queue_fmt **queue, void *request);
+void dp_queue_clear_all(dp_queue_fmt **queue);
+
+#endif
diff --git a/provider/include/download-provider-smack.h b/provider/include/download-provider-smack.h new file mode 100644 index 0000000..aa78d01 --- /dev/null +++ b/provider/include/download-provider-smack.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 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 DOWNLOAD_PROVIDER_SMACK_H +#define DOWNLOAD_PROVIDER_SMACK_H + +#ifdef SUPPORT_SECURITY_PRIVILEGE +#include <security-server.h> +#define SECURITY_PRIVILEGE_INTERNET "system::use_internet" +#endif + +int dp_smack_is_mounted(); +int dp_smack_set_label(char *label, char *source, char *target); +char *dp_smack_get_label_from_socket(int sock); +int dp_smack_is_valid_dir(int uid, int gid, char *smack_label, char *dir); +void dp_rebuild_dir(const char *dirpath, mode_t mode); +int dp_is_valid_dir(const char *dirpath); + + +#endif diff --git a/provider/include/download-provider-utils.h b/provider/include/download-provider-utils.h new file mode 100644 index 0000000..d965db4 --- /dev/null +++ b/provider/include/download-provider-utils.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2012 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 DOWNLOAD_PROVIDER_UTILS_H +#define DOWNLOAD_PROVIDER_UTILS_H + +char *dp_strdup(char *src); +int dp_is_file_exist(const char *file_path); +long dp_get_file_modified_time(const char *file_path); +int dp_remove_file(const char *file_path); + +#endif diff --git a/provider/include/download-provider.h b/provider/include/download-provider.h new file mode 100755 index 0000000..92e1fde --- /dev/null +++ b/provider/include/download-provider.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2012 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 DOWNLOAD_PROVIDER_H +#define DOWNLOAD_PROVIDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + DP_STATE_NONE = 0, + DP_STATE_READY = DP_STATE_NONE + 5, // created id, set some info. + DP_STATE_QUEUED = DP_STATE_NONE + 10, // request to start + DP_STATE_CONNECTING = DP_STATE_NONE + 15, // try to connect to url + DP_STATE_DOWNLOADING = DP_STATE_NONE + 20, // started + DP_STATE_PAUSED = DP_STATE_NONE + 30, // paused actually + DP_STATE_COMPLETED = DP_STATE_NONE + 40, + DP_STATE_CANCELED = DP_STATE_NONE + 45, // stopped with error + DP_STATE_FAILED = DP_STATE_NONE + 50 // failed with error +} dp_state_type; + +typedef enum { + DP_ERROR_NONE = 10, + DP_ERROR_INVALID_PARAMETER = DP_ERROR_NONE + 1, + DP_ERROR_OUT_OF_MEMORY = DP_ERROR_NONE + 2, + DP_ERROR_IO_ERROR = DP_ERROR_NONE + 3, + DP_ERROR_NETWORK_UNREACHABLE = DP_ERROR_NONE + 4, + DP_ERROR_CONNECTION_TIMED_OUT = DP_ERROR_NONE + 5, + DP_ERROR_NO_SPACE = DP_ERROR_NONE + 6, + DP_ERROR_FIELD_NOT_FOUND = DP_ERROR_NONE + 7, + DP_ERROR_INVALID_STATE = DP_ERROR_NONE + 8, + DP_ERROR_CONNECTION_FAILED = DP_ERROR_NONE + 9, + DP_ERROR_INVALID_URL = DP_ERROR_NONE + 10, + DP_ERROR_INVALID_DESTINATION = DP_ERROR_NONE + 11, + DP_ERROR_QUEUE_FULL = DP_ERROR_NONE + 12, + DP_ERROR_ALREADY_COMPLETED = DP_ERROR_NONE + 13, + DP_ERROR_FILE_ALREADY_EXISTS = DP_ERROR_NONE + 14, + DP_ERROR_TOO_MANY_DOWNLOADS = DP_ERROR_NONE + 15, + DP_ERROR_NETWORK_ERROR = DP_ERROR_NONE + 16, + DP_ERROR_NO_DATA = DP_ERROR_NONE + 17, + DP_ERROR_UNHANDLED_HTTP_CODE = DP_ERROR_NONE + 18, + DP_ERROR_CANNOT_RESUME = DP_ERROR_NONE + 19, + DP_ERROR_PERMISSION_DENIED = DP_ERROR_NONE + 20, + DP_ERROR_INVALID_NETWORK_TYPE = DP_ERROR_NONE + 21, + DP_ERROR_RESPONSE_TIMEOUT = DP_ERROR_NONE + 50, + DP_ERROR_REQUEST_TIMEOUT = DP_ERROR_NONE + 55, + DP_ERROR_SYSTEM_DOWN = DP_ERROR_NONE + 60, + DP_ERROR_CLIENT_DOWN = DP_ERROR_NONE + 65, + DP_ERROR_DISK_BUSY = DP_ERROR_NONE + 70, + DP_ERROR_ID_NOT_FOUND = DP_ERROR_NONE + 90, + DP_ERROR_IO_EAGAIN = DP_ERROR_NONE + 97, + DP_ERROR_IO_EINTR = DP_ERROR_NONE + 98, + DP_ERROR_IO_TIMEOUT = DP_ERROR_NONE + 99, + DP_ERROR_UNKNOWN = DP_ERROR_NONE + 100 +} dp_error_type; + +typedef enum { + DP_NOTIFICATION_BUNDLE_TYPE_ONGOING = 0, // Ongoing, Failed + DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE, // Completed + DP_NOTIFICATION_BUNDLE_TYPE_FAILED // Failed +} dp_notification_bundle_type; + +typedef enum { + DP_NOTIFICATION_SERVICE_TYPE_ONGOING = 0, // Ongoing, Failed + DP_NOTIFICATION_SERVICE_TYPE_COMPLETE, // Completed + DP_NOTIFICATION_SERVICE_TYPE_FAILED // Failed +} dp_notification_service_type; + + +typedef enum { + DP_NOTIFICATION_TYPE_NONE = 0, // Not register Noti. + DP_NOTIFICATION_TYPE_COMPLETE_ONLY, // Success, Failed + DP_NOTIFICATION_TYPE_ALL // Ongoing, Success, Failed +} dp_notification_type; + + +#ifndef IPC_SOCKET +#define IPC_SOCKET "/opt/data/download-provider/download-provider.sock" +#endif + +#define MAX_DOWNLOAD_HANDLE 32 +#define DP_MAX_STR_LEN 2048 +#define DP_DEFAULT_BUFFER_SIZE 1024 + +// string to check invalid characters in path before using open() and fopen() API's +#define DP_INVALID_PATH_STRING ";\\\":*?<>|()" + + +#include <unistd.h> + +typedef struct { + pid_t pid; + uid_t uid; + gid_t gid; +} dp_credential; + +typedef enum { + DP_SEC_NONE = 0, + DP_SEC_INIT, + DP_SEC_DEINIT, + DP_SEC_CONTROL, + DP_SEC_GET, + DP_SEC_SET, + DP_SEC_UNSET +} dp_ipc_section_defs; + +typedef enum { + DP_PROP_NONE = 0, + DP_PROP_CREATE, + DP_PROP_START, + DP_PROP_PAUSE, + DP_PROP_CANCEL, + DP_PROP_DESTROY, + DP_PROP_URL, + DP_PROP_DESTINATION, + DP_PROP_FILENAME, + DP_PROP_STATE_CALLBACK, + DP_PROP_PROGRESS_CALLBACK, + DP_PROP_AUTO_DOWNLOAD, + DP_PROP_NETWORK_TYPE, + DP_PROP_NETWORK_BONDING, + DP_PROP_SAVED_PATH, + DP_PROP_TEMP_SAVED_PATH, + DP_PROP_MIME_TYPE, + DP_PROP_RECEIVED_SIZE, + DP_PROP_TOTAL_FILE_SIZE, + DP_PROP_CONTENT_NAME, + DP_PROP_HTTP_STATUS, + DP_PROP_ETAG, + DP_PROP_STATE, + DP_PROP_ERROR, + DP_PROP_HTTP_HEADERS, + DP_PROP_HTTP_HEADER, + DP_PROP_NOTIFICATION_RAW, + DP_PROP_NOTIFICATION_SUBJECT, + DP_PROP_NOTIFICATION_DESCRIPTION, + DP_PROP_NOTIFICATION_TYPE +} dp_ipc_property_defs; + +typedef enum { + DP_CONTENT_UNKNOWN = 0, + DP_CONTENT_IMAGE, + DP_CONTENT_VIDEO, + DP_CONTENT_MUSIC, + DP_CONTENT_PDF, + DP_CONTENT_WORD, + DP_CONTENT_PPT, // 5 + DP_CONTENT_EXCEL, + DP_CONTENT_HTML, + DP_CONTENT_TEXT, + DP_CONTENT_DRM, + DP_CONTENT_SD_DRM, //10 + DP_CONTENT_FLASH, + DP_CONTENT_TPK, + DP_CONTENT_VCAL, //13 +} dp_content_type; + + +typedef struct { + short section; + unsigned property; + int id; + int errorcode; + size_t size; // followed extra packet size +} dp_ipc_fmt; + +typedef struct { + int id; + int state; + int errorcode; + unsigned long long received_size; +} dp_ipc_event_fmt; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/refresh.sh b/refresh.sh new file mode 100755 index 0000000..18dec57 --- /dev/null +++ b/refresh.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +git fetch --all +git reset --hard origin/tizen_2.4 +git pull + diff --git a/res/images/redwood/B03_processing_download_complete.png b/res/images/redwood/B03_processing_download_complete.png Binary files differnew file mode 100644 index 0000000..109512e --- /dev/null +++ b/res/images/redwood/B03_processing_download_complete.png diff --git a/res/images/redwood/B03_processing_download_fail.png b/res/images/redwood/B03_processing_download_fail.png Binary files differnew file mode 100644 index 0000000..be67ffe --- /dev/null +++ b/res/images/redwood/B03_processing_download_fail.png diff --git a/res/images/redwood/U01_icon_broken.png b/res/images/redwood/U01_icon_broken.png Binary files differnew file mode 100644 index 0000000..9020234 --- /dev/null +++ b/res/images/redwood/U01_icon_broken.png diff --git a/res/images/redwood/U01_icon_drm.png b/res/images/redwood/U01_icon_drm.png Binary files differnew file mode 100644 index 0000000..06e682b --- /dev/null +++ b/res/images/redwood/U01_icon_drm.png diff --git a/res/images/redwood/U01_icon_excel.png b/res/images/redwood/U01_icon_excel.png Binary files differnew file mode 100644 index 0000000..6efd14a --- /dev/null +++ b/res/images/redwood/U01_icon_excel.png diff --git a/res/images/redwood/U01_icon_html.png b/res/images/redwood/U01_icon_html.png Binary files differnew file mode 100644 index 0000000..01260ba --- /dev/null +++ b/res/images/redwood/U01_icon_html.png diff --git a/res/images/redwood/U01_icon_pdf.png b/res/images/redwood/U01_icon_pdf.png Binary files differnew file mode 100644 index 0000000..3f8cda6 --- /dev/null +++ b/res/images/redwood/U01_icon_pdf.png diff --git a/res/images/redwood/U01_icon_ppt.png b/res/images/redwood/U01_icon_ppt.png Binary files differnew file mode 100644 index 0000000..79302eb --- /dev/null +++ b/res/images/redwood/U01_icon_ppt.png diff --git a/res/images/redwood/U01_icon_swf.png b/res/images/redwood/U01_icon_swf.png Binary files differnew file mode 100644 index 0000000..39a49da --- /dev/null +++ b/res/images/redwood/U01_icon_swf.png diff --git a/res/images/redwood/U01_icon_text.png b/res/images/redwood/U01_icon_text.png Binary files differnew file mode 100644 index 0000000..5f8b3bd --- /dev/null +++ b/res/images/redwood/U01_icon_text.png diff --git a/res/images/redwood/U01_icon_tpk.png b/res/images/redwood/U01_icon_tpk.png Binary files differnew file mode 100644 index 0000000..796c788 --- /dev/null +++ b/res/images/redwood/U01_icon_tpk.png diff --git a/res/images/redwood/U01_icon_unkown.png b/res/images/redwood/U01_icon_unkown.png Binary files differnew file mode 100644 index 0000000..25a2801 --- /dev/null +++ b/res/images/redwood/U01_icon_unkown.png diff --git a/res/images/redwood/U01_icon_vcs.png b/res/images/redwood/U01_icon_vcs.png Binary files differnew file mode 100644 index 0000000..72dbf76 --- /dev/null +++ b/res/images/redwood/U01_icon_vcs.png diff --git a/res/images/redwood/U01_icon_word.png b/res/images/redwood/U01_icon_word.png Binary files differnew file mode 100644 index 0000000..a45acd7 --- /dev/null +++ b/res/images/redwood/U01_icon_word.png diff --git a/res/images/redwood/U01_list_icon_image.png b/res/images/redwood/U01_list_icon_image.png Binary files differnew file mode 100644 index 0000000..ebb2a3c --- /dev/null +++ b/res/images/redwood/U01_list_icon_image.png diff --git a/res/images/redwood/U01_list_icon_mp3.png b/res/images/redwood/U01_list_icon_mp3.png Binary files differnew file mode 100644 index 0000000..c5176be --- /dev/null +++ b/res/images/redwood/U01_list_icon_mp3.png diff --git a/res/images/redwood/U01_list_icon_mp4.png b/res/images/redwood/U01_list_icon_mp4.png Binary files differnew file mode 100644 index 0000000..2e3c87b --- /dev/null +++ b/res/images/redwood/U01_list_icon_mp4.png diff --git a/res/images/redwood/noti_download_complete.png b/res/images/redwood/noti_download_complete.png Binary files differnew file mode 100644 index 0000000..6171bd8 --- /dev/null +++ b/res/images/redwood/noti_download_complete.png diff --git a/res/images/redwood/noti_download_failed.png b/res/images/redwood/noti_download_failed.png Binary files differnew file mode 100644 index 0000000..5eb122b --- /dev/null +++ b/res/images/redwood/noti_download_failed.png diff --git a/res/images/tizen2.3/B03_Processing_download_complete.png b/res/images/tizen2.3/B03_Processing_download_complete.png Binary files differnew file mode 100644 index 0000000..8dfb542 --- /dev/null +++ b/res/images/tizen2.3/B03_Processing_download_complete.png diff --git a/res/images/tizen2.3/B03_Processing_download_failed.png b/res/images/tizen2.3/B03_Processing_download_failed.png Binary files differnew file mode 100644 index 0000000..11d34ab --- /dev/null +++ b/res/images/tizen2.3/B03_Processing_download_failed.png diff --git a/res/images/tizen2.3/download_manager_icon_date.png b/res/images/tizen2.3/download_manager_icon_date.png Binary files differnew file mode 100644 index 0000000..f1ff0f8 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_date.png diff --git a/res/images/tizen2.3/download_manager_icon_drm.png b/res/images/tizen2.3/download_manager_icon_drm.png Binary files differnew file mode 100644 index 0000000..7965232 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_drm.png diff --git a/res/images/tizen2.3/download_manager_icon_html.png b/res/images/tizen2.3/download_manager_icon_html.png Binary files differnew file mode 100644 index 0000000..f4a2bfc --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_html.png diff --git a/res/images/tizen2.3/download_manager_icon_img.png b/res/images/tizen2.3/download_manager_icon_img.png Binary files differnew file mode 100644 index 0000000..1c2f137 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_img.png diff --git a/res/images/tizen2.3/download_manager_icon_movie.png b/res/images/tizen2.3/download_manager_icon_movie.png Binary files differnew file mode 100644 index 0000000..5902a67 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_movie.png diff --git a/res/images/tizen2.3/download_manager_icon_music.png b/res/images/tizen2.3/download_manager_icon_music.png Binary files differnew file mode 100644 index 0000000..39f4c06 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_music.png diff --git a/res/images/tizen2.3/download_manager_icon_pdf.png b/res/images/tizen2.3/download_manager_icon_pdf.png Binary files differnew file mode 100644 index 0000000..96b1a9a --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_pdf.png diff --git a/res/images/tizen2.3/download_manager_icon_ppt.png b/res/images/tizen2.3/download_manager_icon_ppt.png Binary files differnew file mode 100644 index 0000000..29159cf --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_ppt.png diff --git a/res/images/tizen2.3/download_manager_icon_swf.png b/res/images/tizen2.3/download_manager_icon_swf.png Binary files differnew file mode 100644 index 0000000..b6335d7 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_swf.png diff --git a/res/images/tizen2.3/download_manager_icon_text.png b/res/images/tizen2.3/download_manager_icon_text.png Binary files differnew file mode 100644 index 0000000..4961fb5 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_text.png diff --git a/res/images/tizen2.3/download_manager_icon_tpk.png b/res/images/tizen2.3/download_manager_icon_tpk.png Binary files differnew file mode 100644 index 0000000..58953be --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_tpk.png diff --git a/res/images/tizen2.3/download_manager_icon_unknown.png b/res/images/tizen2.3/download_manager_icon_unknown.png Binary files differnew file mode 100644 index 0000000..9a367ec --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_unknown.png diff --git a/res/images/tizen2.3/download_manager_icon_word.png b/res/images/tizen2.3/download_manager_icon_word.png Binary files differnew file mode 100644 index 0000000..3218b53 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_word.png diff --git a/res/images/tizen2.3/download_manager_icon_xls.png b/res/images/tizen2.3/download_manager_icon_xls.png Binary files differnew file mode 100644 index 0000000..aeddf20 --- /dev/null +++ b/res/images/tizen2.3/download_manager_icon_xls.png diff --git a/script/commit-template b/script/commit-template new file mode 100644 index 0000000..e398cc3 --- /dev/null +++ b/script/commit-template @@ -0,0 +1,10 @@ +[Title] + +[Issue#] N/A +[Problem] N/A +[Cause] N/A +[Solution] N/A + +# please fill the each items. +# If this is the commit to fix issue, please replace N/A to the number of issue. + diff --git a/systemd/download-provider.service b/systemd/download-provider.service new file mode 100644 index 0000000..4286283 --- /dev/null +++ b/systemd/download-provider.service @@ -0,0 +1,12 @@ +[Unit] +Description=Download provider service +After=check-mount.service + +[Service] +Type=simple +ExecStart=/usr/bin/download-provider +MemoryLimit=100M + +[Install] +WantedBy=graphical.target + diff --git a/systemd/download-provider.socket b/systemd/download-provider.socket new file mode 100644 index 0000000..3130e34 --- /dev/null +++ b/systemd/download-provider.socket @@ -0,0 +1,10 @@ +[Socket] +ListenStream=/opt/data/download-provider/download-provider.sock +SocketMode=0777 +PassCredentials=yes +Accept=false +SmackLabelIPIn=download-provider +SmackLabelIPOut=download-provider + +[Install] +WantedBy=sockets.target |