From 73435351b469a7437b8d4aedd105b59c34b8526e Mon Sep 17 00:00:00 2001 From: "gloryj.kim" Date: Tue, 2 Jun 2015 20:07:17 +0900 Subject: [PATCH] Push new sources from Tizen 2.4 Change-Id: If2be781597be2fbf185237d0ee538a3626a66444 --- AUTHORS | 2 + CMakeLists.txt | 102 + LICENSE.APLv2 | 202 ++ NOTICE | 3 + agent/CMakeLists.txt | 116 ++ agent/download-agent-client-mgr.c | 145 ++ agent/download-agent-dl-info.c | 462 +++++ agent/download-agent-dl-mgr.c | 186 ++ agent/download-agent-encoding.c | 261 +++ agent/download-agent-file.c | 908 +++++++++ agent/download-agent-http-mgr.c | 1519 ++++++++++++++ agent/download-agent-http-msg-handler.c | 1125 +++++++++++ agent/download-agent-interface.c | 152 ++ agent/download-agent-mime-util.c | 449 +++++ agent/download-agent-plugin-conf.c | 109 + agent/download-agent-plugin-drm.c | 124 ++ agent/download-agent-plugin-libcurl.c | 702 +++++++ agent/download-agent-plugin-libcurl.c~ | 702 +++++++ agent/include/download-agent-client-mgr.h | 27 + agent/include/download-agent-debug.h | 68 + agent/include/download-agent-defs.h | 85 + agent/include/download-agent-dl-info.h | 197 ++ agent/include/download-agent-dl-mgr.h | 27 + agent/include/download-agent-encoding.h | 27 + agent/include/download-agent-file.h | 45 + agent/include/download-agent-http-mgr.h | 34 + agent/include/download-agent-http-msg-handler.h | 77 + agent/include/download-agent-interface.h | 97 + agent/include/download-agent-mime-util.h | 48 + agent/include/download-agent-plugin-conf.h | 30 + agent/include/download-agent-plugin-drm.h | 25 + agent/include/download-agent-plugin-libcurl.h | 35 + agent/include/download-agent-pthread.h | 144 ++ agent/include/download-agent-type.h | 73 + bi.sh | 16 + blog.txt | 1758 ++++++++++++++++ build.sh | 1 + download-provider-w.manifest | 38 + download-provider-w.manifest~ | 37 + download-provider.manifest | 41 + download-provider.manifest~ | 40 + download-provider.pc.in | 6 + download-provider.res | 1 + dump-download-provider.sh | 14 + gbs.conf | 285 +++ i.sh | 10 + packaging/download-provider.spec | 215 ++ packaging/download-provider.spec~ | 219 ++ po/redwood/CMakeLists.txt | 27 + po/redwood/az.po | 6 + po/redwood/bg.po | 6 + po/redwood/ca.po | 6 + po/redwood/cs.po | 6 + po/redwood/da.po | 6 + po/redwood/de.po | 6 + po/redwood/el_GR.po | 6 + po/redwood/en.po | 6 + po/redwood/en_US.po | 6 + po/redwood/es_ES.po | 6 + po/redwood/es_US.po | 6 + po/redwood/et.po | 6 + po/redwood/eu.po | 6 + po/redwood/fi.po | 6 + po/redwood/fr.po | 6 + po/redwood/fr_CA.po | 6 + po/redwood/gl.po | 6 + po/redwood/hr.po | 6 + po/redwood/hu.po | 6 + po/redwood/hy.po | 6 + po/redwood/is.po | 6 + po/redwood/it_IT.po | 6 + po/redwood/ka.po | 6 + po/redwood/kk.po | 6 + po/redwood/ko_KR.po | 6 + po/redwood/lt.po | 6 + po/redwood/lv.po | 6 + po/redwood/mn_MN.po | 6 + po/redwood/nb.po | 6 + po/redwood/nl.po | 6 + po/redwood/pl.po | 6 + po/redwood/pt_BR.po | 6 + po/redwood/pt_PT.po | 6 + po/redwood/ro.po | 6 + po/redwood/ru_RU.po | 6 + po/redwood/sk.po | 6 + po/redwood/sl.po | 6 + po/redwood/sr.po | 6 + po/redwood/sv.po | 6 + po/redwood/tr_TR.po | 6 + po/redwood/uk.po | 6 + po/redwood/uz.po | 6 + po/tizen2.3/CMakeLists.txt | 30 + po/tizen2.3/ar.po | 6 + po/tizen2.3/az.po | 6 + po/tizen2.3/bg.po | 6 + po/tizen2.3/ca.po | 6 + po/tizen2.3/cs.po | 6 + po/tizen2.3/da.po | 6 + po/tizen2.3/de.po | 6 + po/tizen2.3/el_GR.po | 6 + po/tizen2.3/en.po | 6 + po/tizen2.3/en_PH.po | 6 + po/tizen2.3/en_US.po | 6 + po/tizen2.3/es_ES.po | 6 + po/tizen2.3/es_US.po | 6 + po/tizen2.3/et.po | 6 + po/tizen2.3/eu.po | 6 + po/tizen2.3/fi.po | 6 + po/tizen2.3/fr.po | 6 + po/tizen2.3/fr_CA.po | 6 + po/tizen2.3/ga.po | 6 + po/tizen2.3/gl.po | 6 + po/tizen2.3/hi.po | 6 + po/tizen2.3/hr.po | 6 + po/tizen2.3/hu.po | 6 + po/tizen2.3/hy.po | 6 + po/tizen2.3/is.po | 6 + po/tizen2.3/it_IT.po | 6 + po/tizen2.3/ja_JP.po | 6 + po/tizen2.3/ka.po | 6 + po/tizen2.3/kk.po | 6 + po/tizen2.3/ko_KR.po | 6 + po/tizen2.3/lt.po | 6 + po/tizen2.3/lv.po | 6 + po/tizen2.3/mk.po | 6 + po/tizen2.3/nb.po | 6 + po/tizen2.3/nl.po | 6 + po/tizen2.3/pl.po | 6 + po/tizen2.3/pt_BR.po | 6 + po/tizen2.3/pt_PT.po | 6 + po/tizen2.3/ro.po | 6 + po/tizen2.3/ru_RU.po | 6 + po/tizen2.3/sk.po | 6 + po/tizen2.3/sl.po | 6 + po/tizen2.3/sr.po | 6 + po/tizen2.3/sv.po | 6 + po/tizen2.3/tr_TR.po | 6 + po/tizen2.3/uk.po | 6 + po/tizen2.3/uz.po | 6 + po/tizen2.3/zh_CN.po | 6 + po/tizen2.3/zh_HK.po | 6 + po/tizen2.3/zh_TW.po | 6 + provider-interface/CMakeLists.txt | 49 + provider-interface/download-provider-interface.c | 1563 +++++++++++++++ .../download-provider-interface.pc.in | 8 + .../include/download-provider-interface.h | 143 ++ provider/CMakeLists.txt | 123 ++ provider/download-provider-client-manager.c | 741 +++++++ provider/download-provider-client.c | 2110 ++++++++++++++++++++ provider/download-provider-db.c | 1322 ++++++++++++ provider/download-provider-ipc.c | 132 ++ provider/download-provider-main.c | 66 + provider/download-provider-network.c | 267 +++ provider/download-provider-notification-manager.c | 573 ++++++ provider/download-provider-notification.c | 629 ++++++ provider/download-provider-notify.c | 103 + provider/download-provider-plugin-download-agent.c | 989 +++++++++ provider/download-provider-pthread.c | 110 + provider/download-provider-queue-manager.c | 315 +++ provider/download-provider-queue.c | 194 ++ provider/download-provider-smack.c | 165 ++ provider/download-provider-utils.c | 103 + .../include/download-provider-client-manager.h | 35 + provider/include/download-provider-client.h | 60 + provider/include/download-provider-config.h | 39 + provider/include/download-provider-db-defs.h | 157 ++ provider/include/download-provider-db.h | 55 + provider/include/download-provider-ipc.h | 36 + provider/include/download-provider-log.h | 64 + provider/include/download-provider-network.h | 34 + .../download-provider-notification-manager.h | 33 + provider/include/download-provider-notification.h | 33 + provider/include/download-provider-notify.h | 24 + .../download-provider-plugin-download-agent.h | 31 + provider/include/download-provider-pthread.h | 44 + provider/include/download-provider-queue-manager.h | 25 + provider/include/download-provider-queue.h | 31 + provider/include/download-provider-smack.h | 33 + provider/include/download-provider-utils.h | 25 + provider/include/download-provider.h | 191 ++ refresh.sh | 6 + .../redwood/B03_processing_download_complete.png | Bin 0 -> 3117 bytes .../redwood/B03_processing_download_fail.png | Bin 0 -> 1600 bytes res/images/redwood/U01_icon_broken.png | Bin 0 -> 4017 bytes res/images/redwood/U01_icon_drm.png | Bin 0 -> 4077 bytes res/images/redwood/U01_icon_excel.png | Bin 0 -> 4512 bytes res/images/redwood/U01_icon_html.png | Bin 0 -> 5063 bytes res/images/redwood/U01_icon_pdf.png | Bin 0 -> 4686 bytes res/images/redwood/U01_icon_ppt.png | Bin 0 -> 3946 bytes res/images/redwood/U01_icon_swf.png | Bin 0 -> 4233 bytes res/images/redwood/U01_icon_text.png | Bin 0 -> 3832 bytes res/images/redwood/U01_icon_tpk.png | Bin 0 -> 5319 bytes res/images/redwood/U01_icon_unkown.png | Bin 0 -> 3888 bytes res/images/redwood/U01_icon_vcs.png | Bin 0 -> 3835 bytes res/images/redwood/U01_icon_word.png | Bin 0 -> 4669 bytes res/images/redwood/U01_list_icon_image.png | Bin 0 -> 4162 bytes res/images/redwood/U01_list_icon_mp3.png | Bin 0 -> 4154 bytes res/images/redwood/U01_list_icon_mp4.png | Bin 0 -> 3851 bytes res/images/redwood/noti_download_complete.png | Bin 0 -> 6935 bytes res/images/redwood/noti_download_failed.png | Bin 0 -> 8035 bytes .../tizen2.3/B03_Processing_download_complete.png | Bin 0 -> 1268 bytes .../tizen2.3/B03_Processing_download_failed.png | Bin 0 -> 1421 bytes res/images/tizen2.3/download_manager_icon_date.png | Bin 0 -> 1606 bytes res/images/tizen2.3/download_manager_icon_drm.png | Bin 0 -> 1701 bytes res/images/tizen2.3/download_manager_icon_html.png | Bin 0 -> 2359 bytes res/images/tizen2.3/download_manager_icon_img.png | Bin 0 -> 1765 bytes .../tizen2.3/download_manager_icon_movie.png | Bin 0 -> 1640 bytes .../tizen2.3/download_manager_icon_music.png | Bin 0 -> 1786 bytes res/images/tizen2.3/download_manager_icon_pdf.png | Bin 0 -> 2005 bytes res/images/tizen2.3/download_manager_icon_ppt.png | Bin 0 -> 1499 bytes res/images/tizen2.3/download_manager_icon_swf.png | Bin 0 -> 1878 bytes res/images/tizen2.3/download_manager_icon_text.png | Bin 0 -> 1600 bytes res/images/tizen2.3/download_manager_icon_tpk.png | Bin 0 -> 2546 bytes .../tizen2.3/download_manager_icon_unknown.png | Bin 0 -> 1631 bytes res/images/tizen2.3/download_manager_icon_word.png | Bin 0 -> 1930 bytes res/images/tizen2.3/download_manager_icon_xls.png | Bin 0 -> 1854 bytes script/commit-template | 10 + systemd/download-provider.service | 12 + systemd/download-provider.socket | 10 + 219 files changed, 22291 insertions(+) create mode 100644 AUTHORS create mode 100755 CMakeLists.txt create mode 100644 LICENSE.APLv2 create mode 100644 NOTICE create mode 100755 agent/CMakeLists.txt create mode 100755 agent/download-agent-client-mgr.c create mode 100644 agent/download-agent-dl-info.c create mode 100755 agent/download-agent-dl-mgr.c create mode 100755 agent/download-agent-encoding.c create mode 100755 agent/download-agent-file.c create mode 100755 agent/download-agent-http-mgr.c create mode 100755 agent/download-agent-http-msg-handler.c create mode 100755 agent/download-agent-interface.c create mode 100755 agent/download-agent-mime-util.c create mode 100755 agent/download-agent-plugin-conf.c create mode 100644 agent/download-agent-plugin-drm.c create mode 100644 agent/download-agent-plugin-libcurl.c create mode 100644 agent/download-agent-plugin-libcurl.c~ create mode 100755 agent/include/download-agent-client-mgr.h create mode 100755 agent/include/download-agent-debug.h create mode 100755 agent/include/download-agent-defs.h create mode 100644 agent/include/download-agent-dl-info.h create mode 100755 agent/include/download-agent-dl-mgr.h create mode 100755 agent/include/download-agent-encoding.h create mode 100755 agent/include/download-agent-file.h create mode 100755 agent/include/download-agent-http-mgr.h create mode 100755 agent/include/download-agent-http-msg-handler.h create mode 100755 agent/include/download-agent-interface.h create mode 100755 agent/include/download-agent-mime-util.h create mode 100755 agent/include/download-agent-plugin-conf.h create mode 100644 agent/include/download-agent-plugin-drm.h create mode 100644 agent/include/download-agent-plugin-libcurl.h create mode 100755 agent/include/download-agent-pthread.h create mode 100755 agent/include/download-agent-type.h create mode 100755 bi.sh create mode 100644 blog.txt create mode 100755 build.sh create mode 100644 download-provider-w.manifest create mode 100644 download-provider-w.manifest~ create mode 100644 download-provider.manifest create mode 100644 download-provider.manifest~ create mode 100644 download-provider.pc.in create mode 100644 download-provider.res create mode 100644 dump-download-provider.sh create mode 100644 gbs.conf create mode 100755 i.sh create mode 100644 packaging/download-provider.spec create mode 100644 packaging/download-provider.spec~ create mode 100644 po/redwood/CMakeLists.txt create mode 100644 po/redwood/az.po create mode 100644 po/redwood/bg.po create mode 100644 po/redwood/ca.po create mode 100644 po/redwood/cs.po create mode 100644 po/redwood/da.po create mode 100644 po/redwood/de.po create mode 100644 po/redwood/el_GR.po create mode 100644 po/redwood/en.po create mode 100644 po/redwood/en_US.po create mode 100644 po/redwood/es_ES.po create mode 100644 po/redwood/es_US.po create mode 100644 po/redwood/et.po create mode 100644 po/redwood/eu.po create mode 100644 po/redwood/fi.po create mode 100644 po/redwood/fr.po create mode 100644 po/redwood/fr_CA.po create mode 100644 po/redwood/gl.po create mode 100644 po/redwood/hr.po create mode 100644 po/redwood/hu.po create mode 100644 po/redwood/hy.po create mode 100644 po/redwood/is.po create mode 100644 po/redwood/it_IT.po create mode 100644 po/redwood/ka.po create mode 100644 po/redwood/kk.po create mode 100644 po/redwood/ko_KR.po create mode 100644 po/redwood/lt.po create mode 100644 po/redwood/lv.po create mode 100644 po/redwood/mn_MN.po create mode 100644 po/redwood/nb.po create mode 100644 po/redwood/nl.po create mode 100644 po/redwood/pl.po create mode 100644 po/redwood/pt_BR.po create mode 100644 po/redwood/pt_PT.po create mode 100644 po/redwood/ro.po create mode 100644 po/redwood/ru_RU.po create mode 100644 po/redwood/sk.po create mode 100644 po/redwood/sl.po create mode 100644 po/redwood/sr.po create mode 100644 po/redwood/sv.po create mode 100644 po/redwood/tr_TR.po create mode 100644 po/redwood/uk.po create mode 100644 po/redwood/uz.po create mode 100644 po/tizen2.3/CMakeLists.txt create mode 100644 po/tizen2.3/ar.po create mode 100644 po/tizen2.3/az.po create mode 100644 po/tizen2.3/bg.po create mode 100644 po/tizen2.3/ca.po create mode 100644 po/tizen2.3/cs.po create mode 100644 po/tizen2.3/da.po create mode 100644 po/tizen2.3/de.po create mode 100644 po/tizen2.3/el_GR.po create mode 100644 po/tizen2.3/en.po create mode 100644 po/tizen2.3/en_PH.po create mode 100644 po/tizen2.3/en_US.po create mode 100644 po/tizen2.3/es_ES.po create mode 100644 po/tizen2.3/es_US.po create mode 100644 po/tizen2.3/et.po create mode 100644 po/tizen2.3/eu.po create mode 100644 po/tizen2.3/fi.po create mode 100644 po/tizen2.3/fr.po create mode 100644 po/tizen2.3/fr_CA.po create mode 100644 po/tizen2.3/ga.po create mode 100644 po/tizen2.3/gl.po create mode 100644 po/tizen2.3/hi.po create mode 100644 po/tizen2.3/hr.po create mode 100644 po/tizen2.3/hu.po create mode 100644 po/tizen2.3/hy.po create mode 100644 po/tizen2.3/is.po create mode 100644 po/tizen2.3/it_IT.po create mode 100644 po/tizen2.3/ja_JP.po create mode 100644 po/tizen2.3/ka.po create mode 100644 po/tizen2.3/kk.po create mode 100644 po/tizen2.3/ko_KR.po create mode 100644 po/tizen2.3/lt.po create mode 100644 po/tizen2.3/lv.po create mode 100644 po/tizen2.3/mk.po create mode 100644 po/tizen2.3/nb.po create mode 100644 po/tizen2.3/nl.po create mode 100644 po/tizen2.3/pl.po create mode 100644 po/tizen2.3/pt_BR.po create mode 100644 po/tizen2.3/pt_PT.po create mode 100644 po/tizen2.3/ro.po create mode 100644 po/tizen2.3/ru_RU.po create mode 100644 po/tizen2.3/sk.po create mode 100644 po/tizen2.3/sl.po create mode 100644 po/tizen2.3/sr.po create mode 100644 po/tizen2.3/sv.po create mode 100644 po/tizen2.3/tr_TR.po create mode 100644 po/tizen2.3/uk.po create mode 100644 po/tizen2.3/uz.po create mode 100644 po/tizen2.3/zh_CN.po create mode 100644 po/tizen2.3/zh_HK.po create mode 100644 po/tizen2.3/zh_TW.po create mode 100755 provider-interface/CMakeLists.txt create mode 100755 provider-interface/download-provider-interface.c create mode 100644 provider-interface/download-provider-interface.pc.in create mode 100755 provider-interface/include/download-provider-interface.h create mode 100755 provider/CMakeLists.txt create mode 100644 provider/download-provider-client-manager.c create mode 100644 provider/download-provider-client.c create mode 100755 provider/download-provider-db.c create mode 100644 provider/download-provider-ipc.c create mode 100755 provider/download-provider-main.c create mode 100755 provider/download-provider-network.c create mode 100644 provider/download-provider-notification-manager.c create mode 100755 provider/download-provider-notification.c create mode 100644 provider/download-provider-notify.c create mode 100644 provider/download-provider-plugin-download-agent.c create mode 100644 provider/download-provider-pthread.c create mode 100644 provider/download-provider-queue-manager.c create mode 100644 provider/download-provider-queue.c create mode 100644 provider/download-provider-smack.c create mode 100644 provider/download-provider-utils.c create mode 100644 provider/include/download-provider-client-manager.h create mode 100644 provider/include/download-provider-client.h create mode 100755 provider/include/download-provider-config.h create mode 100644 provider/include/download-provider-db-defs.h create mode 100755 provider/include/download-provider-db.h create mode 100644 provider/include/download-provider-ipc.h create mode 100755 provider/include/download-provider-log.h create mode 100755 provider/include/download-provider-network.h create mode 100644 provider/include/download-provider-notification-manager.h create mode 100755 provider/include/download-provider-notification.h create mode 100644 provider/include/download-provider-notify.h create mode 100644 provider/include/download-provider-plugin-download-agent.h create mode 100755 provider/include/download-provider-pthread.h create mode 100644 provider/include/download-provider-queue-manager.h create mode 100755 provider/include/download-provider-queue.h create mode 100644 provider/include/download-provider-smack.h create mode 100644 provider/include/download-provider-utils.h create mode 100755 provider/include/download-provider.h create mode 100755 refresh.sh create mode 100644 res/images/redwood/B03_processing_download_complete.png create mode 100644 res/images/redwood/B03_processing_download_fail.png create mode 100644 res/images/redwood/U01_icon_broken.png create mode 100644 res/images/redwood/U01_icon_drm.png create mode 100644 res/images/redwood/U01_icon_excel.png create mode 100644 res/images/redwood/U01_icon_html.png create mode 100644 res/images/redwood/U01_icon_pdf.png create mode 100644 res/images/redwood/U01_icon_ppt.png create mode 100644 res/images/redwood/U01_icon_swf.png create mode 100644 res/images/redwood/U01_icon_text.png create mode 100644 res/images/redwood/U01_icon_tpk.png create mode 100644 res/images/redwood/U01_icon_unkown.png create mode 100644 res/images/redwood/U01_icon_vcs.png create mode 100644 res/images/redwood/U01_icon_word.png create mode 100644 res/images/redwood/U01_list_icon_image.png create mode 100644 res/images/redwood/U01_list_icon_mp3.png create mode 100644 res/images/redwood/U01_list_icon_mp4.png create mode 100644 res/images/redwood/noti_download_complete.png create mode 100644 res/images/redwood/noti_download_failed.png create mode 100644 res/images/tizen2.3/B03_Processing_download_complete.png create mode 100644 res/images/tizen2.3/B03_Processing_download_failed.png create mode 100644 res/images/tizen2.3/download_manager_icon_date.png create mode 100644 res/images/tizen2.3/download_manager_icon_drm.png create mode 100644 res/images/tizen2.3/download_manager_icon_html.png create mode 100644 res/images/tizen2.3/download_manager_icon_img.png create mode 100644 res/images/tizen2.3/download_manager_icon_movie.png create mode 100644 res/images/tizen2.3/download_manager_icon_music.png create mode 100644 res/images/tizen2.3/download_manager_icon_pdf.png create mode 100644 res/images/tizen2.3/download_manager_icon_ppt.png create mode 100644 res/images/tizen2.3/download_manager_icon_swf.png create mode 100644 res/images/tizen2.3/download_manager_icon_text.png create mode 100644 res/images/tizen2.3/download_manager_icon_tpk.png create mode 100644 res/images/tizen2.3/download_manager_icon_unknown.png create mode 100644 res/images/tizen2.3/download_manager_icon_word.png create mode 100644 res/images/tizen2.3/download_manager_icon_xls.png create mode 100644 script/commit-template create mode 100644 systemd/download-provider.service create mode 100644 systemd/download-provider.socket diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..707ec6f --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Kwangmin Bang +Jungki Kwak 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 + +#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 +#include + +#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 +#include +#include + +#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 +#include +#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 +#include +#include +#include +#include +#include +#include + +#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 + + +#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 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 +#include +#include +#include + +#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 +#include +#include + +#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 +#include + +#include + +#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 +#include +#include +#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 + +#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 +#include +#include + +#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 +#include +#include + +#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 +#include +#include + +// 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 +#include +#include + + #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 +#include + + #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 */ + 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 +#include +#include + +#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 + +#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 + +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 +#include +#include + +#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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include // for notification bundle +#ifdef T30 +#include +#endif +#include +#include + +#ifdef SUPPORT_CHECK_IPC +#include +#endif + +#define DP_CHECK_CONNECTION do {\ + int dp_errorcode = __check_connections();\ + if (dp_errorcode != DP_ERROR_NONE) {\ + CLIENT_MUTEX_UNLOCK(&g_function_mutex);\ + return __dp_interface_convert_errorcode(dp_errorcode);\ + }\ +} while(0) + +#define DP_PRE_CHECK_ID do {\ + if (id <= 0) {\ + TRACE_ERROR("[CHECK ID] (%d)", id);\ + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER;\ + }\ +} while(0) + +// define type +typedef struct { + int channel; // query & response + int notify; // event from provider +} dp_interface_ipc; + +typedef struct { + int id; + dp_interface_state_changed_cb state; + void *state_data; + dp_interface_progress_cb progress; + void *progress_data; +} dp_interface_slot; + +// declare the variables +dp_interface_ipc *g_dp_client = NULL; +dp_interface_slot g_interface_slots[MAX_DOWNLOAD_HANDLE]; +static pthread_mutex_t g_function_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t g_clear_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_t g_dp_event_thread_id = 0; + +//////////// defines functions ///////////////// + + +static int __dp_interface_convert_state(int state) +{ + switch (state) { + case DP_STATE_READY: + TRACE_DEBUG("READY"); + return DOWNLOAD_ADPATOR_STATE_READY; + case DP_STATE_CONNECTING: + TRACE_DEBUG("CONNECTING/QUEUED"); + return DOWNLOAD_ADPATOR_STATE_QUEUED; + case DP_STATE_QUEUED: + TRACE_DEBUG("QUEUED"); + return DOWNLOAD_ADPATOR_STATE_QUEUED; + case DP_STATE_DOWNLOADING: + TRACE_DEBUG("DOWNLOADING"); + return DOWNLOAD_ADPATOR_STATE_DOWNLOADING; + case DP_STATE_PAUSED: + TRACE_DEBUG("PAUSED"); + return DOWNLOAD_ADPATOR_STATE_PAUSED; + case DP_STATE_COMPLETED: + TRACE_DEBUG("COMPLETED"); + return DOWNLOAD_ADPATOR_STATE_COMPLETED; + case DP_STATE_CANCELED: + TRACE_DEBUG("CANCELED"); + return DOWNLOAD_ADPATOR_STATE_CANCELED; + case DP_STATE_FAILED: + TRACE_DEBUG("FAILED"); + return DOWNLOAD_ADPATOR_STATE_FAILED; + default: + break; + } + return DOWNLOAD_ADPATOR_STATE_NONE; +} + +static int __dp_interface_convert_errorcode(int errorcode) +{ + switch (errorcode) { + case DP_ERROR_NONE: + return DOWNLOAD_ADAPTOR_ERROR_NONE; + case DP_ERROR_INVALID_PARAMETER: + TRACE_DEBUG("ERROR_INVALID_PARAMETER"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + case DP_ERROR_OUT_OF_MEMORY: + TRACE_DEBUG("ERROR_OUT_OF_MEMORY"); + return DOWNLOAD_ADAPTOR_ERROR_OUT_OF_MEMORY; + case DP_ERROR_IO_EAGAIN: + TRACE_DEBUG("ERROR_IO_ERROR(EAGAIN)"); + return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; + case DP_ERROR_IO_EINTR: + TRACE_DEBUG("ERROR_IO_ERROR(EINTR)"); + return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; + case DP_ERROR_IO_ERROR: + TRACE_DEBUG("ERROR_IO_ERROR"); + return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; + case DP_ERROR_NETWORK_UNREACHABLE: + TRACE_DEBUG("ERROR_NETWORK_UNREACHABLE"); + return DOWNLOAD_ADAPTOR_ERROR_NETWORK_UNREACHABLE; + case DP_ERROR_NO_SPACE: + TRACE_DEBUG("ERROR_NO_SPACE"); + return DOWNLOAD_ADAPTOR_ERROR_NO_SPACE; + case DP_ERROR_FIELD_NOT_FOUND: + TRACE_DEBUG("ERROR_FIELD_NOT_FOUND"); + return DOWNLOAD_ADAPTOR_ERROR_FIELD_NOT_FOUND; + case DP_ERROR_INVALID_STATE: + TRACE_DEBUG("ERROR_INVALID_STATE"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_STATE; + case DP_ERROR_CONNECTION_FAILED: + case DP_ERROR_NETWORK_ERROR: + TRACE_DEBUG("ERROR_CONNECTION_TIMED_OUT/CONNECTION_FAILED"); + return DOWNLOAD_ADAPTOR_ERROR_CONNECTION_TIMED_OUT; + case DP_ERROR_INVALID_URL: + TRACE_DEBUG("ERROR_INVALID_URL"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_URL; + case DP_ERROR_INVALID_DESTINATION: + TRACE_DEBUG("ERROR_INVALID_DESTINATION"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_DESTINATION; + case DP_ERROR_PERMISSION_DENIED: + TRACE_DEBUG("ERROR_PERMISSION_DENIED"); + return DOWNLOAD_ADAPTOR_ERROR_PERMISSION_DENIED; + case DP_ERROR_QUEUE_FULL: + TRACE_DEBUG("ERROR_QUEUE_FULL"); + return DOWNLOAD_ADAPTOR_ERROR_QUEUE_FULL; + case DP_ERROR_ALREADY_COMPLETED: + TRACE_DEBUG("ERROR_ALREADY_COMPLETED"); + return DOWNLOAD_ADAPTOR_ERROR_ALREADY_COMPLETED; + case DP_ERROR_FILE_ALREADY_EXISTS: + TRACE_DEBUG("ERROR_FILE_ALREADY_EXISTS"); + return DOWNLOAD_ADAPTOR_ERROR_FILE_ALREADY_EXISTS; + case DP_ERROR_TOO_MANY_DOWNLOADS: + TRACE_DEBUG("ERROR_TOO_MANY_DOWNLOADS"); + return DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; + case DP_ERROR_NO_DATA: + TRACE_DEBUG("ERROR_NO_DATA"); + return DOWNLOAD_ADAPTOR_ERROR_NO_DATA; + case DP_ERROR_UNHANDLED_HTTP_CODE: + TRACE_DEBUG("ERROR_UNHANDLED_HTTP_CODE"); + return DOWNLOAD_ADAPTOR_ERROR_UNHANDLED_HTTP_CODE; + case DP_ERROR_CANNOT_RESUME: + TRACE_DEBUG("ERROR_CANNOT_RESUME"); + return DOWNLOAD_ADAPTOR_ERROR_CANNOT_RESUME; + case DP_ERROR_ID_NOT_FOUND: + TRACE_DEBUG("ERROR_ID_NOT_FOUND"); + return DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND; + case DP_ERROR_UNKNOWN: + TRACE_DEBUG("ERROR_INVALID_STATE/UNKNOWN"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_STATE; + case DP_ERROR_INVALID_NETWORK_TYPE: + TRACE_DEBUG("ERROR_INVALID_NETWORK_TYPE"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_NETWORK_TYPE; + default: + break; + } + return DOWNLOAD_ADAPTOR_ERROR_NONE; +} + +static int __get_my_slot_index(int id) +{ + int i = 0; + // search same info in array. + for (; i < MAX_DOWNLOAD_HANDLE; i++) + if (g_interface_slots[i].id == id) + return i; + return -1; +} + +static int __get_empty_slot_index() +{ + int i = 0; + for (; i < MAX_DOWNLOAD_HANDLE; i++) + if (g_interface_slots[i].id <= 0) + return i; + return -1; +} + +static int __create_socket() +{ + int sockfd = -1; + struct sockaddr_un clientaddr; + + if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + TRACE_STRERROR("[CRITICAL] socket system error"); + return -1; + } + + bzero(&clientaddr, sizeof clientaddr); + clientaddr.sun_family = AF_UNIX; + memset(clientaddr.sun_path, 0x00, sizeof(clientaddr.sun_path)); + strncpy(clientaddr.sun_path, IPC_SOCKET, strlen(IPC_SOCKET)); + clientaddr.sun_path[strlen(IPC_SOCKET)] = '\0'; + if (connect(sockfd, + (struct sockaddr*)&clientaddr, sizeof(clientaddr)) < 0) { + close(sockfd); + if (errno == EACCES || errno == EPERM) { + TRACE_STRERROR("check permission"); + return -DP_ERROR_PERMISSION_DENIED; + } + return -1; + } + TRACE_DEBUG("sockfd [%d]", sockfd); + return sockfd; +} + +static void __clear_interface() +{ + TRACE_DEBUG(""); + CLIENT_MUTEX_LOCK(&g_clear_mutex); + if (g_dp_client != NULL) { + if (g_dp_client->channel >= 0) + close(g_dp_client->channel); + g_dp_client->channel= -1; + if (g_dp_client->notify >= 0) + close(g_dp_client->notify); + g_dp_client->notify = -1; + free(g_dp_client); + g_dp_client = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_clear_mutex); +} + +static int __bp_disconnect(const char *funcname) +{ + TRACE_DEBUG("%s", funcname); + if (g_dp_event_thread_id > 0 && + pthread_kill(g_dp_event_thread_id, 0) != ESRCH) { + if (pthread_cancel(g_dp_event_thread_id) != 0) { + TRACE_STRERROR("pthread:%d", (int)g_dp_event_thread_id); + } + g_dp_event_thread_id = 0; + } + __clear_interface(); + return DP_ERROR_NONE; +} + +// listen ASYNC state event, no timeout +static void *__dp_event_manager(void *arg) +{ + if (g_dp_client == NULL) { + TRACE_STRERROR("[CRITICAL] INTERFACE null"); + return 0; + } + + size_t path_size = sizeof(NOTIFY_DIR) + 11; + char notify_fifo[path_size]; + snprintf((char *)¬ify_fifo, path_size,"%s/%d", NOTIFY_DIR, getpid()); + TRACE_DEBUG("IPC ESTABILISH %s", notify_fifo); + g_dp_client->notify = open(notify_fifo, O_RDONLY, 0600); + if (g_dp_client->notify < 0) { + TRACE_STRERROR("[CRITICAL] failed to ESTABILISH IPC %s", notify_fifo); + g_dp_event_thread_id = 0; + CLIENT_MUTEX_LOCK(&g_function_mutex); + __clear_interface(); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return 0; + } + + // deferred wait to cancal until next function called. + // ex) function : select, read in this thread + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + + while(g_dp_client != NULL && g_dp_client->notify >= 0) { + + if (g_dp_event_thread_id <= 0 || + pthread_self() != g_dp_event_thread_id) { + TRACE_ERROR("competitive threads self:%0x global:%0x", + pthread_self(), g_dp_event_thread_id); + // another thread may work. just terminate + break; + } + + // blocking fifo. + dp_ipc_event_fmt eventinfo; + memset(&eventinfo, 0x00, sizeof(dp_ipc_event_fmt)); + if (dp_ipc_read(g_dp_client->notify, &eventinfo, + sizeof(dp_ipc_event_fmt), __FUNCTION__) <= 0 || + (eventinfo.id <= 0 && + eventinfo.errorcode == DP_ERROR_CLIENT_DOWN)) { + TRACE_INFO("expelled by provider"); + g_dp_event_thread_id = 0; + CLIENT_MUTEX_LOCK(&g_function_mutex); + __clear_interface(); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return 0; + } + + int index = -1; + if ((index = __get_my_slot_index(eventinfo.id)) < 0) { + TRACE_ERROR("[CRITICAL] not found slot id:%d", eventinfo.id); + continue; + } + + // begin protect callback sections & thread safe + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + if (eventinfo.state == DP_STATE_DOWNLOADING && + eventinfo.received_size > 0) { + if (eventinfo.id == g_interface_slots[index].id && + g_interface_slots[index].progress != NULL) { + // progress event + g_interface_slots[index].progress(eventinfo.id, + eventinfo.received_size, + g_interface_slots[index].progress_data); + } + } else { + if (eventinfo.id == g_interface_slots[index].id && + g_interface_slots[index].state != NULL) { + // state event + g_interface_slots[index].state(eventinfo.id, + __dp_interface_convert_state(eventinfo.state), + g_interface_slots[index].state_data); + } + } + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + } // while + + g_dp_event_thread_id = 0; // set 0 to not call pthread_cancel + TRACE_DEBUG("thread end by itself"); + return 0; +} + + + + + + +////////////////// new download-provider /////////////////////////////// +////////////////// created on 7 November, 2013 ///////////////////////// + +#define DP_CHECK_IPC_SOCK (g_dp_client == NULL ? -1 : g_dp_client->channel) + +static void __dp_ipc_clear_garbage(int sock, const size_t length) +{ + if (length > 0) { + char garbage[length]; + if (read(sock, &garbage, length) == 0) { + TRACE_ERROR("sock:%d closed peer", sock); + } + } +} + +static int __dp_ipc_response(int sock, int download_id, short section, + unsigned property, size_t *size) +{ + dp_ipc_fmt *ipc_info = dp_ipc_get_fmt(sock); + if (ipc_info == NULL || ipc_info->section != section || + ipc_info->property != property || + (download_id >= 0 && ipc_info->id != download_id)) { + TRACE_STRERROR("socket read ipcinfo"); + free(ipc_info); + return DP_ERROR_IO_ERROR; + } + int errorcode = ipc_info->errorcode; + if (size != NULL) + *size = ipc_info->size; + free(ipc_info); + return errorcode; +} + +static int __connect_to_provider() +{ + int errorcode = DP_ERROR_NONE; + + CLIENT_MUTEX_LOCK(&g_clear_mutex); + + if (g_dp_client == NULL) { + g_dp_client = + (dp_interface_ipc *)calloc(1, sizeof(dp_interface_ipc)); + + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { + TRACE_ERROR("failed to ignore SIGPIPE signal"); + } + } + + if (g_dp_client != NULL) { + + int connect_retry = 3; + g_dp_client->channel = -1; + while(g_dp_client->channel < 0 && connect_retry-- > 0) { + int ret = __create_socket(); + if (ret == -1) { + TRACE_STRERROR("failed to connect to provider(remains:%d)", connect_retry); + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 20000000; + nanosleep(&ts, NULL); + } else if (ret >= 0) { + struct timeval tv_timeo = { 1, 500000 }; // 1.5 second + g_dp_client->channel = ret; + if (setsockopt(g_dp_client->channel, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, sizeof(tv_timeo)) < 0) { + TRACE_STRERROR("[CRITICAL] setsockopt SO_RCVTIMEO"); + } + } else { + errorcode = -ret; + TRACE_STRERROR("check error:%d", errorcode); + goto EXIT_CONNECT; + } + } + if (g_dp_client->channel < 0) { + TRACE_STRERROR("[CRITICAL] connect system error"); + errorcode = DP_ERROR_IO_ERROR; + goto EXIT_CONNECT; + } + + if (dp_ipc_query(g_dp_client->channel, -1, DP_SEC_INIT, + DP_PROP_NONE, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + goto EXIT_CONNECT; + } +#ifndef SO_PEERCRED + dp_credential cred; + cred.pid = getpid(); + cred.uid = getuid(); + cred.gid = getgid(); + // send PID. Not support SO_PEERCRED + if (dp_ipc_write(g_dp_client->channel, + &cred, sizeof(dp_credential)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + goto EXIT_CONNECT; + } +#endif + + errorcode = __dp_ipc_response(g_dp_client->channel, + -1, DP_SEC_INIT, DP_PROP_NONE, NULL); + // Commented by justine.bang + // Above ipc_query call try to wake up download-provider. + // But, we can sometimes meet EINTR, EAGAIN or EINPROGRESS signal if systemd is slow. + // So, If meet EINTR ,EAGAIN or EINPROGRESS in this line, it's better to wait response from download-provider one more time. + if (errorcode == DP_ERROR_IO_ERROR && (errno == EINTR || errno == EAGAIN || errno == EINPROGRESS)) { + errorcode = __dp_ipc_response(g_dp_client->channel, + -1, DP_SEC_INIT, DP_PROP_NONE, NULL); + } + + if (errorcode == DP_ERROR_NONE && g_dp_event_thread_id <= 0) { + if (pthread_create(&g_dp_event_thread_id, NULL, + __dp_event_manager, g_dp_client) != 0) { + TRACE_STRERROR("failed to create event-manager"); + errorcode = DP_ERROR_IO_ERROR; + } else { + pthread_detach(g_dp_event_thread_id); + } + } + + } + +EXIT_CONNECT: + CLIENT_MUTEX_UNLOCK(&g_clear_mutex); + if (errorcode != DP_ERROR_NONE) + __bp_disconnect(__FUNCTION__); + + return errorcode; +} + +static dp_error_type __check_connections() +{ + int ret = 0; + + if (g_dp_client == NULL) + if ((ret = __connect_to_provider()) != DP_ERROR_NONE) + return ret; + + if (g_dp_client == NULL || g_dp_client->channel < 0) { + TRACE_ERROR("[CHECK IPC]"); + return DP_ERROR_IO_ERROR; + } + return DP_ERROR_NONE; +} + +static int __dp_ipc_set_binary(const int id, const unsigned property, + const bundle_raw *string, const size_t length, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + if (string == NULL || length <= 0) { + TRACE_ERROR("%s check binary (%d)", funcname, length); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_SET, property, DP_ERROR_NONE, length * sizeof(unsigned char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + if (dp_ipc_write(sock, (void*)string, length * sizeof(unsigned char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, DP_SEC_SET, property, NULL); + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +static int __dp_ipc_set_string(const int id, const short section, const unsigned property, + const char *string, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + size_t length = 0; + if (string == NULL || (length = strlen(string)) <= 0 || + length > DP_MAX_STR_LEN) { + TRACE_ERROR("%s check string (%d:%s)", funcname, length, string); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + if (dp_ipc_write(sock, (void*)string, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +static int __dp_ipc_get_string(const int id, const unsigned property, + char **string, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + + if (string == NULL) { + TRACE_ERROR("%s check buffer", funcname); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_GET, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + size_t string_length = 0; + *string = NULL; + errorcode = __dp_ipc_response(sock, id, DP_SEC_GET, property, &string_length); + if (errorcode == DP_ERROR_NONE) { + if (string_length > 0) { + char *recv_str = (char *)calloc((string_length + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("check memory length:%d", string_length); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, string_length); + } else { + if (dp_ipc_read(sock, recv_str, string_length, funcname) <= 0) { + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[string_length] = '\0'; + *string = recv_str; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +// send command and int & return errorcode +static int __dp_ipc_set_int(const int id, const unsigned section, const unsigned property, + const int value, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + if (dp_ipc_write(sock, (void *)&value, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +// send command & return errorcode and int +static int __dp_ipc_get_int(const int id, const unsigned property, + int *value, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + + if (value == NULL) { + TRACE_ERROR("%s check buffer", funcname); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_GET, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + size_t extra_size = 0; + errorcode = __dp_ipc_response(sock, id, DP_SEC_GET, property, &extra_size); + if (errorcode == DP_ERROR_NONE) { + if (extra_size == sizeof(int)) { + if (dp_ipc_read(sock, value, extra_size, funcname) < 0) + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +// send command & return errorcode. +int __dp_ipc_echo(const int id, const short section, + const unsigned property, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +/////////////////////// APIs ///////////////////////////////// + +int dp_interface_create(int *id) +{ + int errorcode = DP_ERROR_NONE; + int index = -1; + + if (id == NULL) { + TRACE_ERROR("[CHECK id variable]"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + CLIENT_MUTEX_LOCK(&g_function_mutex); + + if ((index = __get_empty_slot_index()) < 0) { + TRACE_ERROR + ("[ERROR] TOO_MANY_DOWNLOADS[%d]", MAX_DOWNLOAD_HANDLE); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; + } + + DP_CHECK_CONNECTION; + + dp_ipc_fmt *ipc_info = NULL; + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, -1, DP_SEC_CONTROL, DP_PROP_CREATE, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + } else { + ipc_info = dp_ipc_get_fmt(sock); + if (ipc_info == NULL) { + TRACE_ERROR("[ERROR] IPC INFO is NULL"); + errorcode = DP_ERROR_IO_ERROR; + } else if (ipc_info->section != DP_SEC_CONTROL || + ipc_info->property != DP_PROP_CREATE || + ipc_info->size != 0) { + TRACE_ERROR("sock:%d id:%d section:%d property:%d size:%d", + sock, ipc_info->id, ipc_info->section, ipc_info->property, + ipc_info->size); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_DEBUG("download_id:%d", ipc_info->id); + if (errorcode == DP_ERROR_NONE && ipc_info->id > 0) { + *id = ipc_info->id; + g_interface_slots[index].id = ipc_info->id; + g_interface_slots[index].state = NULL; + g_interface_slots[index].state_data = NULL; + g_interface_slots[index].progress = NULL; + g_interface_slots[index].progress_data = NULL; + } + } + } + free(ipc_info); + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_destroy(const int id) +{ + int index = -1; + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + if ((index = __get_my_slot_index(id)) >= 0) { + g_interface_slots[index].id = 0; + g_interface_slots[index].state = NULL; + g_interface_slots[index].state_data = NULL; + g_interface_slots[index].progress = NULL; + g_interface_slots[index].progress_data = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_DESTROY, __FUNCTION__); +} + +int dp_interface_start(const int id) +{ + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_START, __FUNCTION__); +} + +int dp_interface_pause(const int id) +{ + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_PAUSE, __FUNCTION__); +} + +int dp_interface_cancel(const int id) +{ + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_CANCEL, __FUNCTION__); +} + +int dp_interface_set_url(const int id, const char *url) +{ + if (url == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_URL, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_URL, url, __FUNCTION__); +} + +int dp_interface_get_url(const int id, char **url) +{ + return __dp_ipc_get_string(id, DP_PROP_URL, url, __FUNCTION__); +} + +int dp_interface_set_destination(const int id, const char *path) +{ + if (path == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_DESTINATION, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_DESTINATION, path, __FUNCTION__); +} + +int dp_interface_get_destination(const int id, char **path) +{ + return __dp_ipc_get_string(id, DP_PROP_DESTINATION, path, __FUNCTION__); +} + +int dp_interface_set_file_name(const int id, const char *file_name) +{ + if (file_name == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_FILENAME, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_FILENAME, file_name, __FUNCTION__); +} + +int dp_interface_get_file_name(const int id, char **file_name) +{ + return __dp_ipc_get_string(id, DP_PROP_FILENAME, file_name, __FUNCTION__); +} + +int dp_interface_get_downloaded_file_path(const int id, char **path) +{ + return __dp_ipc_get_string(id, DP_PROP_SAVED_PATH, path, __FUNCTION__); +} + +int dp_interface_get_temp_path(const int id, char **temp_path) +{ + return __dp_ipc_get_string(id, DP_PROP_TEMP_SAVED_PATH, temp_path, __FUNCTION__); +} + +int dp_interface_get_content_name(const int id, char **content_name) +{ + return __dp_ipc_get_string(id, DP_PROP_CONTENT_NAME, content_name, __FUNCTION__); +} + +int dp_interface_get_etag(const int id, char **etag) +{ + return __dp_ipc_get_string(id, DP_PROP_ETAG, etag, __FUNCTION__); +} + +int dp_interface_set_temp_file_path(const int id, const char *path) +{ + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_TEMP_SAVED_PATH, path, __FUNCTION__); +} + +int dp_interface_set_network_type(const int id, int net_type) +{ + return __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NETWORK_TYPE, + net_type, __FUNCTION__); +} + +int dp_interface_get_network_type(const int id, int *net_type) +{ + if (net_type == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_NETWORK_TYPE, net_type, __FUNCTION__); +} + +int dp_interface_get_network_bonding(const int id, int *enable) +{ + if (enable == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_NETWORK_BONDING, enable, __FUNCTION__); +} + +int dp_interface_set_network_bonding(const int id, int enable) +{ + return __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NETWORK_BONDING, + enable, __FUNCTION__); +} + +int dp_interface_set_state_changed_cb(const int id, + dp_interface_state_changed_cb callback, void *user_data) +{ + int errorcode = __dp_ipc_echo(id, DP_SEC_SET, DP_PROP_STATE_CALLBACK, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index < 0) { + index = __get_empty_slot_index(); + if (index >= 0) { + g_interface_slots[index].id = id; + } else { + TRACE_ERROR("too many download limit:%d", + MAX_DOWNLOAD_HANDLE); + errorcode = DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; + } + } + if (index >= 0) { + g_interface_slots[index].state = callback; + g_interface_slots[index].state_data = user_data; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + } + return errorcode; +} + +int dp_interface_unset_state_changed_cb(const int id) +{ + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index >= 0) { + g_interface_slots[index].state = NULL; + g_interface_slots[index].state_data = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + if (index < 0) + return DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND; + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_STATE_CALLBACK, __FUNCTION__); +} + +int dp_interface_set_progress_cb(const int id, + dp_interface_progress_cb callback, void *user_data) +{ + int errorcode = __dp_ipc_echo(id, DP_SEC_SET, DP_PROP_PROGRESS_CALLBACK, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index < 0) { + index = __get_empty_slot_index(); + if (index >= 0) { + g_interface_slots[index].id = id; + } else { + TRACE_ERROR("too many download limit:%d", + MAX_DOWNLOAD_HANDLE); + errorcode = DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; + } + } + if (index >= 0) { + g_interface_slots[index].progress = callback; + g_interface_slots[index].progress_data = user_data; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + } + return errorcode; +} + +int dp_interface_unset_progress_cb(const int id) +{ + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index >= 0) { + g_interface_slots[index].progress = NULL; + g_interface_slots[index].progress_data = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + if (index < 0) + return DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND; + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_PROGRESS_CALLBACK, __FUNCTION__); +} + +int dp_interface_get_state(const int id, int *state) +{ + if (state == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int dp_state = DP_STATE_NONE; + int errorcode = __dp_ipc_get_int(id, DP_PROP_STATE, &dp_state, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) + *state = __dp_interface_convert_state(dp_state); + return errorcode; +} + +int dp_interface_get_content_size(const int id, + unsigned long long *content_size) +{ + int errorcode = DP_ERROR_NONE; + + if (content_size == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_GET, DP_PROP_TOTAL_FILE_SIZE, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", __FUNCTION__, sock); + } else { + size_t extra_size = 0; + errorcode = __dp_ipc_response(sock, id, DP_SEC_GET, DP_PROP_TOTAL_FILE_SIZE, &extra_size); + if (errorcode == DP_ERROR_NONE) { + if (extra_size == sizeof(unsigned long long)) { + if (dp_ipc_read(sock, content_size, extra_size, __FUNCTION__) < 0) + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_get_mime_type(const int id, char **mime_type) +{ + if (mime_type == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_string(id, DP_PROP_MIME_TYPE, mime_type, + __FUNCTION__); +} + +int dp_interface_set_auto_download(const int id, int enable) +{ + short section = DP_SEC_SET; + if (enable <= 0) + section = DP_SEC_UNSET; + return __dp_ipc_echo(id, section, DP_PROP_AUTO_DOWNLOAD, __FUNCTION__); +} + +int dp_interface_get_auto_download(const int id, int *enable) +{ + if (enable == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_AUTO_DOWNLOAD, enable, __FUNCTION__); +} + +int dp_interface_get_error(const int id, int *error) +{ + if (error == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int errorcode = DP_ERROR_NONE; + int ret = __dp_ipc_get_int(id, DP_PROP_ERROR, &errorcode, __FUNCTION__); + if (ret == DOWNLOAD_ADAPTOR_ERROR_NONE) + *error = __dp_interface_convert_errorcode(errorcode); + return ret; +} + +int dp_interface_get_http_status(const int id, int *http_status) +{ + if (http_status == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_HTTP_STATUS, http_status, + __FUNCTION__); +} + +int dp_interface_set_notification_title(const int id, const char *title) +{ + if (title == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_SUBJECT, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_NOTIFICATION_SUBJECT, title, __FUNCTION__); +} + +int dp_interface_get_notification_title(const int id, char **title) +{ + if (title == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_string(id, DP_PROP_NOTIFICATION_SUBJECT, title, __FUNCTION__); +} + +int dp_interface_set_notification_description(const int id, const char *description) +{ + if (description == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_DESCRIPTION, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_NOTIFICATION_DESCRIPTION, description, __FUNCTION__); +} + +int dp_interface_get_notification_description(const int id, char **description) +{ + if (description == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_string(id, DP_PROP_NOTIFICATION_DESCRIPTION, description, __FUNCTION__); +} + +int dp_interface_set_notification_type(const int id, int type) +{ + if (type == DP_NOTIFICATION_TYPE_NONE) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_TYPE, __FUNCTION__); + return __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NOTIFICATION_TYPE, type, __FUNCTION__); +} + +int dp_interface_get_notification_type(const int id, int *type) +{ + if (type == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_NOTIFICATION_TYPE, type, __FUNCTION__); +} + +int dp_interface_set_notification_bundle(const int id, const int type, void *bundle_param) +{ + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_BUNDLE_TYPE_ONGOING && + type != DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE && + type != DP_NOTIFICATION_BUNDLE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + if (bundle_param == NULL) { // unset + return __dp_ipc_set_int(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + } else { // set + int length = 0; + bundle_raw *raw_buffer = NULL; + int result = bundle_encode_raw(bundle_param, &raw_buffer, &length); + if (result == 0 && length > 0) { + errorcode = __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + errorcode = __dp_ipc_set_binary(id, DP_PROP_NOTIFICATION_RAW, raw_buffer, (size_t)length, __FUNCTION__); + } + } else { + TRACE_ERROR("failed to encode raws error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (raw_buffer != NULL) + bundle_free_encoded_rawdata(&raw_buffer); + } + return errorcode; +} + +int dp_interface_get_notification_bundle(const int id, const int type, void **bundle_param) +{ + if (bundle_param == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_BUNDLE_TYPE_ONGOING && + type != DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE && + type != DP_NOTIFICATION_BUNDLE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + + // send type, get errorcode with extra_size, get bundle binary + + errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + const unsigned section = DP_SEC_GET; + const unsigned property = DP_PROP_NOTIFICATION_RAW; + size_t extra_size = 0; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void *)&type, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, &extra_size); + } + } + if (errorcode == DP_ERROR_NONE && extra_size > 0) { + unsigned char *recv_raws = (unsigned char *)calloc(extra_size, sizeof(unsigned char)); + if (recv_raws == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", sock, extra_size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, extra_size); + } else { + if (dp_ipc_read(sock, recv_raws, extra_size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + errorcode = DP_ERROR_IO_ERROR; + free(recv_raws); + } else { + TRACE_DEBUG("sock:%d length:%d raws", sock, extra_size); + *bundle_param = bundle_decode_raw(recv_raws, extra_size); + free(recv_raws); + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_set_notification_service_handle(const int id, const int type, void *handle) +{ + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_SERVICE_TYPE_ONGOING && + type != DP_NOTIFICATION_SERVICE_TYPE_COMPLETE && + type != DP_NOTIFICATION_SERVICE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + if (handle == NULL) { // unset + return __dp_ipc_set_int(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + } else { // set + int length = 0; + bundle_raw *raw_buffer = NULL; + bundle *bundle_data = NULL; + int result = app_control_export_as_bundle((app_control_h) handle, &bundle_data); + if (result == APP_CONTROL_ERROR_NONE) { + result = bundle_encode_raw(bundle_data, &raw_buffer, &length); + if (result == 0 && length > 0) { + errorcode = __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + errorcode = __dp_ipc_set_binary(id, DP_PROP_NOTIFICATION_RAW, raw_buffer, (size_t)length, __FUNCTION__); + } + } else { + TRACE_ERROR("failed to encode raws error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + } else { + TRACE_ERROR("failed to encode service handle error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (raw_buffer != NULL) + bundle_free_encoded_rawdata(&raw_buffer); + if (bundle_data != NULL) + bundle_free(bundle_data); + } + return errorcode; +} + +int dp_interface_get_notification_service_handle(const int id, const int type, void **handle) +{ + bundle *bundle_data = NULL; + if (handle == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_SERVICE_TYPE_ONGOING && + type != DP_NOTIFICATION_SERVICE_TYPE_COMPLETE && + type != DP_NOTIFICATION_SERVICE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + + // send type, get errorcode with extra_size, get bundle binary + + errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + const unsigned section = DP_SEC_GET; + const unsigned property = DP_PROP_NOTIFICATION_RAW; + size_t extra_size = 0; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void *)&type, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, &extra_size); + } + } + if (errorcode == DP_ERROR_NONE && extra_size > 0) { + unsigned char *recv_raws = (unsigned char *)calloc(extra_size, sizeof(unsigned char)); + if (recv_raws == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", sock, extra_size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, extra_size); + } else { + if (dp_ipc_read(sock, recv_raws, extra_size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + errorcode = DP_ERROR_IO_ERROR; + free(recv_raws); + } else { + TRACE_DEBUG("sock:%d length:%d raws", sock, extra_size); + + bundle_data = bundle_decode_raw(recv_raws, extra_size); + if (bundle_data) { + int result = 0; + result = app_control_create((app_control_h *)handle); + if (result == APP_CONTROL_ERROR_NONE) { + result = app_control_import_from_bundle((app_control_h)*handle, bundle_data); + if (result != APP_CONTROL_ERROR_NONE) { + TRACE_ERROR("failed to import service handle error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + } else { + TRACE_ERROR("failed to create service handle error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + bundle_free(bundle_data); + } + free(recv_raws); + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_add_http_header_field(const int id, const char *field, + const char *value) +{ + // cmd + field string + value string + // wait response + int errorcode = DP_ERROR_NONE; + size_t field_length = 0; + size_t value_length = 0; + if (field == NULL || (field_length = strlen(field)) <= 0 || + field_length > DP_MAX_STR_LEN) { + TRACE_ERROR("check field (%d:%s)", field_length, field); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (value == NULL || (value_length = strlen(value)) <= 0 || + value_length > DP_MAX_STR_LEN) { + TRACE_ERROR("check value (%d:%s)", value_length, value); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + short section = DP_SEC_SET; + unsigned property = DP_PROP_HTTP_HEADER; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, field_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void*)field, field_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + if (errorcode == DP_ERROR_NONE) { + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, value_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void*)value, value_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + } + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_get_http_header_field(const int id, const char *field, + char **value) +{ + // cmd + field string + // wait response + value string + int errorcode = DP_ERROR_NONE; + size_t length = 0; + if (field == NULL || (length = strlen(field)) <= 0 || + length > DP_MAX_STR_LEN) { + TRACE_ERROR("check field (%d:%s)", length, field); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (value == NULL) { + TRACE_ERROR("check pointer for value"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + short section = DP_SEC_GET; + unsigned property = DP_PROP_HTTP_HEADER; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void*)field, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + size_t string_length = 0; + *value = NULL; + errorcode = __dp_ipc_response(sock, id, section, property, &string_length); + if (errorcode == DP_ERROR_NONE) { + if (string_length > 0) { + char *recv_str = (char *)calloc((string_length + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("check memory length:%d", string_length); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, string_length); + } else { + if (dp_ipc_read(sock, recv_str, string_length, __FUNCTION__) <= 0) { + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[string_length] = '\0'; + *value = recv_str; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_get_http_header_field_list(const int id, char ***fields, + int *length) +{ + // cmd + // wait response + // wait size + // wait strings + int errorcode = DP_ERROR_NONE; + if (fields == NULL) { + TRACE_ERROR("check pointer for fields"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (length == NULL) { + TRACE_ERROR("check pointer for length"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + short section = DP_SEC_GET; + unsigned property = DP_PROP_HTTP_HEADERS; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + + int array_size = 0; + size_t extra_size = 0; + errorcode = __dp_ipc_response(sock, id, section, property, &extra_size); + if (errorcode == DP_ERROR_NONE) { + if (extra_size == sizeof(int)) { + if (dp_ipc_read(sock, &array_size, extra_size, __FUNCTION__) < 0) { + errorcode = DP_ERROR_IO_ERROR; + } else { + if (array_size <= 0) { + errorcode = DP_ERROR_NO_DATA; + *length = 0; + } else { + int i = 0; + char **recv_strings = NULL; + recv_strings = (char **)calloc(array_size, sizeof(char *)); + if (recv_strings == NULL) { + TRACE_STRERROR("check memory size:%d", array_size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + *length = 0; + } else { + // get strings. + for (; i < array_size; i++) { + size_t string_length = 0; + errorcode = __dp_ipc_response(sock, id, section, property, &string_length); + recv_strings[i] = NULL; + if (errorcode == DP_ERROR_NONE && string_length > 0) { + char *recv_str = (char *)calloc((string_length + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("check memory length:%d", string_length * sizeof(char)); + errorcode = DP_ERROR_OUT_OF_MEMORY; + break; + } else { + if (dp_ipc_read(sock, recv_str, string_length, __FUNCTION__) <= 0) { + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[string_length] = '\0'; + recv_strings[i] = recv_str; + } + } + } + } + *fields = recv_strings; + } + if (errorcode != DP_ERROR_NONE) { // if error, free all allocated memories + int j = 0; + for (; j < i; j++) { + free(recv_strings[j]); + } + free(recv_strings); + *length = 0; + *fields = NULL; + if (errorcode != DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); // clear IPC, can not expect the size of futher packets + } + *length = i; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + + + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_remove_http_header_field(const int id, + const char *field) +{ + return __dp_ipc_set_string(id, DP_SEC_UNSET, DP_PROP_HTTP_HEADER, field, __FUNCTION__); +} diff --git a/provider-interface/download-provider-interface.pc.in b/provider-interface/download-provider-interface.pc.in new file mode 100644 index 0000000..35e1cc9 --- /dev/null +++ b/provider-interface/download-provider-interface.pc.in @@ -0,0 +1,8 @@ +# Package Information + +Name: @PROJECT_NAME@ +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_REQUIRED@ +Libs: -L/usr/lib -l@PROJECT_NAME@ +Cflags: -I/usr/include/@PKG_NAME@ diff --git a/provider-interface/include/download-provider-interface.h b/provider-interface/include/download-provider-interface.h new file mode 100755 index 0000000..e9d3d59 --- /dev/null +++ b/provider-interface/include/download-provider-interface.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DOWNLOAD_PROVIDER_INTERFACE_H__ +#define __DOWNLOAD_PROVIDER_INTERFACE_H__ + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *dp_print_state(int state) +{ + switch(state) + { + case DP_STATE_NONE : + return "NONE"; + case DP_STATE_READY : + return "READY"; + case DP_STATE_QUEUED : + return "QUEUED"; + case DP_STATE_CONNECTING : + return "CONNECTING"; + case DP_STATE_DOWNLOADING : + return "DOWNLOADING"; + case DP_STATE_PAUSED : + return "PAUSED"; + case DP_STATE_COMPLETED : + return "COMPLETED"; + case DP_STATE_CANCELED : + return "CANCELED"; + case DP_STATE_FAILED : + return "FAILED"; + default : + break; + } + return "UNKNOWN"; +} + +char *dp_print_errorcode(int errorcode) +{ + switch(errorcode) + { + case DP_ERROR_NONE : + return "NONE"; + case DP_ERROR_INVALID_PARAMETER : + return "INVALID_PARAMETER"; + case DP_ERROR_OUT_OF_MEMORY : + return "OUT_OF_MEMORY"; + case DP_ERROR_IO_ERROR : + return "IO_ERROR"; + case DP_ERROR_NETWORK_UNREACHABLE : + return "NETWORK_UNREACHABLE"; + case DP_ERROR_CONNECTION_TIMED_OUT : + return "CONNECTION_TIMED_OUT"; + case DP_ERROR_NO_SPACE : + return "NO_SPACE"; + case DP_ERROR_FIELD_NOT_FOUND : + return "FIELD_NOT_FOUND"; + case DP_ERROR_INVALID_STATE : + return "INVALID_STATE"; + case DP_ERROR_CONNECTION_FAILED : + return "CONNECTION_FAILED"; + case DP_ERROR_INVALID_URL : + return "INVALID_URL"; + case DP_ERROR_INVALID_DESTINATION : + return "INVALID_DESTINATION"; + case DP_ERROR_QUEUE_FULL : + return "QUEUE_FULL"; + case DP_ERROR_ALREADY_COMPLETED : + return "ALREADY_COMPLETED"; + case DP_ERROR_FILE_ALREADY_EXISTS : + return "FILE_ALREADY_EXISTS"; + case DP_ERROR_TOO_MANY_DOWNLOADS : + return "TOO_MANY_DOWNLOADS"; + case DP_ERROR_NO_DATA : + return "NO_DATA"; + case DP_ERROR_UNHANDLED_HTTP_CODE : + return "UNHANDLED_HTTP_CODE"; + case DP_ERROR_CANNOT_RESUME : + return "CANNOT_RESUME"; + case DP_ERROR_PERMISSION_DENIED : + return "PERMISSION_DENIED"; + case DP_ERROR_RESPONSE_TIMEOUT : + return "RESPONSE_TIMEOUT"; + case DP_ERROR_REQUEST_TIMEOUT : + return "REQUEST_TIMEOUT"; + case DP_ERROR_SYSTEM_DOWN : + return "SYSTEM_DOWN"; + case DP_ERROR_CLIENT_DOWN : + return "CLIENT_DOWN"; + case DP_ERROR_DISK_BUSY: + return "DISK_BUSY"; + case DP_ERROR_ID_NOT_FOUND : + return "ID_NOT_FOUND"; + default : + break; + } + return "UNKNOWN"; +} + +char *dp_print_section(short section) +{ + switch (section) { + case DP_SEC_NONE: + return "NONE"; + case DP_SEC_INIT: + return "INIT"; + case DP_SEC_DEINIT: + return "DEINIT"; + case DP_SEC_CONTROL: + return "CONTROL"; + case DP_SEC_GET: + return "GET"; + case DP_SEC_SET: + return "SET"; + case DP_SEC_UNSET: + return "UNSET"; + default: + break; + } + return "UNKNOWN"; +} + +char *dp_print_property(unsigned property) +{ + switch (property) { + case DP_PROP_NONE: + return "NONE"; + case DP_PROP_CREATE: + return "CREATE"; + case DP_PROP_START: + return "START"; + case DP_PROP_PAUSE: + return "PAUSE"; + case DP_PROP_CANCEL: + return "CANCEL"; + case DP_PROP_DESTROY: + return "DESTROY"; + case DP_PROP_URL: + return "URL"; + case DP_PROP_DESTINATION: + return "DESTINATION"; + case DP_PROP_FILENAME: + return "FILENAME"; + case DP_PROP_STATE_CALLBACK: + return "STATE_CB"; + case DP_PROP_PROGRESS_CALLBACK: + return "PROGRESS_CB"; + case DP_PROP_AUTO_DOWNLOAD: + return "AUTO_DOWNLOAD"; + case DP_PROP_NETWORK_TYPE: + return "NETWORK_TYPE"; + case DP_PROP_NETWORK_BONDING: + return "NETWORK_BONDING"; + case DP_PROP_SAVED_PATH: + return "SAVED_PATH"; + case DP_PROP_TEMP_SAVED_PATH: + return "TEMP_SAVED_PATH"; + case DP_PROP_MIME_TYPE: + return "MIME_TYPE"; + case DP_PROP_RECEIVED_SIZE: + return "RECEIVED_SIZE"; + case DP_PROP_TOTAL_FILE_SIZE: + return "TOTAL_FILE_SIZE"; + case DP_PROP_CONTENT_NAME: + return "CONTENT_NAME"; + case DP_PROP_HTTP_STATUS: + return "HTTP_STATUS"; + case DP_PROP_ETAG: + return "ETAG"; + case DP_PROP_STATE: + return "STATE"; + case DP_PROP_ERROR: + return "ERROR"; + case DP_PROP_NOTIFICATION_RAW: + return "NOTIFICATION_RAW"; + case DP_PROP_NOTIFICATION_SUBJECT: + return "NOTIFICATION_SUBJECT"; + case DP_PROP_NOTIFICATION_DESCRIPTION: + return "NOTIFICATION_DESCRIPTION"; + case DP_PROP_NOTIFICATION_TYPE: + return "NOTIFICATION_TYPE"; + case DP_PROP_HTTP_HEADERS: + return "HTTP_HEADERS"; + case DP_PROP_HTTP_HEADER: + return "HTTP_HEADER"; + default: + break; + } + return "UNKNOWN"; +} + +static int __dp_get_download_id(dp_client_fmt *client) +{ + int download_id = -1; + static int last_download_id = 0; + int check_duplicate = 0; + int errorcode = DP_ERROR_NONE; + + do { + do { + struct timeval tval; + int cipher = 1; + int c = 0; + + download_id = -1; + gettimeofday(&tval, NULL); + + int usec = tval.tv_usec; + for (c = 0; ; c++, cipher++) { + if ((usec /= 10) <= 0) + break; + } + if (tval.tv_usec == 0) + tval.tv_usec = (tval.tv_sec & 0x0fff); + int disit_unit = 10; + for (c = 0; c < cipher - 3; c++) + disit_unit = disit_unit * 10; + download_id = tval.tv_sec + ((tval.tv_usec << 2) * 100) + + ((tval.tv_usec >> (cipher - 1)) * disit_unit) + + ((tval.tv_usec + (tval.tv_usec % 10)) & 0x0fff); + } while (last_download_id == download_id); + last_download_id = download_id; + check_duplicate = dp_db_check_duplicated_int(client->dbhandle, + DP_TABLE_LOGGING, DP_DB_COL_ID, download_id, &errorcode); + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("ERROR [%d]", errorcode); + } + } while (check_duplicate != 0); // means duplicated id + return download_id; +} + +void dp_request_create(dp_client_fmt *client, dp_request_fmt *request) +{ + // new request + // find the tail of linked list & check limitation + int i = 0; + dp_request_fmt *tailp = client->requests; + dp_request_fmt *prevp = NULL; + for (; i < MAX_DOWNLOAD_HANDLE; i++) { + if (tailp == NULL) + break; + TRACE_DEBUG("link %d info: id:%d access-time:%d", i, tailp->id, tailp->access_time); + prevp = tailp; + tailp = tailp->next; + } + request->next = NULL; + if (prevp == NULL) // it's first link + client->requests = request; + else + prevp->next = request; // attach at the tail + + TRACE_DEBUG("sock:%d download-id:%d", client->channel, request->id); +} + +static int __dp_request_create(dp_client_fmt *client, dp_ipc_fmt *ipc_info) +{ + int errorcode = DP_ERROR_NONE; + + int download_id = __dp_get_download_id(client); + + // allocation new request. + dp_request_fmt *request = (dp_request_fmt *) calloc(1, sizeof(dp_request_fmt)); + if (request == NULL) { + TRACE_ERROR("check memory sock:%d download-id:%d", client->channel, download_id); + return DP_ERROR_OUT_OF_MEMORY; + } + + if (dp_db_new_logging(client->dbhandle, download_id, DP_STATE_READY, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("new log sock:%d download-id:%d", client->channel, download_id); + free(request); + return DP_ERROR_DISK_BUSY; + } + + request->id = download_id; + request->agent_id = -1; + request->state = DP_STATE_READY; + request->error = DP_ERROR_NONE; + request->network_type = DP_NETWORK_ALL; + request->access_time = (int)time(NULL); + request->state_cb = 0; + request->progress_cb = 0; + request->startcount = 0; + request->noti_type = DP_NOTIFICATION_TYPE_NONE; + request->progress_lasttime = 0; + request->received_size = 0; + request->content_type = DP_CONTENT_UNKNOWN; + request->file_size = 0; + request->noti_priv_id = -1; + + dp_request_create(client, request); + ipc_info->id = download_id; + return errorcode; +} + +void dp_request_free(dp_request_fmt *request) +{ + // free notification handle here + TRACE_DEBUG("destory id:%d", request->id); + free(request); +} + +void dp_client_clear_requests(void *slotp) +{ + dp_client_slots_fmt *slot = (dp_client_slots_fmt *)slotp; + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return ; + } + dp_client_fmt *client = &slot->client; + if (client == NULL) { + TRACE_ERROR("check client memory"); + return ; + } + + int now_time = (int)time(NULL); + int i = 0; + unsigned queued_count = 0; + unsigned ongoing_count = 0; + dp_request_fmt *tailp = client->requests; + dp_request_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + + unsigned can_unload = 0; + if (tailp->id <= 0 || tailp->state == DP_STATE_NONE) { + TRACE_ERROR("id:%d unexpected request (%ld/%ld)", tailp->id, tailp->access_time, now_time); + can_unload = 1; + } else if (tailp->access_time > 0 && + (now_time - tailp->access_time) > DP_CARE_CLIENT_CLEAR_INTERVAL) { + // check accesstime. if difference is bigger than DP_CARE_CLIENT_CLEAR_INTERVAL, clear. + + if (tailp->state == DP_STATE_READY || + tailp->state == DP_STATE_COMPLETED || + tailp->state == DP_STATE_CANCELED || + tailp->state == DP_STATE_FAILED) { + can_unload = 1; + } else if (tailp->state == DP_STATE_CONNECTING) { // it take 120 sec over to connect. it means zombie. + TRACE_ERROR("id:%d connection timeout (%ld/%ld)", tailp->id, tailp->access_time, now_time); + if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id); + } + tailp->state = DP_STATE_FAILED; + tailp->error = DP_ERROR_CONNECTION_TIMED_OUT; + if (tailp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + tailp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, tailp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", tailp->id); + } + } + } + } else if (tailp->state == DP_STATE_PAUSED && + dp_is_alive_download(tailp->agent_id) == 0) { + // paused & agent_id not exist.... unload from memory. + TRACE_ERROR("id:%d hanged as paused (%ld/%ld)", tailp->id, tailp->access_time, now_time); + can_unload = 1; + } + + if (can_unload == 1) { + dp_request_fmt *removep = tailp; + if (prevp == NULL) // first request. + client->requests = tailp->next; + else + prevp->next = tailp->next; + tailp = tailp->next; + TRACE_DEBUG("request %d clear: id:%d state:%s", i, removep->id, dp_print_state(removep->state)); + dp_request_free(removep); + continue; + } else { + ongoing_count++; + } + + if (tailp->state == DP_STATE_QUEUED) + queued_count++; + + prevp = tailp; + tailp = tailp->next; + } + TRACE_DEBUG("info requests:%d queued:%d", ongoing_count, queued_count); + if (queued_count > 0) + dp_queue_manager_wake_up(); +} + +int dp_request_destroy(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + int errorcode = DP_ERROR_NONE; + + if (requestp != NULL && client->requests != NULL) { + if (requestp == client->requests) { + // cancel downloading ... after checking status + client->requests = requestp->next; + dp_request_free(requestp); + } else { + int i = 1; + dp_request_fmt *prevp = client->requests; + dp_request_fmt *removep = client->requests->next; + for (; i < MAX_DOWNLOAD_HANDLE; i++) { + if (removep == NULL) { + errorcode = DP_ERROR_ID_NOT_FOUND; + break; + } + if (removep == requestp) { + // cancel downloading ... after checking status + prevp->next = removep->next; + dp_request_free(removep); + break; + } + prevp = removep; + removep = removep->next; + } + } + } + + TRACE_DEBUG("sock:%d id:%d errorcode:%s", client->channel, + (ipc_info) ? ipc_info->id : -1, dp_print_errorcode(errorcode)); + + return errorcode; +} + +static int __dp_request_read_int(int sock, dp_ipc_fmt *ipc_info, int *value) +{ + int errorcode = DP_ERROR_NONE; + if (ipc_info->size == sizeof(int)) { + if (dp_ipc_read(sock, value, ipc_info->size, __FUNCTION__) < 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, ipc_info->size); + errorcode = DP_ERROR_IO_ERROR; + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + return errorcode; +} + +static int __dp_request_feedback_string(int sock, dp_ipc_fmt *ipc_info, void *string, size_t length, int errorvalue) +{ + int errorcode = DP_ERROR_NONE; + + if (length == 0 && errorvalue == DP_ERROR_NONE) + errorvalue = DP_ERROR_NO_DATA; + + if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, length); + } + if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) { + if (dp_ipc_write(sock, string, sizeof(char) * length) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, length); + } + } + return errorcode; +} + +static int __dp_request_read_string(int sock, dp_ipc_fmt *ipc_info, char **string) +{ + int errorcode = DP_ERROR_NONE; + if (ipc_info->size > 0) { + char *recv_str = (char *)calloc((ipc_info->size + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", sock, ipc_info->size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } else { + if (dp_ipc_read(sock, recv_str, ipc_info->size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, ipc_info->size); + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[ipc_info->size] = '\0'; + TRACE_DEBUG("sock:%d length:%d string:%s", sock, ipc_info->size, recv_str); + *string = recv_str; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + return errorcode; +} + +static int __dp_request_feedback_int(int sock, dp_ipc_fmt *ipc_info, void *value, int errorvalue, size_t extra_size) +{ + int errorcode = DP_ERROR_NONE; + if (errorvalue != DP_ERROR_NONE) + extra_size = 0; + if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, extra_size) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + } + if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) { + if (dp_ipc_write(sock, value, extra_size) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + } + } + return errorcode; +} + +static int __dp_request_get_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + int errorcode = DP_ERROR_NONE; + switch (ipc_info->property) { + case DP_PROP_URL: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_DESTINATION: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_FILENAME: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_STATE_CALLBACK: + { + int callback = 0; + if (requestp != NULL) { + callback = requestp->state_cb; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, &callback, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&callback, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_PROGRESS_CALLBACK: + { + int callback = 0; + if (requestp != NULL) { + callback = requestp->progress_cb; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, &callback, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&callback, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_AUTO_DOWNLOAD: + { + int autodownload = 0; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, &autodownload, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&autodownload, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NETWORK_TYPE: + { + int network = 0; + if (requestp != NULL) { + network = requestp->network_type; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, &network, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&network, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NETWORK_BONDING: + { + int network_bonding = 0; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, &network_bonding, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&network_bonding, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_SAVED_PATH: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_TEMP_SAVED_PATH: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_TMP_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_MIME_TYPE: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_MIMETYPE, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_RECEIVED_SIZE: + { + unsigned long long recv_size = 0; + if (requestp != NULL) { + recv_size = requestp->received_size; + } else { + errorcode = DP_ERROR_INVALID_STATE; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&recv_size, errorcode, sizeof(unsigned long long)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_TOTAL_FILE_SIZE: + { + unsigned long long file_size = 0; + if (requestp != NULL) { + file_size = requestp->file_size; + } else { + // load content_size(INT64) from database; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_SIZE, &file_size, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&file_size, errorcode, sizeof(unsigned long long)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_CONTENT_NAME: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_HTTP_STATUS: + { + int httpstatus = 0; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_HTTP_STATUS, &httpstatus, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&httpstatus, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_ETAG: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_ETAG, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_STATE: + { + int state = DP_STATE_NONE; + if (requestp != NULL) { + state = requestp->state; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &state, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&state, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_ERROR: + { + int errorvalue = DP_ERROR_NONE; + if (requestp != NULL) { + errorvalue = requestp->error; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_ERRORCODE, &errorvalue, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&errorvalue, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NOTIFICATION_TYPE: + { + int noti_type = 0; + if (requestp != NULL) { + noti_type = requestp->noti_type; + // if already notification, unregister from notification bar. + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, ¬i_type, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)¬i_type, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NOTIFICATION_SUBJECT: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_NOTIFICATION_DESCRIPTION: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_NOTIFICATION_RAW: // read type, send raw binary for type + { + int bundle_type = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type); + TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type); + char *raw_column = NULL; + if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING) + raw_column = DP_DB_COL_NOTI_RAW_ONGOING; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE) + raw_column = DP_DB_COL_NOTI_RAW_COMPLETE; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED) + raw_column = DP_DB_COL_NOTI_RAW_FAIL; + + if (raw_column == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + TRACE_ERROR("invalid type %d type:%d", dp_print_property(ipc_info->property), bundle_type); + if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section, ipc_info->property, errorcode, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + } + if (errorcode == DP_ERROR_NONE) { + unsigned char *raws_buffer = NULL; + unsigned length = 0; + // get blob binary from database by raw_column + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &raws_buffer, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, raws_buffer, (size_t)length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(raws_buffer); + } + break; + } + case DP_PROP_HTTP_HEADERS: + { + // 1. response + // 2. send the number of header fields by id + // 3. send response & field string for each fields + int field_count = dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ID, ipc_info->id, &errorcode); + if (field_count < 0 ) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + field_count = 0; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&field_count, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } else if (field_count > 0) { + // get fields from database. + int *ids = (int *)calloc(field_count, sizeof(int)); + if (ids == NULL) { + TRACE_ERROR("failed to allocate the clients"); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } else { + // getting ids of clients + int i = 0; + int rows_count = dp_db_get_cond_ids(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ROW_ID, DP_DB_COL_ID, ipc_info->id, ids, field_count, &errorcode); + for (; i < rows_count; i++) { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_cond_string(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ROW_ID, ids[i], DP_DB_COL_HEADER_FIELD, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + free(string); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + break; + } + } + } + } + + break; + } + case DP_PROP_HTTP_HEADER: + { + // 1. read field string + // 2. response with extra size + // 3. send string. + char *header_field = NULL; + char *string = NULL; + unsigned length = 0; + errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field); + if (errorcode == DP_ERROR_NONE && header_field != NULL) { + if (dp_db_get_header_value(client->dbhandle, ipc_info->id, header_field, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_field == NULL) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(header_field); + free(string); + break; + } + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + return errorcode; +} + +static int __dp_request_set_info(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return DP_ERROR_INVALID_PARAMETER; + } + dp_client_fmt *client = &slot->client; + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + // if completed or downloading, invalid state. + int download_state = DP_STATE_NONE; + if (requestp != NULL) { + download_state = requestp->state; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) { + TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; + } + } + // should the state be checked ? + TRACE_DEBUG("state:%s set property:%s", dp_print_state(download_state), dp_print_property(ipc_info->property)); + + switch (ipc_info->property) { + case DP_PROP_URL: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_DESTINATION: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + if (dp_smack_is_mounted() == 1) { + // check here destination is available. with checking smack + char *smack_label = dp_db_get_client_smack_label(slot->pkgname); + if (smack_label == NULL) { + TRACE_SECURE_ERROR("[SMACK][%d] no label", ipc_info->id); + errorcode = DP_ERROR_PERMISSION_DENIED; + } else if (dp_is_valid_dir(recv_str) != 0) { + errorcode = DP_ERROR_INVALID_DESTINATION; + } else if (dp_smack_is_valid_dir(slot->credential.uid, slot->credential.gid, smack_label, recv_str) != 0) { + errorcode = DP_ERROR_PERMISSION_DENIED; + } + free(smack_label); + } + if (errorcode == DP_ERROR_NONE && + dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_TEMP_SAVED_PATH: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_TEMP_FILE_PATH, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_FILENAME: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_STATE_CALLBACK: + { + // check state here + // DP_ERROR_INVALID_STATE if downloading or finished + // update database here + if (requestp != NULL) { + requestp->state_cb = 1; + } + int enable_cb = 1; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_PROGRESS_CALLBACK: + { + // check state here + // DP_ERROR_INVALID_STATE if downloading or finished + // update database here + if (requestp != NULL) { + requestp->progress_cb = 1; + } + int enable_cb = 1; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_AUTO_DOWNLOAD: + { + // update autodownload property as 1 in database + int enable_cb = 1; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NETWORK_TYPE: + { + int recv_int = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int); + if (recv_int <= DP_NETWORK_OFF || + recv_int > DP_NETWORK_ALL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // update in database + if (requestp != NULL) { + if (requestp->state == DP_STATE_QUEUED) { + dp_queue_manager_clear_queue(requestp); + } else { + requestp->network_type = recv_int; + if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + // pause & push queue + if (dp_pause_agent_download_without_update(requestp->agent_id) < 0) { + TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id); + } else { + requestp->state = DP_STATE_PAUSED; + requestp->error = DP_ERROR_NONE; + if (dp_queue_manager_push_queue(slot, requestp) < 0) { + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + } + requestp->state = DP_STATE_FAILED; + requestp->error = DP_ERROR_QUEUE_FULL; + errorcode = DP_ERROR_QUEUE_FULL; + } + } + } + } + } + int enable_cb = recv_int; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + break; + } + case DP_PROP_NETWORK_BONDING: + { + int recv_int = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int); + if (errorcode == DP_ERROR_NONE) { + if(requestp != NULL && requestp->network_type != DP_NETWORK_ALL) { + errorcode = DP_ERROR_INVALID_NETWORK_TYPE; + TRACE_ERROR("[ERROR] wrong network type"); + } else if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, (void *)&recv_int, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + break; + } + case DP_PROP_NOTIFICATION_TYPE: + { + int recv_int = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int); + if (recv_int == DP_NOTIFICATION_TYPE_NONE || + recv_int == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + recv_int == DP_NOTIFICATION_TYPE_ALL) { + // check state request->state == DP_STATE_COMPLETED + // DP_ERROR_INVALID_STATE + // update notificatio type in database + int noti_type = recv_int; + if (requestp != NULL) { + if (recv_int < requestp->noti_type) { + // if already notification, unregister from notification bar. + if (recv_int == DP_NOTIFICATION_TYPE_NONE) { + if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to clear notification %s", dp_print_property(ipc_info->property)); + } + } + if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0) { + TRACE_ERROR("failed to clear ongoing %s", dp_print_property(ipc_info->property)); + } + } + requestp->noti_type = recv_int; + } + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, (void *)¬i_type, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } else { + errorcode = DP_ERROR_INVALID_PARAMETER; + } + break; + } + case DP_PROP_NOTIFICATION_SUBJECT: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_NOTIFICATION_DESCRIPTION: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_NOTIFICATION_RAW: // bundle_type(db column) + bundle_binary + { + int bundle_type = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type); + TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type); + char *raw_column = NULL; + if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING) + raw_column = DP_DB_COL_NOTI_RAW_ONGOING; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE) + raw_column = DP_DB_COL_NOTI_RAW_COMPLETE; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED) + raw_column = DP_DB_COL_NOTI_RAW_FAIL; + else + errorcode = DP_ERROR_INVALID_PARAMETER; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } + if (errorcode == DP_ERROR_NONE) { + dp_ipc_fmt *raw_info = dp_ipc_get_fmt(client->channel); + if (raw_info == NULL || raw_info->section != ipc_info->section || + raw_info->property != ipc_info->property || + (raw_info->id != ipc_info->id)) { + TRACE_ERROR("there is a confusion waiting raw binary in %s section", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_IO_ERROR; + } + if (raw_info != NULL && raw_info->size > 0) { + unsigned char *recv_raws = (unsigned char *)calloc(raw_info->size, sizeof(unsigned char)); + if (recv_raws == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", client->channel, raw_info->size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } else { + if (dp_ipc_read(client->channel, recv_raws, raw_info->size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", client->channel, raw_info->size); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_DEBUG("sock:%d length:%d raws", client->channel, raw_info->size); + // save to database + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, (void *)recv_raws, raw_info->size, 3, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + free(recv_raws); + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + free(raw_info); + } + break; + } + case DP_PROP_HTTP_HEADER: // a request can have one or more fields, a fields can have only one value. + { + char *header_field = NULL; + char *header_value = NULL; + // 1. read field string + // 2. response after checking sql status + // 3. read query IPC for checking IPC + // 4. read value string + // 5. response + errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field); + if (errorcode == DP_ERROR_NONE && header_field != NULL) { + // check sql + int check_field = dp_db_check_duplicated_string(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, 0, header_field, &errorcode); + if (check_field < 0) { + errorcode = DP_ERROR_DISK_BUSY; + } else { + errorcode = DP_ERROR_NONE; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } else { + dp_ipc_fmt *header_ipc = dp_ipc_get_fmt(client->channel); + if (header_ipc == NULL || header_ipc->section != ipc_info->section || + header_ipc->property != ipc_info->property || + (header_ipc->id != ipc_info->id)) { + TRACE_ERROR("there is a confusion during waiting http string in %s section", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = __dp_request_read_string(client->channel, header_ipc, &header_value); + if (errorcode == DP_ERROR_NONE && header_value != NULL) { + if (check_field == 0) { // insert + if (dp_db_new_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } else { // update + if (dp_db_update_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_value == NULL) { + TRACE_ERROR("failed to set %s, do you want to run as unset?", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + } + free(header_ipc); + } + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_field == NULL) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + free(header_field); + free(header_value); + break; + } + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; +} + +static int __dp_request_unset_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + switch (ipc_info->property) { + case DP_PROP_URL: + // it would be run like cancel operation + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + case DP_PROP_DESTINATION: + // if downloading, change destination to da_agent + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + case DP_PROP_FILENAME: + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + case DP_PROP_STATE_CALLBACK: + { + if (requestp != NULL) { + requestp->state_cb = 0; + } + int enable_cb = 0; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, (void *)&enable_cb, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_PROGRESS_CALLBACK: + { + if (requestp != NULL) { + requestp->progress_cb = 0; + } + int enable_cb = 0; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, (void *)&enable_cb, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_AUTO_DOWNLOAD: + { + // update autodownload property as 0 in database + int enable_cb = 0; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, (void *)&enable_cb, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NETWORK_TYPE: + { + // check state here + // update database here + if (requestp != NULL) { + requestp->network_type = DP_NETWORK_OFF; + } + int enable_cb = DP_NETWORK_OFF; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NOTIFICATION_TYPE: + { + int noti_type = DP_NOTIFICATION_TYPE_NONE; + if (requestp != NULL) { + requestp->noti_type = noti_type; + } + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, (void *)¬i_type, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NOTIFICATION_SUBJECT: + { + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + } + case DP_PROP_NOTIFICATION_DESCRIPTION: + { + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + } + case DP_PROP_NOTIFICATION_RAW: + { + int bundle_type = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type); + TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type); + char *raw_column = NULL; + if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING) + raw_column = DP_DB_COL_NOTI_RAW_ONGOING; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE) + raw_column = DP_DB_COL_NOTI_RAW_COMPLETE; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED) + raw_column = DP_DB_COL_NOTI_RAW_FAIL; + if (raw_column != NULL) { + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + } else { + TRACE_ERROR("invalid param set: %s type:%d", dp_print_property(ipc_info->property), bundle_type); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + break; + } + case DP_PROP_HTTP_HEADER: // unset value by field + { + char *header_field = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field); + if (errorcode == DP_ERROR_NONE && header_field != NULL) { + int is_present = dp_db_check_duplicated_string(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, 0, header_field, &errorcode); + if (is_present < 0) + errorcode = DP_ERROR_DISK_BUSY; + else if (is_present == 0) + errorcode = DP_ERROR_FIELD_NOT_FOUND; + else if (dp_db_cond_delete(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, header_field, 2, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s for %s", dp_print_property(ipc_info->property), header_field); + errorcode = DP_ERROR_DISK_BUSY; + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_field == NULL) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + free(header_field); + break; + } + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_UNSET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; +} + +static int __dp_call_cancel_agent(dp_request_fmt *request) +{ + int ret = -1; + if (request != NULL) { + if (request->agent_id >= 0) { + TRACE_INFO("cancel download(%d) id: %d state:%s", request->agent_id, + request->id, dp_print_state(request->state)); + if (dp_cancel_agent_download_without_update(request->agent_id) == 0) + ret = 0; + } else { + TRACE_ERROR("invalid agent-id:%d id:%d", request->agent_id, + request->id); + } + } + return ret; +} + +static int __dp_request_controls(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return DP_ERROR_INVALID_PARAMETER; + } + dp_client_fmt *client = &slot->client; + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + if (ipc_info->property == DP_PROP_CREATE) { + // check packets again + if (ipc_info->size != 0 || ipc_info->id != -1) { + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = __dp_request_create(client, ipc_info); + } + } else { + + // get now state. + int download_state = DP_STATE_NONE; + if (requestp != NULL) { + download_state = requestp->state; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) { + TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; + } + } + TRACE_DEBUG("id:%d state:%s set property:%s", ipc_info->id, dp_print_state(download_state), dp_print_property(ipc_info->property)); + + if (ipc_info->property == DP_PROP_START) { + + if (download_state == DP_STATE_COMPLETED || + download_state == DP_STATE_DOWNLOADING) { + errorcode = DP_ERROR_INVALID_STATE; + } else { + + if (requestp == NULL) { // load from databse + // check state + // load and add new request to client->requests. + } + if (requestp == NULL) { + TRACE_ERROR("failed to load id:%d from database sock:%d", ipc_info->id, client->channel); + errorcode = DP_ERROR_DISK_BUSY; + } + if (errorcode == DP_ERROR_NONE) { + // update database + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_QUEUED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + errorcode = DP_ERROR_DISK_BUSY; + } else { + requestp->state = DP_STATE_QUEUED; + requestp->error = DP_ERROR_NONE; + // if it's the first request for this client-> push a request at the head of queue. + // check count queued, connecting.downloading in requets of client + // else push at the tail of queue. + // push to queue + if (dp_queue_manager_push_queue(slot, requestp) < 0) { + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + } + requestp->state = DP_STATE_FAILED; + requestp->error = DP_ERROR_QUEUE_FULL; + errorcode = DP_ERROR_QUEUE_FULL; + } else { // push ok + dp_queue_manager_wake_up(); + // notification + if (requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0) { + TRACE_ERROR("failed to register notification for id:%d", ipc_info->id); + } + } + } + } + } + TRACE_DEBUG("id:%d check start error:%s", ipc_info->id, dp_print_errorcode(errorcode)); + } + + } else if (ipc_info->property == DP_PROP_PAUSE) { + + if (download_state > DP_STATE_DOWNLOADING) { + errorcode = DP_ERROR_INVALID_STATE; + } else { // change state regardless it's on memory or not. + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_PAUSED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + errorcode = DP_ERROR_DISK_BUSY; + } else { + // call da_pause API + if (requestp != NULL) { + // pop from queue. if state is queued. + if (requestp->state == DP_STATE_QUEUED) { + dp_queue_manager_clear_queue(requestp); + } else if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + if (dp_pause_agent_download_without_update(requestp->agent_id) < 0) { + TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id); + } + } + requestp->state = DP_STATE_PAUSED; + requestp->error = DP_ERROR_NONE; + } + } + } + + } else if (ipc_info->property == DP_PROP_CANCEL) { + + if (download_state > DP_STATE_COMPLETED) { + errorcode = DP_ERROR_INVALID_STATE; + } else { // change state regardless it's on memory or not. + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + errorcode = DP_ERROR_DISK_BUSY; + } else { + // call da_cancel API + if (requestp != NULL) { + // pop from queue. if state is queued. + if (requestp->state == DP_STATE_QUEUED) { + dp_queue_manager_clear_queue(requestp); + } else if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + if (__dp_call_cancel_agent(requestp) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id); + } + } + requestp->agent_id = -1; + requestp->state = DP_STATE_CANCELED; + requestp->error = DP_ERROR_NONE; + if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", ipc_info->id); + } + } + } + } + } + + } else if (ipc_info->property == DP_PROP_DESTROY) { + + // check state + // pop from queue. if state is queued. + if (requestp != NULL) { + if (requestp->state == DP_STATE_QUEUED) + dp_queue_manager_clear_queue(requestp); + if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + // update state property database; + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + } else { + // call da_cancel API + if (__dp_call_cancel_agent(requestp) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id); + } + } + requestp->state = DP_STATE_CANCELED; + } + if (requestp->state == DP_STATE_QUEUED || requestp->state == DP_STATE_CANCELED) { + + if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", ipc_info->id); + } + } + } + requestp->agent_id = -1; + } + errorcode = dp_request_destroy(client, ipc_info, requestp); + + } else { + errorcode = DP_ERROR_INVALID_PARAMETER; + TRACE_ERROR("invalid param - id:%d set property:%s", ipc_info->id, dp_print_property(ipc_info->property)); + } + } + + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_CONTROL, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + + // workaround. client still request the feedback by cancelation + if (ipc_info->property == DP_PROP_CANCEL || + ipc_info->property == DP_PROP_PAUSE) { + if (requestp != NULL && requestp->state_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, ipc_info->id, requestp->state, errorcode, 0) < 0) { + TRACE_ERROR("id:%d disable state callback by IO_ERROR", ipc_info->id); + requestp->state_cb = 0; + } + } + } + + return errorcode; +} + +static int __dp_client_requests(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info) +{ + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return DP_ERROR_INVALID_PARAMETER; + } + dp_client_fmt *client = &slot->client; + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + // check id except create command /////////// DP_ERROR_ID_NOT_FOUND + dp_request_fmt *requestp = NULL; + if (ipc_info->section != DP_SEC_CONTROL || + ipc_info->property != DP_PROP_CREATE) { + // check on requests + int i = 0; + requestp = client->requests; + errorcode = DP_ERROR_ID_NOT_FOUND; + for (; i < MAX_DOWNLOAD_HANDLE; i++) { + if (requestp == NULL) + break; + //TRACE_DEBUG("link %d info: id:%d access-time:%d", i, requestp->id, requestp->access_time); + if (requestp->id == ipc_info->id) { + errorcode = DP_ERROR_NONE; + break; + } + requestp = requestp->next; + } + if (errorcode == DP_ERROR_ID_NOT_FOUND) { + // check in database + if (dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_LOGGING, DP_DB_COL_ID, ipc_info->id, &errorcode) > 0) { + //TRACE_DEBUG("found %d from database", ipc_info->id); + errorcode = DP_ERROR_NONE; + } + } + } + + // Check size for prevent + if (ipc_info->size > 4294967295U) { + TRACE_ERROR("Check socket. Invalid size value. sock:%d", client->channel); + return DP_ERROR_IO_ERROR; + } + if (errorcode != DP_ERROR_NONE) { // prechecking + TRACE_ERROR("precheck errorcode:%s sock:%d id:%d section:%s property:%s", + dp_print_errorcode(errorcode), + client->channel, ipc_info->id, + dp_print_section(ipc_info->section), + dp_print_property(ipc_info->property)); + + // clear followed packets. + if (ipc_info->size > 0) { + char garbage[ipc_info->size]; + if (read(client->channel, &garbage, ipc_info->size) == 0) { + TRACE_ERROR("sock:%d closed peer", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } + } + + if (dp_ipc_query(client->channel, ipc_info->id, + ipc_info->section, ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } + return errorcode; + } + + switch (ipc_info->section) { + case DP_SEC_CONTROL: + errorcode = __dp_request_controls(slot, ipc_info, requestp); + break; + case DP_SEC_GET: + errorcode = __dp_request_get_info(client, ipc_info, requestp); + break; + case DP_SEC_SET: + errorcode = __dp_request_set_info(slot, ipc_info, requestp); + break; + case DP_SEC_UNSET: + errorcode = __dp_request_unset_info(client, ipc_info, requestp); + break; + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + return errorcode; +} + +static void __dp_client_stop_all_requests(dp_client_slots_fmt *slot) +{ + unsigned push_count = 0; + int errorcode = DP_ERROR_NONE; + int i = 0; + dp_request_fmt *tailp = slot->client.requests; + for (; tailp != NULL; i++) { + TRACE_DEBUG("request %d stop id:%d state:%s", i, tailp->id, dp_print_state(tailp->state)); + int state = tailp->state; + if (state == DP_STATE_CONNECTING) { + if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id); + } + } else if (state == DP_STATE_DOWNLOADING) { + if (dp_pause_agent_download(tailp->agent_id) < 0) { + TRACE_ERROR("failed to pause download(%d) id:%d", tailp->agent_id, tailp->id); + } + } + if (state == DP_STATE_DOWNLOADING || state == DP_STATE_CONNECTING) { + tailp->state = DP_STATE_QUEUED; + // This is error code for checking the reason when changing ip configuration process + tailp->error = DP_ERROR_IO_EAGAIN; + // push to queue now + // in da callback, check DP_ERROR_IO_EAGAIN, then ignore. + if (dp_db_update_logging(slot->client.dbhandle, tailp->id, tailp->state, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", slot->client.channel, tailp->id); + } + if (dp_queue_manager_push_queue(slot, tailp) < 0) { + TRACE_ERROR("Fail to push queueg sock:%d download-id:%d", slot->client.channel, tailp->id); + // FIXME later : error case. How can handle this item? + } else { + push_count++; + } + } + tailp = tailp->next; + } + if (push_count > 0) + dp_queue_manager_wake_up(); +} + +void dp_client_sig_handler(int signo) +{ + TRACE_INFO("thread:%0x signal:%d", pthread_self(), signo); +} + +void *dp_client_request_thread(void *arg) +{ + dp_client_slots_fmt *slot = (dp_client_slots_fmt *)arg; + if (slot == NULL) { + TRACE_ERROR("slot null, can not launch the thread for client"); + return 0; + } + + // wait detaching thread + CLIENT_MUTEX_LOCK(&slot->mutex); + + TRACE_INFO("slot %p thread:%0x", slot, slot->thread); + + struct sigaction act = {{0},}; + sigset_t newmask; + sigemptyset(&newmask); + sigaddset(&newmask, SIGUSR1); + act.sa_handler = dp_client_sig_handler; + sigaction(SIGUSR1, &act, NULL); + + fd_set imask, emask; + int errorcode = DP_ERROR_NONE; + dp_client_fmt *client = &slot->client; + int client_sock = client->channel; + struct timeval timeout; // for timeout of select + + CLIENT_MUTEX_UNLOCK(&slot->mutex); + + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + + while (slot != NULL && client_sock >= 0 && + client_sock == slot->client.channel) { + + memset(&timeout, 0x00, sizeof(struct timeval)); + timeout.tv_sec = DP_CARE_CLIENT_REQUEST_INTERVAL; + FD_ZERO(&imask ); + FD_ZERO(&emask ); + FD_SET(client_sock, &imask); + FD_SET(client_sock, &emask); + if (select(client_sock + 1, &imask, 0, &emask, &timeout) < 0 ) { + if (slot != NULL && slot->client.channel >= 0) { + TRACE_INFO("broadcast by client-manager"); + CLIENT_MUTEX_LOCK(&slot->mutex); + // check all requests + __dp_client_stop_all_requests(slot); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + continue; + } else { + TRACE_STRERROR("interrupted by client-manager sock:%d", client_sock); + break; + } + } + if (FD_ISSET(client_sock, &imask) > 0) { + + CLIENT_MUTEX_LOCK(&slot->mutex); + + if (client->dbhandle == 0 || dp_db_check_connection(client->dbhandle) < 0) { + if (dp_db_open_client(&client->dbhandle, slot->pkgname) < 0) { + TRACE_ERROR("failed to open database for sock:%d", client_sock); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + break; + } + } + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + client->access_time = (int)time(NULL); + + // read ipc_fmt first. below func will deal followed packets + dp_ipc_fmt *ipc_info = dp_ipc_get_fmt(client_sock); + if (ipc_info == NULL) { + TRACE_STRERROR("sock:%d maybe closed", client_sock); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_DEBUG("sock:%d id:%d section:%s property:%s errorcode:%s size:%d", + client_sock, ipc_info->id, + dp_print_section(ipc_info->section), + dp_print_property(ipc_info->property), + dp_print_errorcode(ipc_info->errorcode), + ipc_info->size); + + // JOB + errorcode = __dp_client_requests(slot, ipc_info); + } + free(ipc_info); + + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + + if (errorcode == DP_ERROR_IO_ERROR || + errorcode == DP_ERROR_OUT_OF_MEMORY || + errorcode == DP_ERROR_INVALID_PARAMETER) { + TRACE_ERROR("disconnect client errorcode:%s sock:%d", + dp_print_errorcode(errorcode), client_sock); + break; + } + + } else if (FD_ISSET(client_sock, &emask) > 0) { + TRACE_ERROR("[EXCEPTION]"); + break; + } else { + + // timeout + if (CLIENT_MUTEX_TRYLOCK(&slot->mutex) == 0) { + // 1. clear zombie requests. clean requests finished. paused or ready for long time + dp_client_clear_requests(slot); + + int sql_errorcode = DP_ERROR_NONE; + + // 2. maintain only 1000 rows for each client + if (dp_db_limit_rows(client->dbhandle, DP_TABLE_LOGGING, DP_LOG_DB_LIMIT_ROWS, &sql_errorcode) < 0) { + TRACE_INFO("limit rows error:%s", dp_print_errorcode(sql_errorcode)); + } + // 3. maintain for 48 hours + if (dp_db_limit_time(client->dbhandle, DP_TABLE_LOGGING, DP_CARE_CLIENT_INFO_PERIOD, &sql_errorcode) < 0) { + TRACE_INFO("limit rows error:%s", dp_print_errorcode(sql_errorcode)); + } + // 4. if no requests, exit by itself. + if (slot->client.requests == NULL) { + TRACE_DEBUG("no requests"); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + break; + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + } + + FD_CLR(client_sock, &imask); + FD_CLR(client_sock, &emask); + + // if no requests, clear slot after disconnect with client. + CLIENT_MUTEX_LOCK(&slot->mutex); + + TRACE_INFO("thread done slot %p thread:%0x sock:%d", slot, slot->thread, client_sock); + + slot->thread = 0;// to prevent kill thread twice + + int i = 0; + dp_request_fmt *tailp = slot->client.requests; + dp_request_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + if (tailp->state != DP_STATE_QUEUED && + tailp->state != DP_STATE_CONNECTING && + tailp->state != DP_STATE_DOWNLOADING) { + dp_request_fmt *removep = tailp; + if (prevp == NULL) // first request. + client->requests = tailp->next; + else + prevp->next = tailp->next; + tailp = tailp->next; + TRACE_DEBUG("request %d remove: id:%d state:%s", i, removep->id, dp_print_state(removep->state)); + dp_request_free(removep); + continue; + } + TRACE_DEBUG("request %d remain: id:%d state:%s", i, tailp->id, dp_print_state(tailp->state)); + prevp = tailp; + tailp = tailp->next; + + } + // if no requests after clear finished requests. + if (slot->client.requests == NULL) { + dp_client_slot_free(slot); + } else { + if (slot->client.notify >= 0) + close(slot->client.notify); + dp_notify_deinit(slot->credential.pid); + slot->client.notify = -1; + if (slot->client.channel > 0) + close(slot->client.channel); + slot->client.channel = -1; + } + TRACE_INFO("thread done slot %p thread:%0x sock:%d", slot, slot->thread, client_sock); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return 0; +} + diff --git a/provider/download-provider-db.c b/provider/download-provider-db.c new file mode 100755 index 0000000..d05eabd --- /dev/null +++ b/provider/download-provider-db.c @@ -0,0 +1,1322 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#include +//#include +#include +#include // alloc +//#include // unlink + +#include + +#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 +#include + +#include + +#include // 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 +#include +#include +#include + +#include +#include + +#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 + +#ifdef SUPPORT_WIFI_DIRECT +#include +#endif + +pthread_mutex_t g_dp_network_mutex = PTHREAD_MUTEX_INITIALIZER; +int g_network_status = DP_NETWORK_OFF; +connection_h g_network_connection = 0; +int g_network_is_wifi_direct = 0; + +#ifdef SUPPORT_COMPANION_MODE +// support B3 companion mode +#include "vconf.h" +#include "vconf-keys.h" +#include "SAPInterface.h" +#define VCONFKEY_SAP_CONNECTION_NOTIFICATION VCONFKEY_WMS_WMANAGER_CONNECTED +#define VCONFKEY_SAP_CONNECTION_TYPE "memory/private/sap/conn_type" +#endif + +static int __dp_network_is_companion_mode() +{ +#ifdef SUPPORT_COMPANION_MODE + int wms_connected = 0; + int companion_mode = 0; + vconf_get_int(VCONFKEY_SAP_CONNECTION_NOTIFICATION, &wms_connected); + vconf_get_int(VCONFKEY_SAP_CONNECTION_TYPE, &companion_mode); + TRACE_INFO("wms_connected:%d, companion_mode:%d", wms_connected, companion_mode); + if (wms_connected == 1 && (companion_mode & SAP_BT)) + return 1; + +#endif + return 0; +} + +#ifdef SUPPORT_WIFI_DIRECT + +static int __dp_network_wifi_direct_status() +{ + int is_connected = 0; + wifi_direct_state_e wifi_state = WIFI_DIRECT_STATE_DEACTIVATED; + if (wifi_direct_get_state(&wifi_state) == 0) { + if (wifi_state == WIFI_DIRECT_STATE_CONNECTED) { + TRACE_INFO("WIFI_DIRECT_STATE_CONNECTED"); + is_connected = 1; + } + } + return is_connected; +} + +// support WIFI-Direct +static void __dp_network_wifi_direct_changed_cb + (wifi_direct_error_e error_code, + wifi_direct_connection_state_e connection_state, + const char *mac_address, void *data) +{ + pthread_mutex_lock(&g_dp_network_mutex); + if (connection_state == WIFI_DIRECT_CONNECTION_RSP) { + TRACE_INFO("WIFI_DIRECT_CONNECTION_RSP"); + g_network_is_wifi_direct = __dp_network_wifi_direct_status(); + } else { + TRACE_INFO("WIFI_DIRECT_DISCONNECTION"); + g_network_is_wifi_direct = 0; + } + pthread_mutex_unlock(&g_dp_network_mutex); +} +#endif + +////////////////////////////////////////////////////////////////////////// +/// @brief check the status in more detail by connection type +/// @return dp_network_type +static int __dp_get_network_connection_status(connection_h connection, connection_type_e type) +{ + int network_type = DP_NETWORK_OFF; + if (__dp_network_is_companion_mode() == 1) { + network_type = DP_NETWORK_ALL; + TRACE_INFO("COMPANION MODE"); + } else if (type == CONNECTION_TYPE_WIFI) { + connection_wifi_state_e wifi_state; + wifi_state = CONNECTION_WIFI_STATE_DEACTIVATED; + if (connection_get_wifi_state(connection, &wifi_state) != + CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_get_wifi_state"); + } else { + if (wifi_state == CONNECTION_WIFI_STATE_CONNECTED) { + TRACE_INFO("WIFI CONNECTED"); + network_type = DP_NETWORK_WIFI; + } + } + } else if (type == CONNECTION_TYPE_CELLULAR) { + connection_cellular_state_e cellular_state; + cellular_state = CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE; + if (connection_get_cellular_state(connection, + &cellular_state) != CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_get_cellular_state"); + } else { + if (cellular_state == CONNECTION_CELLULAR_STATE_CONNECTED) { + TRACE_INFO("DATA NETWORK CONNECTED"); + network_type = DP_NETWORK_DATA_NETWORK; + } + } + } else if (type == CONNECTION_TYPE_ETHERNET) { + connection_ethernet_state_e ethernet_state; + ethernet_state = CONNECTION_ETHERNET_STATE_DISCONNECTED; + if (connection_get_ethernet_state(connection, + ðernet_state) != CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_get_ethernet_state"); + } else { + if (ethernet_state == CONNECTION_ETHERNET_STATE_CONNECTED) { + TRACE_INFO("ETHERNET CONNECTED"); + network_type = DP_NETWORK_WIFI; + } + } + } else { + TRACE_INFO("DISCONNECTED"); + network_type = DP_NETWORK_OFF; + } + g_network_status = network_type; + return network_type; +} + +////////////////////////////////////////////////////////////////////////// +/// @brief [callback] called whenever changed network status +/// @todo care requests by network status +static void __dp_network_connection_type_changed_cb(connection_type_e type, void *data) +{ + pthread_mutex_lock(&g_dp_network_mutex); + // this callback guarantee that already connected + if (__dp_network_is_companion_mode() == 1) { + TRACE_INFO("COMPANION MODE"); + g_network_status = DP_NETWORK_ALL; + } else if (type == CONNECTION_TYPE_WIFI) { + TRACE_INFO("WIFI CONNECTED"); + g_network_status = DP_NETWORK_WIFI; + } else if (type == CONNECTION_TYPE_CELLULAR) { + TRACE_INFO("DATA NETWORK CONNECTED"); + g_network_status = DP_NETWORK_DATA_NETWORK; + } else if (type == CONNECTION_TYPE_ETHERNET) { + TRACE_INFO("ETHERNET CONNECTED"); + g_network_status = DP_NETWORK_WIFI; + } else { + TRACE_INFO("DISCONNECTED"); + g_network_status = DP_NETWORK_OFF; + } + pthread_mutex_unlock(&g_dp_network_mutex); +} + +////////////////////////////////////////////////////////////////////////// +/// @brief [callback] called when changed network ip +/// @todo auto resume feature +static void __dp_network_connection_ip_changed_cb(const char *ip, const char *ipv6, void *data) +{ + if (dp_network_get_status() != DP_NETWORK_OFF) { + TRACE_DEBUG("[CONNECTION] IP CHANGED"); + // broadcast to all thread for clients + dp_broadcast_signal(); + } +} + +int dp_network_get_status() +{ + int status = DP_NETWORK_OFF; + pthread_mutex_lock(&g_dp_network_mutex); + status = g_network_status; + pthread_mutex_unlock(&g_dp_network_mutex); + return status; +} + +int dp_network_is_wifi_direct() +{ + pthread_mutex_lock(&g_dp_network_mutex); + int status = g_network_is_wifi_direct; + pthread_mutex_unlock(&g_dp_network_mutex); + return status; +} + +////////////////////////////////////////////////////////////////////////// +/// @brief create connection handle & regist callback +/// @return 0 : success -1 : failed +int dp_network_connection_init() +{ + int retcode = 0; + +#ifdef SUPPORT_WIFI_DIRECT + if (wifi_direct_initialize() == 0) { + wifi_direct_set_connection_state_changed_cb + (__dp_network_wifi_direct_changed_cb, NULL); + g_network_is_wifi_direct = __dp_network_wifi_direct_status(); + } +#endif + + if ((retcode = connection_create(&g_network_connection)) != + CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_create [%d]", retcode); + return -1; + } + if ((retcode = connection_set_type_changed_cb(g_network_connection, + __dp_network_connection_type_changed_cb, NULL)) != + CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_set_type_changed_cb [%d]", retcode); + connection_destroy(g_network_connection); + g_network_connection = 0; + return -1; + } + + if ((retcode = connection_set_ip_address_changed_cb + (g_network_connection, __dp_network_connection_ip_changed_cb, + NULL)) != CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed __dp_network_connection_ip_changed_cb [%d]", retcode); + connection_destroy(g_network_connection); + g_network_connection = 0; + return -1; + } + + connection_type_e type = CONNECTION_TYPE_DISCONNECTED; + if ((retcode = connection_get_type(g_network_connection, &type)) != + CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_get_type [%d]", retcode); + connection_destroy(g_network_connection); + g_network_connection = 0; + return -1; + } + g_network_status = + __dp_get_network_connection_status(g_network_connection, type); + return 0; +} + +////////////////////////////////////////////////////////////////////////// +/// @brief destroy connection handle +void dp_network_connection_destroy() +{ + pthread_mutex_lock(&g_dp_network_mutex); +#ifdef SUPPORT_WIFI_DIRECT + wifi_direct_unset_connection_state_changed_cb(); + wifi_direct_deinitialize(); +#endif + + if (g_network_connection != 0) { + connection_unset_type_changed_cb(g_network_connection); + connection_unset_ip_address_changed_cb(g_network_connection); + connection_destroy(g_network_connection); + } + g_network_connection = 0; + pthread_mutex_unlock(&g_dp_network_mutex); +} diff --git a/provider/download-provider-notification-manager.c b/provider/download-provider-notification-manager.c new file mode 100644 index 0000000..ea89c0c --- /dev/null +++ b/provider/download-provider-notification-manager.c @@ -0,0 +1,573 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef SUPPORT_NOTIFICATION +#include +#include // pthread_kill +#include // ESRCH + +#include "download-provider-log.h" +#include "download-provider-pthread.h" +#include "download-provider-client.h" +#include "download-provider-client-manager.h" +#include "download-provider-notification.h" +#include "download-provider-db-defs.h" +#include "download-provider-db.h" +#endif +#include "download-provider-notification-manager.h" + +#ifdef SUPPORT_NOTIFICATION +typedef struct { // manage clients without mutex + int id; + int state; + int noti_priv_id; + double received_size; + double file_size; + dp_noti_type type; + void *slot; // client can not be NULL. it will exist in dummy + void *request; // this can be NULL after destroy + void *next; +} dp_notification_queue_fmt; + + +pthread_mutex_t g_dp_notification_manager_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t g_dp_notification_manager_cond = PTHREAD_COND_INITIALIZER; +pthread_t g_dp_notification_manager_tid = 0; + +static dp_notification_queue_fmt *g_dp_notification_clear = NULL; +static dp_notification_queue_fmt *g_dp_notification_ongoing = NULL; +static dp_notification_queue_fmt *g_dp_notification = NULL; + +pthread_mutex_t g_dp_notification_queue_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t g_dp_notification_queue_ongoing_mutex = PTHREAD_MUTEX_INITIALIZER; + +// normal . push at the tail of queue. +static int __dp_notification_queue_push(dp_notification_queue_fmt **queue, void *slot, void *request, const int id, const int state, const int noti_priv_id, const double received_size, const double file_size, const dp_noti_type type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL || request == NULL) { + TRACE_ERROR("check client and request memory address"); + return -1; + } else if (id <= 0) { + TRACE_ERROR("check slot or download id", id); + return -1; + } + + int ret = -1; + CLIENT_MUTEX_LOCK(&g_dp_notification_queue_mutex); + // search the tail of queue + int i = 0; + dp_notification_queue_fmt *tailp = *queue; + dp_notification_queue_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + prevp = tailp; + tailp = tailp->next; + } + dp_notification_queue_fmt *new_queue = (dp_notification_queue_fmt *)malloc(sizeof(dp_notification_queue_fmt)); + if (new_queue != NULL) { + new_queue->slot = slot; + new_queue->id = id; + new_queue->state = state; + new_queue->noti_priv_id = noti_priv_id; + new_queue->received_size = received_size; + new_queue->file_size = file_size; + new_queue->type = type; + new_queue->request = request; + new_queue->next = NULL; + if (prevp == NULL) + *queue = new_queue; + else + prevp->next = new_queue; + ret = 0; + } + //TRACE_DEBUG("queue push %d id:%d", i, id); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); + return ret; +} + +int __dp_notification_queue_pop(dp_notification_queue_fmt **queue, void **slot, void **request, int *id, int *state, int *noti_priv_id, double *received_size, double *file_size, dp_noti_type *type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL) { + TRACE_ERROR("check client memory address"); + return -1; + } + + int lock = CLIENT_MUTEX_TRYLOCK(&g_dp_notification_queue_mutex); + if (lock != 0) { + TRACE_DEBUG("skip queue is used by other thread"); + return 0; + } + if (queue == NULL || *queue == NULL) { + //TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); + return -1; + } + // get a head of queue + int ret = -1; + do { + dp_notification_queue_fmt *popp = *queue; + *queue = popp->next; + if (popp->slot == NULL) { + TRACE_DEBUG("queue error slot:%p id:%d", popp->slot, popp->id); + } else { + *slot = popp->slot; + if (request != NULL) { + *request = popp->request; + } + *id = popp->id; + *state = popp->state; + if (noti_priv_id != NULL) + *noti_priv_id = popp->noti_priv_id; + if (received_size != NULL) + *received_size = popp->received_size; + if (file_size != NULL) + *file_size = popp->file_size; + *type = popp->type; + ret = 0; + break; + } + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); + return ret; +} + +int __dp_notification_queue_ongoing_pop(dp_notification_queue_fmt **queue, void **slot, void **request, int *id, int *state, double *received_size, double *file_size, dp_noti_type *type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL) { + TRACE_ERROR("check client memory address"); + return -1; + } + + int lock = CLIENT_MUTEX_TRYLOCK(&g_dp_notification_queue_ongoing_mutex); + if (lock != 0) { + TRACE_DEBUG("skip queue is used by other thread"); + return 0; + } + if (queue == NULL || *queue == NULL) { + //TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return -1; + } + // get a head of queue + int ret = -1; + do { + dp_notification_queue_fmt *popp = *queue; + *queue = popp->next; + if (popp->slot == NULL) { + TRACE_DEBUG("queue error slot:%p id:%d", popp->slot, popp->id); + } else { + *slot = popp->slot; + if (request != NULL) { + *request = popp->request; + } + *id = popp->id; + *state = popp->state; + if (received_size != NULL) + *received_size = popp->received_size; + if (file_size != NULL) + *file_size = popp->file_size; + *type = popp->type; + ret = 0; + break; + } + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return ret; +} + +static int __dp_notification_queue_ongoing_push(dp_notification_queue_fmt **queue, void *slot, void *request, const int id, const int state, const double received_size, const double file_size, const dp_noti_type type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL || request == NULL) { + TRACE_ERROR("check client and request memory address"); + return -1; + } else if (id <= 0) { + TRACE_ERROR("check slot or download id", id); + return -1; + } + + int ret = -1; + CLIENT_MUTEX_LOCK(&g_dp_notification_queue_ongoing_mutex); + // search the tail of queue + int i = 0; + dp_notification_queue_fmt *tailp = *queue; + dp_notification_queue_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + if (tailp->slot == slot && tailp->request == request) { + if (tailp->id == id && tailp->state == state && tailp->type == type) { + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return 0; + } + } + prevp = tailp; + tailp = tailp->next; + } + dp_notification_queue_fmt *new_queue = (dp_notification_queue_fmt *)malloc(sizeof(dp_notification_queue_fmt)); + if (new_queue != NULL) { + new_queue->slot = slot; + new_queue->id = id; + new_queue->state = state; + new_queue->received_size = received_size; + new_queue->file_size = file_size; + new_queue->type = type; + new_queue->request = request; + new_queue->next = NULL; + if (prevp == NULL) + *queue = new_queue; + else + prevp->next = new_queue; + ret = 0; + } + //TRACE_DEBUG("queue push %d id:%d", i, id); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return ret; +} + +void __dp_notification_queue_clear(dp_notification_queue_fmt **queue, const int id) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return ; + } + CLIENT_MUTEX_LOCK(&g_dp_notification_queue_mutex); + int i = 0; + dp_notification_queue_fmt *tailp = *queue; + dp_notification_queue_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + if (tailp->id == id) { + // clear. + if (prevp == NULL) + *queue = tailp->next; + else + prevp->next = tailp->next; + TRACE_DEBUG("queue clear this %d id:%d", i, tailp->id); + free(tailp); + break; + } + prevp = tailp; + tailp = tailp->next; + } + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); +} + +int dp_notification_manager_clear_notification(void *slot, void *request, const dp_noti_type type) +{ + dp_request_fmt *requestp = request; + if (request == NULL) { + TRACE_DEBUG("check address request:%p id:%d", + request, (request == NULL ? 0 : requestp->id)); + return -1; + } + __dp_notification_queue_clear(&g_dp_notification, requestp->id); + TRACE_DEBUG("push clear id:%d noti_priv_id:%d", requestp->id, requestp->noti_priv_id); + if (__dp_notification_queue_push(&g_dp_notification_clear, slot, request, requestp->id, requestp->state, -1, 0, 0, type) < 0) { + TRACE_ERROR("failed to push to notification id:%d", requestp->id); + return -1; + } + dp_notification_manager_wake_up(); + return 0; +} + +int dp_notification_manager_push_notification(void *slot, void *request, const dp_noti_type type) +{ + dp_request_fmt *requestp = request; + if (slot == NULL || request == NULL) { + TRACE_DEBUG("check address client:%p request:%p id:%d", slot, + request, (request == NULL ? 0 : requestp->id)); + return -1; + } +// TRACE_DEBUG("push noti id:%d noti_priv_id:%d type:%d", requestp->id, requestp->noti_priv_id, type); + if (type == DP_NOTIFICATION) { + __dp_notification_queue_clear(&g_dp_notification_ongoing, requestp->id); + if (__dp_notification_queue_push(&g_dp_notification, slot, request, requestp->id, requestp->state, requestp->noti_priv_id, 0, (double)requestp->file_size, type) < 0) { + TRACE_ERROR("failed to push to notification id:%d", requestp->id); + return -1; + } + } else { + __dp_notification_queue_clear(&g_dp_notification, requestp->id); + if (__dp_notification_queue_ongoing_push(&g_dp_notification_ongoing, slot, request, requestp->id, requestp->state, (double)requestp->received_size, (double)requestp->file_size, type) < 0) { + TRACE_ERROR("failed to push to notification id:%d", requestp->id); + return -1; + } + } + dp_notification_manager_wake_up(); + return 0; +} + +static void __dp_notification_manager_check_notification() +{ + int pop_queue = 0; + do { + int errorcode = DP_ERROR_NONE; + int download_id = -1; + int state = -1; + dp_noti_type noti_type = -1; + dp_client_slots_fmt *slot = NULL; + dp_request_fmt *request = NULL; + pop_queue = 0; + if (__dp_notification_queue_pop(&g_dp_notification_clear, (void *)&slot, (void *)&request, &download_id, &state, NULL, NULL, NULL, ¬i_type) == 0) { + if (slot != NULL) { + int noti_priv_id = -1; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL && request->id == download_id && request->noti_priv_id >= 0) { + noti_priv_id = request->noti_priv_id; + request->noti_priv_id = -1; + if (dp_db_replace_property(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, (void *)&request->noti_priv_id, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + TRACE_DEBUG("clear ongoing id:%d noti_priv_id:%d type:%d", download_id, noti_priv_id, noti_type); + if (noti_priv_id >= 0) { + if (noti_type > DP_NOTIFICATION) + dp_notification_delete_ongoing(noti_priv_id); + else + dp_notification_delete(noti_priv_id); + } + } + pop_queue++; + continue; + } + int noti_priv_id = -1; + if (__dp_notification_queue_pop(&g_dp_notification, (void *)&slot, (void *)&request, &download_id, &state, ¬i_priv_id, NULL, NULL, ¬i_type) == 0) { + if (slot != NULL) { + __dp_notification_queue_clear(&g_dp_notification_ongoing, download_id); // prevent new ongoing + if (noti_priv_id >= 0) { + TRACE_DEBUG("clear ongoing(%d) id:%d type:%d state:%d", noti_priv_id, download_id, noti_type, state); + dp_notification_delete_ongoing(noti_priv_id); + noti_priv_id = -1; + } + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + TRACE_DEBUG("notification id:%d type:%d state:%d", download_id, noti_type, state); + if (request != NULL && request->id == download_id && request->noti_priv_id >= 0) { + dp_notification_delete_ongoing(request->noti_priv_id); + request->noti_priv_id = -1; + } + dp_content_type content_type = DP_CONTENT_UNKNOWN; + if (request != NULL) + content_type = request->content_type; + noti_priv_id = dp_notification_new(slot->client.dbhandle, download_id, state, content_type, slot->pkgname); // lazy API + TRACE_DEBUG("new notification(%d) id:%d type:%d state:%d", noti_priv_id, download_id, noti_type, state); + if (noti_priv_id < 0) { + TRACE_ERROR("failed to register notification for id:%d", download_id); + } else { + if (request != NULL && request->id == download_id) { + request->noti_priv_id = noti_priv_id; + } + if (dp_db_replace_property(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, (void *)¬i_priv_id, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + pop_queue++; + } + double received_size = 0; + double file_size = 0; + if (__dp_notification_queue_ongoing_pop(&g_dp_notification_ongoing, (void *)&slot, (void *)&request, &download_id, &state, &received_size, &file_size, ¬i_type) == 0) { + if (slot != NULL) { + int noti_priv_id = -1; + int request_id = -1; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL && request->id == download_id) { + request_id = download_id; + if (request->noti_priv_id >= 0) { + noti_priv_id = request->noti_priv_id; + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } else { + TRACE_ERROR("ongoing wrong address id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + continue; + } + + if (request_id < 0) { + TRACE_ERROR("ongoing wrong info id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + slot = NULL; + request = NULL; + continue; + } + if (noti_priv_id < 0 && noti_type > DP_NOTIFICATION_ONGOING) { + TRACE_DEBUG("ongoing precheck id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + noti_type = DP_NOTIFICATION_ONGOING; + } + + TRACE_DEBUG("ongoing id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + + char *subject = NULL; + if (noti_type == DP_NOTIFICATION || noti_type == DP_NOTIFICATION_ONGOING_UPDATE) { + unsigned length = 0; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL) { + if (dp_db_get_property_string(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (unsigned char **)&subject, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get subject id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } else if (subject == NULL && dp_db_get_property_string(slot->client.dbhandle, download_id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (unsigned char **)&subject, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get content_name id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + + if (noti_type > DP_NOTIFICATION_ONGOING) { // update + if (noti_priv_id >= 0 && dp_notification_ongoing_update(noti_priv_id, received_size, file_size, subject) < 0) { + TRACE_ERROR("failed to update ongoing for id:%d", download_id); + } + } else { // new ongoing + if (noti_priv_id >= 0) { + TRACE_DEBUG("clear ongoing id:%d noti_priv_id:%d", download_id, noti_priv_id); + dp_notification_delete(noti_priv_id); + dp_notification_delete_ongoing(noti_priv_id); + noti_priv_id = -1; + } + unsigned char *raws_buffer = NULL; + unsigned length = 0; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (dp_db_get_property_string(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_RAW_ONGOING, &raws_buffer, &length, &errorcode) < 0) { + TRACE_DEBUG("failed to get bundle raws id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + noti_priv_id = dp_notification_ongoing_new(slot->pkgname, subject, raws_buffer, length); + TRACE_DEBUG("new ongoing(%d) id:%d type:%d state:%d", noti_priv_id, download_id, noti_type, state); + free(raws_buffer); + if (noti_priv_id < 0) { + TRACE_ERROR("failed to update ongoing for id:%d", download_id); + } else { + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL) + request->noti_priv_id = noti_priv_id; + if (dp_db_replace_property(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, (void *)¬i_priv_id, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + } + free(subject); + } + pop_queue++; + } + } while (pop_queue > 0); +} + +static void *__dp_notification_manager(void *arg) +{ + pthread_cond_init(&g_dp_notification_manager_cond, NULL); + + dp_notification_set_locale(); + + while (g_dp_notification_manager_tid > 0) { + + if (g_dp_notification_manager_tid <= 0) { + TRACE_DEBUG("notification-manager is closed by other thread"); + break; + } + + // check wifi_direct first + __dp_notification_manager_check_notification(); + + CLIENT_MUTEX_LOCK(&g_dp_notification_manager_mutex); + pthread_cond_wait(&g_dp_notification_manager_cond, &g_dp_notification_manager_mutex); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_manager_mutex); + } + + TRACE_DEBUG("notification-manager's working is done"); + dp_notification_clear_locale(); + pthread_cond_destroy(&g_dp_notification_manager_cond); + pthread_exit(NULL); + return 0; +} + +static int __dp_notification_manager_start() +{ + if (g_dp_notification_manager_tid == 0 || + pthread_kill(g_dp_notification_manager_tid, 0) == ESRCH) { + TRACE_DEBUG("try to create notification-manager"); + if (pthread_create(&g_dp_notification_manager_tid, NULL, + __dp_notification_manager, NULL) != 0) { + TRACE_STRERROR("failed to create notification-manager"); + return -1; + } + } + return 0; +} + +void dp_notification_manager_wake_up() +{ + if (g_dp_notification_manager_tid > 0) { + int locked = CLIENT_MUTEX_TRYLOCK(&g_dp_notification_manager_mutex); + if (locked == 0) { + pthread_cond_signal(&g_dp_notification_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_manager_mutex); + } + } else { + __dp_notification_manager_start(); + } +} + +void dp_notification_manager_kill() +{ + if (g_dp_notification_manager_tid > 0 && + pthread_kill(g_dp_notification_manager_tid, 0) != ESRCH) { + //send signal to notification thread + g_dp_notification_manager_tid = 0; + CLIENT_MUTEX_LOCK(&g_dp_notification_manager_mutex); + pthread_cond_signal(&g_dp_notification_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_manager_mutex); + pthread_cancel(g_dp_notification_manager_tid); + int status; + pthread_join(g_dp_notification_manager_tid, (void **)&status); + } +} +#else + +int dp_notification_manager_clear_notification(void *slot, void *request, const dp_noti_type type) +{ + return 0; +} + +int dp_notification_manager_push_notification(void *slot, void *request, const dp_noti_type type) +{ + return 0; +} + +void dp_notification_manager_wake_up() +{ + return; +} + +void dp_notification_manager_kill() +{ + return; +} +#endif diff --git a/provider/download-provider-notification.c b/provider/download-provider-notification.c new file mode 100755 index 0000000..741fc62 --- /dev/null +++ b/provider/download-provider-notification.c @@ -0,0 +1,629 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef SUPPORT_NOTIFICATION +#include +#include +#include +#include + +#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 +#ifdef T30 +#include +#include +#endif +#include + +#include + +#include +#include +#include +#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 +#include +#include +#include +#include + +#include +#include +#include +#include + +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 +#include +#include +#include +#include +#include +#include +#include +#include // dlopen +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#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 +#include +#include + +#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 +#include // pthread_kill +#include // ESRCH + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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 + +#include +#include +#include +#include +#include + +/* 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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#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 +#include +#include + +#include +#include + +#include +#include +#include + +#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 +#include + +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 +#include + +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 + +// 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 +#include +#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 + +// 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 +#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 + +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 0000000000000000000000000000000000000000..109512eef51535efdaa5e280365f492601f1ba96 GIT binary patch literal 3117 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 Hu0mjfFE`Gb literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..be67ffe053479387bc52ea0e5febd31c369c1c78 GIT binary patch literal 1600 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 literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_icon_pdf.png b/res/images/redwood/U01_icon_pdf.png new file mode 100644 index 0000000000000000000000000000000000000000..3f8cda62226864844803a8b625fa80550fc37b6f GIT binary patch literal 4686 zcmV-U60z-xP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000MhNkl?d$By{&}xo2ko+S%Q^pLgy#-*fJnE2NYt>zZi_fr6+YDu~JyLP*@ z1wx3fK15IZOC<1r+dv$M0d`jl4kL*VP#<2{+rM?m!ta`!HY_Hw1TTdxd-ICwODleN zxjEbpHRZOm@wLy4$^OGb_dg#@PhXtqAJ-rd(6#$k(PfN4((O2 zQ4=Cd)y|#B!2eved|q)*_76K!1;kofQXb;Inf-g|+09I8h@z`)AR&bR<>H==o&9_-)1c5yp8gIU zs>+m7HYVE>JJkpD2tmlBQ(ziuI|G#ZeILu>>}#Hqa4|$z9uL?+#FjK?1!*oUrb$9v zDu^AjxRfwyD*bovXTYm(659MKtsYO;+Rrx{#5P-!yKo6YccP8|rlDxJjK*^5@Rche zTAGfpPcf}0j&c04Z#fIiD?lnw>_||wKuTKveU$LNJx+2lbQKdjs+pp7=P|MZ$Y|8@ z&Px|vo1rzgE~@q9G13MO!UzN%=e%$M;ZlsQgy<21#)B1jf;|XM_`H*`kH3p1lqY^< z(*;D{-sO~KUs*u(+*!1Suxn>tT)8eo2&_XDM9- zc_A!N5~nj}=HxnJ`{rTjW5yFxV!Pv|U*?GS&$vR1AEs5}%F@rB6^jHrI|pA;Ut*Uo zA}tI5&|&DGo8(GwbSFe4=E&OsxV-x>TrA%XK(B`$rNuC@q=NXN7L(u~JqCb=1N*36 z_dR4hj<0tS84K>GO-ffK8P`FSIOD5E;m`VXSP zvah}xEt^(b5|@b;=B_$wvn5!$`J@jXLgY*p^6){7Yq|~|Avph|wPcl!C2im!ir4*| z))U9^74<L1;E$42w(3anvWhKcJTsf{YwbVnNP#uA=J&Afk)h6o+yDfDJh&b18K#ne|a+= z1lBF1$(%HW!iitR=$_>ypT#)h(GSe%nRW}%NxuS z<5D6ayjSB5}>f>oG=>adv27LsvX7E+q|?B>yKH35=U?^}WcMDlWXXm8RFX zB2K<{HB%eH>2b#;M5K*X*cacer4Wk|*|`H>Qy5cxv_807#z?vZuho_?{8oA`dXVm= zW5KqmFW*l63%|lXun#Zb7Xn?^{tJpBAYEwKr%z#@u5>y+2y~Iy7PyfNc$S1#+eY3z zoZJV$P505I*lle999=vQZP!k^X#zw0aBmVgop3#g=PwD>iC4x$nnDExo?6eq7q;Om z?8AvCmJvB!N&Sx3(Rb}6L)Y*K;p+LDq(HPJG+Q>>%()EQR!-pdJ2>@&H5{Hi7BeRo zvu7T4YageZrlkzLgl=aWXt8ZFRy;}G%sGVj?4o+*QslWBvL@b1!NLbP`N$G{b+sQ5 z*C$x0MysvC{OlL#_tbjow!MV4{T0j<1eh>Sj7drUta|}C zyXlu`J#y&&)kTEn%qRTzZZ4HA!>?&6dksKBAnFL3j~phgWH7^Cd(+9%mc_Xje@*zA zCrGy}bV15mLLiz#5Ptj-n*R1z%#y*x&({)ps~n@|jH3Zl7+^vx78|gn#FC)3>pD#& ze~dV#Di#gUgh*Itjl<_r$Te_tX#8#j|T!*6sq3+pM5=TK)5S1y23ZjCjASzQ3KOXzf02KhFW#=jV Q!vFvP07*qoM6N<$g0r632><{9 literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_icon_ppt.png b/res/images/redwood/U01_icon_ppt.png new file mode 100644 index 0000000000000000000000000000000000000000..79302eb0081e1ac4ac5f59469864d014be41fc07 GIT binary patch literal 3946 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 Ef-H4iY5)KL literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_icon_swf.png b/res/images/redwood/U01_icon_swf.png new file mode 100644 index 0000000000000000000000000000000000000000..39a49daea4219a997e7b3fef10a902d54ff262f3 GIT binary patch literal 4233 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 literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_icon_text.png b/res/images/redwood/U01_icon_text.png new file mode 100644 index 0000000000000000000000000000000000000000..5f8b3bd80b9212ad9f01f52a0716c173c6a4acab GIT binary patch literal 3832 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 literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_icon_tpk.png b/res/images/redwood/U01_icon_tpk.png new file mode 100644 index 0000000000000000000000000000000000000000..796c788c9f27cf67ac2aa36b9266b369b86ade99 GIT binary patch literal 5319 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 literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_icon_word.png b/res/images/redwood/U01_icon_word.png new file mode 100644 index 0000000000000000000000000000000000000000..a45acd7fd4a721a74cafb447064197b233576dd3 GIT binary patch literal 4669 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 M07*qoM6N<$g30~DZ2$lO literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..c5176befa6faddc95993e37e32e794de042b5869 GIT binary patch literal 4154 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 Eg2{fr9smFU literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..2e3c87b500396199744b7cfc89801e1d53d8ffd1 GIT binary patch literal 3851 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 N002ovPDHLkV1k$;H*Np` literal 0 HcmV?d00001 diff --git a/res/images/redwood/noti_download_complete.png b/res/images/redwood/noti_download_complete.png new file mode 100644 index 0000000000000000000000000000000000000000..6171bd805c9ab892fcfad09fb35331e75aa644a2 GIT binary patch literal 6935 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..8dfb542dab205a85096444dbcef4dd44ce4c92fc GIT binary patch literal 1268 zcmb7EUufKP98bAf>)hP2S;2}BQU-PNlKZ7eE*E;Xxl3XX%~`JpJ!OcwHDy)L(9QT^~llkbl2l zzMs$M`!~xIg(vs!9@tF~#NPb4QpC@PqpPnM-`9UzG^0hRmcvO@4V#7!3E4swNah`5 z8Wy2p&AoI5ju1rbW4lxi%lgxji5%L9Z0MHbVKhOEjJ7<(tizD3z-imfP&Y2FQlxEV zs3~4g>Rt}k?D2UYPR4<}66WAgV%(DyjtBbSUAjS6an z847!PI|Roo+S9c#*dlj>PO@;?n3mx&fKD=g+a`*yi_-O-5stHE9fU=A$N9VR2c>bJMa`HEVEcovOV42EZP%DpklApc8|IY^)o9q3 zr12cjE1WC?Eve$#q&dJVVmg%tBBv^f(k0jq#9Fk4u|P~}!?G&!vN#NY%85W0L;+;+ zR!)#Pp^MGCL1?%pj6@@>eFvM`5i8|o?BKUm^gLIPq%#m1jp5=z^9wGqeBtuF3;L@9fhH@#TMG zORLw|lc&dCJJz@EE8<^0@x!k_a^$(OTW=m8SUEcILO=O#{L977n+r#>)wp?I-}h_A ztmqd+#WBZEtPi3KL8w zM$ow7#xw>Ti4un!er?&*L39iPaU+^IgOg!4<6u*X0}XNNGJVT9#vcobO+Vg`-}5}b zuea@GzLM0Gj1-+tm+IL}`Qi6o?YS)(zDIt3k<}&&U9D7zAtla8K<5mKH30GOOc?k9 z6Kvf2B`DPCZuyW4R4diqQj!&UJ)_y^RXzsMI$hx=HO8FzypOrR6Z)mr0PHyc}Y0dmN67rG*KcB z^qN!E-ZG?ElmKGUn+jM1jw4p99yeR8Ry-du8gL_KfVZ^(Hjl*axfEEREqo6Qqfgoom7$_jK5*JfAQ9v|C zrbet+94PekS_pj1&xLChd6`_0my!k3hN(;p!}SJCTC~yPOQ5{o)e$_uY%ME(aNYSE z^2>q77{L5M7V9MzRxy;lLTYs(&2T9O(#uE@0ITR`qB2GE#BH<{ z$7!=2x4Z3b1A$uz6K*pa5?GHQD~!MbO;p2j*RjN^Sh83Gj3P<_QH&#`MHmso)L}51%Vg-A6{e-P1?)zO<{EB|qMI%sbV2%0G!tA4xyln?*&Q z&utjo(7bQ&4-GAa)p>iH4nOk8_;~ojKW}Y_5Ifd$e_m|6a_n-~#+<(7%F^Qe7e;^0 zeEeSrccv|Qd_f&ws5^V0@2~jo(QT(=$6tN4hkb6YYqkVO&fR+GnKk9czRRusb!SGI z>`=zr{c2M5#Fe!T<$D%D)RU9p+BNyr``ahFZuXr|-+3-Ay)Tk8=o(5*$^53BeY2{0 z%gMi+vyhi9-+t7V^!sV+nypx?sr00jB7Qp7*?(wSe)>eEKRjDBuuJVca1=W~EUmk6 z@X3+BDHC^BN5^MFmEm=vAdWPvqup8io+x@_{-Nnt1~%@0_q*hc+Ya{paw;uAzuv2u zF1ma(8TT)=?0jved~E##9m9EduifpR!FSvt3{O4i9F6rpb$oy6OZPN<^6}^MXSbwS kg}J%!Z9iRV=^4D;pv!M>q8&Z&g|r`}hxSn)xSrkqA9scRasU7T literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..f1ff0f843c66bf43fdad74c42be4943677f5d204 GIT binary patch literal 1606 zcmah}drT8|96za}!vSin0<+AsZsLSKu2+uU(L!HWtkBXyBj~b)KCbOW+N*a*Tbxtt z3!HTkn43B>roU}ZV5tQktksg&{vDbpBaol$9!nKi0lA{aMK zhFFpcf=NZEi)vuC65iA2Ap}BJ>kHu^GmJ7Nbh{7Mz<3j*Q30q8hNA!wokmE{^*~eF; z8%13`+3|S%ZBl%Di)+V4;8Me#@2 z`v%S*ZIgCev2Ld>(k?toLur`cz( z-i(buk)4y;+h;%Z+s2Z3ucy2|C%W)Jj?8pVcRC8L+?hESp_}r0ZPK1O!nJQ{(z;-H znR6gEH`O}#wu|Eib97CD{0wvEw9nXyyPHMR52!LbEl-D*#K=u~CD8KM4y|vA^_RA0 zCyKfji5l$Rk2~Am6&4mS4*>Yq!RA1A&Sdy+~Sm7Tw?RErNb&Zqtnp@aI9 z_je?2dA@lsoVx3yD{Iw1-;tkbj+a@>jwuyqTPN&2qu#eJ&zx(^ZR!@Uxx1_)e$1C) zXzHKRhECUCwSYF^r3->P*L^z8)aJZN;+mOL(+Ai-{~qOEp+Nxb0anC|4>ev!qsc$J M1-F^@8tPX43l3#UJpcdz literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..796523232967b9b90ecced109eccb3edb5101d29 GIT binary patch literal 1701 zcmah~eNfYO7_J4B6NJ^Fh;x_=&M%;C`jMuU3T@L$9mQHIpde7%R06cAX_OXq4w;7x zRGgx6qHxD1r-D<o6T= zFge$^VNnc*ml@Y5Q^}e*iIK3d4IUe|!(yY+3`SJ6!)7q%U=)yvt;4NSu)nDp1aOlS zOcH9i8k+*k!ejGEEFnK$Z_LjzicMhjQXtA9p$RM)WdIzOT&rE;kbLE6(dN3hs5nzzJO`&gjpkZ~La8wX-@ITnlOT%*=@N{9XH#)Q^( zz0-zqbeNskKpN?Mn8U`wbnM3!xmbpvA|Ary zDrDnWwbf1;tVV2H7pHZ{u-tcIB?=NVPz0$bh}`iC&}I=7Vb3CLfFc0~7AE0V6Om_M zHXjCq*{MclddJUCDw<1X z%YxihwV{hMYqquGh8R{v-C(-*Zu~9z;Np(?^@%e16L5$3ozwKKll{YA$V6Ec1y6uhd*rGPk6L2J;6?9t=2!)z@!ry2M&@Ot0gh_YNkW zm=Q74@96Hx=P&P{+6Y%$8;6jJxU|X)?yToa-LDywel+tP7t(CVoERp<^^?EkaKPPc z;iDHrK>2bRxaVo$$;1;O(O2HfzmTSwH+@oL*Xt*u^5s741Adk93%t@JW;zS{dds%& z2`Fk=a_i>VEaq>|UIIZ=p&n-kl3k`MLfmFofxE}>YL>G!J7Q*G2KQ>iSGwX&jotlI zN?OS?4_E9$wq?#+-QM?1Tc2oHTIJOi7ngEOU#(qeGuo#42JCuuw(IxQ=G$4H#?9{$ zl-8%Ri}Ekr*m-(Q{SSpkJ*)Ja$JDp3r>CMrcc1@WRa1}<{&mT!n9T=v@YeWlOpvV} z#@ltVm*Os`Qg2yXWhyKs&W5r zg-fek+1v4GB=w}b)Pk&9u^KHF}=1fIP%ev`)#?kN6LLhnx5`oWqmMmHl69u7&#Qid$zN= Q#q;A(E923V@{Dc&08o{FlK=n! literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..f4a2bfc18e09a6ef8510850146eb8e0b8e093c0b GIT binary patch literal 2359 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5902a67490cd6d17c6a65bb9020fd8367f0faf2f GIT binary patch literal 1640 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 F{{t8`vjhMD literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..96b1a9ae8f3d97d8cb7d6ed3737cb8110946a381 GIT binary patch literal 2005 zcmah~Yg7|w8jeU1St&(O!BQE5#e&Uca+#1E15A<$L>9!rA)wqsG9lTJOh^V2smetb z6pKJ>yCNdkg;t?ZT3joo^@2qdw<4=W3koQlqNfOmXu*nhqTuciPj}ADe3yBi=e>OI zduC5mWT>;#Y9|tjxUXg~% zP=#t+#zk}kiL_X)jfunKBL2!(VtSgwhM`&YMuJTuZ3wm+6-ph71F2}5)*zrvw4J5^ zT9tqz=R`0fj3QK{4a+v6(b&hiAe#e0;Cld*0W#?f;)bXoo6mvxOfE2g zQ3z`$m6|UTOXh76D*;7=<3>K6Zn0Qs78VUNrO`nik7v_hGN}ZDYTjnR6;`Uj?7N^K zM$Jl-)`)8{17K5Bq+*%4fI@isG6cObBI1>>!91TRB4u=|!bk^c47y%#i|Ym2jLXpf zy75}HIcA#?rOQw=mT6KF=b`ppAQQR!b3-;D;SGP2NlP4xB3+CrGxewemx=`x;tNfs zRq5 za;-sySn<9Qja7&U3LP?f}l>46vdwy_12@0I=Ylj5@a#w~r;yj+*_cfx;v6RwM4*Y1z2 z`y?A~L>}11HrJdzkyLi0uV^Oan2YPd-q;dAxRowlyQ=PAZIziVE#`X`$-^N|#jT%j z#b3xPt=bV-G&no)+g!IrU7_%}(Bb0~y2Lv><%9Tx2ks{qfBtRA;PI~gzpS$0ewV-zp2p$jjQgabC5qs}??vZKeF6anXkKCO!{t{E8~Yh9OC@$VnQ(6x?R8g?!oh;MP#^Bgu|E`crb zjKlk?!OIEOZQa*X3~yMpFx}sq zo`iTvD2u4e3m*@jZjK+Del$!=44v-QS#LM4{-LdH$nKJ}kt_9jQs<29{YUELljJfJ zl5rcj-FvlcYN|%;8`fFntCw>xdNYE<H+um)CQ>^X~oRG4uV~iT%)-=-9k7T|ey(PG9V` zw8`~QTCW#>53adC>XZC^{wd7mh-x&G0$tkW-KS-&Wp9>gS#O7`DE% z^!eDF-L5KbRO_$n3(h;ZHXJP0WOzC(leA9cCLu=;40$OB;&UtC3WD^Eja_YBoxY}7 zN`Cm@IbHDcLTk4^Y>mscFndAf!?VtUw&K5x8oR5OP_w)jUw>Yhlj#<)wSTh95}dng z<(=MrKSqsD`)+?=mtE?W|5WC>Z0d-ElRbq}J)f-lg{(&U^F7gCobTH5@(p z+f~npz{aONZ#4Pc9ZI{heRh(%#qQaiIC1x(!kd{_H)tCl5Bul2BzmMy4;_~89V#lB z+%K;&kH-Fxlb+{Q3ac4gw>-Y#r+DxoIEJ)$`6&DPr>}4Bo35z%vg_8)n{&_Xr#~93 zDJzy`Z~Ta2iav29apdAk#RpDZr`6Q+@714cq*e<{I-+{66wLIfXUO=8q)p4@1&1wz zp(&U9@5X&cDy&a!|ApRj`jl%@U##Ci;<~z%7orAhFB&)daxyxDW{!EZy%ifWe*eT= zvAUsQ_tP~aw8>V^XYa4wDJcD}U@FYDPmt~(dD}iIV%N^`FJ==1i}w4}MQ5!j@06+I zS>|#N@;9V`iIB_V<+_h^sn*;3nHi%kF#s^FH)UVA_2P1>t>S9>K) zU@v4tSmNA>b2v52H0or3Y|$+$PBt^Q!C+>K+u|^a%EC4zQEPN`SD@2JxOA#U>wD8Evmj`A*Q4CB#jrrGY_I_6S-Qt zl5x!FQgosFqH<;18CSJtPiDGl5b=rd8OW7So_wzd!ERl(ZyQf`84JRa$aIf6L~c$Y&|1*Lw*pDos0=lZ!{dw(S+WL>um-*iQ7p# zfnf$+k-@>}C@V#hjMaiBIA+7zQ7eV&^%z0e3>aqDSqK|$)iGF+12^bxRy=`q1|*pc zctJuhuj-w_qL0MVHW9G0Ai4yhK2ZS`K0y{FpAdv?RV4gOH6P%Fu(Tqco@s9xAoAM) z=MV)yJQZJ>pG7~aV<-p8P7LDZYO@C*^GxzGC zW6?2N?#A1@ez}vmY5UHWmfdM3Z;UND7u#&ko;02~J07~U>@{ARdpK zyTQ3P6mglpuJgU`4dE%f=JjCbM;Dy!z0!?Rd6Q&+=H9W(j1O--)aHrazovQJ7_J|L zGj5sBWKaG|eL24WV&|3E-Qzo&Zw!0f8`0bc&XJhlzTPO$|Aea;TAai0T~K|PIFy&Z zD%1tuT3d2g*ZuHHq`L3}U+!c1bd-7z~3ENOs)+K6qB367FMDGtj7?!Bb<;3ZQ z1LJ@l=)E)H9QYvC-0`O;8uH!F3{u~J94l^0`EXQA6l71HiWHAuEr=GpAN#Gi^V9T_ zyyD--Ted}GO}@WfIi1%lkGUdG9X9Q8IpP=VTfO1vHDd(*e4_Eohg$&T3Wp?epS_GxkpH#qV-mOv?4kh1u|k^G75%kkf>(_YSeWOcvv E4@R{ou>b%7 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..b6335d7147a2279eb83564a2551bd1da4b6ba96b GIT binary patch literal 1878 zcmah~c~BE~6iyMUMv+pj6%S@vwFQ-IHpeE}A)VI8MX+EcDDmsRZ(T1Z2#wgIcYy>u=i9_>vK_NDi-jGbPKs=d9(Ms@6Z375U zgc4jK)e5yH4VgqON;i{H=@HR}^kjpA07HU-AREdN7)e$S*o-N(1+^)`=e#I4cWpx; z@Z5w=R)Q~_iqYx-4Pzz&sX!cP5W+BkAOct-MG$xaAQHkNNXXqtAS^+p2r7~RBNxc2 znTZ565(^#C;#Nv9iDgYF1X-+A@+TE@hBSZ-QWf5HcEFaXq)Tu#x1yZoJak z61~PmLXo6}Ni!R`^GKLI3g&Y6dLfq~=MB2lOmT;zPr(>Nnvta0FiZ(@Ujzh2pkk?7 zB-JQzM1&)_7={%RnIaUE$klQL!PF|@D95X?um)3zV3kHJ)~H|@m&nC3M1f1ym=F`H zF%33~4Wliro;Hx9x)i57f>pm3i)zfIo@LC@43jci0lFlHWh_aI3D86#fd2}LCK#(F zz;!$?qQyuv^$AIYni(VTJijRQ3VpQ*QK-~7rcsE+xP*&aji^FHRT32 zugaPDe{u$K&Ool>_)oEnZgCapn!YT3Zt=2tNSf;yGuIjuZEj+&<2Hq1s%YDVo5f3# zCab2kJ*%o+bAE^P{@F4rhrbN#vS-_(0S_? zEe&4mAI$$cdmMk2yVnD~_ST6_$hG<#vahz&zm#3Pm~!N^No#j$6A~X(e>8lrw0L8{ zmdutI_XXXcc8{=CBJI2{o9lC{vBA-;`@0)b)?7GzurqMZZyDD*yoQ7SIB+sP{_lVb z{&e@4c{LK>?>{*h7ZVq2CvjT70-tF9x?c& zw6s)uc{Lxa+`Pqc>ia&y+}U<~Uv@hm^o6$Mm2CWUg>?7!WP94BY9@0E|Krm&#IZS7 z3;P=eorjb;4vpnbXDraaddW8wfuUjOCov32n6U5?aXV0K5&;m3{My#t50`AyXA zyVviIB{Vgie1FH3_!I%=`4%1RxIurz zt+cqswmP@&vG;qot3hab=BXdUXSfa6!`QC;yJt$@vh`~Q9bS2hvQzSXN@Bu2tOd}} ztzV0Rs^Q@h!jBkx-qbp`D6Z>}v1mu5biG&X)+)yD^3Z~DzaH7z^m8~Ik-9T}U0%jm v|JZ=rowWn!V$H+WD+S*y$k-1(bDzcwuYuDSE`Rj9>rWSkM_?7|)tUbQNU`!P literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..4961fb52de6b76187f4b9ee56ac5c9225326d94a GIT binary patch literal 1600 zcmah}drT8|96wN=0{-E)fPx&wY&yra*Ius=TCnZ4+KhIjpx~CpKJE$^Z121~>_K?M z7f!)#*(;ktVR6PS)1_+EZ73AmNpNPOOg8t&5El_q2hN351l$#=+aJVT?(X-v@8|RV z{JxLdQ*2$En!Gd_0Dx5UI?N`FP~=IB7v5#xtyTy_24^hiN+>tyb1(#;!zm{LnmvvR z!bUjonk~JA1^^bg$%rxgqSZPI-97n6gVxP|k`D75qRES}fN)_RdO7jGZJhsNmIruy;n;T`o2-d}r zG)GciFv93?Qq`PRBq)7)1P^VoJR|n9bAb{c z8BwVbHOgREg(y@e3{mQpD2nNIk|@V~Sf$LMkRwv5T#g|yY(#WYmChhn=yb3`p*KpT zQLNd^at^PHi25Z3zjIjlxmdMGge zN-@0P57Y;+{n<0qj}^*HE5uKPQRC!ce0}fLp2XMx2<;4C@9%l(o#v#Te%RgyJm5fY zLhX3rMly3`Bz{=n4+t@R^(@nj)Y?%3^y}ja0^1- z3fs3L*4=Gdwr)n4ZP>jdYx-eXY!FOHf3a_@ZE(rKf`;uSJ6c;pH@I(GT9EYj&=ZyS z>Ec6V`!Z|p>d@M(f>HWa-wK;7*}wO#jr-wNP4y>3V}o5Orl!f1&+hE8Kj`p{$+(Fk zr=1`O3DOt$b$7h`@~09>4wM63xG_AM=x*zx_YB=Rc{`=udhz15yWPk-Yvz|t&CQGM zC8giEd2?a&6-`K&^Kkm{;-<6blO==w!Cg5k0|}RA9zA>|*!y8c`tRqS1pM_q%j2^= zmZryxm&1ukNmBm%e3}3FaX4JtvE$Z&=hxVQ{wr@@4)pfIezNtzfde_n3gA*f{jerD zdTLqsy*_)R|4>5pFao3YzJaSinY*o^-rZMR7T26QX^Z>lVB^f>uJcEJXkT(It6?fc zHs$;N+_pA#O?dcNzWuoF{x~(*DLcCHOwy&(Cr>$P|CyMRI_IX&hODz`o4U3v3f{iF zDLowKGh(ODWlYs;Gx(aCfV1is@6y(^#_@4D_<68r=y2i}b;EdK(q9Xjv$PF+hX(F< zl(Nd)+6y%k;feOl&W}G>Ph@)Ved@ZOhYqD>SBJ;9hJVzJ{L~Xt)(wChUkJZ_#sto! zgzl_4stKeu#D_|@@v+^flY3uY{5LmL`IU5(o&vxC5SM*7VO8e|GV)J18?D$kdi(Z& E0NqGokpKVy literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..58953be579bfcdbf894d2b0094e9cce7722a131c GIT binary patch literal 2546 zcmai0c{o&iA0N6`OmvZ5F%6+GGiNqqY>gR%uCXD-uI85`~IGD&TspEKHvR$&R$PfV73lo0V_BHgb+bsD2Hc<9J_i0iQus9kbVRPh9RJWVH}ru zA-FN#of#Y-5p2yyI@lv@#bg-)7lc>{F*lMYB8%;iUwFx~^};b4iTEM{Mc5&~8s*RM zL{Rxc5J5oUEQ2usfFKf40G>c30u~4?2Ed{*vWI91;K>9c8Eb|3HjpxHLUst*n@0bp zOSZE^hCz^kj7G=C#-d_zD84Wh4Om-SFK}S7mNE%TQ5+9qi7j~|qeTW9C<+#G1Q3VM zLo6_|g80#p9a3iLR~NVf2ID(1PxLKNvXG(0ECCuoVbEOef?r>xMUXf6Uo(CvEn>zA zK(sd~;ztXEW%&p(S_I2t_wR}p1ZCEcJ%k)tQdp5ResDAwM2~VL?sB|nqcO+mb zG=M-`#JciC5Q`TKF6!mT^nSzQ{uN863PBdc7c%+$$i)iq4C6z5Q5au$trMR`MvaIoA1p7@?;$&l(j}~4uuYbDIi^G z6sEXmbQ9N;32OZQ=6C6vTjM7)5XpZ_3K84ZmgubWO$(7oG)n`simhi|a1J3*rPQRw zPytuWQ963NCr<@@khjrnUJ^-^V8j zPu|-PSq~)~Zu@&eY`{nwYNw^@D!Tna-M)SMQy8z@HP7n9@Z8{$2hCUZzj`K)Mb_Gy zuHlSzJSHtunAG~@K8_Acj;|usT9~eh%63x=Wzm&Q<_l)1Rk?ZVO>3GoGRjbG=}j`ZRWU{-@St1B)sv2enOY;ivkGI=l{!T#xC` zkv|}wY(OS}uU~|Y;0BZml}awE*n2xi>N>2zc^JzPgYLsZ6}m*c_#!1JLrb*fnsmD3 z=kuDqZ@n&Q2&(?{*;D<5)ulmRqI{j~U;lx4r@Odm^!8rKYvb%^dGC%DPVdNTO!awK z>|A(DQ@(gvSb)B>VHSN=f`d)!wA)yUh7~|j#rVS9&kgX;HPHMB@OAf9hnux)dR3yu z5or!|QcWGT&CnnwOK`|saAjs4b8;5A?UXVg5&0jE)nEk4qcrjx&K+N3`s$BamN26uJWNrS~)b2p1+xw3kIh1tm3f$;nX`*&u`kqU2(4M&e zq_gQ2w6b*%jr+8ZsCUt1pP{b2N@hx-NNrPBkcD_EgGXh_P1j?;C-u*gXcNRa< z1q~`HtOziOE2~{~qtEPC%k7@6{iK}*gM<5KD=Zp5*>p;$D=b!C*_3utXliEcU4NdN zCy6TmY%*7})@sXd2S4FZ5o1Pp&?Y9erGE4|<+AT@DG7&#+05Jw8?wrYqF)%3-EwD| zJy5OnGis|9iyMLxB1A^D=FPXt+AE~(4$3*ygw<;4*|yQZ?YRpFbxu2fuFfF&Z-&v0 zlQ%q1TGpXyR^zvKU)-yt%=80kb(M{0JDDkxD9MQ48Lje*JHY7Nd+(y|GTFs%>Iz=$ z6^w=MPdR={4Tsffg*#_jUsfqsw^lcy1*i5H@?w@hPEhI5imZ8Sqt}?sGd=Zb<(Z*N z89$Lcp~;+zLsRZBYW|LM)pANHN2i9F@C_po0%s{VZA}>C6$wdxn zz^ggXw6-3qHtgCLL-EnAy!Wf>n`b+9ByB4z5O*8ZCHIKU`dYgO?hi@#o9Le&uP1v$Q4GYsFhG2en%DXoof?z@xILN&kb#M(qpXKwlimmc3kuo|mR)0E@LTtGK!F!@HFS$O>q4A5Rs7a_*0hng zlKaz&q#oD3FL&l;uGjYMyY+d;23w#)mBMuG+y~!tJWSdiYWpapqAn=bUMutSM<8uX7F}0F*%qZ&B?B}xjBgNy5BhM7;Cwf9un)@D4 z%v|t2L%n=zDKWK{2i2TNd;00|wHLUgYrT(~f|UcNl3wFlg+FADL+g%Tbihu(5t#-JKuT)a-b9f#jn&HP;z*@<6w4 zz})y2^4ST?wC1i|A#&vHs`5vD{IcxYO{P=?^&KJMWktk6X*+vWVpj<@Q_>B2XX literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..9a367ec596647b0bc666f8d6b20651d766df6d4b GIT binary patch literal 1631 zcmah}eNfY87!RVr5Qf{t6@?j!+w_n&Nt3jVw6$$ot%K5|U4iYkQQDN|uuV;)EtSm^ zRCMBW4sOl~Y-64u)8WbOPPe-W2aYj4=R|kI^JAiJ-NXau4Xb>(6sg-EoXaJ7pZCr4 z`#s;;VlpmEPMn(v06?-~Ia$cBqR5jF$G?k?XG{4djnfr#X2!|+Z7c<-9ZVSo8r-&W zs*tidDp&PTxd0IBq%FlSY8jRSF_9$44#6;p<02Tva2#F?A`py-A^yg5V3fdc0+E7~myox{ zI-Eoysh_mP?-W88$9V~{*zfm?{1OqvmWyGzTpr;-kQ`nk$5-j$Y=In)FDuGGQa(FN zdpVl%fDuMp8MB&G2zgH*h2Zw)=RYR)_$Cv@r%W8MdBv~@61&}zxF)oHTp{(Z8&hig zER|kLTuAwt)vTSbhchb*=5zOCLlH&Z8=`=v`J&iXl8k+|oAPi5QX%BOh#a(okYE}F z)5>)?qQi9(7?z__xt>I28X1n08Z{KxK^rDV|uMtu0ga2 z8pRqsKF;Q`Q&GD#Z+8+4KM_l4S<1#Stc77#MmxadVmQX@HBkgaule_1SkBvxW=|)jtIE?Ea>~*}_bFMq#mFry_!hOBnb2e{%s=F61Z3gae zpeH^!q$;7)L!tYsbz|@C^S!$xrr!#Rz-(W&W^O37AtvwK#sy2#{|tp=M5M#OhQU=R zeKTCT1~t|;D|}VsykxDd$r!s^G_4bi7o?sYY`*$jlk%NvbIqQ*u3x!hb#XqeADd4=1AYD-*Z#U$k<|L;2`7Nnbe$yAPUmeC>}ebj6ql47a6X?E zTsG~Oi&hf4IC*WhX+?GB%h?TT3%To(bwSpJ-tfr1`GS`UKHAvt zGKCOCI1n5jn9`-j@V+{;*!VEbZHe;TY%4#6;-x1>ZsY_b-G;NB`b>?fikZ zq-^WqSRyR$JoRB~nz2#YT}sioY(>L7>8!>rq3=y`7?$cCY5Jh1rsK+)-5n=;Vnpk1 z4PWjsr&lAwB-eiXu&cg)_6}s|_m1mBt#4)0A2&8;Z0>_@45|VNww3ruFS9^E8Jqx-!Fv7@f!v-3(UDR&01u7hr*THEipmFEd=$0X0J zP3c3GyDj<*<+B;%?5wZv!tm40SVG2?g1p!FK64(M-p_&77fRz*vHb^@=B_W58;|zH kD&CO2cCd~}R{;qSAh6`uHKo=6030q^b^rhX literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..3218b538852a74ac44bf0c24994da18d0aa0d5e5 GIT binary patch literal 1930 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 SRHJhI(UkHi*+EI_%6|Yma?q*( literal 0 HcmV?d00001 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 -- 2.7.4