summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgloryj.kim <gloryj.kim@samsung.com>2015-06-02 20:07:17 +0900
committergloryj.kim <gloryj.kim@samsung.com>2015-06-02 20:07:17 +0900
commit73435351b469a7437b8d4aedd105b59c34b8526e (patch)
treeac0f913425815e84cfc9ddf6e5c20288d1d24481
parent7cbedf051bad1b76d3cba64a76b1181aa913a9e4 (diff)
downloaddownload-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
Change-Id: If2be781597be2fbf185237d0ee538a3626a66444
-rw-r--r--AUTHORS2
-rwxr-xr-xCMakeLists.txt102
-rw-r--r--LICENSE.APLv2202
-rw-r--r--NOTICE3
-rwxr-xr-xagent/CMakeLists.txt116
-rwxr-xr-xagent/download-agent-client-mgr.c145
-rw-r--r--agent/download-agent-dl-info.c462
-rwxr-xr-xagent/download-agent-dl-mgr.c186
-rwxr-xr-xagent/download-agent-encoding.c261
-rwxr-xr-xagent/download-agent-file.c908
-rwxr-xr-xagent/download-agent-http-mgr.c1519
-rwxr-xr-xagent/download-agent-http-msg-handler.c1125
-rwxr-xr-xagent/download-agent-interface.c152
-rwxr-xr-xagent/download-agent-mime-util.c449
-rwxr-xr-xagent/download-agent-plugin-conf.c109
-rw-r--r--agent/download-agent-plugin-drm.c124
-rw-r--r--agent/download-agent-plugin-libcurl.c702
-rw-r--r--agent/download-agent-plugin-libcurl.c~702
-rwxr-xr-xagent/include/download-agent-client-mgr.h27
-rwxr-xr-xagent/include/download-agent-debug.h68
-rwxr-xr-xagent/include/download-agent-defs.h85
-rw-r--r--agent/include/download-agent-dl-info.h197
-rwxr-xr-xagent/include/download-agent-dl-mgr.h27
-rwxr-xr-xagent/include/download-agent-encoding.h27
-rwxr-xr-xagent/include/download-agent-file.h45
-rwxr-xr-xagent/include/download-agent-http-mgr.h34
-rwxr-xr-xagent/include/download-agent-http-msg-handler.h77
-rwxr-xr-xagent/include/download-agent-interface.h97
-rwxr-xr-xagent/include/download-agent-mime-util.h48
-rwxr-xr-xagent/include/download-agent-plugin-conf.h30
-rw-r--r--agent/include/download-agent-plugin-drm.h25
-rw-r--r--agent/include/download-agent-plugin-libcurl.h35
-rwxr-xr-xagent/include/download-agent-pthread.h144
-rwxr-xr-xagent/include/download-agent-type.h73
-rwxr-xr-xbi.sh16
-rw-r--r--blog.txt1758
-rwxr-xr-xbuild.sh1
-rw-r--r--download-provider-w.manifest38
-rw-r--r--download-provider-w.manifest~37
-rw-r--r--download-provider.manifest41
-rw-r--r--download-provider.manifest~40
-rw-r--r--download-provider.pc.in6
-rw-r--r--download-provider.res1
-rw-r--r--dump-download-provider.sh14
-rw-r--r--gbs.conf285
-rwxr-xr-xi.sh10
-rw-r--r--packaging/download-provider.spec215
-rw-r--r--packaging/download-provider.spec~219
-rw-r--r--po/redwood/CMakeLists.txt27
-rw-r--r--po/redwood/az.po6
-rw-r--r--po/redwood/bg.po6
-rw-r--r--po/redwood/ca.po6
-rw-r--r--po/redwood/cs.po6
-rw-r--r--po/redwood/da.po6
-rw-r--r--po/redwood/de.po6
-rw-r--r--po/redwood/el_GR.po6
-rw-r--r--po/redwood/en.po6
-rw-r--r--po/redwood/en_US.po6
-rw-r--r--po/redwood/es_ES.po6
-rw-r--r--po/redwood/es_US.po6
-rw-r--r--po/redwood/et.po6
-rw-r--r--po/redwood/eu.po6
-rw-r--r--po/redwood/fi.po6
-rw-r--r--po/redwood/fr.po6
-rw-r--r--po/redwood/fr_CA.po6
-rw-r--r--po/redwood/gl.po6
-rw-r--r--po/redwood/hr.po6
-rw-r--r--po/redwood/hu.po6
-rw-r--r--po/redwood/hy.po6
-rw-r--r--po/redwood/is.po6
-rw-r--r--po/redwood/it_IT.po6
-rw-r--r--po/redwood/ka.po6
-rw-r--r--po/redwood/kk.po6
-rw-r--r--po/redwood/ko_KR.po6
-rw-r--r--po/redwood/lt.po6
-rw-r--r--po/redwood/lv.po6
-rw-r--r--po/redwood/mn_MN.po6
-rw-r--r--po/redwood/nb.po6
-rw-r--r--po/redwood/nl.po6
-rw-r--r--po/redwood/pl.po6
-rw-r--r--po/redwood/pt_BR.po6
-rw-r--r--po/redwood/pt_PT.po6
-rw-r--r--po/redwood/ro.po6
-rw-r--r--po/redwood/ru_RU.po6
-rw-r--r--po/redwood/sk.po6
-rw-r--r--po/redwood/sl.po6
-rw-r--r--po/redwood/sr.po6
-rw-r--r--po/redwood/sv.po6
-rw-r--r--po/redwood/tr_TR.po6
-rw-r--r--po/redwood/uk.po6
-rw-r--r--po/redwood/uz.po6
-rw-r--r--po/tizen2.3/CMakeLists.txt30
-rw-r--r--po/tizen2.3/ar.po6
-rw-r--r--po/tizen2.3/az.po6
-rw-r--r--po/tizen2.3/bg.po6
-rw-r--r--po/tizen2.3/ca.po6
-rw-r--r--po/tizen2.3/cs.po6
-rw-r--r--po/tizen2.3/da.po6
-rw-r--r--po/tizen2.3/de.po6
-rw-r--r--po/tizen2.3/el_GR.po6
-rw-r--r--po/tizen2.3/en.po6
-rw-r--r--po/tizen2.3/en_PH.po6
-rw-r--r--po/tizen2.3/en_US.po6
-rw-r--r--po/tizen2.3/es_ES.po6
-rw-r--r--po/tizen2.3/es_US.po6
-rw-r--r--po/tizen2.3/et.po6
-rw-r--r--po/tizen2.3/eu.po6
-rw-r--r--po/tizen2.3/fi.po6
-rw-r--r--po/tizen2.3/fr.po6
-rw-r--r--po/tizen2.3/fr_CA.po6
-rw-r--r--po/tizen2.3/ga.po6
-rw-r--r--po/tizen2.3/gl.po6
-rw-r--r--po/tizen2.3/hi.po6
-rw-r--r--po/tizen2.3/hr.po6
-rw-r--r--po/tizen2.3/hu.po6
-rw-r--r--po/tizen2.3/hy.po6
-rw-r--r--po/tizen2.3/is.po6
-rw-r--r--po/tizen2.3/it_IT.po6
-rw-r--r--po/tizen2.3/ja_JP.po6
-rw-r--r--po/tizen2.3/ka.po6
-rw-r--r--po/tizen2.3/kk.po6
-rw-r--r--po/tizen2.3/ko_KR.po6
-rw-r--r--po/tizen2.3/lt.po6
-rw-r--r--po/tizen2.3/lv.po6
-rw-r--r--po/tizen2.3/mk.po6
-rw-r--r--po/tizen2.3/nb.po6
-rw-r--r--po/tizen2.3/nl.po6
-rw-r--r--po/tizen2.3/pl.po6
-rw-r--r--po/tizen2.3/pt_BR.po6
-rw-r--r--po/tizen2.3/pt_PT.po6
-rw-r--r--po/tizen2.3/ro.po6
-rw-r--r--po/tizen2.3/ru_RU.po6
-rw-r--r--po/tizen2.3/sk.po6
-rw-r--r--po/tizen2.3/sl.po6
-rw-r--r--po/tizen2.3/sr.po6
-rw-r--r--po/tizen2.3/sv.po6
-rw-r--r--po/tizen2.3/tr_TR.po6
-rw-r--r--po/tizen2.3/uk.po6
-rw-r--r--po/tizen2.3/uz.po6
-rw-r--r--po/tizen2.3/zh_CN.po6
-rw-r--r--po/tizen2.3/zh_HK.po6
-rw-r--r--po/tizen2.3/zh_TW.po6
-rwxr-xr-xprovider-interface/CMakeLists.txt49
-rwxr-xr-xprovider-interface/download-provider-interface.c1563
-rw-r--r--provider-interface/download-provider-interface.pc.in8
-rwxr-xr-xprovider-interface/include/download-provider-interface.h143
-rwxr-xr-xprovider/CMakeLists.txt123
-rw-r--r--provider/download-provider-client-manager.c741
-rw-r--r--provider/download-provider-client.c2110
-rwxr-xr-xprovider/download-provider-db.c1322
-rw-r--r--provider/download-provider-ipc.c132
-rwxr-xr-xprovider/download-provider-main.c66
-rwxr-xr-xprovider/download-provider-network.c267
-rw-r--r--provider/download-provider-notification-manager.c573
-rwxr-xr-xprovider/download-provider-notification.c629
-rw-r--r--provider/download-provider-notify.c103
-rw-r--r--provider/download-provider-plugin-download-agent.c989
-rw-r--r--provider/download-provider-pthread.c110
-rw-r--r--provider/download-provider-queue-manager.c315
-rw-r--r--provider/download-provider-queue.c194
-rw-r--r--provider/download-provider-smack.c165
-rw-r--r--provider/download-provider-utils.c103
-rw-r--r--provider/include/download-provider-client-manager.h35
-rw-r--r--provider/include/download-provider-client.h60
-rwxr-xr-xprovider/include/download-provider-config.h39
-rw-r--r--provider/include/download-provider-db-defs.h157
-rwxr-xr-xprovider/include/download-provider-db.h55
-rw-r--r--provider/include/download-provider-ipc.h36
-rwxr-xr-xprovider/include/download-provider-log.h64
-rwxr-xr-xprovider/include/download-provider-network.h34
-rw-r--r--provider/include/download-provider-notification-manager.h33
-rwxr-xr-xprovider/include/download-provider-notification.h33
-rw-r--r--provider/include/download-provider-notify.h24
-rw-r--r--provider/include/download-provider-plugin-download-agent.h31
-rwxr-xr-xprovider/include/download-provider-pthread.h44
-rw-r--r--provider/include/download-provider-queue-manager.h25
-rwxr-xr-xprovider/include/download-provider-queue.h31
-rw-r--r--provider/include/download-provider-smack.h33
-rw-r--r--provider/include/download-provider-utils.h25
-rwxr-xr-xprovider/include/download-provider.h191
-rwxr-xr-xrefresh.sh6
-rw-r--r--res/images/redwood/B03_processing_download_complete.pngbin0 -> 3117 bytes
-rw-r--r--res/images/redwood/B03_processing_download_fail.pngbin0 -> 1600 bytes
-rw-r--r--res/images/redwood/U01_icon_broken.pngbin0 -> 4017 bytes
-rw-r--r--res/images/redwood/U01_icon_drm.pngbin0 -> 4077 bytes
-rw-r--r--res/images/redwood/U01_icon_excel.pngbin0 -> 4512 bytes
-rw-r--r--res/images/redwood/U01_icon_html.pngbin0 -> 5063 bytes
-rw-r--r--res/images/redwood/U01_icon_pdf.pngbin0 -> 4686 bytes
-rw-r--r--res/images/redwood/U01_icon_ppt.pngbin0 -> 3946 bytes
-rw-r--r--res/images/redwood/U01_icon_swf.pngbin0 -> 4233 bytes
-rw-r--r--res/images/redwood/U01_icon_text.pngbin0 -> 3832 bytes
-rw-r--r--res/images/redwood/U01_icon_tpk.pngbin0 -> 5319 bytes
-rw-r--r--res/images/redwood/U01_icon_unkown.pngbin0 -> 3888 bytes
-rw-r--r--res/images/redwood/U01_icon_vcs.pngbin0 -> 3835 bytes
-rw-r--r--res/images/redwood/U01_icon_word.pngbin0 -> 4669 bytes
-rw-r--r--res/images/redwood/U01_list_icon_image.pngbin0 -> 4162 bytes
-rw-r--r--res/images/redwood/U01_list_icon_mp3.pngbin0 -> 4154 bytes
-rw-r--r--res/images/redwood/U01_list_icon_mp4.pngbin0 -> 3851 bytes
-rw-r--r--res/images/redwood/noti_download_complete.pngbin0 -> 6935 bytes
-rw-r--r--res/images/redwood/noti_download_failed.pngbin0 -> 8035 bytes
-rw-r--r--res/images/tizen2.3/B03_Processing_download_complete.pngbin0 -> 1268 bytes
-rw-r--r--res/images/tizen2.3/B03_Processing_download_failed.pngbin0 -> 1421 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_date.pngbin0 -> 1606 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_drm.pngbin0 -> 1701 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_html.pngbin0 -> 2359 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_img.pngbin0 -> 1765 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_movie.pngbin0 -> 1640 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_music.pngbin0 -> 1786 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_pdf.pngbin0 -> 2005 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_ppt.pngbin0 -> 1499 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_swf.pngbin0 -> 1878 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_text.pngbin0 -> 1600 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_tpk.pngbin0 -> 2546 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_unknown.pngbin0 -> 1631 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_word.pngbin0 -> 1930 bytes
-rw-r--r--res/images/tizen2.3/download_manager_icon_xls.pngbin0 -> 1854 bytes
-rw-r--r--script/commit-template10
-rw-r--r--systemd/download-provider.service12
-rw-r--r--systemd/download-provider.socket10
219 files changed, 22291 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..707ec6f
--- /dev/null
+++ b/AUTHORS
@@ -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.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..6220b80
--- /dev/null
+++ b/NOTICE
@@ -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
+
diff --git a/bi.sh b/bi.sh
new file mode 100755
index 0000000..201232c
--- /dev/null
+++ b/bi.sh
@@ -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
+info: start building packages from: /home/youngj/dev/spin/tizen_2_4_download-provider/download-provider (git)
+2015-05-14 18:49 +0900
+gbs 0.23
+info: prepare sources...
+info: start 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
+info: retrieving repo metadata...
+info: parsing package data...
+info: building repo metadata ...
+info: resolving skipped packages ...
+info: package dependency resolving ...
+info: next pass:
+download-provider
+info: *** [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]
+info: finished building download-provider
+info: updating local repo
+info: *** Build Status Summary ***
+=== Total succeeded built packages: (1) ===
+info: generated html format report:
+ /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/index.html
+info: generated RPM packages can be found from local repo:
+ /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/RPMS
+info: generated source RPM packages can be found from local repo:
+ /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/SRPMS
+info: build logs can be found in:
+ /home/youngj/GBS-ROOT/local/repos/tizen/armv7l/logs
+info: build 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
diff --git a/i.sh b/i.sh
new file mode 100755
index 0000000..231d0bc
--- /dev/null
+++ b/i.sh
@@ -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 *)&notify_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, &noti_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 *)&noti_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 *)&noti_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 *)&noti_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,
+ &ethernet_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, &noti_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, &noti_priv_id, NULL, NULL, &noti_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 *)&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);
+ }
+ }
+ 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, &noti_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 *)&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);
+ }
+ }
+ }
+ 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
new file mode 100644
index 0000000..109512e
--- /dev/null
+++ b/res/images/redwood/B03_processing_download_complete.png
Binary files differ
diff --git a/res/images/redwood/B03_processing_download_fail.png b/res/images/redwood/B03_processing_download_fail.png
new file mode 100644
index 0000000..be67ffe
--- /dev/null
+++ b/res/images/redwood/B03_processing_download_fail.png
Binary files differ
diff --git a/res/images/redwood/U01_icon_broken.png b/res/images/redwood/U01_icon_broken.png
new file mode 100644
index 0000000..9020234
--- /dev/null
+++ b/res/images/redwood/U01_icon_broken.png
Binary files differ
diff --git a/res/images/redwood/U01_icon_drm.png b/res/images/redwood/U01_icon_drm.png
new file mode 100644
index 0000000..06e682b
--- /dev/null
+++ b/res/images/redwood/U01_icon_drm.png
Binary files differ
diff --git a/res/images/redwood/U01_icon_excel.png b/res/images/redwood/U01_icon_excel.png
new file mode 100644
index 0000000..6efd14a
--- /dev/null
+++ b/res/images/redwood/U01_icon_excel.png
Binary files differ
diff --git a/res/images/redwood/U01_icon_html.png b/res/images/redwood/U01_icon_html.png
new file mode 100644
index 0000000..01260ba
--- /dev/null
+++ b/res/images/redwood/U01_icon_html.png
Binary files differ
diff --git a/res/images/redwood/U01_icon_pdf.png b/res/images/redwood/U01_icon_pdf.png
new file mode 100644
index 0000000..3f8cda6
--- /dev/null
+++ b/res/images/redwood/U01_icon_pdf.png
Binary files differ
diff --git a/res/images/redwood/U01_icon_ppt.png b/res/images/redwood/U01_icon_ppt.png
new file mode 100644
index 0000000..79302eb
--- /dev/null
+++ b/res/images/redwood/U01_icon_ppt.png
Binary files differ
diff --git a/res/images/redwood/U01_icon_swf.png b/res/images/redwood/U01_icon_swf.png
new file mode 100644
index 0000000..39a49da
--- /dev/null
+++ b/res/images/redwood/U01_icon_swf.png
Binary files differ
diff --git a/res/images/redwood/U01_icon_text.png b/res/images/redwood/U01_icon_text.png
new file mode 100644
index 0000000..5f8b3bd
--- /dev/null
+++ b/res/images/redwood/U01_icon_text.png
Binary files differ
diff --git a/res/images/redwood/U01_icon_tpk.png b/res/images/redwood/U01_icon_tpk.png
new file mode 100644
index 0000000..796c788
--- /dev/null
+++ b/res/images/redwood/U01_icon_tpk.png
Binary files differ
diff --git a/res/images/redwood/U01_icon_unkown.png b/res/images/redwood/U01_icon_unkown.png
new file mode 100644
index 0000000..25a2801
--- /dev/null
+++ b/res/images/redwood/U01_icon_unkown.png
Binary files differ
diff --git a/res/images/redwood/U01_icon_vcs.png b/res/images/redwood/U01_icon_vcs.png
new file mode 100644
index 0000000..72dbf76
--- /dev/null
+++ b/res/images/redwood/U01_icon_vcs.png
Binary files differ
diff --git a/res/images/redwood/U01_icon_word.png b/res/images/redwood/U01_icon_word.png
new file mode 100644
index 0000000..a45acd7
--- /dev/null
+++ b/res/images/redwood/U01_icon_word.png
Binary files differ
diff --git a/res/images/redwood/U01_list_icon_image.png b/res/images/redwood/U01_list_icon_image.png
new file mode 100644
index 0000000..ebb2a3c
--- /dev/null
+++ b/res/images/redwood/U01_list_icon_image.png
Binary files differ
diff --git a/res/images/redwood/U01_list_icon_mp3.png b/res/images/redwood/U01_list_icon_mp3.png
new file mode 100644
index 0000000..c5176be
--- /dev/null
+++ b/res/images/redwood/U01_list_icon_mp3.png
Binary files differ
diff --git a/res/images/redwood/U01_list_icon_mp4.png b/res/images/redwood/U01_list_icon_mp4.png
new file mode 100644
index 0000000..2e3c87b
--- /dev/null
+++ b/res/images/redwood/U01_list_icon_mp4.png
Binary files differ
diff --git a/res/images/redwood/noti_download_complete.png b/res/images/redwood/noti_download_complete.png
new file mode 100644
index 0000000..6171bd8
--- /dev/null
+++ b/res/images/redwood/noti_download_complete.png
Binary files differ
diff --git a/res/images/redwood/noti_download_failed.png b/res/images/redwood/noti_download_failed.png
new file mode 100644
index 0000000..5eb122b
--- /dev/null
+++ b/res/images/redwood/noti_download_failed.png
Binary files differ
diff --git a/res/images/tizen2.3/B03_Processing_download_complete.png b/res/images/tizen2.3/B03_Processing_download_complete.png
new file mode 100644
index 0000000..8dfb542
--- /dev/null
+++ b/res/images/tizen2.3/B03_Processing_download_complete.png
Binary files differ
diff --git a/res/images/tizen2.3/B03_Processing_download_failed.png b/res/images/tizen2.3/B03_Processing_download_failed.png
new file mode 100644
index 0000000..11d34ab
--- /dev/null
+++ b/res/images/tizen2.3/B03_Processing_download_failed.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_date.png b/res/images/tizen2.3/download_manager_icon_date.png
new file mode 100644
index 0000000..f1ff0f8
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_date.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_drm.png b/res/images/tizen2.3/download_manager_icon_drm.png
new file mode 100644
index 0000000..7965232
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_drm.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_html.png b/res/images/tizen2.3/download_manager_icon_html.png
new file mode 100644
index 0000000..f4a2bfc
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_html.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_img.png b/res/images/tizen2.3/download_manager_icon_img.png
new file mode 100644
index 0000000..1c2f137
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_img.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_movie.png b/res/images/tizen2.3/download_manager_icon_movie.png
new file mode 100644
index 0000000..5902a67
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_movie.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_music.png b/res/images/tizen2.3/download_manager_icon_music.png
new file mode 100644
index 0000000..39f4c06
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_music.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_pdf.png b/res/images/tizen2.3/download_manager_icon_pdf.png
new file mode 100644
index 0000000..96b1a9a
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_pdf.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_ppt.png b/res/images/tizen2.3/download_manager_icon_ppt.png
new file mode 100644
index 0000000..29159cf
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_ppt.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_swf.png b/res/images/tizen2.3/download_manager_icon_swf.png
new file mode 100644
index 0000000..b6335d7
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_swf.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_text.png b/res/images/tizen2.3/download_manager_icon_text.png
new file mode 100644
index 0000000..4961fb5
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_text.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_tpk.png b/res/images/tizen2.3/download_manager_icon_tpk.png
new file mode 100644
index 0000000..58953be
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_tpk.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_unknown.png b/res/images/tizen2.3/download_manager_icon_unknown.png
new file mode 100644
index 0000000..9a367ec
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_unknown.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_word.png b/res/images/tizen2.3/download_manager_icon_word.png
new file mode 100644
index 0000000..3218b53
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_word.png
Binary files differ
diff --git a/res/images/tizen2.3/download_manager_icon_xls.png b/res/images/tizen2.3/download_manager_icon_xls.png
new file mode 100644
index 0000000..aeddf20
--- /dev/null
+++ b/res/images/tizen2.3/download_manager_icon_xls.png
Binary files differ
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