diff options
author | Jungki Kwak <jungki.kwak@samsung.com> | 2012-08-21 19:50:29 +0900 |
---|---|---|
committer | Jungki Kwak <jungki.kwak@samsung.com> | 2012-08-21 19:50:29 +0900 |
commit | 69a03608a6adc6a82eafd778739c1f02c34d976e (patch) | |
tree | 5072b25a20523a553e7697463e35f103e25d2638 | |
parent | bed963b6c4431be5d3ce04131683172cc43675ea (diff) | |
download | download-provider-69a03608a6adc6a82eafd778739c1f02c34d976e.tar.gz download-provider-69a03608a6adc6a82eafd778739c1f02c34d976e.tar.bz2 download-provider-69a03608a6adc6a82eafd778739c1f02c34d976e.zip |
The download provider daemon is added newly.
The old download-provider package was UI application.
The new download-provider package is download daemon process.
new file: AUTHORS
modified: CMakeLists.txt
deleted: INSTALL
deleted: LICENSE
deleted: NOTICE
modified: debian/changelog
deleted: debian/compat
deleted: debian/control
deleted: debian/dirs
deleted: debian/org.tizen.download-provider.install.in
deleted: debian/org.tizen.download-provider.postinst
deleted: debian/rules
new file: download-provider-service
new file: download-provider.manifest
new file: download-provider.pc.in
new file: include/download-provider-config.h
new file: include/download-provider-db.h
new file: include/download-provider-ipc.h
new file: include/download-provider-log.h
new file: include/download-provider-notification.h
new file: include/download-provider-pthread.h
new file: include/download-provider-utils.h
new file: include/download-provider.h
new file: packaging/download-provider.spec
deleted: packaging/org.tizen.download-provider.spec
deleted: po/CMakeLists.txt
deleted: po/POTFILES.in.in
deleted: po/csv2po
deleted: po/de_DE.po
deleted: po/el_GR.po
deleted: po/en.po
deleted: po/es_ES.po
deleted: po/fr_FR.po
deleted: po/it_IT.po
deleted: po/ja_JP.po
deleted: po/ko_KR.po
deleted: po/nl_NL.po
deleted: po/pt_PT.po
deleted: po/ru_RU.po
deleted: po/tr_TR.po
deleted: po/update-po.sh.in
deleted: po/zh_CN.po
deleted: po/zh_HK.po
deleted: po/zh_TW.po
renamed: res/images/U06_icon_DRM.png -> res/images/Q02_Notification_Download_failed.png
deleted: res/images/U06_icon_Java.png
deleted: res/images/U06_icon_Unknown.png
deleted: res/images/U06_icon_excel.png
deleted: res/images/U06_icon_html.png
deleted: res/images/U06_icon_image.png
deleted: res/images/U06_icon_music.png
deleted: res/images/U06_icon_pdf.png
deleted: res/images/U06_icon_ppt.png
deleted: res/images/U06_icon_ringtone.png
deleted: res/images/U06_icon_text.png
deleted: res/images/U06_icon_video.png
deleted: res/images/U06_icon_word.png
deleted: res/org.tizen.download-provider.desktop.in
deleted: res/org.tizen.download-provider.png
new file: script/commit-template
new file: src/agent/CMakeLists.txt
new file: src/agent/download-agent-basic.c
new file: src/agent/download-agent-client-mgr.c
new file: src/agent/download-agent-debug.c
new file: src/agent/download-agent-dl-info-util.c
new file: src/agent/download-agent-dl-mgr.c
new file: src/agent/download-agent-encoding.c
new file: src/agent/download-agent-file.c
new file: src/agent/download-agent-http-mgr.c
new file: src/agent/download-agent-http-misc.c
new file: src/agent/download-agent-http-msg-handler.c
new file: src/agent/download-agent-http-queue.c
new file: src/agent/download-agent-installation.c
new file: src/agent/download-agent-interface.c
new file: src/agent/download-agent-mime-util.c
new file: src/agent/download-agent-plugin-conf.c
new file: src/agent/download-agent-plugin-drm.c
new file: src/agent/download-agent-plugin-install.c
new file: src/agent/download-agent-plugin-libsoup.c
new file: src/agent/download-agent-utils-dl-req-id-history.c
new file: src/agent/download-agent-utils.c
new file: src/agent/include/download-agent-basic.h
new file: src/agent/include/download-agent-client-mgr.h
new file: src/agent/include/download-agent-debug.h
new file: src/agent/include/download-agent-defs.h
new file: src/agent/include/download-agent-dl-info-util.h
new file: src/agent/include/download-agent-dl-mgr.h
new file: src/agent/include/download-agent-encoding.h
new file: src/agent/include/download-agent-file.h
new file: src/agent/include/download-agent-http-mgr.h
new file: src/agent/include/download-agent-http-misc.h
new file: src/agent/include/download-agent-http-msg-handler.h
new file: src/agent/include/download-agent-http-queue.h
new file: src/agent/include/download-agent-installation.h
new file: src/agent/include/download-agent-interface.h
new file: src/agent/include/download-agent-mime-util.h
new file: src/agent/include/download-agent-plugin-conf.h
new file: src/agent/include/download-agent-plugin-drm.h
new file: src/agent/include/download-agent-plugin-http-interface.h
new file: src/agent/include/download-agent-plugin-install.h
new file: src/agent/include/download-agent-plugin-libsoup.h
new file: src/agent/include/download-agent-pthread.h
new file: src/agent/include/download-agent-type.h
new file: src/agent/include/download-agent-utils-dl-req-id-history.h
new file: src/agent/include/download-agent-utils.h
deleted: src/download-provider-dateTime.cpp
new file: src/download-provider-db.c
deleted: src/download-provider-downloadItem.cpp
deleted: src/download-provider-downloadRequest.cpp
deleted: src/download-provider-event.cpp
deleted: src/download-provider-history-db.cpp
new file: src/download-provider-ipc.c
deleted: src/download-provider-item.cpp
deleted: src/download-provider-items.cpp
new file: src/download-provider-main.c
deleted: src/download-provider-network.cpp
new file: src/download-provider-notification.c
new file: src/download-provider-pid.c
new file: src/download-provider-receiver.c
deleted: src/download-provider-util.cpp
new file: src/download-provider-utils.c
deleted: src/download-provider-view.cpp
deleted: src/download-provider-viewItem.cpp
deleted: src/include/download-provider-common.h
deleted: src/include/download-provider-dateTime.h
deleted: src/include/download-provider-debug.h
deleted: src/include/download-provider-downloadItem.h
deleted: src/include/download-provider-downloadRequest.h
deleted: src/include/download-provider-event.h
deleted: src/include/download-provider-history-db.h
deleted: src/include/download-provider-item.h
deleted: src/include/download-provider-items.h
deleted: src/include/download-provider-network.h
deleted: src/include/download-provider-util.h
deleted: src/include/download-provider-view.h
deleted: src/include/download-provider-viewItem.h
deleted: src/main.cpp
137 files changed, 16447 insertions, 6804 deletions
@@ -0,0 +1 @@ +Kwangmin Bang <justine.bang@samsung.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt index 39c8a0e..cdce885 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,122 +1,75 @@ -# -# Copyright (c) Samsung Electronics Co., Ltd. All rights reserved. -# +ADD_SUBDIRECTORY(src/agent) CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(download-provider C CXX) - -SET(SRCS - src/main.cpp - src/download-provider-event.cpp - src/download-provider-network.cpp - src/download-provider-view.cpp - src/download-provider-viewItem.cpp - src/download-provider-items.cpp - src/download-provider-item.cpp - src/download-provider-downloadItem.cpp - src/download-provider-downloadRequest.cpp - src/download-provider-util.cpp - src/download-provider-history-db.cpp - src/download-provider-dateTime.cpp - src/download-provider-network.cpp -) - -SET(VENDOR "tizen") -SET(PACKAGE ${PROJECT_NAME}) -SET(PKGNAME "org.${VENDOR}.${PACKAGE}") -SET(PREFIX ${CMAKE_INSTALL_PREFIX}) -SET(BINDIR "${PREFIX}/bin") -SET(RESDIR "${PREFIX}/res") -SET(IMAGEDIR "${RESDIR}/images") -SET(DATADIR "${PREFIX}/data") -SET(DBDATADIR "${PREFIX}/data/db") -SET(LOCALEDIR "${RESDIR}/locale") -SET(ICONDIR "${RESDIR}/icons/default/small") -SET(HISTORYDB ".download-history.db") + +## PROJECT NAME +PROJECT(download-provider C) +SET(VERSION "0.0.1") IF("${CMAKE_BUILD_TYPE}" STREQUAL "") - SET(CMAKE_BUILD_TYPE "Release") + SET(CMAKE_BUILD_TYPE "Debug") ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/include) +SET(DATABASE_DIR "/opt/dbspace") +SET(DATABASE_NAME ".download-provider.db") +SET(RES_DIR "/opt/data/download-provider") +SET(IMAGE_DIR "${RES_DIR}") INCLUDE(FindPkgConfig) -pkg_check_modules(pkgs REQUIRED - capi-system-runtime-info - capi-appfw-application - appsvc - libdownload-agent - elementary - aul - ecore-x - vconf - bundle - evas - ecore - ecore-input - edje - icu-i18n - xdgmime - eina - ) - -FIND_LIBRARY(LIB_DL dl) - -FIND_PROGRAM(UNAME NAMES uname) -EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") + +pkg_check_modules(pkgs REQUIRED glib-2.0 + gobject-2.0 + db-util + sqlite3 + capi-appfw-application + capi-network-connection + dlog) FOREACH(flag ${pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) -FOREACH(flag ${pkgs_include_CFLAGS}) - SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") -ENDFOREACH(flag) - -MESSAGE("ARCH: ${ARCH}") -MESSAGE("LIB_DL: ${LIB_DL}") - -SET(CMAKE_C_FLAGS "${INC_FLAGS}${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall") -#SET(CMAKE_C_FLAGS_DEBUG "$[CMAKE_C_FLAGS_DEBUG} -O0 -g") -#SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2") -SET(CMAKE_CXX_FLAGS "${INC_FLAGS} ${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -Wall") -SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g -Wall") -SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") - -IF("${ARCH}" MATCHES "^arm.*") - ADD_DEFINITIONS("-DTARGET") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpie") - SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mabi=aapcs-linux -mfpu=vfp -mfloat-abi=softfp") - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") -ENDIF("${ARCH}" MATCHES "^arm.*") - -SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed -Wl,--hash-style=both") - -ADD_DEFINITIONS("-DVENDOR=\"${VENDOR}\"") -ADD_DEFINITIONS("-DPACKAGE=\"${PACKAGE}\"") -ADD_DEFINITIONS("-DPACKAGE_NAME=\"${PKGNAME}\"") -ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") -ADD_DEFINITIONS("-DRESDIR=\"${RESDIR}\"") -ADD_DEFINITIONS("-DIMAGEDIR=\"${IMAGEDIR}\"") -ADD_DEFINITIONS("-DDATADIR=\"${DATADIR}\"") -ADD_DEFINITIONS("-DDBDATADIR=\"${DBDATADIR}\"") -ADD_DEFINITIONS("-DLOCALEDIR=\"${LOCALEDIR}\"") -ADD_DEFINITIONS("-DICONDIR=\"${ICONDIR}\"") -ADD_DEFINITIONS("-DHISTORYDB=\"${HISTORYDB}\"") - -ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${LIB_DL}) - -INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR}) - -# install desktop file & icon -CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/res/${PKGNAME}.desktop.in ${CMAKE_BINARY_DIR}/${PKGNAME}.desktop) -INSTALL(DIRECTORY DESTINATION ${DATADIR}) -INSTALL(DIRECTORY DESTINATION ${DBDATADIR}) -INSTALL(FILES ${CMAKE_BINARY_DIR}/${PKGNAME}.desktop DESTINATION /opt/share/applications) -INSTALL(FILES ${CMAKE_SOURCE_DIR}/res/${PKGNAME}.png DESTINATION ${ICONDIR}) -INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/res/images DESTINATION ${RESDIR}) - -# i18n -ADD_SUBDIRECTORY(po) +## INCLUDES +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src/agent/include) + +set(LINK_LIBRARIES ${GLIB-2_LIBRARIES} + ${GOBJECT-2_LIBRARIES} + pthread + capi-appfw-application + downloadagent + ) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g -fpie -Wall") + +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed -Wl -fpie,--hash-style=both") + +ADD_DEFINITIONS( + -DDATABASE_DIR=\"${DATABASE_DIR}\" + -DDATABASE_NAME=\"${DATABASE_NAME}\" + -DIMAGE_DIR=\"${IMAGE_DIR}\" + ) + +ADD_EXECUTABLE(${PROJECT_NAME} + ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-pid.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-ipc.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-notification.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-db.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-utils.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-receiver.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-main.c ) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${LINK_LIBRARIES}) +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) + +CONFIGURE_FILE(download-provider.pc.in download-provider.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/download-provider.pc DESTINATION lib/pkgconfig) +INSTALL(FILES include/download-provider.h DESTINATION include/${PROJECT_NAME}) + +INSTALL(PROGRAMS download-provider-service DESTINATION /etc/rc.d/init.d) + +# install images +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/res/images/ DESTINATION /opt/data/download-provider/ + FILES_MATCHING + PATTERN "*.png" + ) diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 3f81c54..0000000 --- a/INSTALL +++ /dev/null @@ -1,33 +0,0 @@ -1. make the build directory - - ex) - - $ mkdir build - - -2. change the working directory to the build directory - - ex) - - $ cd build - - -3. run 'cmake' - - $ cmake ${SOURCE_DIR} -DCMAKE_INSTALL_PREFIX=/opt/apps/@@PKGNAME@@ - - ex) - - $ cmake .. -DCMAKE_INSTALL_PREFIX=/opt/apps/@@PKGNAME@@ - - or - - $ cmake .. - - -4. make & make install - - ex) - - $ make -j 2 && make install - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 7ccb5b5..0000000 --- a/LICENSE +++ /dev/null @@ -1,75 +0,0 @@ -Flora License - -Version 1.0, May, 2012 - -http://www.tizenopensource.org/license - -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. - -"Tizen Certified Platform" shall mean a software platform that complies with the standards set forth in the Compatibility Definition Document and passes the Compatibility Test Suite as defined from time to time by the Tizen Technical Steering Group and certified by the Tizen Association or its designated agent. - -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 solely as incorporated into a Tizen Certified Platform, 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 solely as incorporated into a Tizen Certified Platform 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 pursuant to the copyright license above, in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: - - 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and - - 2. You must cause any modified files to carry prominent notices stating that You changed the files; and - - 3. 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 - - 4. 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 Flora License to your work - -To apply the Flora 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 Flora License, Version 1.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.tizenopensource.org/license - - 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. @@ -1 +0,0 @@ -Copyright (c) Samsung Electronics Co., Ltd. All rights reserved. diff --git a/debian/changelog b/debian/changelog index 928eadd..5bf9374 100644..100755 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,8 @@ -download-provider (1.0.0-0) unstable; urgency=low - * Git: pkgs/d/download-provider - * Tag: download-provider_1.0.0-0 +download-provider2 (0.0.1) unstable; urgency=low - * Tizen release. + * Git: 165.213.180.234:/slp/pkgs/d/download-provider2 + * Tag: download-provider2_0.0.1 - -- Jungki Kwak <jungki.kwak@samsung.com> Fri, 16 Mar 2012 14:41:48 +0900 + * initial making. + -- Kwangmin Bang <justine.bang@samsung.com> Thu, 15 Sep 2011 17:21:13 +0900 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index 7ed6ff8..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/debian/control b/debian/control deleted file mode 100644 index 2d00f93..0000000 --- a/debian/control +++ /dev/null @@ -1,17 +0,0 @@ -Source: download-provider -Section: misc -Priority: extra -Maintainer: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com>, InBum Chang <ibchang@samsung.com> -Build-Depends: debhelper (>= 5), libdownload-agent-dev, libelm-dev, libeina-dev, libaul-1-dev, libecore-dev, libvconf-dev, libbundle-dev, libicu-dev, libxdgmime-dev, capi-system-runtime-info-dev, capi-appfw-application-dev, libappsvc-dev -Standards-Version: 0.1.0 - -Package: org.tizen.download-provider -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, libicu -Description: Application for support of the content download - -Package: org.tizen.download-provider-dbg -Section: debug -Architecture: any -Depends: org.tizen.download-provider (= ${Source-Version}) -Description: Application for support of the content download (unstripped) diff --git a/debian/dirs b/debian/dirs deleted file mode 100644 index ca882bb..0000000 --- a/debian/dirs +++ /dev/null @@ -1,2 +0,0 @@ -usr/bin -usr/sbin diff --git a/debian/org.tizen.download-provider.install.in b/debian/org.tizen.download-provider.install.in deleted file mode 100644 index e95ca2a..0000000 --- a/debian/org.tizen.download-provider.install.in +++ /dev/null @@ -1,4 +0,0 @@ -@PREFIX@/bin/* -@PREFIX@/data -@PREFIX@/res/* -opt/share/applications/* diff --git a/debian/org.tizen.download-provider.postinst b/debian/org.tizen.download-provider.postinst deleted file mode 100644 index 8183086..0000000 --- a/debian/org.tizen.download-provider.postinst +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -#### Download History #### -if [ ${USER} == "root" ] -then - # Change file owner - chown -R 5000:5000 /opt/apps/org.tizen.download-provider/data -fi - -if [ ! -f /opt/apps/org.tizen.download-provider/data/db/.download-history.db ]; -then - sqlite3 /opt/apps/org.tizen.download-provider/data/db/.download-history.db 'PRAGMA journal_mode=PERSIST; - create table history(id integer primary key autoincrement, historyid integer, downloadtype integer, contenttype integer, state integer, err integer, name, vendor, path, url, cookie, date datetime);' -fi - -if [ ${USER} == "root" ] -then -# Change file owner - chown -R 5000:5000 /opt/apps/org.tizen.download-provider/data - chown :6002 /opt/apps/org.tizen.download-provider/data/db/.download-history.db - chown :6002 /opt/apps/org.tizen.download-provider/data/db/.download-history.db-journal - chmod 660 /opt/apps/org.tizen.download-provider/data/db/.download-history.db - chmod 660 /opt/apps/org.tizen.download-provider/data/db/.download-history.db-journal -fi - - diff --git a/debian/rules b/debian/rules deleted file mode 100755 index bbf1a0c..0000000 --- a/debian/rules +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/make -f -# -*- makefile -*- -# Sample debian/rules that uses debhelper. -# This file was originally written by Joey Hess and Craig Small. -# As a special exception, when this file is copied by dh-make into a -# dh-make output file, you may use that output file without restriction. -# This special exception was added by Craig Small in version 0.37 of dh-make. - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -CFLAGS ?= -Wall -g -LDFLAGS ?= -PREFIX ?= /opt/apps/org.tizen.download-provider -RESDIR ?= /opt/apps/org.tizen.download-provider/res -DATADIR ?= /opt/apps/org.tizen.download-provider/data - -ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) - CFLAGS += -O0 - CXXFLAGS += -O0 -else - CFLAGS += -O2 - CXXFLAGS += -O2 -endif - -LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed - -CMAKE_BUILD_DIR ?= $(CURDIR)/cmake_build_tmp - -configure: configure-stamp -configure-stamp: - dh_testdir - # Add here commands to configure the package. - mkdir -p $(CMAKE_BUILD_DIR) && cd $(CMAKE_BUILD_DIR) && \ - CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" cmake .. -DCMAKE_INSTALL_PREFIX="$(PREFIX)" - - touch configure-stamp - -build: build-stamp - -build-stamp: configure-stamp - dh_testdir - - # Add here commands to compile the package. - cd $(CMAKE_BUILD_DIR) && $(MAKE) - - for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ - cat $$f > $${f%.in}; \ - sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \ - sed -i -e "s#@RESDIR@#$(RESDIR)#g" $${f%.in}; \ - sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \ - done - - touch $@ - -clean: - dh_testdir - dh_testroot - rm -f build-stamp configure-stamp - - # Add here commands to clean up after the build process. - rm -rf $(CMAKE_BUILD_DIR) - - for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ - rm -f $${f%.in}; \ - done - - dh_clean - -install: build - dh_testdir - dh_testroot - dh_clean -k -# dh_installdirs - - # Add here commands to install the package into debian/wavplayer. - cd $(CMAKE_BUILD_DIR) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install - - -# Build architecture-independent files here. -binary-indep: build install -# We have nothing to do by default. - -# Build architecture-dependent files here. -binary-arch: build install - dh_testdir - dh_testroot -# dh_installchangelogs -# dh_installdocs -# dh_installexamples - dh_install --sourcedir=debian/tmp -# dh_installmenu -# dh_installdebconf -# dh_installlogrotate -# dh_installemacsen -# dh_installpam -# dh_installmime -# dh_python -# dh_installinit -# dh_installcron -# dh_installinfo - dh_installman - dh_link - dh_strip --dbg-package=org.tizen.download-provider-dbg - dh_compress - dh_fixperms -# dh_perl - dh_makeshlibs - dh_installdeb - dh_shlibdeps - dh_gencontrol - dh_md5sums - dh_builddeb - -binary: binary-indep binary-arch -.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/download-provider-service b/download-provider-service new file mode 100644 index 0000000..40fa113 --- /dev/null +++ b/download-provider-service @@ -0,0 +1,9 @@ +#!/bin/sh + +### A script for running download daemon in booting time. +#dlogutil -v long -f /var/log/download-capi.log -r 100 -n 10 TIZEN_N_URL_DOWNLOAD & +#dlogutil -v long -f /var/log/download-daemon.log -r 1000 -n 10 download-provider DownloadAgent & + +if [ -x /usr/bin/download-provider ]; then +/usr/bin/download-provider & +fi diff --git a/download-provider.manifest b/download-provider.manifest new file mode 100644 index 0000000..38ea367 --- /dev/null +++ b/download-provider.manifest @@ -0,0 +1,11 @@ +<manifest> + <define> + <domain name="download-provider" /> + </define> + <request> + <domain name="download-provider" /> + </request> + <assign> + <filesystem path="/opt/dbspace/.download-provider.db" /> + </assign> +</manifest> diff --git a/download-provider.pc.in b/download-provider.pc.in new file mode 100644 index 0000000..5ec2085 --- /dev/null +++ b/download-provider.pc.in @@ -0,0 +1,9 @@ +# Package Information (download-provider daemon style) + +prefix=/usr +includedir=${prefix}/include + +Name: Download Provider +Description: Download Provider Daemon +Version: @VERSION@ +Cflags: -I${includedir}/download-provider diff --git a/include/download-provider-config.h b/include/download-provider-config.h new file mode 100644 index 0000000..ef73c3e --- /dev/null +++ b/include/download-provider-config.h @@ -0,0 +1,48 @@ +#ifndef DOWNLOAD_PROVIDER_CONFIG_H +#define DOWNLOAD_PROVIDER_CONFIG_H + +#include <app_ui_notification.h> +#include <app_service.h> + +#include <download-provider.h> + +#define DOWNLOAD_PROVIDER_IPC "/tmp/download-provider" +#define DOWNLOAD_PROVIDER_LOCK_PID "/tmp/download-provider.lock" + +#define DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL 5 +#define DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL 3600 + +#define DOWNLOAD_PROVIDER_DOWNLOADING_DB_NAME DATABASE_DIR"/"DATABASE_NAME + +#define MAX_CLIENT 64 // Backgound Daemon should has the limitation of resource. + +#define DOWNLOAD_PROVIDER_REQUESTID_LEN 20 + +#define DOWNLOAD_PROVIDER_HISTORY_DB_LIMIT_ROWS 1000 + +typedef struct { + pid_t pid; + uid_t uid; + gid_t gid; +} download_client_credential; + +typedef struct { + pthread_t thread_pid; + pthread_mutex_t client_mutex; + int clientfd; // socket for client + download_client_credential credentials; + ui_notification_h ui_notification_handle; // notification bar + service_h service_handle; // launch the special app from notification bar + int req_id; + download_request_info *requestinfo; + downloading_state_info *downloadinginfo; + download_content_info *downloadinfo; + char *tmp_saved_path; + download_states state; + download_error err; +} download_clientinfo; + +typedef struct { + download_clientinfo *clientinfo; +} download_clientinfo_slot; +#endif diff --git a/include/download-provider-db.h b/include/download-provider-db.h new file mode 100644 index 0000000..957c613 --- /dev/null +++ b/include/download-provider-db.h @@ -0,0 +1,52 @@ +#ifndef DOWNLOAD_PROVIDER_DB_H +#define DOWNLOAD_PROVIDER_DB_H + +#include "download-provider-config.h" + +typedef struct { + download_states state; + int notification; + int retrycount; + int requestid; + char *packagename; + char *installpath; + char *filename; + char *createdate; + char *url; + char *mimetype; + char *etag; + char *saved_path; +} download_dbinfo; + +typedef struct { + unsigned int count; + download_dbinfo *item; +} download_dbinfo_list; + +typedef enum { + DOWNLOAD_DB_UNIQUEID = 0, + DOWNLOAD_DB_PACKAGENAME = 1, + DOWNLOAD_DB_NOTIFICATION = 2, + DOWNLOAD_DB_INSTALLPATH = 3, + DOWNLOAD_DB_FILENAME = 4, + DOWNLOAD_DB_RETRYCOUNT = 5, + DOWNLOAD_DB_STATE = 6, + DOWNLOAD_DB_URL = 7, + DOWNLOAD_DB_MIMETYPE = 10, + DOWNLOAD_DB_ETAG = 11, + DOWNLOAD_DB_SAVEDPATH = 12 +} download_db_column_type; + +int download_provider_db_requestinfo_new(download_clientinfo *clientinfo); +int download_provider_db_requestinfo_remove(int uniqueid); +int download_provider_db_requestinfo_update_column(download_clientinfo *clientinfo, + download_db_column_type type); +download_dbinfo_list *download_provider_db_get_list(int state); +void download_provider_db_list_free(download_dbinfo_list *list); +int download_provider_db_list_count(int state); +download_request_info *download_provider_db_get_requestinfo(download_dbinfo *dbinfo); +int download_provider_db_history_new(download_clientinfo *clientinfo); +int download_provider_db_history_remove(int uniqueid); +int download_provider_db_history_limit_rows(); + +#endif diff --git a/include/download-provider-ipc.h b/include/download-provider-ipc.h new file mode 100644 index 0000000..a38a965 --- /dev/null +++ b/include/download-provider-ipc.h @@ -0,0 +1,13 @@ +#ifndef DOWNLOAD_PROVIDER_IPC_H +#define DOWNLOAD_PROVIDER_IPC_H + +#include "download-provider-config.h" + +int ipc_receive_header(int fd); +int ipc_send_stateinfo(download_clientinfo *clientinfo); +int ipc_send_downloadinfo(download_clientinfo *clientinfo); +int ipc_send_downloadinginfo(download_clientinfo *clientinfo); +int ipc_send_request_stateinfo(download_clientinfo *clientinfo); +int ipc_receive_request_msg(download_clientinfo *clientinfo); + +#endif diff --git a/include/download-provider-log.h b/include/download-provider-log.h new file mode 100644 index 0000000..2416844 --- /dev/null +++ b/include/download-provider-log.h @@ -0,0 +1,19 @@ +#ifndef DOWNLOAD_PROVIDER_LOG_H +#define DOWNLOAD_PROVIDER_LOG_H +#define DEBUG_MSG + +#ifdef DEBUG_MSG +#include <dlog.h> +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "download-provider" +#define TRACE_DEBUG_MSG(format, ARG...) \ +{ \ +LOGD(format"[%s][%d]", ##ARG, __FUNCTION__, __LINE__); \ +} + +#else +#define TRACE_DEBUG_MSG(format, ARG...) ; +#endif +#endif diff --git a/include/download-provider-notification.h b/include/download-provider-notification.h new file mode 100644 index 0000000..6f526c4 --- /dev/null +++ b/include/download-provider-notification.h @@ -0,0 +1,10 @@ +#ifndef DOWNLOAD_PROVIDER_NOTIFICATION_H +#define DOWNLOAD_PROVIDER_NOTIFICATION_H + +#include "download-provider-config.h" + +int set_downloadinginfo_appfw_notification(download_clientinfo *clientinfo); +int set_downloadedinfo_appfw_notification(download_clientinfo *clientinfo); +int destroy_appfw_notification(download_clientinfo *clientinfo); + +#endif diff --git a/include/download-provider-pthread.h b/include/download-provider-pthread.h new file mode 100644 index 0000000..acbb361 --- /dev/null +++ b/include/download-provider-pthread.h @@ -0,0 +1,90 @@ +#ifndef DOWNLOAD_PROVIDER_PTHREAD_H +#define DOWNLOAD_PROVIDER_PTHREAD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <pthread.h> +#include <errno.h> + +#define CLIENT_MUTEX_INIT(mutex_add, attr) { \ + int ret = 0; \ + do { \ + ret = pthread_mutex_init(mutex_add, attr); \ + if (0 == ret) { \ + break; \ + } else if(EINVAL == ret) { \ + TRACE_DEBUG_MSG("ERR:pthread_mutex_init FAIL with EINVAL."); \ + break; \ + } else if(ENOMEM == ret) { \ + TRACE_DEBUG_MSG("ERR:pthread_mutex_init FAIL with ENOMEM."); \ + break; \ + } else { \ + TRACE_DEBUG_MSG("ERR:pthread_mutex_init FAIL with %d.", ret); \ + break; \ + } \ + }while(1); \ +} + +#define CLIENT_MUTEX_LOCK(mutex_add) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_lock(mutex_add);\ + if (0 == ret) {\ + break;\ + } else if (EINVAL == ret) {\ + TRACE_DEBUG_MSG("ERR:pthread_mutex_lock FAIL with EINVAL.");\ + break;\ + } else if (EDEADLK == ret) {\ + TRACE_DEBUG_MSG("ERR:pthread_mutex_lock FAIL with EDEADLK.");\ + break;\ + } else {\ + TRACE_DEBUG_MSG("ERR:pthread_mutex_lock FAIL with %d.", ret);\ + break;\ + } \ + } while(1);\ +} + +#define CLIENT_MUTEX_UNLOCK(mutex_add) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_unlock(mutex_add);\ + if (0 == ret) {\ + break;\ + } else if (EINVAL == ret) {\ + TRACE_DEBUG_MSG("ERR:pthread_mutex_lock FAIL with EINVAL.");\ + break;\ + } else if (EDEADLK == ret) {\ + TRACE_DEBUG_MSG("ERR:pthread_mutex_lock FAIL with EDEADLK.");\ + break;\ + } else {\ + TRACE_DEBUG_MSG("ERR:pthread_mutex_lock FAIL with %d.", ret);\ + break;\ + } \ + } while(1);\ +} + +#define CLIENT_MUTEX_DESTROY(mutex_add) { \ + int ret = 0; \ + do { \ + ret = pthread_mutex_destroy(mutex_add); \ + if (0 == ret) { \ + break; \ + } else if(EINVAL == ret) { \ + TRACE_DEBUG_MSG("ERR:pthread_mutex_destroy FAIL with EINVAL."); \ + break; \ + } else if(ENOMEM == ret) { \ + TRACE_DEBUG_MSG("ERR:pthread_mutex_destroy FAIL with ENOMEM."); \ + break; \ + } else { \ + TRACE_DEBUG_MSG("ERR:pthread_mutex_destroy FAIL with %d.", ret); \ + break; \ + } \ + }while(1); \ +} + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/download-provider-utils.h b/include/download-provider-utils.h new file mode 100644 index 0000000..3711d6f --- /dev/null +++ b/include/download-provider-utils.h @@ -0,0 +1,15 @@ +#ifndef DOWNLOAD_PROVIDER_UTILS_H +#define DOWNLOAD_PROVIDER_UTILS_H + +#include "download-provider-config.h" + +int get_download_request_id(void); +void clear_clientinfoslot(download_clientinfo_slot *clientinfoslot); +void clear_clientinfo(download_clientinfo *clientinfo); +void clear_socket(download_clientinfo *clientinfo); +int get_downloading_count(download_clientinfo_slot *clientinfo_list); +int get_same_request_slot_index(download_clientinfo_slot *clientinfo_list, + int requestid); +int get_empty_slot_index(download_clientinfo_slot *clientinfo_list); + +#endif diff --git a/include/download-provider.h b/include/download-provider.h new file mode 100644 index 0000000..d97d273 --- /dev/null +++ b/include/download-provider.h @@ -0,0 +1,112 @@ +#ifndef DOWNLOAD_PROVIDER_H +#define DOWNLOAD_PROVIDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define DOWNLOAD_PROVIDER_IPC "/tmp/download-provider" + +#define DP_MAX_STR_LEN_64 64 +#define DP_MAX_STR_LEN 256 +#define DP_MAX_PATH_LEN DP_MAX_STR_LEN +#define DP_MAX_URL_LEN 2048 + + typedef enum { + DOWNLOAD_CONTROL_START = 1, + DOWNLOAD_CONTROL_STOP = 2, + DOWNLOAD_CONTROL_PAUSE = 3, + DOWNLOAD_CONTROL_RESUME = 4, + DOWNLOAD_CONTROL_GET_DOWNLOADING_INFO = 11, + DOWNLOAD_CONTROL_GET_STATE_INFO = 13, + DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO = 14, + DOWNLOAD_CONTROL_GET_REQUEST_STATE_INFO = 15 + } download_controls; + + typedef enum { + DOWNLOAD_STATE_NONE = 0, + DOWNLOAD_STATE_READY = 1, + DOWNLOAD_STATE_PENDED = 2, + DOWNLOAD_STATE_PAUSE_REQUESTED = 3, + DOWNLOAD_STATE_PAUSED = 4, + DOWNLOAD_STATE_DOWNLOADING = 5, + DOWNLOAD_STATE_INSTALLING = 6, + DOWNLOAD_STATE_FINISHED = 7, + DOWNLOAD_STATE_STOPPED = 10, + DOWNLOAD_STATE_FAILED = 11 + } download_states; + + typedef enum { + DOWNLOAD_ERROR_NONE = 0, + DOWNLOAD_ERROR_INVALID_PARAMETER = 1, + DOWNLOAD_ERROR_OUT_OF_MEMORY = 2, + DOWNLOAD_ERROR_IO_ERROR = 3, + DOWNLOAD_ERROR_NETWORK_UNREACHABLE = 4, + DOWNLOAD_ERROR_CONNECTION_TIMED_OUT = 5, + DOWNLOAD_ERROR_NO_SPACE = 6, + DOWNLOAD_ERROR_FILED_NOT_FOUND = 7, + DOWNLOAD_ERROR_INVALID_STATE = 8, + DOWNLOAD_ERROR_CONNECTION_FAILED = 9, + DOWNLOAD_ERROR_INVALID_URL = 10, + DOWNLOAD_ERROR_INVALID_DESTINATION = 11, + DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS = 12, + DOWNLOAD_ERROR_ALREADY_COMPLETED = 13, + DOWNLOAD_ERROR_INSTALL_FAIL = 20, + DOWNLOAD_ERROR_FAIL_INIT_AGENT = 100, + DOWNLOAD_ERROR_UNKOWN = 900 + } download_error; + + typedef struct { + unsigned int started; + unsigned int paused; + unsigned int completed; + unsigned int stopped; + unsigned int progress; + } callback_info; + + typedef struct { + unsigned int length; + char *str; + } download_flexible_string; + + typedef struct { + unsigned int rows; + download_flexible_string *str; + } download_flexible_double_string; + + typedef struct { + unsigned int received_size; + char saved_path[DP_MAX_PATH_LEN]; + } downloading_state_info; + + typedef struct { + download_states state; + download_error err; + } download_state_info; + + typedef struct { + unsigned int file_size; + char mime_type[DP_MAX_STR_LEN]; + char content_name[DP_MAX_STR_LEN]; + } download_content_info; + + typedef struct { + callback_info callbackinfo; + unsigned int notification; + int requestid; + download_flexible_string client_packagename; + download_flexible_string url; + download_flexible_string install_path; + download_flexible_string filename; + download_flexible_double_string headers; + } download_request_info; + + typedef struct { + download_state_info stateinfo; + int requestid; + } download_request_state_info; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/packaging/download-provider.spec b/packaging/download-provider.spec new file mode 100644 index 0000000..be509d4 --- /dev/null +++ b/packaging/download-provider.spec @@ -0,0 +1,105 @@ +Name: download-provider +Summary: download the contents in background. +Version: 0.0.3 +Release: 2 +Group: TO_BE/FILLED_IN +License: TO_BE/FILLED_IN +Source0: %{name}-%{version}.tar.gz +Requires(post): /usr/bin/sqlite3 +BuildRequires: cmake +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gobject-2.0) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(libsoup-2.4) +BuildRequires: pkgconfig(xdgmime) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(db-util) +BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(capi-appfw-application) +BuildRequires: pkgconfig(capi-network-connection) +BuildRequires: pkgconfig(drm-client) +BuildRequires: pkgconfig(drm-trusted) + +%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 (developement files) + +%prep +%setup -q + +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} + +%build +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +mkdir -p %{buildroot}%{_sysconfdir}/rc.d/rc3.d +ln -s %{_sysconfdir}/rc.d/init.d/download-provider-service %{buildroot}%{_sysconfdir}/rc.d/rc3.d/S70download-provider-service +mkdir -p %{buildroot}%{_sysconfdir}/rc.d/rc5.d +ln -s %{_sysconfdir}/rc.d/init.d/download-provider-service %{buildroot}%{_sysconfdir}/rc.d/rc5.d/S70download-provider-service + +mkdir -p %{buildroot}/opt/data/download-provider + +%post +mkdir -p /opt/dbspace/ +if [ ! -f /opt/dbspace/.download-provider.db ]; +then + sqlite3 /opt/dbspace/.download-provider.db 'PRAGMA journal_mode=PERSIST; + CREATE TABLE downloading (id INTEGER PRIMARY KEY AUTOINCREMENT, uniqueid INTEGER UNIQUE, packagename TEXT, notification INTEGER, installpath TEXT, filename TEXT, creationdate TEXT, retrycount INTEGER, state INTEGER, url TEXT, mimetype TEXT, etag TEXT, savedpath TEXT);' + sqlite3 /opt/dbspace/.download-provider.db 'PRAGMA journal_mode=PERSIST; + CREATE TABLE history (id INTEGER PRIMARY KEY AUTOINCREMENT, uniqueid INTEGER UNIQUE, packagename TEXT, filename TEXT, creationdate TEXT, state INTEGER, mimetype TEXT, savedpath TEXT);' +fi + +%files +%defattr(-,root,root,-) +%dir /opt/data/download-provider +/opt/data/download-provider/*.png +%{_libdir}/libdownloadagent.so.0.0.1 +%{_libdir}/libdownloadagent.so +%{_bindir}/download-provider +%{_sysconfdir}/rc.d/init.d/download-provider-service +%{_sysconfdir}/rc.d/rc3.d/S70download-provider-service +%{_sysconfdir}/rc.d/rc5.d/S70download-provider-service + +%files devel +%defattr(-,root,root,-) +%{_libdir}/libdownloadagent.so.0.0.1 +%{_libdir}/libdownloadagent.so +%{_bindir}/download-provider +%{_includedir}/download-provider/download-provider.h +%{_libdir}/pkgconfig/download-provider.pc + +%changelog +* Tue Aug 17 2012 Jungki Kwak <jungki.kwak@samsung.com> +- Enable to use destination path +- Add to handle invalid id + +* Tue Aug 16 2012 Jungki Kwak <jungki.kwak@samsung.com> +- Change socket close timing + +* Mon Aug 13 2012 Kwangmin Bang <justine.bang@samsung.com> +- Disable default dlog in launching script. + +* Tue Aug 09 2012 Jungki Kwak <jungki.kwak@samsung.com> +- The function to init dbus glib is removed + +* Tue Aug 08 2012 Jungki Kwak <jungki.kwak@samsung.com> +- The function to init dbus glib is added for connection network CAPI + +* Tue Aug 07 2012 Jungki Kwak <jungki.kwak@samsung.com> +- Change the name of temp direcoty. +- When add requestinfo to slot, save it to DB. + +* Mon Aug 06 2012 Jungki Kwak <jungki.kwak@samsung.com> +- Initial version is updated. + diff --git a/packaging/org.tizen.download-provider.spec b/packaging/org.tizen.download-provider.spec deleted file mode 100644 index 32aaf76..0000000 --- a/packaging/org.tizen.download-provider.spec +++ /dev/null @@ -1,71 +0,0 @@ - -Name: org.tizen.download-provider -Summary: Application for support of the content download -Version: 1.0.0 -Release: 1 -Group: TO_BE_FILLED_IN -License: Flora Software License -URL: N/A -Source0: %{name}-%{version}.tar.gz -BuildRequires: pkgconfig(capi-system-runtime-info) -BuildRequires: pkgconfig(capi-appfw-application) -BuildRequires: pkgconfig(appsvc) -BuildRequires: pkgconfig(libdownload-agent) -BuildRequires: pkgconfig(elementary) -BuildRequires: pkgconfig(aul) -BuildRequires: pkgconfig(ecore) -BuildRequires: pkgconfig(vconf) -BuildRequires: pkgconfig(bundle) -BuildRequires: pkgconfig(xdgmime) -BuildRequires: pkgconfig(notification) -BuildRequires: pkgconfig(icu-i18n) -BuildRequires: cmake -BuildRequires: gettext-devel -BuildRequires: expat-devel -BuildRequires: edje-tools - -%description -Application for support of the content download - -%prep -%setup -q - -%build -cmake . -DCMAKE_INSTALL_PREFIX="/opt/apps/org.tizen.download-provider" - -make %{?jobs:-j%jobs} - -%install -rm -rf %{buildroot} -%make_install - -%post -#### Download History #### -if [ ${USER} == "root" ] -then - # Change file owner - chown -R 5000:5000 /opt/apps/org.tizen.download-provider/data -fi - -if [ ! -f /opt/apps/org.tizen.download-provider/data/db/.download-history.db ]; -then - sqlite3 /opt/apps/org.tizen.download-provider/data/db/.download-history.db 'PRAGMA journal_mode=PERSIST; - create table history(id integer primary key autoincrement, historyid integer, downloadtype integer, contenttype integer, state integer, err integer, name, vendor, path, url, cookie, date datetime);' -fi - -if [ ${USER} == "root" ] -then - chown -R 5000:5000 /opt/apps/org.tizen.download-provider/data - chown :6002 /opt/apps/org.tizen.download-provider/data/db/.download-history.db - chown :6002 /opt/apps/org.tizen.download-provider/data/db/.download-history.db-journal - chmod 660 /opt/apps/org.tizen.download-provider/data/db/.download-history.db - chmod 660 /opt/apps/org.tizen.download-provider/data/db/.download-history.db-journal -fi - -%files -%defattr(-,root,root,-) -/opt/apps/org.tizen.download-provider/bin/* -/opt/apps/org.tizen.download-provider/data -/opt/apps/org.tizen.download-provider/res/* -/opt/share/applications/* - diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt deleted file mode 100644 index 0197f3d..0000000 --- a/po/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -# for i18n - -SET(POFILES en.po de_DE.po el_GR.po es_ES.po fr_FR.po it_IT.po ja_JP.po ko_KR.po nl_NL.po pt_PT.po ru_RU.po tr_TR.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 ${LOCALEDIR}/${lang}/LC_MESSAGES RENAME ${PROJECT_NAME}.mo) - SET(moFiles ${moFiles} ${moFile}) -ENDFOREACH(pofile) - -MESSAGE(".mo files: ${moFiles}") -ADD_CUSTOM_TARGET(po ALL DEPENDS ${moFiles}) diff --git a/po/POTFILES.in.in b/po/POTFILES.in.in deleted file mode 100644 index bcb7f1f..0000000 --- a/po/POTFILES.in.in +++ /dev/null @@ -1,2 +0,0 @@ -# List of source files containing translatable strings. -@@APPNAME@@.c diff --git a/po/csv2po b/po/csv2po Binary files differdeleted file mode 100644 index 0c9a53a..0000000 --- a/po/csv2po +++ /dev/null diff --git a/po/de_DE.po b/po/de_DE.po deleted file mode 100644 index 4532322..0000000 --- a/po/de_DE.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "Installation gescheitert" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "Benachrichtigung..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "Verarbeitung abgeschlossen" - -msgid "IDS_BR_SK_RETRY" -msgstr "Ern. vers." - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "Download-Manager" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "Ungültiger Descriptor" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "Keine Downloads" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "Abgeschlossen" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "Datei kann nicht geöffnet werden" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "Herunterladen?" - diff --git a/po/el_GR.po b/po/el_GR.po deleted file mode 100644 index 1eaacb2..0000000 --- a/po/el_GR.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "Αποτυχία εγκατάστασης" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "Ειδοποίηση..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "Ολοκλήρωση επεξεργασίας" - -msgid "IDS_BR_SK_RETRY" -msgstr "Επανάληψη" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "Διαχείριση λήψεων" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "Μη έγκυρη περιγραφή" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "Δεν υπάρχουν λήψεις" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "Ολοκληρώθηκε" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "Δεν είναι δυνατό το άνοιγμα αρχείου" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "Λήψη;" - diff --git a/po/en.po b/po/en.po deleted file mode 100644 index c7289d7..0000000 --- a/po/en.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "Installation failed" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "Notifying..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "Processing completed" - -msgid "IDS_BR_SK_RETRY" -msgstr "Retry" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "Download manager" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "Invalid descriptor" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "No downloads" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "Complete" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "Unable to open file" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "Download?" - diff --git a/po/es_ES.po b/po/es_ES.po deleted file mode 100644 index 1434878..0000000 --- a/po/es_ES.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "Fallo en la instalación" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "Notificando..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "Procesamiento finalizado" - -msgid "IDS_BR_SK_RETRY" -msgstr "Reint." - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "Administrador de descarga" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "Descriptor no válido" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "Sin descargas" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "Completo" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "No se puede abrir el archivo" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "¿Descargar?" - diff --git a/po/fr_FR.po b/po/fr_FR.po deleted file mode 100644 index e408209..0000000 --- a/po/fr_FR.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "Echec de l'installation" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "Notification..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "Traitement terminé" - -msgid "IDS_BR_SK_RETRY" -msgstr "Réessayer" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "Gestionnaire de téléchargement" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "Descripteur non valide" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "Aucun téléchargement" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "OK" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "Impossible d'ouvrir le fichier" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "Télécharger ?" - diff --git a/po/it_IT.po b/po/it_IT.po deleted file mode 100644 index 5ce8183..0000000 --- a/po/it_IT.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "Installazione fallita" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "Notifica in corso..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "Elaborazione completata" - -msgid "IDS_BR_SK_RETRY" -msgstr "Riprova" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "Gestione download" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "Descrittore non valido" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "Nessun download" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "Completo" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "Impossibile aprire file" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "Scaricare?" - diff --git a/po/ja_JP.po b/po/ja_JP.po deleted file mode 100644 index 467255b..0000000 --- a/po/ja_JP.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "インストール失敗" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "通知中..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "処理が完了しました" - -msgid "IDS_BR_SK_RETRY" -msgstr "再接続" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "ダウンロードマネージャー" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "識別子が無効です" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr " ダウンロードなし" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "完了" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "ファイルを開くことができません" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "ダウンロードしますか?" - diff --git a/po/ko_KR.po b/po/ko_KR.po deleted file mode 100644 index d29d75b..0000000 --- a/po/ko_KR.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "설치하지 못하였습니다" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "알림 준비 중..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "완료되었습니다" - -msgid "IDS_BR_SK_RETRY" -msgstr "재시도" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "다운로드 관리자" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "설명이 바르지 않습니다" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "다운로드가 없습니다" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "완료" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "파일을 열 수 없습니다" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "다운로드할까요?" - diff --git a/po/nl_NL.po b/po/nl_NL.po deleted file mode 100644 index fb28efe..0000000 --- a/po/nl_NL.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "Installatie mislukt" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "Melden..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "Verwerken voltooid" - -msgid "IDS_BR_SK_RETRY" -msgstr "Opnieuw" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "Downloadmanager" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "Ongeldige descriptor" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "Geen downloads" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "Voltooid" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "Kan bestand niet openen" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "Downloaden?" - diff --git a/po/pt_PT.po b/po/pt_PT.po deleted file mode 100644 index 4ea32df..0000000 --- a/po/pt_PT.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "Instalação falhou" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "A notificar..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "Processamento concluído" - -msgid "IDS_BR_SK_RETRY" -msgstr "Repetir" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "Gestor de transferências" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "Descrição inválida" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "Nenhumas transferências" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "Concluída" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "Impossível abrir ficheiro" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "Transferir?" - diff --git a/po/ru_RU.po b/po/ru_RU.po deleted file mode 100644 index bbeb1dd..0000000 --- a/po/ru_RU.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "Сбой установки" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "Уведомление..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "Обработка завершена" - -msgid "IDS_BR_SK_RETRY" -msgstr "Повтор" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "Диспетчер загрузки" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "Неверный дескриптор" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "Нет загрузок" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "Завершено" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "Невозможно открыть файл" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "Загрузить?" - diff --git a/po/tr_TR.po b/po/tr_TR.po deleted file mode 100644 index 63f05e2..0000000 --- a/po/tr_TR.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "Yükleme başarısız" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "Bildiriliyor..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "İşlem tamamlandı" - -msgid "IDS_BR_SK_RETRY" -msgstr "Y.dene" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "İndirme Yöneticisi" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "Geçersiz Tanımlayıcı" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "İndirme yok" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "Tamamlandı" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "Dosyayı açamıyor" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "Yüklensin mi?" - diff --git a/po/update-po.sh.in b/po/update-po.sh.in deleted file mode 100644 index df45634..0000000 --- a/po/update-po.sh.in +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh - -PACKAGE=@@APPNAME@@ -SRCROOT=.. -POTFILES=POTFILES.in - -#ALL_LINGUAS= am az be ca cs da de el en_CA en_GB es et fi fr hr hu it ja ko lv mk ml ms nb ne nl pa pl pt pt_BR ru rw sk sl sr sr@Latn sv ta tr uk vi zh_CN zh_TW -ALL_LINGUAS="en_US en_GB ja ko zh_CN" - -XGETTEXT=/usr/bin/xgettext -MSGMERGE=/usr/bin/msgmerge - -echo -n "Make ${PACKAGE}.pot " -if [ ! -e $POTFILES ] ; then - echo "$POTFILES not found" - exit 1 -fi - -$XGETTEXT --default-domain=${PACKAGE} --directory=${SRCROOT} \ - --add-comments --keyword=_ --keyword=N_ --files-from=$POTFILES -if [ $? -ne 0 ]; then - echo "xgettext error" - exit 1 -fi - -if [ ! -f ${PACKAGE}.po ]; then - echo "No such file: ${PACKAGE}.po" - exit 1 -fi - -rm -f ${PACKAGE}.pot && mv ${PACKAGE}.po ${PACKAGE}.pot -echo "done" - -for LANG in $ALL_LINGUAS; do - echo "$LANG : " - - if [ ! -e $LANG.po ] ; then - sed 's/CHARSET/UTF-8/g' ${PACKAGE}.pot > ${LANG}.po - echo "${LANG}.po created" - else - if $MSGMERGE ${LANG}.po ${PACKAGE}.pot -o ${LANG}.new.po ; then - if cmp ${LANG}.po ${LANG}.new.po > /dev/null 2>&1; then - rm -f ${LANG}.new.po - else - if mv -f ${LANG}.new.po ${LANG}.po; then - echo "" - else - echo "msgmerge for $LANG.po failed: cannot move $LANG.new.po to $LANG.po" 1>&2 - rm -f ${LANG}.new.po - exit 1 - fi - fi - else - echo "msgmerge for $LANG failed!" - rm -f ${LANG}.new.po - fi - fi - echo "" -done - diff --git a/po/zh_CN.po b/po/zh_CN.po deleted file mode 100644 index 88675f3..0000000 --- a/po/zh_CN.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "安装失败" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "通知中..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "处理完成" - -msgid "IDS_BR_SK_RETRY" -msgstr "重试" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "下载管理器" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "描述符无效" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "无下载项" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "完成" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "无法打开文件" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "下载?" - diff --git a/po/zh_HK.po b/po/zh_HK.po deleted file mode 100644 index cb6fc1b..0000000 --- a/po/zh_HK.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "安裝失敗" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "正在通知..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "處理完成" - -msgid "IDS_BR_SK_RETRY" -msgstr "重試" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "下載管理員" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "無效描述項" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "無下載項目" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "完成" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "無法開啟檔案" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "要下載嗎?" - diff --git a/po/zh_TW.po b/po/zh_TW.po deleted file mode 100644 index 9a9c0f5..0000000 --- a/po/zh_TW.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "IDS_BR_POP_INSTALLATION_FAILED" -msgstr "安裝失敗" - -msgid "IDS_BR_BODY_NOTIFYING_ING" -msgstr "正在通知..." - -msgid "IDS_BR_BODY_PROCESSING_COMPLETED" -msgstr "處理完成" - -msgid "IDS_BR_SK_RETRY" -msgstr "重試" - -msgid "IDS_BR_HEADER_DOWNLOAD_MANAGER" -msgstr "下載管理員" - -msgid "IDS_BR_POP_INVALIDDESCRIPTOR" -msgstr "描述元無效" - -msgid "IDS_DL_BODY_NO_DOWNLOADS" -msgstr "無下載" - -msgid "IDS_EMAIL_BODY_COMPLETE" -msgstr "完成" - -msgid "IDS_BR_POP_UNABLE_TO_OPEN_FILE" -msgstr "無法開啟檔案" - -msgid "IDS_BR_POP_DOWNLOAD_Q" -msgstr "要下載嗎?" - diff --git a/res/images/U06_icon_excel.png b/res/images/Q02_Notification_Download_failed.png Binary files differindex 2ef1042..04ec4f0 100644 --- a/res/images/U06_icon_excel.png +++ b/res/images/Q02_Notification_Download_failed.png diff --git a/res/images/U06_icon_DRM.png b/res/images/U06_icon_DRM.png Binary files differdeleted file mode 100644 index adb9254..0000000 --- a/res/images/U06_icon_DRM.png +++ /dev/null diff --git a/res/images/U06_icon_Java.png b/res/images/U06_icon_Java.png Binary files differdeleted file mode 100644 index 317be17..0000000 --- a/res/images/U06_icon_Java.png +++ /dev/null diff --git a/res/images/U06_icon_Unknown.png b/res/images/U06_icon_Unknown.png Binary files differdeleted file mode 100644 index 024cfc1..0000000 --- a/res/images/U06_icon_Unknown.png +++ /dev/null diff --git a/res/images/U06_icon_html.png b/res/images/U06_icon_html.png Binary files differdeleted file mode 100644 index 72fed4a..0000000 --- a/res/images/U06_icon_html.png +++ /dev/null diff --git a/res/images/U06_icon_image.png b/res/images/U06_icon_image.png Binary files differdeleted file mode 100644 index 5b11f78..0000000 --- a/res/images/U06_icon_image.png +++ /dev/null diff --git a/res/images/U06_icon_music.png b/res/images/U06_icon_music.png Binary files differdeleted file mode 100644 index 12b6cb8..0000000 --- a/res/images/U06_icon_music.png +++ /dev/null diff --git a/res/images/U06_icon_pdf.png b/res/images/U06_icon_pdf.png Binary files differdeleted file mode 100644 index b99803e..0000000 --- a/res/images/U06_icon_pdf.png +++ /dev/null diff --git a/res/images/U06_icon_ppt.png b/res/images/U06_icon_ppt.png Binary files differdeleted file mode 100644 index 60341e3..0000000 --- a/res/images/U06_icon_ppt.png +++ /dev/null diff --git a/res/images/U06_icon_ringtone.png b/res/images/U06_icon_ringtone.png Binary files differdeleted file mode 100644 index 4ea1672..0000000 --- a/res/images/U06_icon_ringtone.png +++ /dev/null diff --git a/res/images/U06_icon_text.png b/res/images/U06_icon_text.png Binary files differdeleted file mode 100644 index b156b91..0000000 --- a/res/images/U06_icon_text.png +++ /dev/null diff --git a/res/images/U06_icon_video.png b/res/images/U06_icon_video.png Binary files differdeleted file mode 100644 index 0ee8587..0000000 --- a/res/images/U06_icon_video.png +++ /dev/null diff --git a/res/images/U06_icon_word.png b/res/images/U06_icon_word.png Binary files differdeleted file mode 100644 index 96d3e50..0000000 --- a/res/images/U06_icon_word.png +++ /dev/null diff --git a/res/org.tizen.download-provider.desktop.in b/res/org.tizen.download-provider.desktop.in deleted file mode 100644 index e94bc6c..0000000 --- a/res/org.tizen.download-provider.desktop.in +++ /dev/null @@ -1,12 +0,0 @@ -Name=Download Provider -Name[en_US]=Download Provider -Exec=/opt/apps/org.tizen.download-provider/bin/download-provider -Icon=icon_default.png -Type=Application -Comment=Download Provider -nodisplay=true -X-TIZEN-TaskManage=false -X-TIZEN-Multiple=false -X-TIZEN-Removable=false -X-TIZEN-SVC= http://tizen.org/appsvc/operation/download|http|NULL;http://tizen.org/appsvc/operation/download|NULL|NULL -Version=0.1.0-0 diff --git a/res/org.tizen.download-provider.png b/res/org.tizen.download-provider.png Binary files differdeleted file mode 100644 index bffa6bb..0000000 --- a/res/org.tizen.download-provider.png +++ /dev/null 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/src/agent/CMakeLists.txt b/src/agent/CMakeLists.txt new file mode 100644 index 0000000..4310a58 --- /dev/null +++ b/src/agent/CMakeLists.txt @@ -0,0 +1,92 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(downloadagent C) + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Debug") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(VERSION "0.0.1") +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") + +#DA Engine Include Directory +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include) + +INCLUDE(FindPkgConfig) +pkg_check_modules(subpkgs REQUIRED + drm-client + drm-trusted + libsoup-2.4 + xdgmime + vconf + capi-network-connection + glib-2.0 + dlog +) + +FOREACH(flag ${subpkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g -Wall") +SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed -Wl,--hash-style=both") + +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-D_TARGET") + SET(CMAKE_C_FLAGS_RELEASE "-mabi=aapcs-linux -msoft-float -O2") +ENDIF("${ARCH}" MATCHES "^arm.*") + +ADD_DEFINITIONS("-D_EFL_PLATFORM") +#allow to install widget, deb pkg and apk for testing +ADD_DEFINITIONS("-DDA_DEBUG_USING_DLOG") +#This should be removed when release a target +ADD_DEFINITIONS("-D_SAMSUNG_MIME_POLICY") + +############################################################################# +#+++++++++++++++++++++++++DA ENGINE+++++++++++++++++++++++++++++++++++++++++++ +############################################################################# + +SET(SRCS_PATH ".") +SET(SRCS_DA_ENGINE + ${SRCS_PATH}/download-agent-debug.c + ${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-util.c + ${SRCS_PATH}/download-agent-http-queue.c + ${SRCS_PATH}/download-agent-http-misc.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-utils.c + ${SRCS_PATH}/download-agent-utils-dl-req-id-history.c + ${SRCS_PATH}/download-agent-basic.c + ${SRCS_PATH}/download-agent-installation.c + ${SRCS_PATH}/download-agent-file.c + ${SRCS_PATH}/download-agent-plugin-drm.c + ${SRCS_PATH}/download-agent-plugin-libsoup.c + ${SRCS_PATH}/download-agent-plugin-conf.c + ${SRCS_PATH}/download-agent-plugin-install.c + ${SRCS_PATH}/download-agent-mime-util.c +) + +SET(HEADERS + include/download-agent-defs.h + include/download-agent-interface.h +) + +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS_DA_ENGINE}) +#TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${subpkgs_LDFLAGS} "-ldl") +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${subpkgs_LDFLAGS}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION 0.0.1) + +############################################################################# +#+++++++++++++++++++++++++INSTALLATION++++++++++++++++++++++++++++++++++++++++ +############################################################################# + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib COMPONENT RuntimeLibraries) + diff --git a/src/agent/download-agent-basic.c b/src/agent/download-agent-basic.c new file mode 100644 index 0000000..db40f45 --- /dev/null +++ b/src/agent/download-agent-basic.c @@ -0,0 +1,371 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-basic.c + * @brief functions for basic (http) download + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + ***/ + +#include <stdlib.h> + +#include "download-agent-basic.h" +#include "download-agent-debug.h" +#include "download-agent-client-mgr.h" +#include "download-agent-utils.h" +#include "download-agent-http-mgr.h" +#include "download-agent-http-misc.h" +#include "download-agent-dl-mgr.h" +#include "download-agent-installation.h" +#include "download-agent-pthread.h" + +static void* __thread_start_download(void* data); +void __thread_clean_up_handler_for_start_download(void *arg); + +static da_result_t __make_source_info_basic_download( + stage_info *stage, + client_input_t *client_input); +static da_result_t __download_content(stage_info *stage); + +da_result_t start_download(const char *url , da_handle_t *dl_req_id) +{ + DA_LOG_FUNC_START(Default); + return start_download_with_extension(url, dl_req_id, NULL); +} + +da_result_t start_download_with_extension( + const char *url, + da_handle_t *dl_req_id, + extension_data_t *extension_data) +{ + da_result_t ret = DA_RESULT_OK; + int download_id = 0; + const char **request_header = DA_NULL; + const char *install_path = DA_NULL; + const char *file_name = DA_NULL; + int request_header_count = 0; + void *user_data = DA_NULL; + client_input_t *client_input = DA_NULL; + client_input_basic_t *client_input_basic = DA_NULL; + download_thread_input *thread_info = DA_NULL; + + DA_LOG_FUNC_START(Default); + + if (extension_data) { + request_header = extension_data->request_header; + if (extension_data->request_header_count) + request_header_count = *(extension_data->request_header_count); + install_path = extension_data->install_path; + file_name = extension_data->file_name; + user_data = extension_data->user_data; + } + + ret = get_available_download_id(&download_id); + if (DA_RESULT_OK != ret) + return ret; + + *dl_req_id = GET_DL_REQ_ID(download_id); + + client_input = (client_input_t *)calloc(1, sizeof(client_input_t)); + if (!client_input) { + DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } else { + client_input->user_data = user_data; + if (install_path) { + int install_path_len = strlen(install_path); + if (install_path[install_path_len-1] == '/') + install_path_len--; + + client_input->install_path = (char *)calloc(1, install_path_len+1); + if (client_input->install_path) + snprintf(client_input->install_path, install_path_len+1, install_path); + } + + if (file_name) { + client_input->file_name = (char *)calloc(1, strlen(file_name)+1); + if (client_input->file_name) + strncpy(client_input->file_name, file_name, strlen(file_name)); + } + + client_input_basic = &(client_input->client_input_basic); + client_input_basic->req_url = (char *)calloc(1, strlen(url)+1); + if(DA_NULL == client_input_basic->req_url) { + DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + strncpy(client_input_basic->req_url ,url,strlen(url)); + + if (request_header_count > 0) { + int i = 0; + client_input_basic->user_request_header = + (char **)calloc(1, sizeof(char *)*request_header_count); + if(DA_NULL == client_input_basic->user_request_header) { + DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + for (i = 0; i < request_header_count; i++) + { + client_input_basic->user_request_header[i] = strdup(request_header[i]); + } + client_input_basic->user_request_header_count = request_header_count; + } + } + + thread_info = (download_thread_input *)calloc(1, sizeof(download_thread_input)); + if(!thread_info) { + DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } else { + thread_info->download_id = download_id; + thread_info->client_input = client_input; + } + + if(pthread_create(&GET_DL_THREAD_ID(download_id), DA_NULL, __thread_start_download, thread_info) < 0) { + DA_LOG_ERR(Thread, "making thread failed.."); + ret = DA_ERR_FAIL_TO_CREATE_THREAD; + } else { + if (GET_DL_THREAD_ID(download_id) < 1) { + DA_LOG_ERR(Thread, "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. + goto ERR; + } + } + DA_LOG_CRITICAL(Thread, "download thread create download_id[%d] thread id[%lu]", + download_id,GET_DL_THREAD_ID(download_id)); + +ERR: + if (DA_RESULT_OK != ret) { + if (client_input) { + clean_up_client_input_info(client_input); + free(client_input); + client_input = DA_NULL; + } + if (thread_info) { + free(thread_info); + thread_info = DA_NULL; + } + destroy_download_info(download_id); + } + return ret; +} + +da_result_t __make_source_info_basic_download( + stage_info *stage, + client_input_t *client_input) +{ + da_result_t ret = DA_RESULT_OK; + client_input_basic_t *client_input_basic = DA_NULL; + source_info_t *source_info = DA_NULL; + source_info_basic_t *source_info_basic = DA_NULL; + + DA_LOG_FUNC_START(Default); + + if (!stage) { + DA_LOG_ERR(Default, "no stage; DA_ERR_INVALID_ARGUMENT"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + client_input_basic = &(client_input->client_input_basic); + if (DA_NULL == client_input_basic->req_url) { + DA_LOG_ERR(Default, "DA_ERR_INVALID_URL"); + ret = DA_ERR_INVALID_URL; + goto ERR; + } + + source_info_basic = (source_info_basic_t*)calloc(1, sizeof(source_info_basic_t)); + if (DA_NULL == source_info_basic) { + DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + + source_info_basic->url = client_input_basic->req_url; + client_input_basic->req_url = DA_NULL; + + if (client_input_basic->user_request_header) { + source_info_basic->user_request_header = + client_input_basic->user_request_header; + source_info_basic->user_request_header_count = + client_input_basic->user_request_header_count; + client_input_basic->user_request_header = DA_NULL; + client_input_basic->user_request_header_count = 0; + } + + source_info = GET_STAGE_SOURCE_INFO(stage); + memset(source_info, 0, sizeof(source_info_t)); + + source_info->source_info_type.source_info_basic = source_info_basic; + + DA_LOG(Default, "BASIC HTTP STARTED: URL=%s", + source_info->source_info_type.source_info_basic->url); +ERR: + return ret; +} + +void __thread_clean_up_handler_for_start_download(void *arg) +{ + DA_LOG_CRITICAL(Default, "cleanup for thread id = %d", pthread_self()); +} + +static void *__thread_start_download(void *data) +{ + da_result_t ret = DA_RESULT_OK; + download_thread_input *thread_info = DA_NULL; + client_input_t *client_input = DA_NULL; + stage_info *stage = DA_NULL; + int download_id = DA_INVALID_ID; + + DA_LOG_FUNC_START(Thread); + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, DA_NULL); + + thread_info = (download_thread_input*)data; + if (DA_NULL == thread_info) { + DA_LOG_ERR(Thread, "thread_info is NULL.."); + ret = DA_ERR_INVALID_ARGUMENT; + return DA_NULL; + } else { + download_id = thread_info->download_id; + client_input = thread_info->client_input; + + if(thread_info) { + free(thread_info); + thread_info = DA_NULL; + } + } + + pthread_cleanup_push(__thread_clean_up_handler_for_start_download, (void *)NULL); + + if (DA_FALSE == is_valid_dl_ID(download_id)) { + ret = DA_ERR_INVALID_ARGUMENT; + DA_LOG_ERR(Default, "Invalid Download ID"); + goto ERR; + } + + if (!client_input) { + ret = DA_ERR_INVALID_ARGUMENT; + DA_LOG_ERR(Default, "Invalid client_input"); + goto ERR; + } + + stage = Add_new_download_stage(download_id); + if (!stage) { + ret = DA_ERR_FAIL_TO_MEMALLOC; + DA_LOG_ERR(Default, "STAGE ADDITION FAIL!"); + goto ERR; + } + DA_LOG(Default, "new added Stage : %p", stage); + + GET_DL_USER_DATA(download_id) = client_input->user_data; + GET_DL_USER_INSTALL_PATH(download_id) = client_input->install_path; + client_input->install_path = DA_NULL; + GET_DL_USER_FILE_NAME(download_id) = client_input->file_name; + client_input->file_name = DA_NULL; + + ret = __make_source_info_basic_download(stage, client_input); + /* to save memory */ + if (client_input) { + clean_up_client_input_info(client_input); + free(client_input); + client_input = DA_NULL; + } + + if (ret == DA_RESULT_OK) + ret = __download_content(stage); + +ERR: + if (client_input) { + clean_up_client_input_info(client_input); + free(client_input); + client_input = DA_NULL; + } + + if (DA_RESULT_OK == ret) { + DA_LOG_CRITICAL(Default, "Whole download flow is finished."); + send_user_noti_and_finish_download_flow(download_id); + } else { + DA_LOG_CRITICAL(Default, "DA_STATE_FAILED -Return = %d", ret); + send_client_da_state(download_id, DA_STATE_FAILED, ret); + destroy_download_info(download_id); + } + + pthread_cleanup_pop(0); + DA_LOG_CRITICAL(Thread, "=====thread_start_download - EXIT====="); + pthread_exit((void *)NULL); + return DA_NULL; +} + +da_result_t __download_content(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + download_state_t download_state = 0; + da_bool_t isDownloadComplete = DA_FALSE; + int download_id = DA_INVALID_ID; + + DA_LOG_FUNC_START(Default); + + download_id = GET_STAGE_DL_ID(stage); + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD, stage); + + do { + stage = GET_DL_CURRENT_STAGE(download_id); + _da_thread_mutex_lock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); + download_state = GET_DL_STATE_ON_STAGE(stage); + DA_LOG(Default, "download_state to - [%d] ", download_state); + _da_thread_mutex_unlock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); + + switch(download_state) { + case DOWNLOAD_STATE_NEW_DOWNLOAD: + ret = requesting_download(stage); + + _da_thread_mutex_lock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); + download_state = GET_DL_STATE_ON_STAGE(stage); + _da_thread_mutex_unlock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); + + if (download_state == DOWNLOAD_STATE_CANCELED) { + break; + } else { + if (DA_RESULT_OK == ret) { + ret = handle_after_download(stage); + } + } + break; + case DOWNLOAD_STATE_READY_TO_INSTAL: + send_client_da_state(download_id, DA_STATE_DOWNLOAD_COMPLETE, DA_RESULT_OK); + ret = process_install(stage); + if (DA_RESULT_OK == ret) { + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_FINISH,stage); + } + break; + default: + isDownloadComplete = DA_TRUE; + break; + } + }while ((DA_RESULT_OK == ret) && (DA_FALSE == isDownloadComplete)); + + return ret; +} diff --git a/src/agent/download-agent-client-mgr.c b/src/agent/download-agent-client-mgr.c new file mode 100644 index 0000000..c9c04b3 --- /dev/null +++ b/src/agent/download-agent-client-mgr.c @@ -0,0 +1,619 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-client-mgr.c + * @brief client manager module for notifying download ststus information + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + ***/ + +#include <unistd.h> + +#include "download-agent-client-mgr.h" +#include "download-agent-debug.h" +#include "download-agent-utils.h" +#include "download-agent-file.h" + +#define IS_CLIENT_Q_HAVING_DATA(QUEUE) (QUEUE->having_data) + +static client_app_mgr_t client_app_mgr; + +static da_result_t __launch_client_thread(void); +static void *__thread_for_client_noti(void *data); +void __thread_clean_up_handler_for_client_thread(void *arg); +static void __pop_client_noti(client_noti_t **out_client_noti); + +void __client_q_goto_sleep_without_lock(void); +void __client_q_wake_up_without_lock(void); +void destroy_client_noti(client_noti_t *client_noti); + +da_result_t init_client_app_mgr() +{ + DA_LOG_FUNC_START(ClientNoti); + + if(client_app_mgr.is_init) + return DA_RESULT_OK; + + client_app_mgr.is_init = DA_TRUE; + client_app_mgr.client_app_info.is_using = DA_FALSE; + client_app_mgr.client_app_info.is_manual_download = DA_FALSE; + client_app_mgr.client_app_info.client_user_agent = DA_NULL; + client_app_mgr.is_thread_init = DA_FALSE; + + return DA_RESULT_OK; +} + +da_bool_t is_client_app_mgr_init(void) +{ + return client_app_mgr.is_init; +} + +da_bool_t is_client_app_mgr_manual_download(void) +{ + return client_app_mgr.is_manual_download; +} + +da_result_t reg_client_app( + da_client_cb_t *da_client_callback, + da_download_managing_method download_method + ) +{ + da_result_t ret = DA_RESULT_OK; + client_queue_t *queue = DA_NULL; + client_noti_t *client_noti = DA_NULL; + + DA_LOG_FUNC_START(ClientNoti); + + if (client_app_mgr.client_app_info.is_using) + return DA_ERR_CLIENT_IS_ALREADY_REGISTERED; + + client_app_mgr.client_app_info.is_using = DA_TRUE; + if (download_method == DA_DOWNLOAD_MANAGING_METHOD_MANUAL) + client_app_mgr.client_app_info.is_manual_download = DA_TRUE; + else + client_app_mgr.client_app_info.is_manual_download = DA_FALSE; + + memset(&(client_app_mgr.client_app_info.client_callback), + 0, sizeof(da_client_cb_t)); + memcpy(&(client_app_mgr.client_app_info.client_callback), + da_client_callback, sizeof(da_client_cb_t)); + + _da_thread_mutex_init(&(client_app_mgr.mutex_client_mgr), DA_NULL); + + /* If some noti is existed at queue, delete all */ + do { + __pop_client_noti(&client_noti); + destroy_client_noti(client_noti); + } while(client_noti != DA_NULL); + + queue = &(client_app_mgr.client_queue); + DA_LOG_VERBOSE(ClientNoti, "client queue = %p", queue); + _da_thread_mutex_init(&(queue->mutex_client_queue), DA_NULL); + _da_thread_cond_init(&(queue->cond_client_queue), DA_NULL); + + ret = __launch_client_thread(); + + return ret; +} + +da_result_t dereg_client_app(void) +{ + client_noti_t *client_noti = DA_NULL; + + DA_LOG_FUNC_START(ClientNoti); + + client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); + if (!client_noti) { + DA_LOG_ERR(ClientNoti, "calloc fail"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + + client_noti->download_id = DA_INVALID_ID; + client_noti->noti_type = Q_CLIENT_NOTI_TYPE_TERMINATE; + client_noti->next = DA_NULL; + + _da_thread_mutex_lock(&(client_app_mgr.mutex_client_mgr)); + if (client_app_mgr.is_thread_init != DA_TRUE) { + DA_LOG_CRITICAL(ClientNoti, "try to cancel client mgr thread id[%lu]", client_app_mgr.thread_id); + if (pthread_cancel(client_app_mgr.thread_id) < 0) { + DA_LOG_ERR(ClientNoti, "cancel thread is failed!!!"); + } + } else { + void *t_return = NULL; + DA_LOG_VERBOSE(ClientNoti, "pushing Q_CLIENT_NOTI_TYPE_TERMINATE"); + push_client_noti(client_noti); + DA_LOG_CRITICAL(Thread, "===try to join client mgr thread id[%lu]===", client_app_mgr.thread_id); + if (pthread_join(client_app_mgr.thread_id, &t_return) < 0) { + DA_LOG_ERR(Thread, "join client thread is failed!!!"); + } + DA_LOG_CRITICAL(Thread, "===thread join return[%d]===", (char*)t_return); + } + _da_thread_mutex_unlock(&(client_app_mgr.mutex_client_mgr)); + + /* ToDo: This clean up should be done at the end of client_thread. */ + client_app_mgr.client_app_info.is_using= DA_FALSE; + client_app_mgr.client_app_info.is_manual_download = DA_FALSE; + if(client_app_mgr.client_app_info.client_user_agent) { + free(client_app_mgr.client_app_info.client_user_agent); + client_app_mgr.client_app_info.client_user_agent = DA_NULL; + } + _da_thread_mutex_lock(&(client_app_mgr.mutex_client_mgr)); + client_app_mgr.is_thread_init = DA_FALSE; + _da_thread_mutex_unlock(&(client_app_mgr.mutex_client_mgr)); + _da_thread_mutex_destroy(&(client_app_mgr.mutex_client_mgr)); + return DA_RESULT_OK; +} + +da_result_t send_client_da_state (int download_id, da_state state, int err) +{ + client_noti_t *client_noti = DA_NULL; + user_notify_info_t *send_state_info = DA_NULL; + da_state cur_da_state; + + DA_LOG_FUNC_START(ClientNoti); + + DA_LOG_VERBOSE(ClientNoti, "da_state[%s], download_id[%d]", print_dl_state(state), download_id); + + if (!is_valid_dl_ID(download_id)) { + DA_LOG_ERR(ClientNoti, "Download ID is not valid"); + /* Returning DA_RESULT_OK if download_id is not valid, + * because sending da_state should not effect to download flow. */ + return DA_RESULT_OK; + } + + if (state_watcher_need_redirect_Q(download_id)) { + state_watcher_redirect_state(download_id, state, err); + return DA_RESULT_OK; + } + + cur_da_state = GET_DL_DA_STATE(download_id); + + if ((DA_STATE_SUSPENDED != state) && (cur_da_state == state)) { + DA_LOG(ClientNoti, "inserting da_state is same with current da_state! Not inserting! inserting: %d, cur : %d", state, cur_da_state); + return DA_RESULT_OK; + } + + GET_DL_DA_STATE(download_id) = state; + DA_LOG_VERBOSE(ClientNoti, "change da_state to %d", state); + + client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); + if (!client_noti) { + DA_LOG_ERR(ClientNoti, "calloc fail"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + + client_noti->download_id = download_id; + client_noti->user_data = GET_DL_USER_DATA(download_id); + client_noti->noti_type = Q_CLIENT_NOTI_TYPE_SEND_STATE; + client_noti->next = DA_NULL; + + send_state_info = (user_notify_info_t *)&(client_noti->type.da_state_info); + send_state_info->da_dl_req_id = GET_DL_REQ_ID(download_id); + send_state_info->state = state; + send_state_info->err = err; + + DA_LOG(ClientNoti, "pushing da_state=%d, download_id=%d, err=%d, dl_req_id=%d", + state, download_id, err, GET_DL_REQ_ID(download_id)); + + push_client_noti(client_noti); + + return DA_RESULT_OK; +} + +da_result_t send_client_update_downloading_info ( + int download_id, + int dl_req_id, + unsigned long int total_received_size, + char *saved_path + ) +{ + client_noti_t *client_noti = DA_NULL; + user_downloading_info_t *downloading_info = DA_NULL; + + DA_LOG_FUNC_START(ClientNoti); + + if (!is_valid_dl_ID(download_id)) { + DA_LOG_ERR(ClientNoti, "Download ID is not valid"); + return DA_ERR_INVALID_DL_REQ_ID; + } + + client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); + if (!client_noti) { + DA_LOG_ERR(ClientNoti, "calloc fail"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + + client_noti->download_id = download_id; + client_noti->user_data = GET_DL_USER_DATA(download_id); + client_noti->noti_type = Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO; + client_noti->next = DA_NULL; + + downloading_info = (user_downloading_info_t *)&(client_noti->type.update_downloading_info); + downloading_info->da_dl_req_id = dl_req_id; + downloading_info->total_received_size = total_received_size; + + /* These strings MUST be copied to detach __thread_for_client_noti from download_info */ + if (saved_path) + downloading_info->saved_path = strdup(saved_path); + DA_LOG(ClientNoti, "pushing received_size=%lu, download_id=%d, dl_req_id=%d", + total_received_size, download_id, dl_req_id); + + push_client_noti(client_noti); + + return DA_RESULT_OK; +} + +da_result_t send_client_update_dl_info ( + int download_id, + int dl_req_id, + char *file_type, + unsigned long int file_size, + char *tmp_saved_path, + char *http_response_header, + char *http_chunked_data + ) +{ + client_noti_t *client_noti = DA_NULL; + user_download_info_t *update_dl_info = DA_NULL; + + DA_LOG_FUNC_START(ClientNoti); + + if (!is_valid_dl_ID(download_id)) { + DA_LOG_ERR(ClientNoti, "Download ID is not valid"); + return DA_ERR_INVALID_DL_REQ_ID; + } + + client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); + if (!client_noti) { + DA_LOG_ERR(ClientNoti, "calloc fail"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + + client_noti->download_id = download_id; + client_noti->user_data = GET_DL_USER_DATA(download_id); + client_noti->noti_type = Q_CLIENT_NOTI_TYPE_UPDATE_DL_INFO; + client_noti->next = DA_NULL; + + update_dl_info = (user_download_info_t *)&(client_noti->type.update_dl_info); + update_dl_info->da_dl_req_id = dl_req_id; + update_dl_info->file_size = file_size; + + /* These strings MUST be copied to detach __thread_for_client_noti from download_info */ + if (file_type) + update_dl_info->file_type = strdup(file_type); + + if (tmp_saved_path) + update_dl_info->tmp_saved_path = strdup(tmp_saved_path); + + if (http_response_header) { + update_dl_info->http_response_header = strdup(http_response_header); + } + if (http_chunked_data) + update_dl_info->http_chunked_data = calloc (1, file_size); + if (update_dl_info->http_chunked_data) + memcpy(update_dl_info->http_chunked_data, http_chunked_data, + file_size); + DA_LOG(ClientNoti, "pushing file_size=%lu, download_id=%d, dl_req_id=%d", + file_size, download_id, dl_req_id); + + push_client_noti(client_noti); + + return DA_RESULT_OK; +} + +da_result_t __launch_client_thread(void) +{ + pthread_t thread_id = DA_NULL; + + DA_LOG_FUNC_START(Thread); + + if (pthread_create(&thread_id,DA_NULL,__thread_for_client_noti,DA_NULL) < 0) { + DA_LOG_ERR(Thread, "making thread failed.."); + return DA_ERR_FAIL_TO_CREATE_THREAD; + } + DA_LOG(Thread, "client mgr thread id[%d]", thread_id); + client_app_mgr.thread_id = thread_id; + return DA_RESULT_OK; +} + +void destroy_client_noti(client_noti_t *client_noti) +{ + if (client_noti) { + if (client_noti->noti_type == Q_CLIENT_NOTI_TYPE_UPDATE_DL_INFO) { + user_download_info_t *update_dl_info = DA_NULL; + update_dl_info = (user_download_info_t*)&(client_noti->type.update_dl_info); + if (update_dl_info->file_type) { + free(update_dl_info->file_type); + update_dl_info->file_type = DA_NULL; + } + if (update_dl_info->tmp_saved_path) { + free(update_dl_info->tmp_saved_path); + update_dl_info->tmp_saved_path = DA_NULL; + } + if (update_dl_info->http_response_header) { + free(update_dl_info->http_response_header); + update_dl_info->http_response_header = DA_NULL; + } + if (update_dl_info->http_chunked_data) { + free(update_dl_info->http_chunked_data); + update_dl_info->http_chunked_data = DA_NULL; + } + } else if (client_noti->noti_type == + Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO) { + user_downloading_info_t *downloading_info = DA_NULL; + downloading_info = (user_downloading_info_t*)&(client_noti->type.update_downloading_info); + if (downloading_info->saved_path) { + free(downloading_info->saved_path); + downloading_info->saved_path = DA_NULL; + } + } + free(client_noti); + } +} + + +void push_client_noti(client_noti_t *client_noti) +{ + client_queue_t *queue = DA_NULL; + client_noti_t *head = DA_NULL; + client_noti_t *pre = DA_NULL; + client_noti_t *cur = DA_NULL; + + /* DA_LOG_FUNC_START(ClientNoti); */ + + if(!is_this_client_available()) { + DA_LOG_ERR(ClientNoti, "invalid client"); + return; + } + queue = &(client_app_mgr.client_queue); + _da_thread_mutex_lock (&(queue->mutex_client_queue)); + + head = queue->client_q_head; + if (!head) { + queue->client_q_head = client_noti; + } else { + cur = head; + while (cur->next) { + pre = cur; + cur = pre->next; + } + + if (DA_TRUE == is_this_client_manual_download_type()) { + cur->next = client_noti; + } else if (client_noti->noti_type == Q_CLIENT_NOTI_TYPE_SEND_STATE) { + cur->next = client_noti; + } else { + if (cur->noti_type == Q_CLIENT_NOTI_TYPE_SEND_STATE) { + cur->next = client_noti; + } else if (cur->noti_type == Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO) { + /* For UI performance. If the update noti info is existed at queue, + replace it with new update noti info */ + if (cur->download_id == client_noti->download_id) { + /* DA_LOG(ClientNoti, "exchange queue's tail and pushing item"); */ + if (pre == DA_NULL) + queue->client_q_head = client_noti; + else + pre->next = client_noti; + destroy_client_noti(cur); + } else { + cur->next = client_noti; + } + } + } + } + + queue->having_data = DA_TRUE; + + __client_q_wake_up_without_lock(); + + _da_thread_mutex_unlock (&(queue->mutex_client_queue)); +} + +void __pop_client_noti(client_noti_t **out_client_noti) +{ + client_queue_t *queue = DA_NULL; + + /* DA_LOG_FUNC_START(ClientNoti); */ + + queue = &(client_app_mgr.client_queue); + + _da_thread_mutex_lock (&(queue->mutex_client_queue)); + + if (queue->client_q_head) { + *out_client_noti = queue->client_q_head; + queue->client_q_head = queue->client_q_head->next; + } else { + *out_client_noti = DA_NULL; + } + + if (queue->client_q_head == DA_NULL) { + queue->having_data = DA_FALSE; + } + + _da_thread_mutex_unlock (&(queue->mutex_client_queue)); +} + +void __client_q_goto_sleep_without_lock(void) +{ + client_queue_t *queue = DA_NULL; + + /* DA_LOG_FUNC_START(ClientNoti); */ + + queue = &(client_app_mgr.client_queue); + _da_thread_cond_wait(&(queue->cond_client_queue), &(queue->mutex_client_queue)); +} + +void __client_q_wake_up_without_lock(void) +{ + client_queue_t *queue = DA_NULL; + + /* DA_LOG_FUNC_START(ClientNoti); */ + + queue = &(client_app_mgr.client_queue); + _da_thread_cond_signal(&(queue->cond_client_queue)); +} + +void __thread_clean_up_handler_for_client_thread(void *arg) +{ + DA_LOG_CRITICAL(Thread, "cleanup for thread id = %d", pthread_self()); +} + +static void *__thread_for_client_noti(void *data) +{ + da_result_t ret = DA_RESULT_OK; + da_bool_t need_wait = DA_TRUE; + client_queue_t *queue = DA_NULL; + client_noti_t *client_noti = DA_NULL; + + DA_LOG_FUNC_START(Thread); + + _da_thread_mutex_lock(&(client_app_mgr.mutex_client_mgr)); + client_app_mgr.is_thread_init = DA_TRUE; + _da_thread_mutex_unlock(&(client_app_mgr.mutex_client_mgr)); + + queue = &(client_app_mgr.client_queue); + DA_LOG(ClientNoti, "client queue = %p", queue); + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, DA_NULL); + pthread_cleanup_push(__thread_clean_up_handler_for_client_thread, (void *)DA_NULL); + + do { + _da_thread_mutex_lock(&(queue->mutex_client_queue)); + if (DA_FALSE == IS_CLIENT_Q_HAVING_DATA(queue)) { + DA_LOG(Thread, "Sleep @ thread_for_client_noti!"); + __client_q_goto_sleep_without_lock(); + DA_LOG(Thread, "Woke up @ thread_for_client_noti"); + } + _da_thread_mutex_unlock(&(queue->mutex_client_queue)); + + do { + __pop_client_noti(&client_noti); + if (client_noti == DA_NULL) { + DA_LOG_ERR(ClientNoti, "There is no data on client queue!"); + ret = DA_ERR_INVALID_STATE; + need_wait = DA_FALSE; + } else { + switch (client_noti->noti_type) { + case Q_CLIENT_NOTI_TYPE_UPDATE_DL_INFO: + { + user_download_info_t *update_dl_info = DA_NULL;; + update_dl_info = (user_download_info_t*)(&(client_noti->type.update_dl_info)); + if (client_app_mgr.client_app_info.client_callback.update_dl_info_cb) { + client_app_mgr.client_app_info.client_callback.update_dl_info_cb(update_dl_info, client_noti->user_data); + DA_LOG(ClientNoti, "Update download info for download_id=%d, dl_req_id=%d, received size=%lu- DONE", + client_noti->download_id, + update_dl_info->da_dl_req_id, + update_dl_info->file_size + ); + } + } + break; + case Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO: + { + user_downloading_info_t *downloading_info = DA_NULL;; + downloading_info = (user_downloading_info_t*)(&(client_noti->type.update_downloading_info)); + if (client_app_mgr.client_app_info.client_callback.update_progress_info_cb) { + client_app_mgr.client_app_info.client_callback.update_progress_info_cb(downloading_info, client_noti->user_data); + DA_LOG(ClientNoti, "Update downloading info for download_id=%d, dl_req_id=%d, received size=%lu - DONE", + client_noti->download_id, + downloading_info->da_dl_req_id, + downloading_info->total_received_size); + } + } + break; + case Q_CLIENT_NOTI_TYPE_SEND_STATE: + { + user_notify_info_t *da_state_info = DA_NULL; + da_state_info = (user_notify_info_t *)(&(client_noti->type.da_state_info)); + + if (client_app_mgr.client_app_info.client_callback.user_noti_cb) { + DA_LOG(ClientNoti, "User Noti info for download_id=%d, dl_req_id=%d, da_state=%d, err=%d", + client_noti->download_id, + da_state_info->da_dl_req_id, da_state_info->state, + da_state_info->err); + client_app_mgr.client_app_info.client_callback.user_noti_cb(da_state_info, client_noti->user_data); + DA_LOG(ClientNoti, "User Noti info for download_id=%d, dl_req_id=%d, da_state=%d, err=%d - DONE", + client_noti->download_id, + da_state_info->da_dl_req_id, + da_state_info->state, da_state_info->err); + } + } + break; + case Q_CLIENT_NOTI_TYPE_TERMINATE: + DA_LOG_CRITICAL(ClientNoti, "Q_CLIENT_NOTI_TYPE_TERMINATE"); + need_wait = DA_FALSE; + break; + } + destroy_client_noti(client_noti); + } + + if(DA_TRUE == need_wait) { + _da_thread_mutex_lock(&(queue->mutex_client_queue)); + if (DA_FALSE == IS_CLIENT_Q_HAVING_DATA(queue)) { + _da_thread_mutex_unlock (&(queue->mutex_client_queue)); + break; + } else { + _da_thread_mutex_unlock (&(queue->mutex_client_queue)); + } + } else { + break; + } + } while (1); + } while (DA_TRUE == need_wait); + + _da_thread_mutex_destroy(&(queue->mutex_client_queue)); + _da_thread_cond_destroy(&(queue->cond_client_queue)); + + pthread_cleanup_pop(0); + DA_LOG_CRITICAL(Thread, "=====thread_for_client_noti- EXIT====="); + pthread_exit((void *)NULL); + return DA_NULL; +} + +da_bool_t is_this_client_available(void) +{ + return client_app_mgr.client_app_info.is_using; +} + +da_bool_t is_this_client_manual_download_type(void) +{ + return client_app_mgr.client_app_info.is_manual_download; +} + +da_result_t get_client_download_path(char **out_path) +{ + if (!out_path) { + DA_LOG_ERR(ClientNoti, "DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + /* change the directory policy. it doesn't clean the temp direcoty when deinitializing */ + *out_path = strdup(DA_DEFAULT_TMP_FILE_DIR_PATH); + DA_LOG_VERBOSE(ClientNoti, "client download path = [%s]", *out_path); + + return DA_RESULT_OK; +} + +char *get_client_user_agent_string(void) +{ + if (!client_app_mgr.is_init) + return DA_NULL; + + return client_app_mgr.client_app_info.client_user_agent; +} diff --git a/src/agent/download-agent-debug.c b/src/agent/download-agent-debug.c new file mode 100644 index 0000000..501e0ac --- /dev/null +++ b/src/agent/download-agent-debug.c @@ -0,0 +1,216 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-debug.c + * @brief for log system on Download Agent + * @author Keunsoon Lee (keunsoon.lee@samsung.com) + * @author Jungki Kwak (jungki.kwak@samsung.com) + ***/ + +#include <stdlib.h> +#include <string.h> + +#include "download-agent-debug.h" +#include "download-agent-utils.h" + +#define STRING_IT(x) #x +#define TURN_ON_LOG(channel) (DALogBitMap |= (0x1<<(channel))) + +int DALogBitMap; + +char *__get_log_env(void); +char **__parsing_log_env(char *in_log_env); +char *__copying_str(char *source, int length); +char *__get_channel_name_from_enum(da_log_channel channel_enum); + +da_result_t init_log_mgr(void) { + da_result_t ret = DA_RESULT_OK; + static da_bool_t did_log_mgr_init = DA_FALSE; + char *log_env = DA_NULL; + char **parsed_log_env = DA_NULL; + char **cur_parsed_log_env = DA_NULL; + int i = 0; + + if (did_log_mgr_init) + return ret; + + did_log_mgr_init = DA_TRUE; + + log_env = __get_log_env(); + if (!log_env) { + /* If no environment values are found, do behave like all logs are turned on except for Soup log */ + DALogBitMap = ~(0x1 << Soup); + return ret; + } + + TURN_ON_LOG(Default); + + parsed_log_env = __parsing_log_env(log_env); + if (parsed_log_env) { + char *channel_keyward = DA_NULL; + for (cur_parsed_log_env = parsed_log_env; *cur_parsed_log_env; cur_parsed_log_env++) { + if (!*cur_parsed_log_env) + break; + for (i = 0; i < DA_LOG_CHANNEL_MAX; i++) { + channel_keyward = __get_channel_name_from_enum(i); + if (channel_keyward && !strcmp(*cur_parsed_log_env, + channel_keyward)) { + TURN_ON_LOG(i); + break; + } + } + free(*cur_parsed_log_env); + } + free(parsed_log_env); + } + + if (log_env) + free(log_env); + + return ret; +} + +char *__get_log_env(void) { + char *log_env = DA_NULL; + + /* environment value has higher priority than configure file */ + log_env = getenv(DA_DEBUG_ENV_KEY); + if (log_env && strlen(log_env)) + return strdup(log_env); + + if (read_data_from_file(DA_DEBUG_CONFIG_FILE_PATH, &log_env)) + return log_env; + + return DA_NULL; +} + +char **__parsing_log_env(char *in_log_env) { + char **out_parsed_result = DA_NULL; + + char **temp_result_array = DA_NULL; + char **cur_temp_result_array = DA_NULL; + int how_many_item = 0; + int how_many_delimeter = 0; + + char delimiter = ','; + + char *org_str = in_log_env; + char *cur_char = org_str; + char *start = org_str; + char *end = org_str; + int target_len = 0; + + if (!org_str) + return DA_NULL; + + /* counting delimiter to know how many items should be memory allocated. + * This causes two round of loop (counting delimiter and real operation). + * But I think it is tolerable, because input parameter is from console. + * And it is also a reason why we should not use fixed length array. + * Users are hard to input very long environment, but it is possible. */ + for (cur_char = org_str; *cur_char; cur_char++) { + if (*cur_char == delimiter) + how_many_delimeter++; + } + how_many_item = how_many_delimeter + 1; + temp_result_array = (char**) calloc(1, how_many_item + 1); + if (!(temp_result_array)) + goto ERR; + + cur_temp_result_array = temp_result_array; + cur_char = org_str; + while (1) { + if (*cur_char == delimiter) { + end = cur_char; + target_len = (int) (end - start); + *cur_temp_result_array++ = __copying_str(start, + target_len); + start = ++cur_char; + continue; + } else if (!(*cur_char)) { + end = cur_char; + target_len = (int) (end - start); + *cur_temp_result_array++ = __copying_str(start, + target_len); + *cur_temp_result_array = DA_NULL; + break; + } else { + cur_char++; + } + } + out_parsed_result = temp_result_array; +ERR: + return out_parsed_result; +} + +char *__copying_str(char *source, int length) { + char *copied_str = DA_NULL; + char *cur_pos = DA_NULL; + char white_space = ' '; + char end_of_line = 10; /* ASCII for LF */ + int i = 0; + + if (!source || !(length > 0)) + return DA_NULL; + + copied_str = (char*) calloc(1, length + 1); + if (copied_str) { + cur_pos = copied_str; + for (i = 0; i < length; i++) { + if ((source[i] != white_space) && (source[i] + != end_of_line)) + *cur_pos++ = source[i]; + } + } + + return copied_str; +} + +char *__get_channel_name_from_enum(da_log_channel channel_enum) { + switch (channel_enum) { + case Soup: + return STRING_IT(Soup); + case HTTPManager: + return STRING_IT(HTTPManager); + case InstallManager: + return STRING_IT(InstallManager); + case FileManager: + return STRING_IT(FileManager); + case DRMManager: + return STRING_IT(DRMManager); + case DownloadManager: + return STRING_IT(DownloadManager); + case ClientNoti: + return STRING_IT(ClientNoti); + case HTTPMessageHandler: + return STRING_IT(HTTPMessageHandler); + case Encoding: + return STRING_IT(Encoding); + case QueueManager: + return STRING_IT(QueueManager); + case Parsing: + return STRING_IT(Parsing); + case Thread: + return STRING_IT(Thread); + case Default: + return STRING_IT(Default); + default: + return DA_NULL; + } +} diff --git a/src/agent/download-agent-dl-info-util.c b/src/agent/download-agent-dl-info-util.c new file mode 100644 index 0000000..bf78d9d --- /dev/null +++ b/src/agent/download-agent-dl-info-util.c @@ -0,0 +1,685 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-dl-info-util.c + * @brief create and destroy functions for download_info + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + ***/ + +#include <string.h> + +#include "download-agent-client-mgr.h" +#include "download-agent-dl-info-util.h" +#include "download-agent-debug.h" +#include "download-agent-utils.h" +#include "download-agent-file.h" +#include "download-agent-http-mgr.h" +#include "download-agent-plugin-conf.h" + +pthread_mutex_t mutex_download_state[DA_MAX_DOWNLOAD_ID]; +static pthread_mutex_t mutex_download_mgr = PTHREAD_MUTEX_INITIALIZER; +download_mgr_t download_mgr; + +void init_state_watcher(state_watcher_t *state_watcher); +void cleanup_state_watcher(state_watcher_t *state_watcher); + +da_result_t set_default_header_info(void); + +void cleanup_source_info_basic_download(source_info_basic_t *source_info_basic); +void cleanup_req_dl_info_http(req_dl_info *http_download); +void destroy_file_info(file_info *file); + +da_result_t init_download_mgr() { + da_result_t ret = DA_RESULT_OK; + int i = 0; + + DA_LOG_FUNC_START(Default); + + if (is_client_app_mgr_init() == DA_FALSE) { + DA_LOG_ERR(Default, "client app manager is not initiated!"); + return DA_ERR_INVALID_CLIENT; + } + + _da_thread_mutex_lock(&mutex_download_mgr); + + if (download_mgr.is_init == DA_FALSE) { + download_mgr.is_init = DA_TRUE; + + for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) { + _da_thread_mutex_init(&mutex_download_state[i], DA_NULL); + init_download_info(i); + } + + init_state_watcher(&(download_mgr.state_watcher)); + init_dl_req_id_history(&(download_mgr.dl_req_id_history)); + + download_mgr.default_hdr_info = (default_http_hdr_info_t *) calloc(1, + sizeof(default_http_hdr_info_t)); + if (download_mgr.default_hdr_info) { + /* Don't check return value, + * because UA and UAprof is not mandatory field at HTTP request header */ + set_default_header_info(); + } else { + DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + } + } + + _da_thread_mutex_unlock(&mutex_download_mgr); + + return ret; +} + +da_result_t deinit_download_mgr(void) { + da_result_t ret = DA_RESULT_OK; + + DA_LOG_FUNC_START(Default); + + _da_thread_mutex_lock(&mutex_download_mgr); + if (download_mgr.is_init == DA_TRUE) { + int i = 0; + download_info_t *dl_info = DA_NULL; + void *t_return = NULL; + for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) { + dl_info = &(download_mgr.download_info[i]); + if (dl_info && dl_info->is_using) { + request_to_abort_http_download(GET_DL_CURRENT_STAGE(i)); + DA_LOG_CRITICAL(Thread, "===download id[%d] thread id[%lu] join===",i, GET_DL_THREAD_ID(i)); + if (pthread_join(GET_DL_THREAD_ID(i), &t_return) < 0) { + DA_LOG_ERR(Thread, "join client thread is failed!!!"); + } + DA_LOG_CRITICAL(Thread, "===download id[%d] thread join return[%d]===",i, (char*)t_return); +} +} + download_mgr.is_init = DA_FALSE; + cleanup_state_watcher(&(download_mgr.state_watcher)); + if (NULL != download_mgr.default_hdr_info) { + if (NULL != download_mgr.default_hdr_info->user_agent_string) + free(download_mgr.default_hdr_info->user_agent_string); + + download_mgr.default_hdr_info->user_agent_string = NULL; + + free(download_mgr.default_hdr_info); + download_mgr.default_hdr_info = NULL; + } + deinit_dl_req_id_history(&(download_mgr.dl_req_id_history)); + } + _da_thread_mutex_unlock(&mutex_download_mgr); + return ret; +} + +da_result_t set_default_header_info(void) +{ + da_result_t ret = DA_RESULT_OK; + + ret = get_user_agent_string( + &download_mgr.default_hdr_info->user_agent_string); + + if (DA_RESULT_OK != ret) + goto ERR; + else + DA_LOG(Default, "download_mgr.default_hdr_info->user_agent_string = %s ", + download_mgr.default_hdr_info->user_agent_string); +ERR: + return ret; +} + +void init_download_info(int download_id) +{ + download_info_t *dl_info = DA_NULL; + +// DA_LOG_FUNC_START(Default); + + _da_thread_mutex_lock(&mutex_download_state[download_id]); + DA_LOG(Default, "Init download_id [%d] Info", download_id); + dl_info = &(download_mgr.download_info[download_id]); + + dl_info->is_using = DA_FALSE; + dl_info->state = DOWNLOAD_STATE_IDLE; + dl_info->download_stage_data = DA_NULL; + dl_info->dl_req_id = DA_NULL; + dl_info->user_install_path = DA_NULL; + dl_info->user_data = DA_NULL; + + Q_init_queue(&(dl_info->queue)); + + DA_LOG(Default, "Init download_id [%d] Info END", download_id); + _da_thread_mutex_unlock(&mutex_download_state[download_id]); + + return; +} + +void destroy_download_info(int download_id) +{ + download_info_t *dl_info = DA_NULL; + + DA_LOG_FUNC_START(Default); + + DA_LOG(Default, "Destroying download_id [%d] Info", download_id); + + if (download_id == DA_INVALID_ID) { + DA_LOG_ERR(Default, "invalid download_id"); + return; + } + + dl_info = &(download_mgr.download_info[download_id]); + if (DA_FALSE == dl_info->is_using) { +/* DA_LOG_ERR(Default, "invalid download_id"); */ + return; + } + + _da_thread_mutex_lock (&mutex_download_state[download_id]); + dl_info->state = DOWNLOAD_STATE_IDLE; + DA_LOG(Default, "Changed download_state to - [%d] ", dl_info->state); + + dl_info->active_dl_thread_id = 0; + + if (dl_info->download_stage_data != DA_NULL) { + remove_download_stage(download_id, dl_info->download_stage_data); + dl_info->download_stage_data = DA_NULL; + } + dl_info->dl_req_id = DA_NULL; + if (dl_info->user_install_path) { + free(dl_info->user_install_path); + dl_info->user_install_path = DA_NULL; + } + dl_info->user_data = DA_NULL; + dl_info->cur_da_state = DA_STATE_WAITING; + + Q_destroy_queue(&(dl_info->queue)); + + dl_info->is_using = DA_FALSE; + + DA_LOG(Default, "Destroying download_id [%d] Info END", download_id); + _da_thread_mutex_unlock (&mutex_download_state[download_id]); + return; +} + +void *Add_new_download_stage(int download_id) +{ + stage_info *download_stage_data = NULL; + stage_info *new_download_stage_data = NULL; + + DA_LOG_FUNC_START(Default); + + new_download_stage_data = (stage_info*)calloc(1, sizeof(stage_info)); + if (!new_download_stage_data) + goto ERR; + + new_download_stage_data->dl_id = download_id; + download_stage_data = GET_DL_CURRENT_STAGE(download_id); + if (download_stage_data) { + while (download_stage_data->next_stage_info) { + download_stage_data + = download_stage_data->next_stage_info; + }; + download_stage_data->next_stage_info = new_download_stage_data; + } else { + GET_DL_CURRENT_STAGE(download_id) = new_download_stage_data; + } + DA_LOG(Default, "NEW STAGE ADDED FOR DOWNLOAD ID[%d] new_stage[%p]", download_id,new_download_stage_data); + +ERR: + return new_download_stage_data; +} + +void remove_download_stage(int download_id, stage_info *in_stage) +{ + stage_info *stage = DA_NULL; + + DA_LOG_FUNC_START(Default); + + stage = GET_DL_CURRENT_STAGE(download_id); + if (DA_NULL == stage) { + DA_LOG_VERBOSE(Default, "There is no stage field on download_id = %d", download_id); + goto ERR; + } + + if (DA_NULL == in_stage) { + DA_LOG_VERBOSE(Default, "There is no in_stage to remove."); + goto ERR; + } + + if (in_stage == stage) { + DA_LOG_VERBOSE(Default, "Base stage will be removed. in_stage[%p]",in_stage); + DA_LOG_VERBOSE(Default, "next stage[%p]",stage->next_stage_info); + GET_DL_CURRENT_STAGE(download_id) = stage->next_stage_info; + empty_stage_info(in_stage); + free(in_stage); + in_stage = DA_NULL; + } else { + while (in_stage != stage->next_stage_info) { + stage = stage->next_stage_info; + } + if (in_stage == stage->next_stage_info) { + stage->next_stage_info + = stage->next_stage_info->next_stage_info; + DA_LOG_VERBOSE(Default, "Stage will be removed. in_stage[%p]",in_stage); + DA_LOG_VERBOSE(Default, "next stage[%p]",stage->next_stage_info); + empty_stage_info(in_stage); + free(in_stage); + in_stage = DA_NULL; + } + } + +ERR: + return; +} + +void empty_stage_info(stage_info *in_stage) +{ + source_info_t *source_information = NULL; + req_dl_info *request_download_info = NULL; + file_info *file_information = NULL; + + DA_LOG_FUNC_START(Default); + + DA_LOG(Default, "Stage to Remove:[%p]", in_stage); + source_information = GET_STAGE_SOURCE_INFO(in_stage); + + cleanup_source_info_basic_download( + GET_SOURCE_BASIC(source_information)); + + request_download_info = GET_STAGE_TRANSACTION_INFO(in_stage); + + cleanup_req_dl_info_http(request_download_info); + + file_information = GET_STAGE_CONTENT_STORE_INFO(in_stage); + destroy_file_info(file_information); +} + +void cleanup_source_info_basic_download(source_info_basic_t *source_info_basic) +{ + if (NULL == source_info_basic) + goto ERR; + + DA_LOG_FUNC_START(Default); + + if (NULL != source_info_basic->url) { + free(source_info_basic->url); + source_info_basic->url = DA_NULL; + } + +ERR: + return; + +} + +void cleanup_req_dl_info_http(req_dl_info *http_download) +{ + DA_LOG_FUNC_START(Default); + + if (http_download->http_info.http_msg_request) { + http_msg_request_destroy( + &(http_download->http_info.http_msg_request)); + } + + if (http_download->http_info.http_msg_response) { + http_msg_response_destroy( + &(http_download->http_info.http_msg_response)); + } + + if (DA_NULL != http_download->location_url) { + free(http_download->location_url); + http_download->location_url = DA_NULL; + } + if (DA_NULL != http_download->content_type_from_header) { + free(http_download->content_type_from_header); + http_download->content_type_from_header = DA_NULL; + } + + if (DA_NULL != http_download->etag_from_header) { + free(http_download->etag_from_header); + http_download->etag_from_header = DA_NULL; + } + + http_download->invloved_transaction_id = DA_INVALID_ID; + http_download->content_len_from_header = 0; + http_download->downloaded_data_size = 0; + + _da_thread_mutex_destroy(&(http_download->mutex_http_state)); + + return; +} + +void destroy_file_info(file_info *file_information) +{ +// DA_LOG_FUNC_START(Default); + + if (!file_information) + return; + + if (file_information->file_name_tmp) { + free(file_information->file_name_tmp); + file_information->file_name_tmp = NULL; + } + + if (file_information->file_name_final) { + free(file_information->file_name_final); + file_information->file_name_final = NULL; + } + + if (file_information->content_type) { + free(file_information->content_type); + file_information->content_type = NULL; + } + + if (file_information->pure_file_name) { + free(file_information->pure_file_name); + file_information->pure_file_name = NULL; + } + + if (file_information->extension) { + free(file_information->extension); + file_information->extension = NULL; + } + return; +} + +void clean_up_client_input_info(client_input_t *client_input) +{ + DA_LOG_FUNC_START(Default); + + if (client_input) { + client_input->user_data = NULL; + + if (client_input->install_path) { + free(client_input->install_path); + client_input->install_path = DA_NULL; + } + + if (client_input->file_name) { + free(client_input->file_name); + client_input->file_name = DA_NULL; + } + + client_input_basic_t *client_input_basic = + &(client_input->client_input_basic); + + if (client_input_basic && client_input_basic->req_url) { + free(client_input_basic->req_url); + client_input_basic->req_url = DA_NULL; + } + + if (client_input_basic && client_input_basic->user_request_header) { + int i = 0; + int count = client_input_basic->user_request_header_count; + for (i = 0; i < count; i++) + { + if (client_input_basic->user_request_header[i]) { + free(client_input_basic->user_request_header[i]); + client_input_basic->user_request_header[i] = DA_NULL; + } + } + + free(client_input_basic->user_request_header); + client_input_basic->user_request_header = DA_NULL; + client_input_basic->user_request_header_count = 0; + } + } else { + DA_LOG_ERR(Default, "client_input is NULL."); + } + + return; +} + +da_result_t get_download_id_for_dl_req_id( + da_handle_t dl_req_id, + da_handle_t* download_id) +{ + da_result_t ret = DA_ERR_INVALID_DL_REQ_ID; + int iter = 0; + + if (dl_req_id < 0) { + DA_LOG_ERR(Default, "dl_req_id is less than 0 - %d", dl_req_id); + return DA_ERR_INVALID_DL_REQ_ID; + } + + _da_thread_mutex_lock(&mutex_download_mgr); + for (iter = 0; iter < DA_MAX_DOWNLOAD_ID; iter++) { + if (download_mgr.download_info[iter].is_using == DA_TRUE) { + if (download_mgr.download_info[iter].dl_req_id == + dl_req_id) { + *download_id = iter; + ret = DA_RESULT_OK; + break; + } + } + } + _da_thread_mutex_unlock(&mutex_download_mgr); + + return ret; +} + + +da_result_t get_available_download_id(da_handle_t *available_id) +{ + da_result_t ret = DA_ERR_ALREADY_MAX_DOWNLOAD; + int i; + + _da_thread_mutex_lock(&mutex_download_mgr); + for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) { + if (download_mgr.download_info[i].is_using == DA_FALSE) { + init_download_info(i); + + download_mgr.download_info[i].is_using = DA_TRUE; + + download_mgr.download_info[i].dl_req_id + = get_available_dl_req_id(&(download_mgr.dl_req_id_history)); + + *available_id = i; + DA_LOG_CRITICAL(Default, "available download id = %d", *available_id); + ret = DA_RESULT_OK; + + break; + } + } + _da_thread_mutex_unlock(&mutex_download_mgr); + + return ret; +} + +da_bool_t is_valid_dl_ID( download_id) +{ + da_bool_t ret = DA_FALSE; + + if (download_id >= 0 && download_id < DA_MAX_DOWNLOAD_ID) { + if (download_mgr.download_info[download_id].is_using == DA_TRUE) + ret = DA_TRUE; + } + + return ret; +} + +void init_state_watcher(state_watcher_t *state_watcher) +{ + DA_LOG_FUNC_START(Default); + + _da_thread_mutex_init(&(state_watcher->mutex), DA_NULL); + + _da_thread_mutex_lock(&(state_watcher->mutex)); + state_watcher->type = STATE_WATCHER_TYPE_NONE; + state_watcher->state_watching_bitmap = 0; + state_watcher->is_progressing_to_all = DA_FALSE; + _da_thread_mutex_unlock(&(state_watcher->mutex)); +} + +void cleanup_state_watcher(state_watcher_t *state_watcher) +{ + DA_LOG_FUNC_START(Default); + + _da_thread_mutex_lock(&(state_watcher->mutex)); + state_watcher->type = STATE_WATCHER_TYPE_NONE; + state_watcher->state_watching_bitmap = 0; + state_watcher->is_progressing_to_all = DA_FALSE; + _da_thread_mutex_unlock(&(state_watcher->mutex)); + + _da_thread_mutex_destroy(&(state_watcher->mutex)); +} + +void state_watcher_flag_ON_for_download_id( + state_watcher_t *state_watcher, + int download_id) +{ + unsigned short mask = 0; + + _da_thread_mutex_lock(&(state_watcher->mutex)); + + mask = 1 << download_id; + + state_watcher->state_watching_bitmap |= mask; + + DA_LOG(Default, "state_watcher [%d], download_id [%d]", state_watcher->state_watching_bitmap, download_id); + + _da_thread_mutex_unlock(&(state_watcher->mutex)); +} + +void state_watcher_flag_OFF_for_download_id( + state_watcher_t *state_watcher, + int download_id) +{ + unsigned short mask = 0; + + _da_thread_mutex_lock(&(state_watcher->mutex)); + + mask = ~(1 << download_id); + + state_watcher->state_watching_bitmap &= mask; + + DA_LOG(Default, "state_watcher [%d], download_id [%d]", state_watcher->state_watching_bitmap, download_id); + + _da_thread_mutex_unlock(&(state_watcher->mutex)); +} + +da_bool_t state_watcher_is_flag_on_for_download_id_Q( + state_watcher_t *state_watcher, + int download_id) +{ + da_bool_t b_ret = DA_FALSE; + unsigned short mask = 0; + unsigned short result = 0; + + _da_thread_mutex_lock(&(state_watcher->mutex)); + + mask = 1 << download_id; + + result = state_watcher->state_watching_bitmap & mask; + + /* DA_LOG(Default, "state_watcher after [%d]", state_watcher->state_watching_bitmap); */ + + _da_thread_mutex_unlock(&(state_watcher->mutex)); + + if (result) + b_ret = DA_TRUE; + else + b_ret = DA_FALSE; + + return b_ret; +} + +da_bool_t state_watcher_need_redirect_Q(int download_id) +{ + da_bool_t b_ret = DA_FALSE; + state_watcher_t *state_watcher = DA_NULL; + + state_watcher = &(download_mgr.state_watcher); + + b_ret = state_watcher_is_flag_on_for_download_id_Q(state_watcher, + download_id); + + DA_LOG(Default, "state_watcher - need to redirect? [%d]", b_ret); + + return b_ret; +} + +void state_watcher_redirect_state(int download_id, da_state state, int err) +{ + state_watcher_t *state_watcher = DA_NULL; + + DA_LOG_FUNC_START(Default); + + DA_LOG(Default, "download_id = [%d], receiving state = [%d]", download_id, state); + + state_watcher = &(download_mgr.state_watcher); + + switch (state) { + case DA_STATE_FAILED: + case DA_STATE_FINISHED: + state_watcher_flag_OFF_for_download_id(state_watcher, + download_id); + send_client_da_state(download_id, state, err); + + break; + + case DA_STATE_CANCELED: + state_watcher_flag_OFF_for_download_id(state_watcher, + download_id); + + if (state_watcher->type == STATE_WATCHER_TYPE_CANCEL) { + if (!(state_watcher->state_watching_bitmap) && + (state_watcher->is_progressing_to_all + == DA_FALSE)) { + send_client_da_state(download_id, + DA_STATE_CANCELED_ALL, + DA_RESULT_OK); + } + } else { + send_client_da_state(download_id, state, err); + } + + break; + + case DA_STATE_SUSPENDED: + state_watcher_flag_OFF_for_download_id(state_watcher, + download_id); + + if (state_watcher->type == STATE_WATCHER_TYPE_SUSPEND) { + if (!(state_watcher->state_watching_bitmap) && + (state_watcher->is_progressing_to_all + == DA_FALSE)) { + send_client_da_state(download_id, + DA_STATE_SUSPENDED_ALL, + DA_RESULT_OK); + } + } + + break; + + case DA_STATE_RESUMED: + state_watcher_flag_OFF_for_download_id(state_watcher, + download_id); + + if (state_watcher->type == STATE_WATCHER_TYPE_RESUME) { + if (!(state_watcher->state_watching_bitmap) && + (state_watcher->is_progressing_to_all + == DA_FALSE)) { + send_client_da_state(download_id, + DA_STATE_RESUMED_ALL, + DA_RESULT_OK); + } + } + + break; + + default: + DA_LOG(Default, "blocked..."); + break; + } +} diff --git a/src/agent/download-agent-dl-mgr.c b/src/agent/download-agent-dl-mgr.c new file mode 100644 index 0000000..84518b0 --- /dev/null +++ b/src/agent/download-agent-dl-mgr.c @@ -0,0 +1,606 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-dl-mgr.c + * @brief common functions for oma and direct download + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + ***/ + +#include "download-agent-client-mgr.h" +#include "download-agent-debug.h" +#include "download-agent-dl-mgr.h" +#include "download-agent-utils.h" +#include "download-agent-http-mgr.h" +#include "download-agent-installation.h" +#include "download-agent-file.h" +#include "download-agent-plugin-drm.h" +#include "download-agent-plugin-conf.h" + + +static da_result_t __cancel_download_with_download_id(int download_id); +static da_result_t __suspend_download_with_download_id(int download_id); + + +da_result_t requesting_download(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + req_dl_info *request_session = DA_NULL; + download_state_t download_state = DA_INVALID_ID; + + DA_LOG_FUNC_START(Default); + + if (!stage) { + DA_LOG_ERR(Default, "stage is null.."); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + ret = make_req_dl_info_http(stage, GET_STAGE_TRANSACTION_INFO(stage)); + if (ret != DA_RESULT_OK) + goto ERR; + + request_session = GET_STAGE_TRANSACTION_INFO(stage); + ret = request_http_download(stage); + if (DA_RESULT_OK == ret) { + DA_LOG(Default, "Http download is complete."); + } else { + DA_LOG_ERR(Default, "Http download is failed. ret = %d", ret); + goto ERR; + } + + _da_thread_mutex_lock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); + download_state = GET_DL_STATE_ON_STAGE(stage); + _da_thread_mutex_unlock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); + + /* Ignore install content process if the download is failed or paused or canceled */ + if (download_state == DOWNLOAD_STATE_PAUSED || + download_state == DOWNLOAD_STATE_CANCELED) { + return ret; + } + +ERR: + return ret; +} + +da_result_t handle_after_download(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + da_mime_type_id_t mime_type = DA_MIME_TYPE_NONE; + + DA_LOG_FUNC_START(Default); + + if (DA_TRUE == is_this_client_manual_download_type()) { + if (DA_RESULT_OK == ret) { + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_FINISH,stage); + } + return ret; + } + mime_type = get_mime_type_id( + GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage))); + + switch (mime_type) { + case DA_MIME_PLAYREADY_INIT: + DA_LOG_VERBOSE(Default, "DA_MIME_PLAYREADY_INIT"); + ret = process_play_ready_initiator(stage); + break; + case DA_MIME_TYPE_NONE: + DA_LOG(Default, "DA_MIME_TYPE_NONE"); + ret = DA_ERR_MISMATCH_CONTENT_TYPE; + break; + default: + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_READY_TO_INSTAL,stage); + break; + } /* end of switch */ + + return ret; +} + +da_result_t process_install(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + + DA_LOG_FUNC_START(Default); + + if (DA_NULL == stage) + return DA_ERR_INVALID_ARGUMENT; + + /* install process. */ + ret = install_content(stage); + + if (DA_RESULT_OK == ret) { + int download_id = GET_STAGE_DL_ID(stage); + char *content_type = DA_NULL; + + if (GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage))) { + content_type = strdup( + GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage))); + } else { + /* Fixme : Is Content-Type on HTTP header mandatory? */ + DA_LOG_ERR(Default, "no content type!"); + ret = DA_ERR_MISMATCH_CONTENT_TYPE; + return ret; + } + + /* update installed path */ + send_client_update_downloading_info( + download_id, + GET_DL_REQ_ID(download_id), + GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), + GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)) + ); + + if (content_type) { + free(content_type); + content_type = DA_NULL; + } + + return DA_RESULT_OK; + } + return ret; +} + +static da_result_t __cancel_download_with_download_id(int download_id) +{ + da_result_t ret = DA_RESULT_OK; + download_state_t download_state; + stage_info *stage = DA_NULL; + + DA_LOG_FUNC_START(Default); + + _da_thread_mutex_lock (&mutex_download_state[download_id]); + download_state = GET_DL_STATE_ON_ID(download_id); + DA_LOG(Default, "download_state = %d", GET_DL_STATE_ON_ID(download_id)); + if (download_state == DOWNLOAD_STATE_IDLE) { + /* FIXME later : It is better to check and exit itself at download thread */ + pthread_cancel(GET_DL_THREAD_ID(download_id)); + } else if (download_state >= DOWNLOAD_STATE_READY_TO_INSTAL) { + DA_LOG_CRITICAL(Default, "Already download is completed. Do not send cancel request"); + _da_thread_mutex_unlock (&mutex_download_state[download_id]); + return ret; + } + _da_thread_mutex_unlock (&mutex_download_state[download_id]); + + if (ret != DA_RESULT_OK) + goto ERR; + + stage = GET_DL_CURRENT_STAGE(download_id); + if (!stage) + return DA_RESULT_OK; + + ret = request_to_cancel_http_download(stage); + if (ret != DA_RESULT_OK) + goto ERR; + DA_LOG(Default, "Download cancel Successful for download id - %d", download_id); +ERR: + return ret; +} + +da_result_t cancel_download(int dl_req_id) +{ + da_result_t ret = DA_RESULT_OK; + + int download_id = DA_INVALID_ID; + + DA_LOG_FUNC_START(Default); + + if ((dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS) || + (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI)) { + DA_LOG(Default, "All download items will be cancelled"); + ret = cancel_download_all(dl_req_id); + return ret; + } + + ret = get_download_id_for_dl_req_id(dl_req_id, &download_id); + if (ret != DA_RESULT_OK) { + DA_LOG_ERR(Default, "dl req ID is not Valid"); + goto ERR; + } + + if (DA_FALSE == is_valid_dl_ID(download_id)) { + DA_LOG_ERR(Default, "Download ID is not Valid"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + ret = __cancel_download_with_download_id(download_id); + +ERR: + return ret; + +} + +da_result_t cancel_download_all(int dl_req_id) +{ + da_result_t ret = DA_RESULT_OK; + + int download_id = DA_INVALID_ID; + int iter = 0; + da_bool_t b_any_flag_on = DA_FALSE; + + state_watcher_t *state_watcher = DA_NULL; + + DA_LOG_FUNC_START(Default); + + if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { + state_watcher = &(download_mgr.state_watcher); + + _da_thread_mutex_lock(&(state_watcher->mutex)); + state_watcher->type = STATE_WATCHER_TYPE_CANCEL; + state_watcher->is_progressing_to_all = DA_TRUE; + _da_thread_mutex_unlock(&(state_watcher->mutex)); + } + + for (iter = 0; iter < DA_MAX_DOWNLOAD_ID; iter++) { + if (download_mgr.download_info[iter].is_using == DA_TRUE) { + download_id = iter; + + if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { + state_watcher_flag_ON_for_download_id(state_watcher, + download_id); + } + b_any_flag_on = DA_TRUE; + + /* ToDo: retry if fail, check download_state, don't set flag for state_watcher if state is invalid */ + ret = __cancel_download_with_download_id(download_id); + /*if (ret == DA_RESULT_OK) { + state_watcher_flag_ON_for_download_id( + state_watcher, download_id); + b_any_flag_on = DA_TRUE; + }*/ + } + + } + + if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { + _da_thread_mutex_lock(&(state_watcher->mutex)); + state_watcher->is_progressing_to_all = DA_FALSE; + _da_thread_mutex_unlock(&(state_watcher->mutex)); + } + + if (b_any_flag_on == DA_FALSE) { + DA_LOG_ERR(Default, "There is no item to be able to cancel."); + ret = DA_ERR_INVALID_DL_REQ_ID; + } + + return ret; +} + +static da_result_t __suspend_download_with_download_id(int download_id) +{ + da_result_t ret = DA_RESULT_OK; + download_state_t download_state; + stage_info *stage = DA_NULL; + + DA_LOG_FUNC_START(Default); + + _da_thread_mutex_lock (&mutex_download_state[download_id]); + download_state = GET_DL_STATE_ON_ID(download_id); + DA_LOG(Default, "download_state = %d", GET_DL_STATE_ON_ID(download_id)); + _da_thread_mutex_unlock (&mutex_download_state[download_id]); + + if (ret != DA_RESULT_OK) + goto ERR; + + stage = GET_DL_CURRENT_STAGE(download_id); + if (!stage) + return DA_ERR_CANNOT_SUSPEND; + + ret = request_to_suspend_http_download(stage); + if (ret != DA_RESULT_OK) + goto ERR; + DA_LOG(Default, "Download Suspend Successful for download id-%d", download_id); +ERR: + return ret; +} + +da_result_t suspend_download(int dl_req_id) +{ + da_result_t ret = DA_RESULT_OK; + int download_id = DA_INVALID_ID; + + DA_LOG_FUNC_START(Default); + + if ((dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS) || + (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI)) { + DA_LOG(Default, "All download items will be suspended"); + ret = suspend_download_all(dl_req_id); + return ret; + } + + ret = get_download_id_for_dl_req_id(dl_req_id, &download_id); + if (ret != DA_RESULT_OK) { + DA_LOG_ERR(Default, "dl req ID is not Valid"); + goto ERR; + } + + if (DA_FALSE == is_valid_dl_ID(download_id)) { + DA_LOG_ERR(Default, "Download ID is not Valid"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + ret = __suspend_download_with_download_id(download_id); + +ERR: + return ret; + +} + +da_result_t suspend_download_all(int dl_req_id) +{ + da_result_t ret = DA_RESULT_OK; + + int download_id = DA_INVALID_ID; + int iter = 0; + da_bool_t b_any_flag_on = DA_FALSE; + + state_watcher_t *state_watcher = DA_NULL; + + DA_LOG_FUNC_START(Default); + + if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { + state_watcher = &(download_mgr.state_watcher); + + _da_thread_mutex_lock(&(state_watcher->mutex)); + state_watcher->type = STATE_WATCHER_TYPE_SUSPEND; + state_watcher->is_progressing_to_all = DA_TRUE; + _da_thread_mutex_unlock(&(state_watcher->mutex)); + } + + for (iter = 0; iter < DA_MAX_DOWNLOAD_ID; iter++) { + if (download_mgr.download_info[iter].is_using == DA_TRUE) { + download_id = iter; + /* ToDo: retry if fail, check download_state, don't set flag for state_watcher if state is invalid */ + ret = __suspend_download_with_download_id(download_id); + if (ret == DA_RESULT_OK) { + if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { + state_watcher_flag_ON_for_download_id( + state_watcher, download_id); + } + b_any_flag_on = DA_TRUE; + } + } + + } + + if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { + _da_thread_mutex_lock(&(state_watcher->mutex)); + state_watcher->is_progressing_to_all = DA_FALSE; + _da_thread_mutex_unlock(&(state_watcher->mutex)); + } + + if (b_any_flag_on == DA_FALSE) { + DA_LOG_ERR(Default, "There is no item to be able to suspend."); + ret = DA_ERR_CANNOT_SUSPEND; + } + + return ret; +} + +static da_result_t __resume_download_with_download_id(int download_id) +{ + da_result_t ret = DA_RESULT_OK; + download_state_t download_state; + stage_info *stage = DA_NULL; + + DA_LOG_FUNC_START(Default); + + _da_thread_mutex_lock (&mutex_download_state[download_id]); + download_state = GET_DL_STATE_ON_ID(download_id); + DA_LOG(Default, "download_state = %d", GET_DL_STATE_ON_ID(download_id)); + _da_thread_mutex_unlock (&mutex_download_state[download_id]); + + if (ret != DA_RESULT_OK) + goto ERR; + + stage = GET_DL_CURRENT_STAGE(download_id); + + ret = request_to_resume_http_download(stage); + if (ret != DA_RESULT_OK) + goto ERR; + DA_LOG(Default, "Download Resume Successful for download id-%d", download_id); +ERR: + return ret; +} + +da_result_t resume_download(int dl_req_id) +{ + da_result_t ret = DA_RESULT_OK; + int download_id = DA_INVALID_ID; + + DA_LOG_FUNC_START(Default); + + if ((dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS) || + (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI)) { + DA_LOG(Default, "All download items will be resumed"); + ret = resume_download_all(dl_req_id); + return ret; + } + + ret = get_download_id_for_dl_req_id(dl_req_id, &download_id); + if (ret != DA_RESULT_OK) + goto ERR; + + if (DA_FALSE == is_valid_dl_ID(download_id)) { + DA_LOG_ERR(Default, "Download ID is not Valid"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + ret = __resume_download_with_download_id(download_id); + +ERR: + return ret; +} + +da_result_t resume_download_all(int dl_req_id) +{ + da_result_t ret = DA_RESULT_OK; + + int download_id = DA_INVALID_ID; + int iter = 0; + da_bool_t b_any_flag_on = DA_FALSE; + + state_watcher_t *state_watcher = DA_NULL; + + DA_LOG_FUNC_START(Default); + + if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { + state_watcher = &(download_mgr.state_watcher); + + _da_thread_mutex_lock(&(state_watcher->mutex)); + state_watcher->type = STATE_WATCHER_TYPE_RESUME; + state_watcher->is_progressing_to_all = DA_TRUE; + _da_thread_mutex_unlock(&(state_watcher->mutex)); + } + + for (iter = 0; iter < DA_MAX_DOWNLOAD_ID; iter++) { + if (download_mgr.download_info[iter].is_using == DA_TRUE) { + download_id = iter; + + if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { + state_watcher_flag_ON_for_download_id(state_watcher, + download_id); + } + b_any_flag_on = DA_TRUE; + + /* ToDo: retry if fail, check download_state, don't set flag for state_watcher if state is invalid */ + ret = __resume_download_with_download_id(download_id); + /*if (ret == DA_RESULT_OK) { + state_watcher_flag_ON_for_download_id( + state_watcher, download_id); + b_any_flag_on = DA_TRUE; + }*/ + } + + } + + if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { + _da_thread_mutex_lock(&(state_watcher->mutex)); + state_watcher->is_progressing_to_all = DA_FALSE; + _da_thread_mutex_unlock(&(state_watcher->mutex)); + } + + if (b_any_flag_on == DA_FALSE) { + DA_LOG(Default, "There is no item to be able to cancel."); + ret = DA_ERR_INVALID_DL_REQ_ID; + } + + return ret; +} + +da_result_t send_user_noti_and_finish_download_flow(int download_id) +{ + da_result_t ret = DA_RESULT_OK; + download_state_t download_state = DA_NULL; + da_bool_t need_destroy_download_info = DA_FALSE; + + DA_LOG_FUNC_START(Default); + + _da_thread_mutex_lock (&mutex_download_state[download_id]); + download_state = GET_DL_STATE_ON_ID(download_id); + DA_LOG(Default, "state = %d", download_state); + _da_thread_mutex_unlock (&mutex_download_state[download_id]); + + switch (download_state) { + case DOWNLOAD_STATE_FINISH: + send_client_da_state(download_id, DA_STATE_FINISHED, + DA_RESULT_OK); + need_destroy_download_info = DA_TRUE; + break; + case DOWNLOAD_STATE_CANCELED: + send_client_da_state(download_id, DA_STATE_CANCELED, + DA_RESULT_OK); + need_destroy_download_info = DA_TRUE; + break; + default: + DA_LOG(Default, "download state = %d", download_state); + break; + } + + if (need_destroy_download_info == DA_TRUE) { + destroy_download_info(download_id); + } else { + DA_LOG_CRITICAL(Default, "download info is not destroyed"); + } + + return ret; +} + +da_result_t process_play_ready_initiator(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + int download_id = GET_STAGE_DL_ID(stage); + stage_info *next_stage = DA_NULL; + source_info_t *source_info = DA_NULL; + char *rights_url = DA_NULL; + char *content_url = DA_NULL; + + DA_LOG_FUNC_START(Default); + + discard_download(stage); + + rights_url = GET_SOURCE_BASIC(GET_STAGE_SOURCE_INFO(stage))->url; + DA_LOG_VERBOSE(Default, "len = %d, rights_url = %s \n", strlen(rights_url), rights_url); + + ret = EDRM_wm_get_license(rights_url, &content_url); + if (ret != DA_RESULT_OK) { + DA_LOG_ERR(Default, "EDRM_wm_get_license() failed."); + goto ERR; + } + + if (content_url) { + DA_LOG_VERBOSE(Default, "Starting new download with content_url = [%s]", content_url); + + next_stage = Add_new_download_stage(download_id); + if (!next_stage) { + DA_LOG_ERR(Default, "STAGE ADDITION FAIL!"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + + source_info = GET_STAGE_SOURCE_INFO(next_stage); + source_info->source_info_type.source_info_basic + = (source_info_basic_t*)calloc(1, + sizeof(source_info_basic_t)); + if (DA_NULL == source_info->source_info_type.source_info_basic) { + DA_LOG_ERR(Default, "DA_ERR_INVALID_ARGUMENT"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + source_info->source_info_type.source_info_basic->url + = content_url; + + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD, next_stage); + remove_download_stage(download_id, stage); + } else { + DA_LOG_VERBOSE(Default, "content url is null. So, do nothing with normal termination."); + + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_FINISH, stage); + } + +ERR: + if (ret != DA_RESULT_OK) { + if (content_url) + free(content_url); + } + + return ret; +} diff --git a/src/agent/download-agent-encoding.c b/src/agent/download-agent-encoding.c new file mode 100644 index 0000000..18c9643 --- /dev/null +++ b/src/agent/download-agent-encoding.c @@ -0,0 +1,291 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-encoding.c + * @brief Utilities to manipulate encoding and charset + * @author Keunsoon Lee (keunsoon.lee@samsung.com) + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <glib.h> + +#include "download-agent-encoding.h" +#include "download-agent-debug.h" + +da_result_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_LOG_ERR(Default, "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", "?="); // ?= + } + +// DA_LOG(Default, "needle = [%s], haystack = [%s]", first_needle, haystack); + + found_str = strstr(haystack, first_needle); + if (found_str) { + if (found_str == haystack) { +// DA_LOG(Default, "Input string is starting with %s", needle); + haystack = haystack + strlen(haystack) - strlen(second_needle); +// DA_LOG(Default, "second haystack is [%s]", haystack); + if(!strcmp(haystack, second_needle)) + return DA_TRUE; + } + } + return DA_FALSE; +} + +da_result_t decode_base64_encoded_str(const char *in_encoded_str, + char **out_decoded_ascii_str) +{ + da_result_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_LOG(Default, "input str = [%s]", in_encoded_str); + + org_str = in_encoded_str; + if(!org_str) { + DA_LOG_ERR(Default, "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; + } + +// DA_LOG(Default, "charset = [%s], encoding = [%c], raw = [%s]", charset_type, encoding_type, raw_encoded_str); + + if(encoding_type != 'B') { + DA_LOG_ERR(Default, "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_LOG(Default, "g_decoded_text = [%s]", g_decoded_text); + decoded_str = (char*)calloc(1, g_decoded_text_len+1); + if(!decoded_str) { + DA_LOG_ERR(Default, "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_LOG(Default, "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_result_t _parsing_base64_encoded_str(const char *in_encoded_str, + char **out_charset_type, + char *out_encoding_type, + char **out_raw_encoded_str) +{ + da_result_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_LOG_ERR(Default, "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_LOG_ERR(Default, "DA_ERR_INVALID_ARGUMENT"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } else { + wanted_str = wanted_str_end + strlen(needle); + DA_LOG(Default, "strip [%s]", wanted_str); + } + + // for charset + haystack = wanted_str_start = wanted_str; + needle[0] = '?'; + wanted_str_end = strchr(haystack, needle[0]); + if (!wanted_str_end) { + DA_LOG_ERR(Default, "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_LOG_ERR(Default, "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_LOG(Default, "charset [%s]", charset_type); + } + + + // for encoding + encoding_type = *(++wanted_str_end); + DA_LOG(Default, "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_LOG_ERR(Default, "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_LOG_ERR(Default, "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_LOG(Default, "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/src/agent/download-agent-file.c b/src/agent/download-agent-file.c new file mode 100644 index 0000000..004d2c7 --- /dev/null +++ b/src/agent/download-agent-file.c @@ -0,0 +1,1185 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-file.c + * @brief functions for file operation + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + ***/ + +#include <dirent.h> +#include <unistd.h> +#include <math.h> + +#include "download-agent-client-mgr.h" +#include "download-agent-debug.h" +#include "download-agent-utils.h" +#include "download-agent-dl-mgr.h" +#include "download-agent-file.h" +#include "download-agent-installation.h" +#include "download-agent-plugin-drm.h" +#include "download-agent-mime-util.h" +#include "download-agent-http-mgr.h" + +#define NO_NAME_TEMP_STR "No name" + +static da_result_t __set_file_size(stage_info *stage); +static da_result_t __tmp_file_open(stage_info *stage); + +static char *__derive_extension(stage_info *stage); +static da_result_t __divide_file_name_into_pure_name_N_extesion( + const char *in_file_name, + char **out_pure_file_name, + char **out_extension); +static da_result_t __get_candidate_file_name(stage_info *stage, + char **out_pure_file_name, char **out_extension); + +static da_result_t __file_write_buf_make_buf(file_info *file_storage); +static da_result_t __file_write_buf_destroy_buf(file_info *file_storage); +static da_result_t __file_write_buf_flush_buf(stage_info *stage, + file_info *file_storage); +static da_result_t __file_write_buf_copy_to_buf(file_info *file_storage, + char *body, int body_len); +static da_result_t __file_write_buf_directly_write(stage_info *stage, + file_info *file_storage, char *body, int body_len); + + +da_result_t create_temp_saved_dir(void) +{ + da_result_t ret = DA_RESULT_OK; + char *client_dir_path = DA_NULL; + + DA_LOG_FUNC_START(FileManager); + + ret = get_client_download_path(&client_dir_path); + if (DA_RESULT_OK != ret) { + goto ERR; + } else { + if (DA_NULL == client_dir_path) { + DA_LOG_ERR(FileManager, "client_dir_path is DA_NULL"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + } + + if (DA_FALSE == is_dir_exist(client_dir_path)) { + ret = create_dir(client_dir_path); + } + +ERR: + if (client_dir_path) { + free(client_dir_path); + client_dir_path = DA_NULL; + } + return ret; +} + +da_result_t clean_files_from_dir(char* dir_path) +{ + da_result_t ret = DA_RESULT_OK; + struct dirent *d = DA_NULL; + DIR *dir; + char file_path[DA_MAX_FULL_PATH_LEN] = { 0, }; + + DA_LOG_FUNC_START(FileManager); + + if (dir_path == DA_NULL) { + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + if (is_dir_exist(dir_path)) { + dir = opendir(dir_path); + if (DA_NULL == dir) { + DA_LOG_ERR(FileManager, "opendir() for DA_DEFAULT_TMP_FILE_DIR_PATH is failed."); + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + } else { + while (DA_NULL != (d = readdir(dir))) { + DA_LOG(FileManager, "%s",d->d_name); + if (0 == strncmp(d->d_name, ".", strlen(".")) + || 0 == strncmp(d->d_name, + "..", + strlen(".."))) { + continue; + } + + memset(file_path, 0x00, DA_MAX_FULL_PATH_LEN); + snprintf(file_path, DA_MAX_FULL_PATH_LEN, + "%s/%s", dir_path, d->d_name); + if (remove(file_path) < 0) { + DA_LOG_ERR(FileManager, "fail to remove file"); + } + } + + closedir(dir); + if (remove(dir_path) < 0) { + DA_LOG_ERR(FileManager, "fail to remove dir"); + } + } + } + +ERR: + return ret; +} + +/* Priority to obtain MIME Type + * 1. HTTP response header's <Content-Type> field + * 2. from OMA descriptor file's <content-type> attribute (mandatory field) + * 3. Otherwise, leave blank for MIME Type + */ +da_result_t get_mime_type(stage_info *stage, char **out_mime_type) +{ + char *mime_type = DA_NULL; + + if (!GET_STAGE_SOURCE_INFO(stage)) + return DA_ERR_INVALID_ARGUMENT; + + /* Priority 1 */ + if (GET_REQUEST_HTTP_HDR_CONT_TYPE(GET_STAGE_TRANSACTION_INFO(stage))) { + mime_type = GET_REQUEST_HTTP_HDR_CONT_TYPE(GET_STAGE_TRANSACTION_INFO(stage)); + DA_LOG(FileManager, "content type from HTTP response header [%s]", mime_type); + } + + if (!mime_type) { + DA_LOG(FileManager, "no content type derived"); + return DA_RESULT_OK; + } + + /* FIXME really need memory allocation? */ + *out_mime_type = (char *) calloc(1, strlen(mime_type) + 1); + if (*out_mime_type) { + snprintf(*out_mime_type, strlen(mime_type) + 1, mime_type); + DA_LOG_VERBOSE(FileManager, "out_mime_type str[%s] ptr[%p] len[%d]", + *out_mime_type,*out_mime_type,strlen(*out_mime_type)); + } else { + DA_LOG_ERR(FileManager, "fail to allocate memory"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + + DA_LOG(FileManager, "mime type = %s", *out_mime_type); + return DA_RESULT_OK; +} + +da_bool_t is_file_exist(const char *file_path) +{ + struct stat dir_state; + int stat_ret; + + if (file_path == DA_NULL) { + DA_LOG_ERR(FileManager, "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_LOG(FileManager, "Exist! %s is a regular file & its size = %lu", file_path, dir_state.st_size); + return DA_TRUE; + } + + return DA_FALSE; + } + return DA_FALSE; + +} + +da_bool_t is_dir_exist(char *file_path) +{ + struct stat dir_state; + int stat_ret; + + if (file_path == DA_NULL) { + DA_LOG_ERR(FileManager, "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_IFDIR) { + DA_LOG(FileManager, "Exist! %s is a directory.", file_path); + return DA_TRUE; + } + + return DA_FALSE; + } + return DA_FALSE; +} + +void get_file_size(char *file_path, int *out_file_size) +{ + struct stat dir_state; + int stat_ret; + + *out_file_size = -1; + + if (file_path == DA_NULL) { + DA_LOG_ERR(FileManager, "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_LOG(FileManager, "size = %lu", dir_state.st_size); + *out_file_size = dir_state.st_size; + } + } + return; +} + +da_result_t __tmp_file_open(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + + file_info *file_storage = DA_NULL; + char *actual_file_path = DA_NULL; + char *tmp_file_path = DA_NULL; + void *fd = DA_NULL; + + DA_LOG_FUNC_START(FileManager); + + file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); + if (!file_storage) + return DA_ERR_INVALID_ARGUMENT; + + actual_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage); + DA_LOG(FileManager, "actual_file_path = %s", actual_file_path); + if (!actual_file_path) + return DA_ERR_INVALID_ARGUMENT; + + tmp_file_path = (char *) calloc(1, (strlen(actual_file_path) + 1)); + if (!tmp_file_path) { + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + snprintf(tmp_file_path, strlen(actual_file_path) + 1, "%s", actual_file_path); + + GET_CONTENT_STORE_TMP_FILE_NAME(file_storage) = tmp_file_path; + DA_LOG(FileManager, "GET_CONTENT_STORE_TMP_FILE_NAME = %s ",GET_CONTENT_STORE_TMP_FILE_NAME(file_storage)); + + if (is_content_drm_dm(GET_CONTENT_STORE_CONTENT_TYPE(file_storage))) { + void *hConvert = DA_NULL; + + if (DA_TRUE != EDRM_open_convert(tmp_file_path, &hConvert)) { + DA_LOG_ERR(FileManager, "file open for dcf convertion fails "); + ret = DA_ERR_DRM_FILE_FAIL; + goto ERR; + } + DA_LOG(FileManager, "file opened for dcf convertion "); + GET_CONTENT_STORE_FILE_HANDLE(file_storage) = hConvert; + + } else { + fd = fopen(tmp_file_path, "a"); // for resume + if (fd == DA_NULL) { + DA_LOG_ERR(FileManager, "File open failed"); + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + GET_CONTENT_STORE_FILE_HANDLE(file_storage) = fd; + } + + DA_LOG(FileManager, "file path for tmp saving = %s", GET_CONTENT_STORE_TMP_FILE_NAME(file_storage)); + +ERR: + if (DA_RESULT_OK != ret) { + if (tmp_file_path) { + free(tmp_file_path); + } + if (file_storage != DA_NULL) { + GET_CONTENT_STORE_TMP_FILE_NAME(file_storage) = DA_NULL; + GET_CONTENT_STORE_FILE_HANDLE(file_storage) = DA_NULL; + } + } + return ret; +} + +da_result_t __set_file_size(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + req_dl_info *stage_req_info = DA_NULL; + file_info *file_storage = DA_NULL; + + DA_LOG_FUNC_START(FileManager); + + if (!stage) { + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + stage_req_info = GET_STAGE_TRANSACTION_INFO(stage); + + file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); + if (!file_storage) + goto ERR; + + if (GET_REQUEST_HTTP_HDR_CONT_LEN(stage_req_info) != DA_NULL) { + GET_CONTENT_STORE_FILE_SIZE(file_storage) + = GET_REQUEST_HTTP_HDR_CONT_LEN(stage_req_info); + } else { + GET_CONTENT_STORE_FILE_SIZE(file_storage) = 0; + } + DA_LOG(FileManager, "file size = %d", GET_CONTENT_STORE_FILE_SIZE(file_storage)); +ERR: + return ret; + +} + +/* Priority to derive extension + * 1. according to MIME-Type + * 2. if MIME-Type is ambiguous or blank, + * 2-1. derived from <Content-Disposition> field's "filename" attribute + * 2-2. derived from url + * 3. if url does not have extension, leave blank for extension + */ +char *__derive_extension(stage_info *stage) +{ + if (!stage) + return DA_NULL; + + source_info_t *source_info = GET_STAGE_SOURCE_INFO(stage); + req_dl_info *request_info = GET_STAGE_TRANSACTION_INFO(stage); + file_info *file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); + char *extension = DA_NULL; + char *url = DA_NULL; + + /* Priority 1 */ + char *mime_type = DA_NULL; + mime_type = GET_CONTENT_STORE_CONTENT_TYPE(file_info_data); + if (mime_type && !is_ambiguous_MIME_Type(mime_type)) { + char *extension = DA_NULL; + da_result_t ret = get_extension_from_mime_type(mime_type, &extension); + if (ret == DA_RESULT_OK && extension) + return extension; + } + + /* Priority 2-1 */ + http_msg_response_t *http_msg_response = DA_NULL; + http_msg_response = request_info->http_info.http_msg_response; + if (http_msg_response) { + char *file_name = DA_NULL; + da_bool_t b_ret = http_msg_response_get_content_disposition(http_msg_response, + DA_NULL, &file_name); + if (b_ret && file_name) { + char *extension = DA_NULL; + DA_LOG(FileManager, "Name from Content-Disposition :[%s]", file_name); + __divide_file_name_into_pure_name_N_extesion(file_name, DA_NULL, &extension); + if (file_name) { + free(file_name); + file_name = DA_NULL; + } + if (extension) + return extension; + } + } + /* Priority 2-2 */ + /* If there is location url from response header in case of redirection, + * it try to parse the extention name from the location url */ + if (GET_REQUEST_HTTP_REQ_LOCATION(request_info)) + url = GET_REQUEST_HTTP_REQ_LOCATION(request_info); + else + url = GET_SOURCE_BASIC_URL(source_info); + if (url) { + DA_LOG(FileManager, "url:[%s]", 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. what client wants, which is conveyed by DA_FEATURE_FILE_NAME + * 2. 'filename' option on HTTP response header's Content-Disposition field + * 3. requesting URL + * 4. Otherwise, define it as "No name" + */ +da_result_t __get_candidate_file_name(stage_info *stage, char **out_pure_file_name, char **out_extension) +{ + da_result_t ret = DA_RESULT_OK; + source_info_t *source_info = DA_NULL; + char *pure_file_name = DA_NULL; + char *extension = DA_NULL; + + DA_LOG_FUNC_START(FileManager); + + if (!stage || !out_pure_file_name) + return DA_ERR_INVALID_ARGUMENT; + + source_info = GET_STAGE_SOURCE_INFO(stage); + if (!source_info) + return DA_ERR_INVALID_ARGUMENT; + + /* Priority 1 */ + if (!pure_file_name && GET_DL_USER_FILE_NAME(GET_STAGE_DL_ID(stage))) { + __divide_file_name_into_pure_name_N_extesion( + GET_DL_USER_FILE_NAME(GET_STAGE_DL_ID(stage)), + &pure_file_name, &extension); + } + + /* Priority 2 */ + if (!pure_file_name) { + req_dl_info *request_info = GET_STAGE_TRANSACTION_INFO(stage); + http_msg_response_t *http_msg_response = DA_NULL; + http_msg_response = request_info->http_info.http_msg_response; + if (http_msg_response) { + char *file_name = DA_NULL; + da_bool_t b_ret = http_msg_response_get_content_disposition(http_msg_response, + DA_NULL, &file_name); + if (b_ret && file_name) { + DA_LOG(FileManager, "Name from Content-Disposition :[%s]", file_name); + __divide_file_name_into_pure_name_N_extesion(file_name, &pure_file_name, DA_NULL); + if (file_name) { + free(file_name); + file_name = DA_NULL; + } + } + } + } + + /* Priority 3 */ + if (!pure_file_name) { + char *url = DA_NULL; + req_dl_info *request_info = GET_STAGE_TRANSACTION_INFO(stage); + /* If there is location url from response header in case of redirection, + * it try to parse the file name from the location url */ + if (GET_REQUEST_HTTP_REQ_LOCATION(request_info)) + url = GET_REQUEST_HTTP_REQ_LOCATION(request_info); + else + url = GET_SOURCE_BASIC_URL(source_info); + if (url) { + DA_LOG(FileManager, "url: [%s]", url); + da_get_file_name_from_url(url, &pure_file_name); + } + } + + /* Priority 4 */ + if (!pure_file_name) { + pure_file_name = strdup(NO_NAME_TEMP_STR); + if (!pure_file_name) { + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + } + + *out_pure_file_name = pure_file_name; + pure_file_name = DA_NULL; + DA_LOG(FileManager, "candidate file name [%s]", *out_pure_file_name); + + if (out_extension) { + if (extension) { + *out_extension = extension; + extension = DA_NULL; + } else { + *out_extension = __derive_extension(stage); + DA_LOG(FileManager, "candidate extension [%s]", *out_extension); + } + } + + if (extension) + free(extension); + + return DA_RESULT_OK; + +ERR: + if (pure_file_name) + free(pure_file_name); + + if (extension) + free(extension); + + return ret; +} + + +da_result_t decide_final_file_path(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + char *default_dir = DA_NULL; + char *extension = DA_NULL; + char *tmp_file_path = DA_NULL; + char *file_name_without_extension = DA_NULL; + file_info *file_info_data = DA_NULL; + + DA_LOG_FUNC_START(FileManager); + + file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); + if (!file_info_data) + return DA_ERR_INVALID_ARGUMENT; + + ret = __get_candidate_file_name(stage, &file_name_without_extension, &extension); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = get_client_download_path(&default_dir); + if (DA_RESULT_OK != ret || DA_NULL == default_dir) { + goto ERR; + } + + tmp_file_path = get_full_path_avoided_duplication(default_dir, file_name_without_extension, extension); + if (tmp_file_path) { + GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)) + = tmp_file_path; + tmp_file_path = DA_NULL; + } else { + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + + if (file_name_without_extension && !GET_CONTENT_STORE_PURE_FILE_NAME(file_info_data)) { + GET_CONTENT_STORE_PURE_FILE_NAME(file_info_data) = file_name_without_extension; + file_name_without_extension = DA_NULL; + } + + if (extension && !GET_CONTENT_STORE_EXTENSION(file_info_data)) { + GET_CONTENT_STORE_EXTENSION(file_info_data) = extension; + extension = DA_NULL; + } + +ERR: + DA_LOG(FileManager, "decided file path = %s", GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_info_data)); + if (default_dir) { + free(default_dir); + default_dir = DA_NULL; + } + + if (file_name_without_extension) { + free(file_name_without_extension); + file_name_without_extension = DA_NULL; + } + + if (extension) { + free(extension); + extension = DA_NULL; + } + + return ret; +} + +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 final_path_len = 0; + int extension_len = 0; + + int suffix_count = 0; /* means suffix on file name. up to "_99" */ + const int max_suffix_count = 99; + int suffix_len = (int)log10(max_suffix_count+1) + 1; /* 1 means "_" */ + + if (!in_dir || !in_candidate_file_name) + return DA_NULL; + +// DA_LOG_FUNC_START(FileManager); + DA_LOG(FileManager, "in_candidate_file_name=[%s], in_extension=[%s]", in_candidate_file_name, in_extension); + + if (extension) + extension_len = strlen(extension); + + /* first 1 for "/", second 1 for ".", last 1 for DA_NULL */ + final_path_len = strlen(dir) + 1 + strlen(file_name) + 1 + + suffix_len + extension_len + 1; + + final_path = (char*)calloc(1, final_path_len); + if (!final_path) { + DA_LOG_ERR(FileManager, "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_LOG(FileManager, "decided path = [%s]", final_path); + return final_path; +} + +da_result_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_result_t ret = DA_RESULT_OK; + + DA_LOG_FUNC_START(FileManager); + + 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_LOG(FileManager, "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_LOG(FileManager, "pure file name [%s]", *out_pure_file_name); + return ret; +} + +da_result_t __file_write_buf_make_buf(file_info *file_storage) +{ + da_result_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + + DA_LOG_FUNC_START(FileManager); + + buffer = (char*) calloc(DOWNLOAD_NOTIFY_LIMIT, 1); + if (DA_NULL == buffer) { + DA_LOG_ERR(FileManager, "Calloc failure "); + ret = DA_ERR_FAIL_TO_MEMALLOC; + } else { + GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0; + GET_CONTENT_STORE_FILE_BUFFER(file_storage) = buffer; + } + + return ret; +} + +da_result_t __file_write_buf_destroy_buf(file_info *file_storage) +{ + da_result_t ret = DA_RESULT_OK; + + DA_LOG_FUNC_START(FileManager); + + if (GET_CONTENT_STORE_FILE_BUFFER(file_storage)) + free(GET_CONTENT_STORE_FILE_BUFFER(file_storage)); + + GET_CONTENT_STORE_FILE_BUFFER(file_storage) = DA_NULL; + GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0; + + return ret; +} + +da_result_t __file_write_buf_flush_buf(stage_info *stage, file_info *file_storage) +{ + da_result_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + int buffer_size = 0; + int write_success_len = 0; + void *fd = DA_NULL; + + // DA_LOG_FUNC_START(FileManager); + + buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage); + buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage); + + if (buffer_size == 0) { + DA_LOG_ERR(FileManager, "no data on buffer.."); + return ret; + } + + fd = GET_CONTENT_STORE_FILE_HANDLE(file_storage); + if (DA_NULL == fd) { + DA_LOG_ERR(FileManager, "There is no file handle."); + + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + + if (is_content_drm_dm(GET_CONTENT_STORE_CONTENT_TYPE(file_storage))) { + if (DA_TRUE != EDRM_write_convert(fd, (unsigned char*) buffer, + buffer_size)) { + DA_LOG_ERR(FileManager, "write convert fails "); + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) + += buffer_size; + } else { + write_success_len = fwrite(buffer, sizeof(char), buffer_size, + (FILE *) fd); + fflush((FILE *) fd); + if (write_success_len != buffer_size) { + DA_LOG_ERR(FileManager, "write fails "); + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) + += write_success_len; + DA_LOG(FileManager, "write %d bytes", write_success_len); + } + IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(file_storage) = DA_TRUE; + GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0; + +ERR: + return ret; +} + +da_result_t __file_write_buf_copy_to_buf(file_info *file_storage, char *body, + int body_len) +{ + da_result_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + int buffer_size = 0; + + // DA_LOG_FUNC_START(FileManager); + + buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage); + buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage); + + memcpy(buffer + buffer_size, body, body_len); + GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) += body_len; + + return ret; +} + +da_result_t __file_write_buf_directly_write(stage_info *stage, + file_info *file_storage, char *body, int body_len) +{ + da_result_t ret = DA_RESULT_OK; + int write_success_len = 0; + void *fd = DA_NULL; + + // DA_LOG_FUNC_START(FileManager); + + fd = GET_CONTENT_STORE_FILE_HANDLE(file_storage); + if (DA_NULL == fd) { + DA_LOG_ERR(FileManager, "There is no file handle."); + + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + + if (is_content_drm_dm(GET_CONTENT_STORE_CONTENT_TYPE(file_storage))) { + if (DA_TRUE != EDRM_write_convert(fd, (unsigned char*) body, + body_len)) { + DA_LOG_ERR(FileManager, "write convert fails "); + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + } else { + write_success_len = fwrite(body, sizeof(char), body_len, + (FILE *) fd); + fflush((FILE *) fd); + if (write_success_len != body_len) { + DA_LOG_ERR(FileManager, "write fails "); + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) + += write_success_len; + DA_LOG(FileManager, "write %d bytes", write_success_len); + } + IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(file_storage) = DA_TRUE; + +ERR: + return ret; +} + +da_result_t file_write_ongoing(stage_info *stage, char *body, int body_len) +{ + da_result_t ret = DA_RESULT_OK; + file_info *file_storage = DA_NULL; + int buffer_size = 0; + char *buffer = DA_NULL; + + // DA_LOG_FUNC_START(FileManager); + + if (DA_TRUE == is_this_client_manual_download_type()) { + return ret; + } + file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); + if (!file_storage) { + DA_LOG_ERR(FileManager, "file_info is empty."); + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + + buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage); + buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage); + IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(file_storage) = DA_FALSE; + + if (DA_NULL == buffer) { + if (body_len < DOWNLOAD_NOTIFY_LIMIT) { + ret = __file_write_buf_make_buf(file_storage); + if (ret != DA_RESULT_OK) + goto ERR; + + __file_write_buf_copy_to_buf(file_storage, body, body_len); + } else { + ret = __file_write_buf_directly_write(stage, + file_storage, body, body_len); + if (ret != DA_RESULT_OK) + goto ERR; + } + } else { + if (DOWNLOAD_NOTIFY_LIMIT <= body_len) { + ret = __file_write_buf_flush_buf(stage, file_storage); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = __file_write_buf_directly_write(stage, + file_storage, body, body_len); + if (ret != DA_RESULT_OK) + goto ERR; + + } else if ((DOWNLOAD_NOTIFY_LIMIT - buffer_size) <= body_len) { + ret = __file_write_buf_flush_buf(stage, file_storage); + if (ret != DA_RESULT_OK) + goto ERR; + + __file_write_buf_copy_to_buf(file_storage, body, body_len); + } else { + __file_write_buf_copy_to_buf(file_storage, body, body_len); + } + } + +ERR: + if (ret != DA_RESULT_OK) { + if (file_storage) { + GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0; + if (GET_CONTENT_STORE_FILE_BUFFER(file_storage)) { + free( + GET_CONTENT_STORE_FILE_BUFFER(file_storage)); + GET_CONTENT_STORE_FILE_BUFFER(file_storage) + = DA_NULL; + } + } + } + return ret; +} + +da_result_t file_write_complete(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + file_info*file_storage = DA_NULL; + char *buffer = DA_NULL; + unsigned int buffer_size = 0; + void *fd = DA_NULL; + + DA_LOG_FUNC_START(FileManager); + + if (DA_TRUE == is_this_client_manual_download_type()) { + return ret; + } + file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); + if (!file_storage) { + DA_LOG_ERR(FileManager, "file_info is DA_NULL."); + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + + buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage); + buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage); + + if (DA_NULL == buffer) { + DA_LOG_ERR(FileManager, "file buffer is DA_NULL"); + } else { + if (buffer_size != 0) { + ret = __file_write_buf_flush_buf(stage, file_storage); + if (ret != DA_RESULT_OK) + goto ERR; + } + __file_write_buf_destroy_buf(file_storage); + } + fd = GET_CONTENT_STORE_FILE_HANDLE(file_storage); + + if (fd) { + // call sync + fsync(fileno(fd)); + if (is_content_drm_dm( + GET_CONTENT_STORE_CONTENT_TYPE(file_storage))) { + EDRM_close_convert(&fd); + } else { + fclose(fd); + } + fd = DA_NULL; + } + GET_CONTENT_STORE_FILE_HANDLE(file_storage) = DA_NULL; +ERR: + return ret; +} + +da_result_t start_file_writing(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + file_info *file_info_data = DA_NULL; + + DA_LOG_FUNC_START(FileManager); + + if (DA_TRUE == is_this_client_manual_download_type()) { + return ret; + } + file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); + ret = get_mime_type(stage, + &GET_CONTENT_STORE_CONTENT_TYPE(file_info_data)); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = decide_final_file_path(stage); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = __set_file_size(stage); + if (DA_RESULT_OK != ret) + goto ERR; + + GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) + = 0; + + ret = __tmp_file_open(stage); + +ERR: + return ret; +} + +da_result_t start_file_writing_append(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + + DA_LOG_FUNC_START(FileManager); + if (DA_TRUE == is_this_client_manual_download_type()) { + return ret; + } + + ret = __tmp_file_open(stage); + + return ret; +} + +da_result_t discard_download(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + file_info *file_storage = DA_NULL; + char *temp_file_path = DA_NULL; + FILE *f_handle = DA_NULL; + + DA_LOG_FUNC_START(FileManager); + + file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); + + f_handle = GET_CONTENT_STORE_FILE_HANDLE(file_storage); + if (f_handle) { + if (is_content_drm_dm( + GET_CONTENT_STORE_CONTENT_TYPE(file_storage))) { + EDRM_close_convert((void **)&f_handle); + } else { + fclose(f_handle); + } + GET_CONTENT_STORE_FILE_HANDLE(file_storage) = DA_NULL; + } + temp_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage); + if (temp_file_path) { + remove_file((const char*) temp_file_path); + free(temp_file_path); + GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage) = DA_NULL; + } + + return ret; +} + +void clean_paused_file(stage_info *stage) +{ + file_info *file_info_data = DA_NULL; + char *paused_file_path = DA_NULL; + FILE *fd = DA_NULL; + + DA_LOG_FUNC_START(FileManager); + + file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); + + fd = GET_CONTENT_STORE_FILE_HANDLE(file_info_data); + if (fd) { + if (is_content_drm_dm( + GET_CONTENT_STORE_CONTENT_TYPE(file_info_data))) { + EDRM_close_convert((void **)&fd); + } else { + fclose(fd); + } + GET_CONTENT_STORE_FILE_HANDLE(file_info_data) = DA_NULL; + } + + paused_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_info_data); + remove_file((const char*) paused_file_path); + + return; +} + +da_result_t replace_content_file_in_stage(stage_info *stage, + const char *dest_dd_file_path) +{ + da_result_t ret = DA_RESULT_OK; + char *dd_file_path = DA_NULL; + int len; + + DA_LOG_FUNC_START(FileManager); + + if (!dest_dd_file_path + && (DA_FALSE == is_file_exist(dest_dd_file_path))) { + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + dd_file_path + =GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)); + + if (DA_NULL != dd_file_path) { + remove_file((const char*) dd_file_path); + free(dd_file_path); + } + len = strlen(dest_dd_file_path); + dd_file_path = calloc(1, len + 1); + if (!dd_file_path) { + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + strncpy(dd_file_path, dest_dd_file_path, len); + GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)) + = dd_file_path; + +ERR: + return ret; + +} + +da_result_t copy_file(const char *src, const char *dest) +{ + FILE *fs = DA_NULL; + FILE *fd = DA_NULL; + int freadnum = 0; + int fwritenum = 0; + char buff[4096] = { 0, }; + + DA_LOG_FUNC_START(FileManager); + + /* open files to copy */ + fs = fopen(src, "rb"); + if (!fs) { + DA_LOG_ERR(FileManager, "Fail to open src file"); + return DA_ERR_FAIL_TO_ACCESS_FILE; + } + + fd = fopen(dest, "wb"); + if (!fd) { + DA_LOG_ERR(FileManager, "Fail to open dest file"); + + fclose(fs); + return DA_ERR_FAIL_TO_ACCESS_FILE; + } + + /* actual copy */ + while (!feof(fs)) { + memset(buff, 0x00, 4096); + freadnum = fread(buff, sizeof(char), sizeof(buff), fs); + if (freadnum > 0) { + fwritenum = fwrite(buff, sizeof(char), freadnum, fd); + if (fwritenum <= 0) { + DA_LOG(FileManager, "written = %d",fwritenum); + break; + } + } else { + DA_LOG(FileManager, "read = %d",freadnum); + break; + } + } + + fflush(fd); + fsync(fileno(fd)); + fclose(fd); + fclose(fs); + + return DA_RESULT_OK; +} + +da_result_t create_dir(const char *install_dir) +{ + da_result_t ret = DA_RESULT_OK; + /* read/write/search permissions for owner and group, + * and with read/search permissions for others. */ + if (mkdir(install_dir, S_IRWXU | S_IRWXG | S_IRWXO)) { + DA_LOG_ERR(FileManager, "Fail to creaate directory [%s]", install_dir); + ret = DA_ERR_FAIL_TO_ACCESS_STORAGE; + } else { + DA_LOG(FileManager, "[%s] is created!", install_dir); + } + return ret; +} + diff --git a/src/agent/download-agent-http-mgr.c b/src/agent/download-agent-http-mgr.c new file mode 100644 index 0000000..7627534 --- /dev/null +++ b/src/agent/download-agent-http-mgr.c @@ -0,0 +1,1705 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-http-mgr.c + * @brief Including functions regarding http mgr + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + ***/ + +#include "download-agent-utils.h" +#include "download-agent-debug.h" +#include "download-agent-client-mgr.h" +#include "download-agent-http-mgr.h" +#include "download-agent-http-misc.h" +#include "download-agent-http-msg-handler.h" +#include "download-agent-file.h" +#include "download-agent-plugin-conf.h" +#include "download-agent-installation.h" +#include "download-agent-plugin-http-interface.h" + +da_result_t make_default_http_request_hdr(const char *url, + char **user_request_header, + int user_request_heaer_count, + http_msg_request_t **out_http_msg_request); +da_result_t create_resume_http_request_hdr(stage_info *stage, + http_msg_request_t **out_resume_request); + +da_result_t start_new_transaction(stage_info *stage); +da_result_t set_http_request_hdr(stage_info *stage); +da_result_t make_transaction_info_and_start_transaction(stage_info *stage); + +da_result_t pause_for_flow_control(stage_info *stage); +da_result_t unpause_for_flow_control(stage_info *stage); + +da_result_t handle_any_input(stage_info *stage); +da_result_t handle_event_control(stage_info *stage, q_event_t *event); +da_result_t handle_event_http(stage_info *stage, q_event_t *event); +da_result_t handle_event_http_packet(stage_info *stage, q_event_t *event); +da_result_t handle_event_http_final(stage_info *stage, q_event_t *event); +da_result_t handle_event_http_abort(stage_info *stage, q_event_t *event); + +da_result_t exchange_url_from_header_for_redirection(stage_info *stage, + http_msg_response_t *http_msg_response); + +da_result_t handle_event_abort(stage_info *stage); +da_result_t handle_event_cancel(stage_info *stage); +da_result_t handle_event_suspend(stage_info *stage); +da_result_t handle_event_resume(stage_info *stage); + +da_result_t handle_http_hdr(stage_info *stage, + http_msg_response_t *http_msg_response, int http_status); +da_result_t handle_http_status_code(stage_info *stage, + http_msg_response_t *http_msg_response, int http_status); +da_result_t handle_http_body(stage_info *stage, char *body, int body_len); + +da_result_t set_hdr_fields_on_download_info(stage_info *stage); + +da_result_t _check_content_type_is_matched(stage_info *stage); +da_result_t _check_enough_memory_for_this_download(stage_info *stage); +da_result_t _check_downloaded_file_size_is_same_with_header_content_size( + stage_info *stage); + +da_result_t _check_this_partial_download_is_available(stage_info *stage, + http_msg_response_t *new_http_msg_response); + +da_result_t _cancel_transaction(stage_info *stage); +da_result_t _disconnect_transaction(stage_info *stage); + +void __parsing_user_request_header(char *user_request_header, + char **out_field, char **out_value); + +http_mgr_t http_mgr; + +da_result_t init_http_mgr(void) +{ + da_result_t ret = DA_RESULT_OK; + + DA_LOG_FUNC_START(HTTPManager); + + if (http_mgr.is_http_init == DA_FALSE) { + http_mgr.is_http_init = DA_TRUE; + ret = PI_http_init(); + } + + return ret; +} + + +da_result_t request_to_abort_http_download(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + q_event_t *q_event = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + if (!stage) { + DA_LOG_ERR(HTTPManager, "Stage is NULL. download info is already destroyed"); + return DA_ERR_INVALID_ARGUMENT; + } + + DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_ABORT"); + ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_ABORT, &q_event); + if (ret != DA_RESULT_OK) { + DA_LOG_ERR(HTTPManager, "fail to make q_control_event"); + goto ERR; + } else { + DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage))); + Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), q_event); + } + +ERR: + return ret; +} + +void deinit_http_mgr(void) +{ + DA_LOG_FUNC_START(HTTPManager); + + if (http_mgr.is_http_init == DA_TRUE) { + http_mgr.is_http_init = DA_FALSE; + PI_http_deinit(); + } + + return; +} + +da_result_t request_http_download(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + + int download_id = DA_INVALID_ID; + http_state_t http_state = 0; + da_bool_t need_wait = DA_TRUE; + + queue_t *queue = DA_NULL; + req_dl_info *req_info = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + + download_id = GET_STAGE_DL_ID(stage); + queue = GET_DL_QUEUE(download_id); + req_info = GET_STAGE_TRANSACTION_INFO(stage); + + DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(download_id)); + + CHANGE_HTTP_STATE(HTTP_STATE_READY_TO_DOWNLOAD, stage); + + do { + ret = handle_any_input(stage); + if (ret != DA_RESULT_OK) { + if (DA_RESULT_OK == GET_REQUEST_HTTP_RESULT(req_info)) { + GET_REQUEST_HTTP_RESULT(req_info) = ret; + DA_LOG_CRITICAL(HTTPManager, "setting internal error [%d]", ret); + } + _cancel_transaction(stage); + } + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + http_state = GET_HTTP_STATE_ON_STAGE(stage); + DA_LOG(HTTPManager, "http_state = %d", http_state); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + + switch (http_state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + ret = start_new_transaction(stage); + if (ret != DA_RESULT_OK) { + if (DA_RESULT_OK == GET_REQUEST_HTTP_RESULT(req_info)) { + GET_REQUEST_HTTP_RESULT(req_info) = ret; + DA_LOG_CRITICAL(HTTPManager, "setting internal error [%d]", ret); + } + DA_LOG(HTTPManager, "exiting with error..."); + need_wait = DA_FALSE; + break; + } + + CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_REQUESTED, stage); + + send_client_da_state(download_id, + DA_STATE_DOWNLOAD_STARTED, + DA_RESULT_OK); + break; + + case HTTP_STATE_CANCELED: + case HTTP_STATE_DOWNLOAD_FINISH: + case HTTP_STATE_ABORTED: + DA_LOG(HTTPManager, "exiting..."); + need_wait = DA_FALSE; + break; + + default: + break; + } + + if (need_wait == DA_TRUE) { + _da_thread_mutex_lock(&(queue->mutex_queue)); + if (DA_FALSE == GET_IS_Q_HAVING_DATA(queue)) { + unpause_for_flow_control(stage); + +// DA_LOG(HTTPManager, "Waiting for input"); + Q_goto_sleep(queue); +// DA_LOG(HTTPManager, "Woke up to receive new packet or control event"); + } + _da_thread_mutex_unlock (&(queue->mutex_queue)); + + } + + } while (need_wait == DA_TRUE); + + ret = GET_REQUEST_HTTP_RESULT(req_info); + DA_LOG(HTTPManager, "--------------Exiting request_http_download! ret = %d", ret); + return ret; +} + +da_result_t request_to_cancel_http_download(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + q_event_t *q_event = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + + DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_CANCEL"); + ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_CANCEL, &q_event); + if (ret != DA_RESULT_OK) { + DA_LOG_ERR(HTTPManager, "fail to make q_control_event"); + goto ERR; + } else { + DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage))); + Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), q_event); + } + +ERR: + return ret; +} + +da_result_t request_to_suspend_http_download(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + q_event_t *q_event = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + http_state = GET_HTTP_STATE_ON_STAGE(stage); + DA_LOG(HTTPManager, "http_state = %d", http_state); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + + switch (http_state) { + case HTTP_STATE_PAUSED: + case HTTP_STATE_REQUEST_PAUSE: + DA_LOG_CRITICAL(HTTPManager, "Already paused. http_state = %d", http_state); + ret = DA_ERR_ALREADY_SUSPENDED; + break; + + default: + DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_SUSPEND"); + ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_SUSPEND, + &q_event); + if (ret != DA_RESULT_OK) { + DA_LOG_ERR(HTTPManager, "fail to make q_control_event"); + goto ERR; + } else { + DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage))); + Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), + q_event); + } + + break; + } + +ERR: + return ret; +} + +da_result_t request_to_resume_http_download(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + q_event_t *q_event = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + http_state = GET_HTTP_STATE_ON_STAGE(stage); + DA_LOG(HTTPManager, "[%d] http_state = %d", GET_STAGE_DL_ID(stage), http_state); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + + switch (http_state) { + case HTTP_STATE_PAUSED: + DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_RESUME"); + ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_RESUME, + &q_event); + if (ret != DA_RESULT_OK) { + DA_LOG_ERR(HTTPManager, "fail to make q_control_event"); + goto ERR; + } else { + DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage))); + Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), + q_event); + } + + break; + + case HTTP_STATE_REQUEST_PAUSE: + DA_LOG_ERR(HTTPManager, "[%d] Fail to resume. Previous pause is not finished. http_state = %d", GET_STAGE_DL_ID(stage), http_state); + ret = DA_ERR_INVALID_STATE; + + break; + + case HTTP_STATE_RESUMED: + ret = DA_ERR_ALREADY_RESUMED; + + break; + + default: + DA_LOG_ERR(HTTPManager, "[%d] Fail to resume. This is not a paused ID. http_state = %d", GET_STAGE_DL_ID(stage), http_state); + ret = DA_ERR_INVALID_STATE; + + break; + } + +ERR: + return ret; +} + +da_result_t start_new_transaction(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + + ret = set_http_request_hdr(stage); + if (ret != DA_RESULT_OK) + return ret; + + ret = make_transaction_info_and_start_transaction(stage); + return ret; +} + +da_result_t make_default_http_request_hdr(const char *url, + char **user_request_header, + int user_request_header_count, + http_msg_request_t **out_http_msg_request) +{ + da_result_t ret = DA_RESULT_OK; + + http_msg_request_t *http_msg_request = NULL; + char *user_agent = NULL; + + DA_LOG_FUNC_START(HTTPManager); + + if (!url) { + DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL"); + ret = DA_ERR_INVALID_URL; + goto ERR; + } + + ret = http_msg_request_create(&http_msg_request); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = http_msg_request_set_url(http_msg_request, url); + if (ret != DA_RESULT_OK) + goto ERR; + + user_agent = get_user_agent(); + if (user_agent) + 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 (user_request_header && user_request_header_count > 0) { + int i = 0; + for (i = 0; i < user_request_header_count; i++) + { + char *field = NULL; + char *value = NULL; + __parsing_user_request_header(user_request_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 { + DA_LOG_ERR(HTTPManager, "Fail to parse user request header"); + } + } + } else + DA_LOG(HTTPManager, "no user reqeust header inserted"); + + *out_http_msg_request = http_msg_request; + +ERR: + if (ret != DA_RESULT_OK) + http_msg_request_destroy(&http_msg_request); + + return ret; +} + +da_result_t set_http_request_hdr(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + req_dl_info *request_info = DA_NULL; + + char *url = DA_NULL; + char **user_request_header = DA_NULL; + int user_request_header_count = 0; + http_msg_request_t* http_msg_request = NULL; + + DA_LOG_FUNC_START(HTTPManager); + + request_info = GET_STAGE_TRANSACTION_INFO(stage); + + if (DA_NULL == + (url = GET_REQUEST_HTTP_REQ_URL(request_info))) { + DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL"); + ret = DA_ERR_INVALID_URL; + goto ERR; + } + + user_request_header = GET_REQUEST_HTTP_USER_REQUEST_HEADER( + request_info); + user_request_header_count = GET_REQUEST_HTTP_USER_REQUEST_HEADER_COUNT( + request_info); + + ret = make_default_http_request_hdr(url, user_request_header, + user_request_header_count, &http_msg_request); + if (ret == DA_RESULT_OK) + request_info->http_info.http_msg_request = http_msg_request; + +ERR: + return ret; + +} + +da_result_t make_transaction_info_and_start_transaction(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + + int download_id = DA_INVALID_ID; + req_dl_info *request_info = DA_NULL; + + input_for_tranx_t *input_for_tranx = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + + download_id = GET_STAGE_DL_ID(stage); + + request_info = GET_STAGE_TRANSACTION_INFO(stage); + + if (GET_REQUEST_HTTP_REQ_URL(request_info) == DA_NULL) { + DA_LOG_ERR(HTTPManager, "url is NULL"); + ret = DA_ERR_INVALID_URL; + goto ERR; + } + + input_for_tranx = (input_for_tranx_t*) calloc(1, + sizeof(input_for_tranx_t)); + if (input_for_tranx == DA_NULL) { + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } else { + input_for_tranx->proxy_addr = get_proxy_address(); + input_for_tranx->queue = GET_DL_QUEUE(download_id); + + input_for_tranx->http_method = PI_HTTP_METHOD_GET; + input_for_tranx->http_msg_request + = request_info->http_info.http_msg_request; + } + + ret = PI_http_start_transaction(input_for_tranx, + &(GET_REQUEST_HTTP_TRANS_ID(request_info))); + if (ret != DA_RESULT_OK) + goto ERR; + +ERR: + if (input_for_tranx) { + free(input_for_tranx); + input_for_tranx = DA_NULL; + } + + return ret; +} + +da_result_t make_req_dl_info_http(stage_info *stage, req_dl_info *out_info) +{ + char *url = DA_NULL; + char **user_request_header = DA_NULL; + int user_request_header_count = 0; + source_info_t *source_info = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + + if (!stage) { + DA_LOG_ERR(HTTPManager, "stage is NULL"); + return DA_ERR_INVALID_ARGUMENT; + } + + source_info = GET_STAGE_SOURCE_INFO(stage); + + url = source_info->source_info_type.source_info_basic->url; + user_request_header = + source_info->source_info_type.source_info_basic->user_request_header; + user_request_header_count = + source_info->source_info_type.source_info_basic->user_request_header_count; + DA_LOG(HTTPManager, "url [%s]", url); + + if (url) { + GET_REQUEST_HTTP_REQ_URL(out_info) = url; + GET_REQUEST_HTTP_USER_REQUEST_HEADER(out_info) = user_request_header; + GET_REQUEST_HTTP_USER_REQUEST_HEADER_COUNT(out_info) = + user_request_header_count; + } else { + DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL"); + return DA_ERR_INVALID_URL; + } + + _da_thread_mutex_init(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)), NULL); + + return DA_RESULT_OK; +} + +da_result_t pause_for_flow_control(stage_info *stage) +{ + return DA_RESULT_OK; +} + +da_result_t unpause_for_flow_control(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + + // DA_LOG_FUNC_START(HTTPManager); + + PI_http_unpause_transaction( + GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage))); + return ret; +} +da_result_t handle_event_abort(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + http_state_t state = 0; + + DA_LOG_FUNC_START(HTTPManager); + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + state = GET_HTTP_STATE_ON_STAGE(stage); + DA_LOG(HTTPManager, "http_state = %d", state); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + switch (state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_DOWNLOAD_STARTED: + case HTTP_STATE_DOWNLOADING: + case HTTP_STATE_REQUEST_RESUME: + case HTTP_STATE_REQUEST_PAUSE: + case HTTP_STATE_RESUMED: + case HTTP_STATE_PAUSED: + case HTTP_STATE_REQUEST_CANCEL: + CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage); + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); + _disconnect_transaction(stage); + break; + case HTTP_STATE_DOWNLOAD_FINISH: + break; + default: + DA_LOG_ERR(HTTPManager, "have to check the flow for this case"); + break; + } + return ret; +} +da_result_t handle_event_cancel(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + http_state_t state = 0; + + DA_LOG_FUNC_START(HTTPManager); + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + state = GET_HTTP_STATE_ON_STAGE(stage); + DA_LOG(HTTPManager, "http_state = %d", state); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + switch (state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + CHANGE_HTTP_STATE(HTTP_STATE_CANCELED,stage); + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); + break; + + case HTTP_STATE_PAUSED: + discard_download(stage); + CHANGE_HTTP_STATE(HTTP_STATE_CANCELED,stage); + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); + break; + + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_DOWNLOAD_STARTED: + case HTTP_STATE_DOWNLOADING: + case HTTP_STATE_REQUEST_RESUME: + case HTTP_STATE_RESUMED: + _cancel_transaction(stage); + CHANGE_HTTP_STATE(HTTP_STATE_REQUEST_CANCEL, stage); + break; + + case HTTP_STATE_DOWNLOAD_FINISH: + break; + + case HTTP_STATE_REQUEST_CANCEL: + DA_LOG(HTTPManager, "HTTP_STATE_REQUEST_CANCEL : cancel is already in progress... "); + break; + + default: + DA_LOG_ERR(HTTPManager, "have to check the flow for this case"); + break; + } + + return ret; +} + +da_result_t handle_event_suspend(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + http_state = GET_HTTP_STATE_ON_STAGE(stage); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + + switch (http_state) { + case HTTP_STATE_REQUEST_PAUSE: + DA_LOG(HTTPManager, "already requested to pause! do nothing"); + break; + + case HTTP_STATE_READY_TO_DOWNLOAD: + CHANGE_HTTP_STATE(HTTP_STATE_PAUSED,stage); + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_PAUSED, stage); + send_client_da_state(GET_STAGE_DL_ID(stage), + DA_STATE_SUSPENDED, DA_RESULT_OK); + break; + + default: + _cancel_transaction(stage); + GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)) = DA_RESULT_OK; + DA_LOG_CRITICAL(HTTPManager, "[%d] cleanup internal error", GET_STAGE_DL_ID(stage)); + CHANGE_HTTP_STATE(HTTP_STATE_REQUEST_PAUSE,stage); + break; + } + + return ret; +} + +da_result_t handle_event_resume(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + http_msg_request_t *resume_request = NULL; + + http_state_t http_state = 0; + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + http_state = GET_HTTP_STATE_ON_STAGE(stage); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + + if (http_state != HTTP_STATE_PAUSED) { + DA_LOG_ERR(HTTPManager, "Not HTTP_STATE_PAUSED! http_state = %d", http_state); + ret = DA_ERR_INVALID_STATE; + goto ERR; + } + + GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)) = DA_RESULT_OK; + DA_LOG_CRITICAL(HTTPManager, "[%d] cleanup internal error", GET_STAGE_DL_ID(stage)); + + CHANGE_HTTP_STATE(HTTP_STATE_REQUEST_RESUME,stage); + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD,stage); + + ret = create_resume_http_request_hdr(stage, &resume_request); + if (ret != DA_RESULT_OK) + goto ERR; + + if (GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_request) + free(GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_request); + + GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_request + = resume_request; + + make_transaction_info_and_start_transaction(stage); + +ERR: + return ret; + +} + +da_result_t create_resume_http_request_hdr(stage_info *stage, + http_msg_request_t **out_resume_request) +{ + da_result_t ret = DA_RESULT_OK; + da_bool_t b_ret = DA_FALSE; + + req_dl_info *request_info = NULL; + + http_msg_response_t *first_response = NULL; + http_msg_request_t *resume_request = NULL; + + char *value = NULL; + char *url = NULL; + unsigned int downloaded_data_size = 0; + char downloaded_data_size_to_str[32] = { 0, }; + + char *etag_from_response = NULL; + char *date_from_response = NULL; + + DA_LOG_FUNC_START(HTTPManager); + + request_info = GET_STAGE_TRANSACTION_INFO(stage); + + if (!(url = GET_REQUEST_HTTP_REQ_URL(GET_STAGE_TRANSACTION_INFO(stage)))) { + DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL"); + ret = DA_ERR_INVALID_URL; + goto ERR; + } + + first_response = request_info->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_LOG(HTTPManager, "[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_LOG(HTTPManager, "[Date][%s]", date_from_response); + } + + downloaded_data_size + = GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)); + DA_LOG(HTTPManager, "downloaded_data_size = %u", downloaded_data_size); + snprintf(downloaded_data_size_to_str, sizeof(downloaded_data_size_to_str), "bytes=%u-", + downloaded_data_size); + DA_LOG(HTTPManager, "downloaded_data_size_to_str = %s", downloaded_data_size_to_str); + } + + ret = make_default_http_request_hdr(url, NULL, 0, &resume_request); + if (ret != DA_RESULT_OK) + goto ERR; + + 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(downloaded_data_size_to_str) > 0) + http_msg_request_add_field(resume_request, HTTP_FIELD_RANGE, + downloaded_data_size_to_str); + + *out_resume_request = resume_request; + +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_result_t handle_any_input(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + + int download_id = GET_STAGE_DL_ID(stage); + + queue_t *queue = DA_NULL; + q_event_t *event = DA_NULL; + + // DA_LOG_FUNC_START(HTTPManager); + + queue = GET_DL_QUEUE(download_id); + + Q_pop_event(queue, &event); + if (event == DA_NULL) { + DA_LOG(HTTPManager, "There is no data on the queue!"); + return DA_RESULT_OK; + } + + switch (event->event_type) { + case Q_EVENT_TYPE_CONTROL: + ret = handle_event_control(stage, event); + break; + + case Q_EVENT_TYPE_DATA_HTTP: + ret = handle_event_http(stage, event); + break; + + case Q_EVENT_TYPE_DATA_DRM: + break; + + default: + break; + } + + Q_destroy_q_event(&event); + + return ret; +} + +da_result_t handle_event_control(stage_info *stage, q_event_t *event) +{ + da_result_t ret = DA_RESULT_OK; + + DA_LOG_FUNC_START(HTTPManager); + + if (event->event_type == Q_EVENT_TYPE_CONTROL) { + switch (event->type.q_event_control.control_type) { + case Q_EVENT_TYPE_CONTROL_CANCEL: + DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_CANCEL"); + ret = handle_event_cancel(stage); + break; + + case Q_EVENT_TYPE_CONTROL_SUSPEND: + DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_SUSPEND"); + ret = handle_event_suspend(stage); + break; + + case Q_EVENT_TYPE_CONTROL_RESUME: + DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_RESUME"); + ret = handle_event_resume(stage); + break; + case Q_EVENT_TYPE_CONTROL_ABORT: + DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_ABORT"); + ret = handle_event_abort(stage); + break; + /* Fixme: need to think how we use this type. For now, this type is not used. */ + case Q_EVENT_TYPE_CONTROL_NET_DISCONNECTED: + DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_NET_DISCONNECTED"); + break; + } + } + + return ret; +} + +da_result_t handle_event_http(stage_info *stage, q_event_t *event) +{ + da_result_t ret = DA_RESULT_OK; + q_event_data_http_t *q_event_data_http = DA_NULL; + + // DA_LOG_FUNC_START(HTTPManager); + + if (event->event_type == Q_EVENT_TYPE_DATA_HTTP) { + q_event_data_http = &(event->type.q_event_data_http); + switch (q_event_data_http->data_type) { + case Q_EVENT_TYPE_DATA_PACKET: + ret = handle_event_http_packet(stage, event); + + break; + + case Q_EVENT_TYPE_DATA_FINAL: + DA_LOG(HTTPManager, "Q_EVENT_TYPE_DATA_FINAL"); + ret = handle_event_http_final(stage, event); + + break; + + case Q_EVENT_TYPE_DATA_ABORT: + DA_LOG(HTTPManager, "Q_EVENT_TYPE_DATA_ABORT"); + ret = handle_event_http_abort(stage, event); + + break; + } + } + + return ret; +} + +da_result_t handle_event_http_packet(stage_info *stage, q_event_t *event) +{ + da_result_t ret = DA_RESULT_OK; + da_bool_t is_handle_hdr_success = DA_TRUE; + q_event_data_http_t *received_data = DA_NULL; + + // DA_LOG_FUNC_START(HTTPManager); + + received_data = &(event->type.q_event_data_http); + + if (received_data->http_response_msg) { + ret = handle_http_hdr(stage, received_data->http_response_msg, + received_data->http_response_msg->status_code); + if (DA_RESULT_OK != ret) { + is_handle_hdr_success = DA_FALSE; + } + + received_data->http_response_msg = NULL; + } + + if (received_data->body_len > 0) { + if (is_handle_hdr_success == DA_TRUE) { + ret = handle_http_body(stage, received_data->body_data, + received_data->body_len); + } + /*For all cases body_data should be deleted*/ + free(received_data->body_data); + received_data->body_data = DA_NULL; + } + + return ret; +} + +da_result_t handle_event_http_final(stage_info *stage, q_event_t *event) +{ + da_result_t ret = DA_RESULT_OK; + + http_state_t http_state = 0; + int download_id = DA_INVALID_ID; + + DA_LOG_FUNC_START(HTTPManager); + + download_id = GET_STAGE_DL_ID(stage); + _disconnect_transaction(stage); + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + http_state = GET_HTTP_STATE_ON_STAGE(stage); + DA_LOG(HTTPManager, "http_state = %d", http_state); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + + switch (http_state) { + case HTTP_STATE_REDIRECTED: + CHANGE_HTTP_STATE(HTTP_STATE_READY_TO_DOWNLOAD,stage); + break; + + case HTTP_STATE_DOWNLOAD_REQUESTED: + DA_LOG(HTTPManager, "case HTTP_STATE_DOWNLOAD_REQUESTED"); + CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_FINISH, stage); + break; + + case HTTP_STATE_DOWNLOADING: + DA_LOG(HTTPManager, "case HTTP_STATE_DOWNLOADING"); + ret = file_write_complete(stage); + if (ret != DA_RESULT_OK) { + discard_download(stage); + goto ERR; + } + /* ret = _check_downloaded_file_size_is_same_with_header_content_size(stage); + if(ret != DA_RESULT_OK) + { + discard_download(stage) ; + goto ERR; + } + */ + CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_FINISH, stage); + send_client_update_downloading_info( + download_id, + GET_DL_REQ_ID(download_id), + GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), + DA_NULL); + break; + + case HTTP_STATE_REQUEST_PAUSE: + if (GET_CONTENT_STORE_FILE_HANDLE(GET_STAGE_CONTENT_STORE_INFO(stage))) { + ret = file_write_complete(stage); + send_client_update_downloading_info( + download_id, + GET_DL_REQ_ID(download_id), + GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), + GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage))); + + IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage)) + = DA_FALSE; + } + CHANGE_HTTP_STATE(HTTP_STATE_PAUSED,stage); + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_PAUSED, stage); + send_client_da_state(download_id, DA_STATE_SUSPENDED, + DA_RESULT_OK); + DA_LOG(HTTPManager, "Server Notification code is set to NULL"); + break; + + case HTTP_STATE_ABORTED: + case HTTP_STATE_CANCELED: + discard_download(stage); + break; + + case HTTP_STATE_REQUEST_CANCEL: + ret = file_write_complete(stage); + if (ret != DA_RESULT_OK) + goto ERR; + discard_download(stage); + CHANGE_HTTP_STATE(HTTP_STATE_CANCELED, stage); + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); + break; + + default: + ret = file_write_complete(stage); + if (ret != DA_RESULT_OK) + goto ERR; + discard_download(stage); + CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage); + break; + } + +ERR: + /* When file complete is failed */ + if (DA_RESULT_OK != ret) { + CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_FINISH, stage); + } + return ret; +} + +da_result_t handle_event_http_abort(stage_info *stage, q_event_t *event) +{ + da_result_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + + DA_LOG_FUNC_START(HTTPManager); + + GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)) + = event->type.q_event_data_http.error_type; + DA_LOG_CRITICAL(HTTPManager, "set internal error code : [%d]", GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage))); + _disconnect_transaction(stage); + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + http_state = GET_HTTP_STATE_ON_STAGE(stage); + DA_LOG(HTTPManager, "http_state = %d", http_state); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + + switch (http_state) { + case HTTP_STATE_REQUEST_PAUSE: + CHANGE_HTTP_STATE(HTTP_STATE_PAUSED,stage); + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_PAUSED, stage); + send_client_da_state(GET_STAGE_DL_ID(stage), + DA_STATE_SUSPENDED, DA_RESULT_OK); + ret = file_write_complete(stage); + if (ret != DA_RESULT_OK) + goto ERR; + break; + + case HTTP_STATE_REQUEST_CANCEL: + CHANGE_HTTP_STATE(HTTP_STATE_CANCELED,stage); + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); + ret = file_write_complete(stage); + if (ret != DA_RESULT_OK) + goto ERR; + discard_download(stage); + break; + + default: + CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage); + ret = file_write_complete(stage); + if (ret != DA_RESULT_OK) + goto ERR; + discard_download(stage); + break; + } +ERR: + return ret; +} + +da_result_t handle_http_hdr(stage_info *stage, + http_msg_response_t *http_msg_response, int http_status) +{ + da_result_t ret = DA_RESULT_OK; + int download_id = DA_INVALID_ID; + http_state_t http_state = 0; + char *response_header_data = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + + download_id = GET_STAGE_DL_ID(stage); + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + http_state = GET_HTTP_STATE_ON_STAGE(stage); + DA_LOG(HTTPManager, "http_state = %d", http_state); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + + switch (http_state) { + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_REQUEST_PAUSE: + case HTTP_STATE_REQUEST_RESUME: + case HTTP_STATE_REDIRECTED: + /* In case of manual download, this is first update. + * So, the client can know the mime type at second update */ + if (DA_TRUE == is_this_client_manual_download_type() && + http_msg_response) { + // SHOULD free response_header_data when it is not used any more + response_header_data = get_http_response_header_raw(http_msg_response); + send_client_update_dl_info( + download_id, + GET_DL_REQ_ID(download_id), + GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)), + GET_CONTENT_STORE_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), + DA_NULL, + response_header_data, + DA_NULL); + if (response_header_data) { + free(response_header_data); + response_header_data = NULL; + } + } + ret = handle_http_status_code(stage, http_msg_response, + http_status); + if (ret != DA_RESULT_OK) + goto ERR; + break; + + case HTTP_STATE_REQUEST_CANCEL: + DA_LOG(HTTPManager, "Cancel is in progress.. http_state = %d", http_state); + break; + + default: + DA_LOG_ERR(HTTPManager, "http_state = %d", http_state); + goto ERR; + } + +ERR: + return ret; +} + +da_result_t handle_http_status_code(stage_info *stage, + http_msg_response_t *http_msg_response, int http_status) +{ + da_result_t ret = DA_RESULT_OK; + + int download_id = DA_INVALID_ID; + req_dl_info *request_info = DA_NULL; + http_state_t http_state = 0; + + DA_LOG_FUNC_START(HTTPManager); + + download_id = GET_STAGE_DL_ID(stage); + request_info = GET_STAGE_TRANSACTION_INFO(stage); + + GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_response + = http_msg_response; + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + http_state = GET_HTTP_STATE_ON_STAGE(stage); + DA_LOG(HTTPManager, "http_state = %d", http_state); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + + switch (http_status) { + case 200: + case 201: + case 202: + case 203: + if (http_state == HTTP_STATE_REQUEST_RESUME) + clean_paused_file(stage); + ret = set_hdr_fields_on_download_info(stage); + if (ret != DA_RESULT_OK) + goto ERR; + ret = _check_content_type_is_matched(stage); + if (ret != DA_RESULT_OK) + goto ERR; + ret = _check_enough_memory_for_this_download(stage); + if (ret != DA_RESULT_OK) + goto ERR; + CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_STARTED,stage); + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD,stage); // ? + break; + + case 206: + DA_LOG(HTTPManager, "HTTP Status is %d - Partial download for resume!",http_status); + if (http_state != HTTP_STATE_REQUEST_RESUME) { + DA_LOG_ERR(HTTPManager, "This download is not resumed, revoke"); + ret = DA_ERR_INVALID_STATE; + goto ERR; + } + ret = _check_this_partial_download_is_available(stage, + http_msg_response); + if (ret != DA_RESULT_OK) + goto ERR; + CHANGE_HTTP_STATE(HTTP_STATE_RESUMED,stage); + CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD,stage); + break; + + case 300: + case 301: + case 302: + case 303: + case 305: + case 306: + case 307: + DA_LOG(HTTPManager, "HTTP Status is %d - redirection!",http_status); + ret = exchange_url_from_header_for_redirection(stage, http_msg_response); + if (ret != DA_RESULT_OK) + goto ERR; + CHANGE_HTTP_STATE(HTTP_STATE_REDIRECTED,stage); + http_msg_response_destroy(&http_msg_response); + break; + + case 100: + case 101: + case 102: + case 204: + case 304: + DA_LOG(HTTPManager, "HTTP Status is %d - 204 means 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_LOG_CRITICAL(HTTPManager, "set internal error code : DA_ERR_UNREACHABLE_SERVER [%d]", DA_ERR_UNREACHABLE_SERVER); + break; + } + +ERR: + return ret; +} + +da_result_t exchange_url_from_header_for_redirection(stage_info *stage, + http_msg_response_t *http_msg_response) +{ + da_result_t ret = DA_RESULT_OK; + char *location = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + + if (http_msg_response_get_location(http_msg_response, &location)) { + DA_LOG(HTTPManager, "location = %s\n", location); + GET_REQUEST_HTTP_REQ_LOCATION(GET_STAGE_TRANSACTION_INFO(stage)) = location; + } + + return ret; +} + +da_result_t handle_http_body(stage_info *stage, char *body, int body_len) +{ + da_result_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + int download_id = DA_INVALID_ID; + + // DA_LOG_FUNC_START(HTTPManager); + + download_id = GET_STAGE_DL_ID(stage); + + if (DA_RESULT_OK + != GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage))) { + DA_LOG_CRITICAL(HTTPManager, "ignore because internal error code is set with [%d]", + GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage))); + return ret; + } + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + http_state = GET_HTTP_STATE_ON_STAGE(stage); + // DA_LOG(HTTPManager, "http_state = %d", http_state); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + + if (http_state == HTTP_STATE_DOWNLOAD_STARTED) { + ret = start_file_writing(stage); + if (DA_RESULT_OK != ret) + goto ERR; + + CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOADING, stage); + send_client_da_state(download_id, DA_STATE_DOWNLOADING, + DA_RESULT_OK); + send_client_update_dl_info( + download_id, + GET_DL_REQ_ID(download_id), + GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)), + GET_CONTENT_STORE_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), + GET_CONTENT_STORE_TMP_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)), + DA_NULL, + DA_NULL); + } else if (http_state == HTTP_STATE_RESUMED) { + ret = start_file_writing_append(stage); + if (DA_RESULT_OK != ret) + goto ERR; + + CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOADING,stage); + send_client_da_state(download_id, DA_STATE_RESUMED, + DA_RESULT_OK); + send_client_da_state(download_id, DA_STATE_DOWNLOADING, + DA_RESULT_OK); + } + + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + http_state = GET_HTTP_STATE_ON_STAGE(stage); + // DA_LOG(HTTPManager, "http_state = %d", http_state); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + + switch (http_state) { + case HTTP_STATE_REDIRECTED: + DA_LOG(HTTPManager, "Just ignore http body, because this body is not for redirection one."); + break; + + case HTTP_STATE_DOWNLOADING: + /* 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(stage, body, body_len); + if (ret != DA_RESULT_OK) + goto ERR; + if (DA_TRUE == is_this_client_manual_download_type()) { + send_client_update_dl_info( + download_id, + GET_DL_REQ_ID(download_id), + GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)), + body_len, + GET_CONTENT_STORE_TMP_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)), + DA_NULL, + body); + } else if ((DA_TRUE == + IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage)))) { + send_client_update_downloading_info( + download_id, + GET_DL_REQ_ID(download_id), + GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), + DA_NULL); + + IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage)) + = DA_FALSE; + } + break; + + case HTTP_STATE_REQUEST_PAUSE: + if (DA_TRUE == is_this_client_manual_download_type()) { + send_client_update_dl_info( + download_id, + GET_DL_REQ_ID(download_id), + GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)), + GET_CONTENT_STORE_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), + GET_CONTENT_STORE_TMP_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)), + body, + DA_NULL); + } else { + ret = file_write_ongoing(stage, body, body_len); + if (ret != DA_RESULT_OK) + goto ERR; + } + break; + + default: + DA_LOG(HTTPManager, "Do nothing! http_state is in case %d", http_state); + + goto ERR; + } + +ERR: + return ret; +} + +/* Function should be renamed , as it is actually not setting the header fields in download info */ +da_result_t set_hdr_fields_on_download_info(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + da_bool_t b_ret = DA_FALSE; + + req_dl_info *request_info = DA_NULL; + http_msg_response_t *http_msg_response = NULL; + + char *value = NULL; + int int_value = 0; + + DA_LOG_FUNC_START(HTTPManager); + + request_info = GET_STAGE_TRANSACTION_INFO(stage); + + http_msg_response + = request_info->http_info.http_msg_response; + if (!http_msg_response) { + DA_LOG_ERR(HTTPManager, "There is no header data!!"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + b_ret = http_msg_response_get_content_type(http_msg_response, &value); + if (b_ret) { + GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info) = value; + value = NULL; + DA_LOG(HTTPManager, "[Content-Type][%s] - stored", GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info)); + } + + b_ret = http_msg_response_get_content_length(http_msg_response, + &int_value); + if (b_ret) { + GET_REQUEST_HTTP_HDR_CONT_LEN(request_info) = int_value; + int_value = 0; + DA_LOG(HTTPManager, "[Content-Length][%d] - stored", GET_REQUEST_HTTP_HDR_CONT_LEN(request_info)); + } + + b_ret = http_msg_response_get_ETag(http_msg_response, &value); + if (b_ret) { + GET_REQUEST_HTTP_HDR_ETAG(request_info) = value; + value = NULL; + DA_LOG(HTTPManager, "[ETag][%s] - stored ", GET_REQUEST_HTTP_HDR_ETAG(request_info)); + } + +ERR: + return ret; +} + +da_result_t _check_content_type_is_matched(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + req_dl_info *request_info = DA_NULL; + source_info_t *source_info = DA_NULL; + char *content_type_from_server = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + + request_info = GET_STAGE_TRANSACTION_INFO(stage); + source_info = GET_STAGE_SOURCE_INFO(stage); + + content_type_from_server = GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info); + if (content_type_from_server == DA_NULL) { + DA_LOG(HTTPManager, "http header has no Content-Type field, no need to compare"); + return DA_RESULT_OK; + } + + return ret; +} + +da_result_t _check_enough_memory_for_this_download(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + + req_dl_info *request_info = DA_NULL; + + long long cont_len = 0; + da_storage_size_t memory; + + DA_LOG_FUNC_START(HTTPManager); + + memset(&memory, 0x00, sizeof(da_storage_size_t)); + request_info = GET_STAGE_TRANSACTION_INFO(stage); + + cont_len = (long long) GET_REQUEST_HTTP_HDR_CONT_LEN(request_info); + if (cont_len) { + ret = get_available_memory(DA_STORAGE_PHONE, &memory); + if (DA_RESULT_OK == ret) { + DA_LOG(HTTPManager, "Memory avail: %lu, Memory block :%lu Content: %lld",memory.b_available,memory.b_size, cont_len); + if (memory.b_available < ((cont_len + + SAVE_FILE_BUFFERING_SIZE_50KB) + / memory.b_size)) /* 50KB buffering */ + { + ret = DA_ERR_DISK_FULL; + goto ERR; + } + } + } + +ERR: + return ret; +} + +da_result_t _check_this_partial_download_is_available(stage_info *stage, + http_msg_response_t *new_http_msg_response) +{ + da_result_t ret = DA_RESULT_OK; + da_bool_t b_ret = DA_FALSE; + + char *origin_ETag = NULL; + char *new_ETag = NULL; + + int remained_content_len = 0; + da_storage_size_t memory; + + char *value = NULL; + int int_value = 0; + + DA_LOG_FUNC_START(HTTPManager); + + origin_ETag + = GET_REQUEST_HTTP_HDR_ETAG(GET_STAGE_TRANSACTION_INFO(stage)); + + b_ret = http_msg_response_get_content_length(new_http_msg_response, + &int_value); + if (b_ret) { + remained_content_len = int_value; + int_value = 0; + DA_LOG(HTTPManager, "[remained_content_len][%d]", remained_content_len); + } + + b_ret = http_msg_response_get_ETag(new_http_msg_response, &value); + if (b_ret) { + new_ETag = value; + value = NULL; + DA_LOG(HTTPManager, "[new ETag][%s]", new_ETag); + } else { + goto ERR; + } + + if (0 != strcmp(origin_ETag, new_ETag)) { + DA_LOG_ERR(HTTPManager, "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) { + ret = get_available_memory(DA_STORAGE_PHONE, &memory); + if (DA_RESULT_OK == ret) { + DA_LOG(HTTPManager, "Memory avail: %lu, Memory block :%lu Content: %lld",memory.b_available,memory.b_size, remained_content_len ); + if (memory.b_available < ((remained_content_len + + SAVE_FILE_BUFFERING_SIZE_50KB) + / memory.b_size)) /* 50KB buffering */ + { + ret = DA_ERR_DISK_FULL; + goto ERR; + } + } + } + +ERR: + if (new_ETag) { + free(new_ETag); + new_ETag = DA_NULL; + } + + return ret; +} + +da_result_t _check_downloaded_file_size_is_same_with_header_content_size( + stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + + req_dl_info *request_info = DA_NULL; + file_info *file_info_data = DA_NULL; + + char *real_file_path = DA_NULL; + int content_size_from_real_file = DA_INVALID_ID; + unsigned int content_size_from_http_header = DA_INVALID_ID; + + DA_LOG_FUNC_START(HTTPManager); + + request_info = GET_STAGE_TRANSACTION_INFO(stage); + file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); + + content_size_from_http_header + = GET_CONTENT_STORE_FILE_SIZE(file_info_data); + + if (content_size_from_http_header > 0) { + real_file_path + = GET_CONTENT_STORE_TMP_FILE_NAME(file_info_data); + if (is_content_drm_dm( + GET_CONTENT_STORE_CONTENT_TYPE(file_info_data))) { + /* FIXME Later : How can get the file size of DRM file. */ + content_size_from_real_file + = content_size_from_http_header; + } else { + get_file_size(real_file_path, + &content_size_from_real_file); + } + + if ((unsigned int) content_size_from_real_file + != content_size_from_http_header) { + DA_LOG_ERR(HTTPManager, "size from header = %d, real size = %d, DA_ERR_MISMATCH_CONTENT_SIZE", content_size_from_http_header, content_size_from_real_file); + ret = DA_ERR_MISMATCH_CONTENT_SIZE; + } + } + + return ret; +} + +da_result_t _disconnect_transaction(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + int transaction_id = DA_INVALID_ID; + + DA_LOG_FUNC_START(HTTPManager); + + transaction_id + = GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage)); + + DA_LOG(HTTPManager, "transaction_id = %d download_id = %d", transaction_id, GET_STAGE_DL_ID(stage)); + + if (transaction_id != DA_INVALID_ID) { + ret = PI_http_disconnect_transaction(transaction_id); + GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage)) + = DA_INVALID_ID; + } + + return ret; +} + +da_result_t _cancel_transaction(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + int transaction_id = DA_INVALID_ID; + + DA_LOG_FUNC_START(HTTPManager); + + transaction_id + = GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage)); + + DA_LOG(HTTPManager, "transaction_id = %d", transaction_id); + + if (transaction_id != DA_INVALID_ID) { + http_state_t state = 0; + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + state = GET_HTTP_STATE_ON_STAGE(stage); + if (state <= HTTP_STATE_DOWNLOAD_REQUESTED) + ret = PI_http_cancel_transaction(transaction_id, DA_TRUE); + else + ret = PI_http_cancel_transaction(transaction_id, DA_FALSE); + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); + } + + return ret; +} + +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_LOG_FUNC_START(HTTPManager); + + if (!user_request_header) { + DA_LOG_ERR(HTTPManager, "user_request_header is NULL"); + goto ERR; + } + + pos = strchr(user_request_header, ':'); + if (!pos) { + DA_LOG_ERR(HTTPManager, "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_LOG_ERR(HTTPManager, "Wrong field name"); + goto ERR; + } + field = (char *)calloc(1, len + 1); + if (!field) { + DA_LOG_ERR(HTTPManager, "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_LOG_ERR(HTTPManager, "Fail to calloc"); + goto ERR; + } + strncpy(value, pos, len); + *out_field = field; + *out_value = value; + DA_LOG(HTTPManager, "field[%s], value[%s]", field, value); + + return; +ERR: + if (field) { + free(field); + field = NULL; + } + if (value) { + free(value); + value = NULL; + } + return; +} + diff --git a/src/agent/download-agent-http-misc.c b/src/agent/download-agent-http-misc.c new file mode 100644 index 0000000..b43be29 --- /dev/null +++ b/src/agent/download-agent-http-misc.c @@ -0,0 +1,71 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-http-misc.c + * @brief Including miscellaneous functions for http + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + ***/ + +#include "download-agent-http-misc.h" +#include "download-agent-debug.h" +#include "download-agent-dl-mgr.h" +#include "download-agent-plugin-conf.h" +#include "download-agent-client-mgr.h" + +#define DEFAULT_HTTP_ACCEPT_HEADERS \ + "Accept-Language: en\r\n" \ + "Accept-Charset: utf-8\r\n" \ + + +char* get_user_agent() +{ + char *uagent_str = DA_NULL; + + DA_LOG_FUNC_START(Default); + + uagent_str = get_client_user_agent_string(); + if (uagent_str) { + return uagent_str; + } else { + return GET_USER_AGENT; + } +} + +da_bool_t is_supporting_protocol(const char* protocol) +{ + if((protocol == NULL) || (1 > strlen(protocol))) + { + return DA_FALSE; + } + + if(!strcasecmp(protocol, "http")) + { + return DA_TRUE; + } + else if(!strcasecmp(protocol, "https")) + { + return DA_TRUE; + } + else + { + return DA_FALSE; + } + +} diff --git a/src/agent/download-agent-http-msg-handler.c b/src/agent/download-agent-http-msg-handler.c new file mode 100644 index 0000000..d5e3333 --- /dev/null +++ b/src/agent/download-agent-http-msg-handler.c @@ -0,0 +1,1350 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-http-msg-handler.c + * @brief Utilities to manipulate HTTP messages + * @author Keunsoon Lee (keunsoon.lee@samsung.com) + */ + +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include "download-agent-http-msg-handler.h" +#include "download-agent-debug.h" +#include "download-agent-http-misc.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_result_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_result_t http_msg_request_create(http_msg_request_t **http_msg_request) +{ + http_msg_request_t *temp_http_msg_request = NULL; + + DA_LOG_FUNC_START(HTTPManager); + + 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_LOG_ERR(HTTPManager, "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_LOG(HTTPManager, "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_LOG_FUNC_START(HTTPManager); + + 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_result_t http_msg_request_set_method(http_msg_request_t *http_msg_request, + const char *method) +{ + DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_request || !method) { + DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + // ToDo: check method is valid + + http_msg_request->http_method = strdup(method); + + DA_LOG(HTTPManager, "http method : %s", http_msg_request->http_method); + + return DA_RESULT_OK; +} + +da_result_t http_msg_request_get_method(http_msg_request_t *http_msg_request, + const char **method) +{ + // DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_request) { + DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + if (http_msg_request->http_method) { + *method = http_msg_request->http_method; + return DA_RESULT_OK; + } else { + *method = DA_NULL; + return DA_ERR_INVALID_ARGUMENT; + } +} + +da_result_t http_msg_request_set_url(http_msg_request_t *http_msg_request, + const char *url) +{ + DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_request) { + DA_LOG_ERR(HTTPManager, "http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + if (!url) { + DA_LOG_ERR(HTTPManager, "url is NULL; DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_URL; + } + + http_msg_request->url = strdup(url); + + DA_LOG(HTTPManager, "http url : %s", http_msg_request->url); + + return DA_RESULT_OK; +} + +da_result_t http_msg_request_get_url(http_msg_request_t *http_msg_request, + const char **url) +{ + // DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_request) { + DA_LOG_ERR(HTTPManager, "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_result_t http_msg_request_set_body(http_msg_request_t *http_msg_request, + const char *body) +{ + // DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_request) { + DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + if (!body) + return DA_RESULT_OK; + + http_msg_request->http_body = strdup(body); + + DA_LOG(HTTPManager, "http body : %s", http_msg_request->http_body); + + return DA_RESULT_OK; +} + +da_result_t http_msg_request_get_body(http_msg_request_t *http_msg_request, + const char **body) +{ + // DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_request) { + DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + if (http_msg_request->http_body) { + *body = http_msg_request->http_body; + return DA_RESULT_OK; + } else { + *body = DA_NULL; + return DA_ERR_INVALID_ARGUMENT; + } +} + +/* FIXME later : check to free filed and value after this API is called */ +da_result_t http_msg_request_add_field(http_msg_request_t *http_msg_request, + const char *field, const char *value) +{ + // DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_request) { + DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + return __http_header_add_field(&(http_msg_request->head), field, value, WITHOUT_PARSING_OPTION); +} + +da_result_t http_msg_response_create(http_msg_response_t **http_msg_response) +{ + http_msg_response_t *temp_http_msg_response = NULL; + + DA_LOG_FUNC_START(HTTPManager); + + temp_http_msg_response = (http_msg_response_t *)calloc(1, + sizeof(http_msg_response_t)); + if (!temp_http_msg_response) { + DA_LOG_ERR(HTTPManager, "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_LOG_FUNC_START(HTTPManager); + 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_result_t http_msg_response_set_status_code( + http_msg_response_t *http_msg_response, int status_code) +{ + // DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_response) { + DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + http_msg_response->status_code = status_code; + + return DA_RESULT_OK; +} + +da_result_t http_msg_response_get_status_code( + http_msg_response_t *http_msg_response, int *status_code) +{ + DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_response) { + DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + *status_code = http_msg_response->status_code; + + return DA_RESULT_OK; +} + +da_result_t http_msg_response_add_field(http_msg_response_t *http_msg_response, + const char *field, const char *value) +{ + // DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_response) { + DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + return __http_header_add_field(&(http_msg_response->head), field, value, WITH_PARSING_OPTION); +} + +da_result_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_LOG_FUNC_START(HTTPManager); + DA_LOG(HTTPManager, "[%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 && + strncmp(cur->field, field, strlen(field)) == 0) { + DA_LOG(HTTPManager, "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_LOG_ERR(HTTPManager, "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; + + // DA_LOG_FUNC_START(HTTPManager); + + cur = *head; + + while (cur) { + if (cur->field) { + DA_LOG(HTTPManager, "field= %s", 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)); + + 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_LOG_FUNC_START(HTTPManager); + + cur = *head; + + while (cur) { + if (cur->field) { + DA_LOG(HTTPManager, "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_result_t http_msg_request_get_iter(http_msg_request_t *http_msg_request, + http_msg_iter_t *http_msg_iter) +{ + DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_request) { + DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + *http_msg_iter = http_msg_request->head; + + return DA_RESULT_OK; +} + +da_result_t http_msg_response_get_iter(http_msg_response_t *http_msg_response, + http_msg_iter_t *http_msg_iter) +{ + // DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_response) { + DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + *http_msg_iter = http_msg_response->head; + // DA_LOG(HTTPManager, "retrieve iter = 0x%x", (unsigned int)http_msg_iter); + + 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; + + // DA_LOG_FUNC_START(HTTPManager); + + // DA_LOG(HTTPManager, "getting iter = 0x%x", (unsigned int)cur); + + if (cur) { + *out_field = cur->field; + *out_value = cur->value; + *http_msg_iter = cur->next; + + return DA_TRUE; + } else { + // DA_LOG(HTTPManager, "end of iter"); + 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; + + // DA_LOG_FUNC_START(HTTPManager); + + // DA_LOG(HTTPManager, "getting iter = 0x%x", (unsigned int)cur); + + if (cur) { + *out_field = cur->field; + *out_header = cur; + *http_msg_iter = cur->next; + + return DA_TRUE; + } else { + // DA_LOG(HTTPManager, "end of iter"); + 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_LOG_FUNC_START(HTTPManager); + + 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_LOG(HTTPManager, "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_result_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_LOG_FUNC_START(HTTPManager); + + if (!org_str) + return NULL; + + /* Do Not use strtok(). It's not thread safe. */ + // DA_LOG_CRITICAL(HTTPManager, "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_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + strncpy(wanted_str, wanted_str_start, wanted_str_len); + + // DA_LOG_CRITICAL(HTTPManager, "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; + + // DA_LOG_FUNC_START(HTTPManager); + + raw_value = http_header_field->raw_value; + // DA_LOG_CRITICAL(HTTPManager, "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_LOG_ERR(HTTPManager, "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_LOG(HTTPManager, "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_LOG_FUNC_START(HTTPManager); + + if (!header_option) { + DA_LOG_ERR(HTTPManager, "input header_option is NULL."); + return DA_FALSE; + } + + cur = header_option; + while (cur) { + if (cur->field) { + if (!strncmp(cur->field, in_field, strlen(cur->field))) { + DA_LOG(HTTPManager, "[%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_LOG_FUNC_START(HTTPManager); + + 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 && !strncmp(field, in_field, strlen(field))) { + DA_LOG(HTTPManager, "[%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_LOG_FUNC_START(HTTPManager); + + 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_LOG_FUNC_START(HTTPManager); + + b_ret = __get_http_header_for_field(http_msg_response, "Content-Type", + &header); + if (!b_ret) { + DA_LOG(HTTPManager, "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_LOG_FUNC_START(HTTPManager); + + if (!http_msg_response || !in_type) + return; + + b_ret = __get_http_header_for_field(http_msg_response, "Content-Type", + &header); + if (b_ret) { + if (header->raw_value && (!strncmp(header->raw_value, in_type, + strlen(header->raw_value)))) + return; + + DA_LOG(HTTPManager, "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), + "Content-Type", in_type, WITH_PARSING_OPTION); + } +} + +da_bool_t http_msg_response_get_content_length( + http_msg_response_t *http_msg_response, int *out_length) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOG_FUNC_START(HTTPManager); + + b_ret = __get_http_header_for_field(http_msg_response, + "Content-Length", &header); + if (!b_ret) { + DA_LOG(HTTPManager, "no Content-Length"); + return DA_FALSE; + } + + if (out_length) + *out_length = atoi(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_LOG_FUNC_START(HTTPManager); + + b_ret = __get_http_header_for_field(http_msg_response, + "Content-Disposition", &header); + if (!b_ret) { + DA_LOG(HTTPManager, "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_LOG(HTTPManager, "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_LOG(HTTPManager, "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_LOG_ERR(HTTPManager, "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_LOG(HTTPManager, "It's base64 encoded-word string"); + if (DA_RESULT_OK == decode_base64_encoded_str( + wanted_str, &decoded_str)) { + DA_LOG(HTTPManager, "base64 decoded str = [%s]", decoded_str); + free(wanted_str); + wanted_str = decoded_str; + decoded_str = NULL; + } else { + DA_LOG(HTTPManager, "Fail to base64 decode. Just use un-decoded string."); + } + } else { + DA_LOG(HTTPManager, "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_LOG(HTTPManager, "Url decoded str = [%s]", decoded_str); + free(wanted_str); + wanted_str = decoded_str; + decoded_str = NULL; + } + + *out_file_name = wanted_str; + + DA_LOG(HTTPManager, "out_file_name = [%s]", *out_file_name); + + return DA_TRUE; + } else { + DA_LOG_ERR(HTTPManager, "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_LOG_FUNC_START(HTTPManager); + + b_ret = __get_http_header_for_field(http_msg_response, "ETag", &header); + if (!b_ret) { + DA_LOG(HTTPManager, "no ETag"); + return DA_FALSE; + } + + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; +} + +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_LOG_FUNC_START(HTTPManager); + + b_ret = __get_http_header_for_field(http_msg_response, "Date", &header); + if (!b_ret) { + DA_LOG(HTTPManager, "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_LOG_FUNC_START(HTTPManager); + + b_ret = __get_http_header_for_field(http_msg_response, "Location", &header); + if (!b_ret) { + DA_LOG(HTTPManager, "no Location"); + return DA_FALSE; + } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; +} + +da_result_t http_msg_response_get_boundary( + http_msg_response_t *http_msg_response, char **out_val) +{ + da_result_t ret = DA_RESULT_OK; + + http_msg_iter_t http_msg_iter; + char *field = NULL; + char *value = NULL; + char *boundary = NULL; + + DA_LOG_FUNC_START(HTTPManager); + + if (!http_msg_response) { + DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + return DA_ERR_INVALID_ARGUMENT; + } + + http_msg_response_get_iter(http_msg_response, &http_msg_iter); + while (http_msg_get_field_with_iter(&http_msg_iter, &field, &value)) { + if ((field != DA_NULL) && (value != DA_NULL)) { + if (!strncmp(field, "Content-Type", + strlen("Content-Type"))) { + char *org_str = NULL; + char *boundary_str_start = NULL; + char *boundary_value_start = NULL; + char *boundary_value_end = NULL; + int boundary_value_len = 0; + + org_str = value; + + boundary_str_start + = strstr(org_str, "boundary"); + if (boundary_str_start) { + DA_LOG(HTTPManager, "boundary_str_start = %s", boundary_str_start); + // this "Content-Type" value has "boundary" in it, so get the value + boundary_value_start = strchr( + boundary_str_start, '"'); + boundary_value_start += 1; // start without " + + boundary_value_end = strchr( + boundary_value_start, '"'); + boundary_value_len = boundary_value_end + - boundary_value_start; + + DA_LOG(HTTPManager, "boundary_value_start = %s", boundary_value_start); + DA_LOG(HTTPManager, "boundary_value_end = %s", boundary_value_end); + DA_LOG(HTTPManager, "boundary_value_len = %d", boundary_value_len); + + } else { + // no "boundary" field on this "Content-Type" value + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + // end of clear + + boundary = (char *)calloc(1, + boundary_value_len + 1); + if (!boundary) { + DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + + goto ERR; + } + strncpy(boundary, boundary_value_start, + boundary_value_len); + DA_LOG(HTTPManager, "[boundary][%s]", boundary); + break; + } + } + } + + *out_val = boundary; + +ERR: + return ret; +} + +char *get_http_response_header_raw(http_msg_response_t *http_msg_response) +{ + http_msg_iter_t http_msg_iter; + http_header_t *header = NULL; + char *field = NULL; + char tmp_buf[1024*4] = {0,}; + char line_buf[1024] = {0,}; + int len = 0; + char *buff = NULL; + + DA_LOG_FUNC_START(HTTPManager); + + 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) { + // FIXME later :: buffer length is more than total length. think about getting header's conent length from libsoup + len = strlen(field) + strlen(header->value) + 2; + snprintf(line_buf, len,"%s:%s", field, header->value); + strncat(tmp_buf, line_buf, len); + strcat(tmp_buf, "\n"); + } + } + if (strlen(tmp_buf) > 0) { + buff = (char *)calloc(1, strlen(tmp_buf) + 1); + if (buff == DA_NULL) { + DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + return DA_NULL; + } + memcpy(buff, tmp_buf, strlen(tmp_buf)); + DA_LOG(HTTPManager, "\n---raw response header---\n%s\n------\n",buff); + return buff; + } else { + return DA_NULL; + } +} + +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_LOG_ERR(Default,"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_LOG_ERR(Default,"INVALID ARGUMENT"); + return NULL; + } + + look_ptr = (char*)calloc(1, length_find + 1); + + if (look_ptr == NULL) { + DA_LOG_ERR(Default,"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_LOG_ERR(Default,"INVALID ARGUMENT"); + return DA_FALSE; + } + + if (strlen(szHeadStr) <= 0 || strlen(szFindStr) <= 0) { + DA_LOG_ERR(Default,"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 == strcmp(szFindStr, "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_LOG_ERR(Default," strLen is < 1"); + goto ERR; + } + + *ppRtnValue = (char*)calloc(1, sizeof(char) * (strLen + 1)); + + if (*ppRtnValue == NULL) { + DA_LOG_ERR(Default," *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; +} + diff --git a/src/agent/download-agent-http-queue.c b/src/agent/download-agent-http-queue.c new file mode 100644 index 0000000..55efac4 --- /dev/null +++ b/src/agent/download-agent-http-queue.c @@ -0,0 +1,405 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-http-queue.c + * @brief Including functions regarding http queue + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + +#include "download-agent-http-queue.h" +#include "download-agent-http-mgr.h" +#include "download-agent-debug.h" +#include "download-agent-pthread.h" + +void init_q_event_data_http(q_event_t *q_event); +void init_q_event_control(q_event_t *q_event); + +void Q_init_queue(queue_t *queue) +{ + queue->having_data = DA_FALSE; + queue->control_head = DA_NULL; + queue->data_head = DA_NULL; + queue->queue_size = 0; + + _da_thread_mutex_init(&(queue->mutex_queue), DA_NULL); + _da_thread_cond_init(&(queue->cond_queue), DA_NULL); +} + +void Q_destroy_queue(queue_t *queue) +{ + q_event_t *event = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + + do { + Q_pop_event(queue, &event); + Q_destroy_q_event(&event); + } while(event); + + queue->having_data = DA_FALSE; + queue->control_head = DA_NULL; + queue->data_head = DA_NULL; + queue->queue_size = 0; + + _da_thread_mutex_destroy(&(queue->mutex_queue)); + _da_thread_cond_destroy(&(queue->cond_queue)); +} + +void Q_init_q_event(q_event_t *q_event) +{ + switch(q_event->event_type) { + case Q_EVENT_TYPE_DATA_HTTP: + init_q_event_data_http(q_event); + break; + + case Q_EVENT_TYPE_DATA_DRM: +// init_q_event_data_drm(q_event); + break; + + case Q_EVENT_TYPE_CONTROL: + init_q_event_control(q_event); + break; + } + + q_event->size = 0; + q_event->next = DA_NULL; +} + +void Q_destroy_q_event(q_event_t **in_q_event) +{ + q_event_t *q_event = DA_NULL; + q_event = *in_q_event; + + if(q_event == DA_NULL) + return; + +// DA_LOG(HTTPManager, "destroying size = %d", q_event->size); + + switch(q_event->event_type) { + case Q_EVENT_TYPE_DATA_HTTP: + init_q_event_data_http(q_event); + q_event->size = 0; + q_event->next = DA_NULL; + free(q_event); + break; + + case Q_EVENT_TYPE_DATA_DRM: +// init_q_event_data_drm(q_event); + q_event->size = 0; + q_event->next = DA_NULL; + free(q_event); + break; + + case Q_EVENT_TYPE_CONTROL: + init_q_event_control(q_event); + q_event->size = 0; + q_event->next = DA_NULL; + free(q_event); + break; + } +} + +da_result_t Q_make_control_event(q_event_type_control control_type, q_event_t **out_event) +{ + da_result_t ret = DA_RESULT_OK; + q_event_t *q_event = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + + q_event = (q_event_t *)calloc(1, sizeof(q_event_t)); + if(q_event == DA_NULL) { + DA_LOG_ERR(HTTPManager, "calloc fail for q_event"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + + *out_event = DA_NULL; + } else { + q_event->event_type = Q_EVENT_TYPE_CONTROL; + q_event->type.q_event_control.control_type = control_type; + q_event->next = DA_NULL; + + *out_event = q_event; + } + + return ret; +} + +da_result_t Q_make_http_data_event(q_event_type_data data_type, q_event_t **out_event) +{ + da_result_t ret = DA_RESULT_OK; + q_event_t *q_event = DA_NULL; + +// DA_LOG_FUNC_START(HTTPManager); + + q_event = (q_event_t *)calloc(1, sizeof(q_event_t)); + if(q_event == DA_NULL) { + DA_LOG_ERR(HTTPManager, "calloc fail for q_event"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + *out_event = DA_NULL; + } else { + q_event->event_type = Q_EVENT_TYPE_DATA_HTTP; + q_event->type.q_event_data_http.data_type = data_type; + q_event->next = DA_NULL; + + *out_event = q_event; + +// DA_LOG(HTTPManager, "made event = %x", *out_event); + } + + return ret; + +} + +da_result_t Q_set_status_code_on_http_data_event(q_event_t *q_event, int status_code) +{ + da_result_t ret = DA_RESULT_OK; + +// DA_LOG_FUNC_START(HTTPManager); + + if(q_event->event_type != Q_EVENT_TYPE_DATA_HTTP) { + DA_LOG_ERR(HTTPManager, "status_code can be set only for Q_EVENT_TYPE_DATA_HTTP."); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + q_event->type.q_event_data_http.status_code = status_code; + +// DA_LOG(HTTPManager, "status_code = %d, q_event = %x", q_event->type.q_event_data_http.status_code, q_event); + +ERR: + return ret; + +} + +da_result_t Q_set_http_body_on_http_data_event(q_event_t *q_event, int body_len, char *body_data) +{ + da_result_t ret = DA_RESULT_OK; + +// DA_LOG_FUNC_START(HTTPManager); + + if(q_event->event_type != Q_EVENT_TYPE_DATA_HTTP) { + DA_LOG_ERR(HTTPManager, "http body can be set only for Q_EVENT_TYPE_DATA_HTTP."); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + q_event->type.q_event_data_http.body_len = body_len; + q_event->type.q_event_data_http.body_data = body_data; + q_event->size = body_len; + +// DA_LOG(HTTPManager, "body_len = %d, body_data = %x, q_event = %x", q_event->type.q_event_data_http.body_len, q_event->type.q_event_data_http.body_data, q_event); + +ERR: + return ret; + +} + +da_result_t Q_set_error_type_on_http_data_event(q_event_t *q_event, int error_type) +{ + da_result_t ret = DA_RESULT_OK; + +// DA_LOG_FUNC_START(HTTPManager); + + if(q_event->event_type != Q_EVENT_TYPE_DATA_HTTP) { + DA_LOG_ERR(HTTPManager, "error_type can be set only for Q_EVENT_TYPE_DATA_HTTP."); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + q_event->type.q_event_data_http.error_type = error_type; + + DA_LOG(HTTPManager, "error_type = %d, q_event = %p", q_event->type.q_event_data_http.error_type, q_event); + +ERR: + return ret; + +} + +da_bool_t Q_push_event(const queue_t *in_queue, const q_event_t *in_event) +{ + da_bool_t b_ret = DA_FALSE; + queue_t *queue = (queue_t *)in_queue; + + _da_thread_mutex_lock (&(queue->mutex_queue)); + b_ret = Q_push_event_without_lock(in_queue, in_event); + _da_thread_mutex_unlock (&(queue->mutex_queue)); + + return b_ret; +} + +da_bool_t Q_push_event_without_lock(const queue_t *in_queue, const q_event_t *in_event) +{ + da_bool_t b_ret = DA_FALSE; + queue_t *queue = (queue_t *)in_queue; + q_event_t *event = (q_event_t *)in_event; + q_event_type event_type; + q_event_t *head = DA_NULL; + q_event_t *cur = DA_NULL; + +// DA_LOG_FUNC_START(HTTPManager); +// DA_LOG(HTTPManager, "queue = %x", in_queue); + + event_type = event->event_type; + +// _da_thread_mutex_lock (&(queue->mutex_queue)); + + if(event_type == Q_EVENT_TYPE_CONTROL) { + head = queue->control_head; + if(head == DA_NULL) { + queue->control_head = event; + } else { + cur = head; + + while(cur->next != DA_NULL) { + cur = cur->next; + } + cur->next= event; + } + b_ret = DA_TRUE; + } else { + if((event->size == 0) || (queue->queue_size < MAX_QUEUE_SIZE)) { + head = queue->data_head; + if(head == DA_NULL) { + queue->data_head = event; + } else { + cur = head; + while(cur->next != DA_NULL) { + cur = cur->next; + } + cur->next= event ; + } + + queue->queue_size += event->size; +// DA_LOG(HTTPManager, "queue size is %d", queue->queue_size); + + b_ret = DA_TRUE; + } else { + DA_LOG_CRITICAL(HTTPManager, "rejected event's size is %d queue_size %d", event->size, queue->queue_size); + b_ret = DA_FALSE; + } + } + + queue->having_data = DA_TRUE; + Q_wake_up(queue); +// _da_thread_mutex_unlock (&(queue->mutex_queue)); + return b_ret; +} + +void Q_pop_event(const queue_t *in_queue, q_event_t **out_event) +{ + queue_t *queue = (queue_t*)in_queue; + +// DA_LOG_FUNC_START(HTTPManager); +// DA_LOG(HTTPManager, "queue = %x", in_queue); + + /** Pop Priority + * 1. If there are control event, control event should pop first + * 2. If there is no control event, data event should pop + * 3. If there is no control and data event on queue, pop NULL + */ + + _da_thread_mutex_lock (&(queue->mutex_queue)); + + if(queue->control_head != DA_NULL) {/* Priority 1 */ + *out_event = queue->control_head; + queue->control_head = queue->control_head->next; + } else { + if(queue->data_head != DA_NULL) {/* Priority 2 */ + *out_event = queue->data_head; + queue->data_head = queue->data_head->next; + queue->queue_size -= (*out_event)->size; +// DA_LOG(HTTPManager, "queue size is %d", queue->queue_size); + } else {/* Priority 3 */ + *out_event = DA_NULL; + } + } + + if((queue->control_head == DA_NULL) && (queue->data_head == DA_NULL)) { + queue->having_data = DA_FALSE; + } else { + queue->having_data = DA_TRUE; + } + + _da_thread_mutex_unlock (&(queue->mutex_queue)); + +} + +void Q_goto_sleep(const queue_t *in_queue) +{ +// DA_LOG_FUNC_START(HTTPManager); + DA_LOG(HTTPManager, "sleep for %p", in_queue); + +//** SHOULD NOT use mutex **// + +// _da_thread_mutex_lock (&(in_queue->mutex_queue)); + _da_thread_cond_wait((pthread_cond_t*)(&(in_queue->cond_queue)),(pthread_mutex_t*) (&(in_queue->mutex_queue))); +// _da_thread_mutex_unlock (&(in_queue->mutex_queue)); +} + +void Q_wake_up(const queue_t *in_queue) +{ +// DA_LOG_FUNC_START(HTTPManager); + DA_LOG(HTTPManager, "wake up for %p", in_queue); + +//** SHOULD NOT use mutex **// + +// _da_thread_mutex_lock (&(in_queue->mutex_queue)); + _da_thread_cond_signal((pthread_cond_t*)(&(in_queue->cond_queue))); +// _da_thread_mutex_unlock (&(in_queue->mutex_queue)); +} + +void init_q_event_data_http(q_event_t *q_event) +{ + q_event_data_http_t *q_event_data_http; + +// DA_LOG_FUNC_START(HTTPManager); + + if(q_event->event_type == Q_EVENT_TYPE_DATA_HTTP) { + q_event_data_http = &(q_event->type.q_event_data_http); + + if(q_event_data_http) { + q_event_data_http->status_code = DA_NULL; + if(q_event_data_http->http_response_msg) { + http_msg_response_destroy(&(q_event_data_http->http_response_msg)); + } + + if(q_event_data_http->body_len > 0 ) { + if (q_event_data_http->body_data) { + free(q_event_data_http->body_data); + q_event_data_http->body_data = DA_NULL; + } + } + q_event_data_http->error_type = DA_NULL; + } + } +} + +void init_q_event_control(q_event_t *q_event) +{ + q_event_control_t *q_event_control; + +// DA_LOG_FUNC_START(HTTPManager); + + if(q_event->event_type == Q_EVENT_TYPE_CONTROL) { + q_event_control = &(q_event->type.q_event_control); + if(q_event_control) { + q_event_control->control_type = DA_NULL; + } + } + +} diff --git a/src/agent/download-agent-installation.c b/src/agent/download-agent-installation.c new file mode 100644 index 0000000..f0ffcfa --- /dev/null +++ b/src/agent/download-agent-installation.c @@ -0,0 +1,136 @@ +/*
+ * Download Agent
+ *
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @file download-agent-installation.c
+ * @brief Functions for Content Installation
+ * @author Keunsoon Lee(keunsoon.lee@samsung.com)
+ * @author Jungki Kwak(jungki.kwak@samsung.com)
+ ***/
+
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "download-agent-client-mgr.h"
+#include "download-agent-dl-info-util.h"
+#include "download-agent-http-mgr.h"
+#include "download-agent-http-misc.h"
+#include "download-agent-installation.h"
+#include "download-agent-file.h"
+#include "download-agent-plugin-install.h"
+
+da_result_t _extract_file_path_which_will_be_installed(char *in_file_name, char *in_extension, char *in_install_path_client_wants, char **out_will_install_path);
+
+da_result_t install_content(stage_info *stage)
+{
+ da_result_t ret = DA_RESULT_OK;
+
+ file_info *file_storage = DA_NULL;
+ char *temp_saved_file_path = DA_NULL;
+ char *install_file_path = DA_NULL;
+ unsigned int start_time = 0;
+
+ DA_LOG_FUNC_START(InstallManager);
+
+ if (!stage)
+ return DA_ERR_INVALID_ARGUMENT;
+
+ file_storage = GET_STAGE_CONTENT_STORE_INFO(stage);
+ if (!file_storage) {
+ DA_LOG_ERR(InstallManager,"file_storage structure is NULL");
+ ret = DA_ERR_INVALID_ARGUMENT;
+ goto ERR;
+ }
+
+ temp_saved_file_path =
+ GET_CONTENT_STORE_TMP_FILE_NAME(file_storage);
+ DA_LOG(InstallManager,"Source path[%s]",temp_saved_file_path);
+
+ ret = check_enough_storage(stage);
+ if (ret != DA_RESULT_OK)
+ goto ERR;
+
+ ret = _extract_file_path_which_will_be_installed(
+ GET_CONTENT_STORE_PURE_FILE_NAME(file_storage),
+ GET_CONTENT_STORE_EXTENSION(file_storage),
+ GET_DL_USER_INSTALL_PATH(GET_STAGE_DL_ID(stage)),
+ &install_file_path);
+ if (ret != DA_RESULT_OK)
+ goto ERR;
+
+ DA_LOG(InstallManager,"Installing path [%s]", install_file_path);
+ DA_LOG(InstallManager,"Move start time : [%ld]",start_time=time(NULL));
+ ret = move_file(temp_saved_file_path, install_file_path);
+ if (ret != DA_RESULT_OK)
+ goto ERR;
+
+ if (GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage))
+ free(GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage));
+ GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage) = install_file_path;
+ install_file_path = DA_NULL;
+
+
+ERR:
+ if (ret != DA_RESULT_OK) {
+ remove_file(GET_CONTENT_STORE_TMP_FILE_NAME(file_storage));
+ remove_file(install_file_path);
+ } else {
+ }
+ return ret;
+}
+
+da_result_t _extract_file_path_which_will_be_installed(char *in_file_name, char *in_extension, char *in_install_path_client_wants, char **out_will_install_path)
+{
+ da_result_t ret = DA_RESULT_OK;
+ char *install_dir = NULL;
+ char *default_install_dir = NULL;
+ char *final_path = NULL;
+ char *pure_file_name = in_file_name;
+ char *extension = in_extension;
+
+ if (!in_file_name || !out_will_install_path)
+ return DA_ERR_INVALID_ARGUMENT;
+
+ *out_will_install_path = DA_NULL;
+
+ if (in_install_path_client_wants) {
+ install_dir = in_install_path_client_wants;
+ } else {
+ default_install_dir = PI_get_default_install_dir();
+ if (default_install_dir)
+ install_dir = default_install_dir;
+ else
+ return DA_ERR_FAIL_TO_INSTALL_FILE;
+ }
+
+ if (DA_FALSE == is_dir_exist(install_dir)) {
+ ret = create_dir(install_dir);
+ if (ret != DA_RESULT_OK)
+ return DA_ERR_FAIL_TO_INSTALL_FILE;
+ }
+
+ final_path = get_full_path_avoided_duplication(install_dir, pure_file_name, extension);
+ if (!final_path)
+ ret = DA_ERR_FAIL_TO_INSTALL_FILE;
+
+ *out_will_install_path = final_path;
+
+ DA_LOG(InstallManager,"Final install path[%s]", *out_will_install_path);
+
+ return ret;
+}
diff --git a/src/agent/download-agent-interface.c b/src/agent/download-agent-interface.c new file mode 100644 index 0000000..292233c --- /dev/null +++ b/src/agent/download-agent-interface.c @@ -0,0 +1,322 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-interface.c + * @brief Interface for Download Agent. + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + ***/ + +#include "download-agent-interface.h" +#include "download-agent-debug.h" +#include "download-agent-utils.h" +#include "download-agent-http-mgr.h" +#include "download-agent-http-misc.h" +#include "download-agent-client-mgr.h" +#include "download-agent-dl-mgr.h" +#include "download-agent-basic.h" +#include "download-agent-file.h" +#include "download-agent-installation.h" + +int da_init( + da_client_cb_t *da_client_callback, + da_download_managing_method download_method) +{ + da_result_t ret = DA_RESULT_OK; + + DA_LOG_FUNC_START(Default); + + if (!da_client_callback) { + ret = DA_ERR_INVALID_ARGUMENT; + return ret; + } + + ret = init_log_mgr(); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = init_client_app_mgr(); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = reg_client_app(da_client_callback, download_method); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = init_http_mgr(); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = init_download_mgr(); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = create_temp_saved_dir(); + if (ret != DA_RESULT_OK) + goto ERR; + +ERR: + if (DA_RESULT_OK != ret) + da_deinit(); + + DA_LOG_CRITICAL(Default, "Return ret = %d", ret); + + return ret; +} + +/* TODO:: deinit should clean up all the clients... */ +int da_deinit() +{ + da_result_t ret = DA_RESULT_OK; + char *client_dir_path = DA_NULL; + + DA_LOG_FUNC_START(Default); + if (DA_FALSE == is_this_client_available()) { + ret = DA_ERR_INVALID_CLIENT; + return ret; + } + + deinit_http_mgr(); + deinit_download_mgr(); + + ret = get_client_download_path(&client_dir_path); + if (ret == DA_RESULT_OK) { + ret = clean_files_from_dir(client_dir_path); + + if (client_dir_path) { + free(client_dir_path); + client_dir_path = DA_NULL; + } + } + + dereg_client_app(); + DA_LOG(Default, "====== da_deinit EXIT ====="); + + return ret; +} + +int da_start_download( + const char *url, + da_handle_t *da_dl_req_id) +{ + da_result_t ret = DA_RESULT_OK; + + DA_LOG_FUNC_START(Default); + + DA_LOG(Default, "url = %s", url); + + *da_dl_req_id = DA_INVALID_ID; + + if (DA_FALSE == is_this_client_available()) { + ret = DA_ERR_INVALID_CLIENT; + goto ERR; + } + + if (DA_FALSE == is_valid_url(url, &ret)) + goto ERR; + + ret = start_download(url, da_dl_req_id); + if (ret != DA_RESULT_OK) + goto ERR; + +ERR: + DA_LOG_CRITICAL(Default, "Return: Dl req id = %d, ret = %d", *da_dl_req_id, ret); + return ret; +} + +int da_start_download_with_extension( + const char *url, + da_handle_t *da_dl_req_id, + ... +) +{ + da_result_t ret = DA_RESULT_OK; + va_list argptr; + char *property_name = NULL; + int req_header_count = 0; + int i = 0; + + extension_data_t extension_data; + + DA_LOG_FUNC_START(Default); + + DA_LOG(Default, "url = %s", url); + + *da_dl_req_id = DA_INVALID_ID; + extension_data.request_header= NULL; + extension_data.request_header_count = NULL; + extension_data.install_path = NULL; + extension_data.file_name = NULL; + extension_data.user_data = NULL; + + if (DA_FALSE == is_this_client_available()) { + ret = DA_ERR_INVALID_CLIENT; + goto ERR; + } + + if (DA_FALSE == is_valid_url(url, &ret)) + goto ERR; + + va_start(argptr, da_dl_req_id); + property_name = va_arg(argptr, char*); + + // FIXME How about changing type for property_name enum? + if (!property_name) { + DA_LOG_ERR(Default, "No property input!"); + ret = DA_ERR_INVALID_ARGUMENT; + } else { + while (property_name && (ret == DA_RESULT_OK)) { + DA_LOG_VERBOSE(Default, "property_name = [%s]", property_name); + + if (!strncmp(property_name, DA_FEATURE_USER_DATA, strlen(DA_FEATURE_USER_DATA))) { + extension_data.user_data = va_arg(argptr, void*); + if (extension_data.user_data) { + property_name = va_arg(argptr, char*); + } else { + DA_LOG_ERR(Default, "No property value for DA_FEATURE_USER_DATA!"); + ret = DA_ERR_INVALID_ARGUMENT; + } + } else if (!strncmp(property_name, DA_FEATURE_INSTALL_PATH, strlen(DA_FEATURE_INSTALL_PATH))) { + extension_data.install_path = va_arg(argptr, const char*); + if (extension_data.install_path) { + property_name = va_arg(argptr, char*); + } else { + DA_LOG_ERR(Default, "No property value for DA_FEATURE_INSTALL_PATH!"); + ret = DA_ERR_INVALID_ARGUMENT; + } + } else if (!strncmp(property_name, DA_FEATURE_FILE_NAME, strlen(DA_FEATURE_FILE_NAME))) { + extension_data.file_name = va_arg(argptr, const char*); + if (extension_data.file_name) { + property_name = va_arg(argptr, char*); + } else { + DA_LOG_ERR(Default, "No property value for DA_FEATURE_FILE_NAME!"); + ret = DA_ERR_INVALID_ARGUMENT; + } + } else if (!strncmp(property_name, DA_FEATURE_REQUEST_HEADER, strlen(DA_FEATURE_REQUEST_HEADER))) { + extension_data.request_header = va_arg(argptr, const char **); + extension_data.request_header_count = va_arg(argptr, const int *); + if (extension_data.request_header && + extension_data.request_header_count) { + property_name = va_arg(argptr, char *); + } else { + DA_LOG_ERR(Default, "No property value for DA_FEATURE_REQUEST_HEADER!"); + ret = DA_ERR_INVALID_ARGUMENT; + } + } else { + DA_LOG_ERR(Default, "Unknown property name; [%s]", property_name); + ret = DA_ERR_INVALID_ARGUMENT; + } + } + } + + va_end(argptr); + + if (ret != DA_RESULT_OK) + goto ERR; + + if (extension_data.request_header_count) { + DA_LOG_VERBOSE(Default, "input request_header_count = [%d]", + *(extension_data.request_header_count)); + for (i = 0; i < *(extension_data.request_header_count); i++) + { + if (extension_data.request_header[i]) { + req_header_count++; + DA_LOG_VERBOSE(Default, "request_header = [%s]", + extension_data.request_header[i]); + } + } + DA_LOG(Default, "actual request_header_count = [%d]", req_header_count); + if (*(extension_data.request_header_count) != req_header_count) { + DA_LOG_ERR(Default, "Request header count is not matched with number of request header array"); + extension_data.request_header = NULL; + extension_data.request_header_count = NULL; + } + } + + if (extension_data.install_path) + DA_LOG_VERBOSE(Default, "install path = [%s]", extension_data.install_path); + + if (extension_data.file_name) + DA_LOG_VERBOSE(Default, "file_name = [%s]", extension_data.file_name); + + ret = start_download_with_extension(url, da_dl_req_id, &extension_data); + +ERR: + DA_LOG_CRITICAL(Default, "Return: Dl req id = %d, ret = %d", *da_dl_req_id, ret); + return ret; +} + +int da_cancel_download(da_handle_t da_dl_req_id) +{ + da_result_t ret = DA_RESULT_OK; + + DA_LOG_FUNC_START(Default); + + DA_LOG_VERBOSE(Default, "Cancel for dl_req_id = %d", da_dl_req_id); + + if (DA_FALSE == is_this_client_available()) { + ret = DA_ERR_INVALID_CLIENT; + goto ERR; + } + + ret = cancel_download(da_dl_req_id); + +ERR: + DA_LOG_CRITICAL(Default, "Return: Cancel id = %d, ret = %d", da_dl_req_id, ret); + return ret; +} + +int da_suspend_download(da_handle_t da_dl_req_id) +{ + da_result_t ret = DA_RESULT_OK; + + DA_LOG_FUNC_START(Default); + + DA_LOG_VERBOSE(Default, "Suspend for dl_req_id = %d", da_dl_req_id); + + if (DA_FALSE == is_this_client_available()) { + ret = DA_ERR_INVALID_CLIENT; + goto ERR; + } + ret = suspend_download(da_dl_req_id); + +ERR: + DA_LOG_CRITICAL(Default, "Return: Suspend id = %d, ret = %d", da_dl_req_id, ret); + return ret; +} + +int da_resume_download(da_handle_t da_dl_req_id) +{ + da_result_t ret = DA_RESULT_OK; + + DA_LOG_FUNC_START(Default); + + DA_LOG_VERBOSE(Default, "Resume for dl_req_id = %d", da_dl_req_id); + + if (DA_FALSE == is_this_client_available()) { + ret = DA_ERR_INVALID_CLIENT; + goto ERR; + } + ret = resume_download(da_dl_req_id); + +ERR: + DA_LOG_CRITICAL(Default, "Return: Resume id = %d, ret = %d", da_dl_req_id, ret); + return ret; +} + diff --git a/src/agent/download-agent-mime-util.c b/src/agent/download-agent-mime-util.c new file mode 100644 index 0000000..8b63a21 --- /dev/null +++ b/src/agent/download-agent-mime-util.c @@ -0,0 +1,405 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-mime-util.c + * @brief mime utility functions + * @author Jungki Kwak(jungki.kwak@samsung.com) + ***/ + +#include <string.h> +#include <stdlib.h> + +#include <xdgmime.h> + +#include "download-agent-debug.h" +#include "download-agent-mime-util.h" + +#define IS_PROHIBITED_CHAR(c) ((c) == ';' || (c) == '\\' || (c) == '/' || (c) == ':' || (c) == '*' || (c) == '?' || (c) == '"' || (c) == '>' || (c) == '<' || (c) == '|' || (c) == '(' || (c) == ')') +#define IS_SPACE_CHARACTER(c) ((c) == ' ' || (c) == '\t') + +#define DD_MIME_STR "application/vnd.oma.dd+xml" +#define DD_EXT_STR "*.dd" +#define DRM_MIME_STR "application/vnd.oma.drm.message" +#define DRM_EXT_STR "*.dcf" +#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" +}; + +da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type) +{ +// DA_LOG_FUNC_START(Default); + + 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_LOG(Default,"It is ambiguous! [%s]", ambiguous_MIME_Type_list[index]); + return DA_TRUE; + } + } + + return DA_FALSE; +} + +da_result_t da_mime_get_ext_name(char *mime, char **ext) +{ + da_result_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_LOG_FUNC_START(Default); + + if (DA_NULL == mime || DA_NULL == ext) { + ret = DA_ERR_INVALID_ARGUMENT; + DA_LOG_ERR(Default,"Invalid mime type"); + goto ERR; + } + DA_LOG_VERBOSE(Default,"mime str[%s]ptr[%p]len[%d]",mime,mime,strlen(mime)); + /* unaliased_mimetype means representative mime among similar types */ + unaliased_mimetype = xdg_mime_unalias_mime_type(mime); + + if (unaliased_mimetype == DA_NULL) { + ret = DA_ERR_INVALID_MIME_TYPE; + DA_LOG_ERR(Default,"Invalid mime type : No unsaliased mime type"); + goto ERR; + } + DA_LOG(Default,"unaliased_mimetype[%s]\n",unaliased_mimetype); + + /* Get extension name from shared-mime-info */ + extlist = xdg_mime_get_file_names_from_mime_type(unaliased_mimetype); + if (extlist == DA_NULL || *extlist == DA_NULL) { + int i = 0; + ret = DA_ERR_INVALID_MIME_TYPE; + DA_LOG(Default,"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_LOG(Default,"extlist[%s]\n",*extlist); + strncpy(ext_temp, *extlist, DA_MAX_STR_LEN); + /* 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_LOG(Default,"index[%d]\n",i); + /* If there is a mime at extension transform table */ + if (i < MAX_EXT_TABLE_INDEX) { + break; + } + DA_LOG(Default,"extlist[%s]\n",*extlist); + extlist++; + } + DA_LOG(Default,"extension from shared mime info[%s]",ext_temp); + } + + if (strlen(ext_temp) < 1) { + /* If there is no mime string for OMD 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_STR,mime,strlen(DD_MIME_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_LOG_ERR(Default,"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_LOG(Default,"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_LOG_FUNC_START(Default); + + if (DA_NULL == url || DA_NULL == ext) { + ret = DA_FALSE; + DA_LOG_ERR(Default,"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_LOG_ERR(Default,"Memory Fail"); + goto ERR; + } + strncpy(*ext,buff,buf_len); + DA_LOG(Default,"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_LOG_FUNC_START(Default); + + if (DA_NULL == url || DA_NULL == name) { + ret = DA_FALSE; + DA_LOG_ERR(Default,"Invalid Argument"); + goto ERR; + } + *name = DA_NULL; + if (!strstr(url, "http") && !strstr(url, "https")) { + ret = DA_FALSE; + DA_LOG_ERR(Default,"Invalid Argument"); + goto ERR; + } + + buff = (char*) calloc(1, strlen(url) +1); + if(DA_NULL == buff) { + ret = DA_FALSE; + DA_LOG_ERR(Default,"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_LOG(Default,"file name BEFORE removing prohibited character = %s", name_buff); + delete_prohibited_char(name_buff, strlen(name_buff)); + DA_LOG(Default,"file name AFTER removing prohibited character = %s", name_buff); + len_name = strlen(name_buff); + *name = (char*) calloc(1, len_name + 1); + if (*name) { + strncpy(*name, name_buff,len_name); + } + } + DA_LOG(Default,"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_LOG_ERR(Default,"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; +} + diff --git a/src/agent/download-agent-plugin-conf.c b/src/agent/download-agent-plugin-conf.c new file mode 100644 index 0000000..6a510b6 --- /dev/null +++ b/src/agent/download-agent-plugin-conf.c @@ -0,0 +1,176 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-plugin-conf.c + * @brief Platform dependent functions for get configuration data from target + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + ***/ + +#include <string.h> +#include <stdlib.h> +#include <glib-object.h> + +#ifdef _EFL_PLATFORM +#include <vconf.h> +#include <vconf-keys.h> +#include <net_connection.h> +#endif /* _EFL_PLATFORM */ + +#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_result_t __get_conf_string(const char *key, char **out_string); + +da_result_t __get_conf_string(const char *key, char **out_string) +{ +#ifdef _EFL_PLATFORM + if (!key || !out_string) { + DA_LOG_ERR(Default,"Invalid Argument"); + return DA_ERR_INVALID_ARGUMENT; + } + + *out_string = vconf_get_str(key); + return DA_RESULT_OK; +#else + if (out_string) + *out_string = NULL; + + return DA_RESULT_OK; +#endif +} + +da_result_t get_storage_type(da_storage_type_t *type) +{ + da_result_t ret = DA_RESULT_OK; +#ifdef _EFL_PLATFORM + int value = -1; +#endif + + if (!type) { + DA_LOG_ERR(Default,"DA_ERR_CONF_FAIL"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + +#ifdef _EFL_PLATFORM + if (0 != vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_WAP_INT, &value)) { + DA_LOG_ERR(Default,"DA_ERR_CONF_FAIL"); + ret = DA_ERR_FAIL_TO_GET_CONF_VALUE; + goto ERR; + } + + switch (value) { + case SETTING_DEF_MEMORY_PHONE: + DA_LOG(Default,"Storage set - DA_STORAGE_PHONE"); + *type = DA_STORAGE_PHONE; + break; + case SETTING_DEF_MEMORY_MMC: + *type = DA_STORAGE_MMC; + DA_LOG(Default,"Storage set - DA_STORAGE_MMC"); + break; + case SETTING_DEF_MEMORY_MAX: + *type = DA_STORAGE_SYSTEM; + DA_LOG(Default,"Storage set - DA_STORAGE_SYSTEM"); + break; + default: + DA_LOG_ERR(Default,"DA_ERR_CONF_FAIL"); + ret = DA_ERR_FAIL_TO_GET_CONF_VALUE; + break; + } +#endif + +ERR: + return ret; + +} + +da_result_t get_user_agent_string(char **uagent_str) +{ + da_result_t ret = DA_RESULT_OK; +#ifdef _EFL_PLATFORM + char *key = DA_NULL; +#endif + + DA_LOG_FUNC_START(Default); + + if (!uagent_str) { + DA_LOG_ERR(Default,"Invalid Argument"); + return DA_ERR_INVALID_ARGUMENT; + } + +#ifdef _EFL_PLATFORM + key = VCONFKEY_ADMIN_UAGENT; + ret = __get_conf_string(key, uagent_str); + if(ret == DA_RESULT_OK) { + if(*uagent_str) { + DA_LOG(Default,"getting uagent_str = \n%s", *uagent_str); + return ret; + } + } + DA_LOG_ERR(Default,"No UA information from vconf !!"); + *uagent_str = strdup(DEFAULT_UA_STR); + DA_LOG(Default,"Set default UA"); +#else + *uagent_str = strdup(DEFAULT_UA_STR); +#endif + return ret; +} + +char *get_proxy_address(void) +{ +#ifdef _EFL_PLATFORM + char *proxy = NULL; + char *proxyRet = NULL; + connection_h handle = NULL; + connection_address_family_e family = CONNECTION_ADDRESS_FAMILY_IPV4; + + DA_LOG_FUNC_START(Default); + if (connection_create(&handle) < 0) { + DA_LOG_ERR(Default,"Fail to create connection handle"); + return NULL; + } + + if (connection_get_proxy(handle, family, &proxyRet) < 0) { + DA_LOG_ERR(Default,"Fail to get proxy address"); + connection_destroy(handle); + return NULL; + } + + if (proxyRet) { + DA_LOG(Default,"===== Proxy address[%s] =====", proxyRet); + proxy = strdup(proxyRet); + free(proxyRet); + proxyRet = NULL; + connection_destroy(handle); + return proxy; + } + + if (connection_destroy(handle) < 0) { + DA_LOG_ERR(Default,"Fail to desctory connection handle"); + return NULL; + } + return NULL; +#else + return NULL; +#endif +} diff --git a/src/agent/download-agent-plugin-drm.c b/src/agent/download-agent-plugin-drm.c new file mode 100644 index 0000000..8460540 --- /dev/null +++ b/src/agent/download-agent-plugin-drm.c @@ -0,0 +1,185 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-plugin-drm.c + * @brief Platform dependent functions for emerald DRM from SISO + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <drm_client.h> +#include <drm_client_types.h> +#include <drm_trusted_client.h> +#include <drm_trusted_client_types.h> +#include "download-agent-debug.h" +#include "download-agent-plugin-drm.h" + +da_bool_t EDRM_check_dcf_file(const char *file_path) +{ + drm_file_info_s file_info; + int ret = -1; + + ret = drm_get_file_info(file_path, &file_info); + if (ret != DRM_RETURN_SUCCESS) { + DA_LOG(DRMManager,"error : ret[%d]\n", ret); + return DA_FALSE; + } + + if (file_info.oma_info.version == DRM_OMA_DRMV1_RIGHTS && + (file_info.oma_info.method == DRM_METHOD_TYPE_COMBINED_DELIVERY || + file_info.oma_info.method == DRM_METHOD_TYPE_SEPARATE_DELIVERY)) { + return DA_TRUE; + } else { + return DA_FALSE; + } +} + +da_bool_t EDRM_has_vaild_ro(const char *file_path) +{ + int ret = -1; + drm_license_status_e status = DRM_LICENSE_STATUS_UNDEFINED; + ret = drm_get_license_status(file_path, DRM_PERMISSION_TYPE_ANY, &status); + + if (status == DRM_LICENSE_STATUS_VALID) + return DA_TRUE; + else + return DA_FALSE; +} + +da_bool_t EDRM_open_convert(const char *file_path, void **fd) +{ + DRM_TRUSTED_CONVERT_HANDLE hConvert; + drm_trusted_opn_conv_info_s input = {{0,},}; + + if (!file_path || !fd) { + DA_LOG_ERR(DRMManager,"Invalid paramter"); + return DA_FALSE; + } + strncpy(input.filePath, file_path, sizeof(input.filePath) - 1); + if (drm_trusted_open_convert(&input, &hConvert) < 0) { + DA_LOG_ERR(DRMManager,"Fail to open convert"); + return DA_FALSE; + } + *fd = hConvert; + return DA_TRUE; +} + +da_bool_t EDRM_write_convert(void *fd, unsigned char *buffer, int buffer_size) +{ + DRM_TRUSTED_CONVERT_HANDLE hConvert; + drm_trusted_write_conv_info_s input = {0,}; + drm_trusted_write_conv_resp_s output = {0,}; + + if (!fd || !buffer || buffer_size < 0) { + DA_LOG_ERR(DRMManager,"Invalid paramter"); + return DA_FALSE; + } + hConvert = fd; + input.data_len = buffer_size; + input.data = buffer; + if (drm_trusted_write_convert(&input,&output,fd) < 0) { + DA_LOG_ERR(DRMManager,"Fail to write convert"); + return DA_FALSE; + } + if (buffer_size != output.write_size) { + DA_LOG_ERR(DRMManager,"written size is failed"); + return DA_FALSE; + } + return DA_TRUE; +} + +da_bool_t EDRM_close_convert(void **fd) +{ + DRM_TRUSTED_CONVERT_HANDLE hConvert; + if (!fd) { + DA_LOG_ERR(DRMManager,"Invalid paramter"); + return DA_FALSE; + } + hConvert = *fd; + if (drm_trusted_close_convert(&hConvert) < 0) { + DA_LOG_ERR(DRMManager,"Fail to close convert"); + return DA_FALSE; + } + return DA_TRUE; +} + +da_bool_t EDRM_http_user_cancel(void *roap_session) +{ + return DA_FALSE; +} + +da_result_t EDRM_wm_get_license(char *rights_url, char **out_content_url) +{ + drm_initiator_info_s init_info; + drm_web_server_resp_data_s resp_data; + int ret = 0; + int len = 0; + + 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_LOG(DRMManager,"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); + if (content_url_len == 0) { + DA_LOG(DRMManager,"content_url is NULL. Join/Leave Domain, Metering case."); + *out_content_url = DA_NULL; + return DA_RESULT_OK; + } else { + 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_LOG(DRMManager,"drm sumitted initiator url " + "succeeded with [%s]", *out_content_url); + return DA_RESULT_OK; + } else { + DA_LOG_ERR(DRMManager,"DA_ERR_FAIL_TO_MEMALLOC"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + } + } else { + DA_LOG_ERR(DRMManager,"resp_data.content url is NULL"); + return DA_ERR_DRM_FAIL; + } + } else { + DA_LOG_ERR(DRMManager,"drm_process_request() failed"); + return DA_ERR_DRM_FAIL; + } +} + diff --git a/src/agent/download-agent-plugin-install.c b/src/agent/download-agent-plugin-install.c new file mode 100644 index 0000000..81f703a --- /dev/null +++ b/src/agent/download-agent-plugin-install.c @@ -0,0 +1,44 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-plugin-install.c + * @brief Platform dependency functions for installation a content to target + * @author Jungki,Kwak(jungki.kwak@samsung.com) + ***/ + +#include "download-agent-plugin-install.h" +#include "download-agent-debug.h" +#include "download-agent-plugin-conf.h" + +#define DA_DEFAULT_INSTALL_PATH_FOR_PHONE "/opt/media/Downloads" +#define DA_DEFAULT_INSTALL_PATH_FOR_MMC "/opt/storage/sdcard/Downloads" + +char *PI_get_default_install_dir(void) +{ + da_storage_type_t type; + + if (DA_RESULT_OK != get_storage_type(&type)) + return NULL; + + /* ToDo: need to refactoring later */ + if (type == DA_STORAGE_MMC) + return DA_DEFAULT_INSTALL_PATH_FOR_MMC; + else + return DA_DEFAULT_INSTALL_PATH_FOR_PHONE; +} diff --git a/src/agent/download-agent-plugin-libsoup.c b/src/agent/download-agent-plugin-libsoup.c new file mode 100644 index 0000000..676c4c6 --- /dev/null +++ b/src/agent/download-agent-plugin-libsoup.c @@ -0,0 +1,968 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-plugin-libsoup.c + * @brief Platform dependent functions for interface of libsoup http module + * @author Keunsoon Lee (keunsoon.lee@samsung.com) + * @author Jungki Kwak (jungki.kwak@samsung.com) + ***/ + +#include <stdio.h> +#include <string.h> + +#include "download-agent-debug.h" +#include "download-agent-plugin-libsoup.h" +#include "download-agent-http-misc.h" +#include "download-agent-utils.h" +#include "download-agent-pthread.h" + +pthread_mutex_t mutex_for_session_table = PTHREAD_MUTEX_INITIALIZER; + +pi_session_table_t pi_session_table[MAX_SESSION_COUNT] = { { 0, }, }; +da_bool_t using_content_sniffing; + +da_bool_t _pi_http_is_this_session_table_entry_using( + const int in_session_table_entry); + +da_result_t PI_http_init(void) +{ + DA_LOG_FUNC_START(HTTPManager); + + using_content_sniffing = DA_TRUE; + + return DA_RESULT_OK; +} + +void PI_http_deinit(void) +{ + DA_LOG_FUNC_START(HTTPManager); + + return; +} + +da_result_t _set_proxy_on_soup_session(SoupSession *session, char *proxy_addr) +{ + da_result_t ret = DA_RESULT_OK; + + + if (proxy_addr && strlen(proxy_addr) > 0) { + DA_LOG_CRITICAL(HTTPManager,"received proxy = %s \n", proxy_addr); + if (!strstr(proxy_addr, "0.0.0.0")) { + if (strstr((const char *)proxy_addr, "http") == DA_NULL) { + /* DA_LOG(Default,"There is no \"http://\" on received uri, so, add it."); */ + + 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_LOG_ERR(HTTPManager,"DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + snprintf(tmp_str, needed_len, "%s%s", + SCHEME_HTTP, proxy_addr); + + g_object_set(session, SOUP_SESSION_PROXY_URI, + soup_uri_new(tmp_str), NULL); + + free(tmp_str); + } else { + DA_LOG(HTTPManager,"There is \"http\" on uri, so, push this address to soup directly."); + g_object_set(session, SOUP_SESSION_PROXY_URI, + soup_uri_new(proxy_addr), NULL); + } + } + } else { + DA_LOG(HTTPManager,"There is no proxy value"); + } +ERR: + return ret; +} + +void _fill_soup_msg_header(SoupMessage *msg, + const input_for_tranx_t *input_for_tranx) +{ + SoupMessageHeaders *headers = msg->request_headers; + + http_msg_request_t *input_http_msg_request; + http_msg_iter_t http_msg_iter; + http_msg_iter_t http_msg_iter_pre; + + char *field; + char *value; + + input_http_msg_request = input_for_tranx->http_msg_request; + + http_msg_request_get_iter(input_http_msg_request, &http_msg_iter); + http_msg_iter_pre = http_msg_iter; + while (http_msg_get_field_with_iter(&http_msg_iter, &field, &value)) { + if ((field != DA_NULL) && (value != DA_NULL)) { + DA_LOG(HTTPManager,"[%s] %s", field, value); + soup_message_headers_append(headers, field, value); + } + http_msg_iter_pre = http_msg_iter; + } + + if (input_http_msg_request->http_body) { + char body_len_str[16] = { 0, }; + int body_len = strlen(input_http_msg_request->http_body); + + snprintf(body_len_str, sizeof(body_len_str), "%d", body_len); + + soup_message_headers_append(headers, "Content-Length", + body_len_str); + soup_message_headers_append(headers, "Content-Type", + "text/plain"); + soup_message_body_append(msg->request_body, SOUP_MEMORY_COPY, + input_http_msg_request->http_body, body_len); + } +} + +da_result_t PI_http_start_transaction(const input_for_tranx_t *input_for_tranx, + int *out_tranx_id) +{ + da_result_t ret = DA_RESULT_OK; + + int session_table_entry = -1; + pi_http_method_t pi_http_method = PI_HTTP_METHOD_GET; + + queue_t *queue = DA_NULL; + + char *url = DA_NULL; + + SoupSession *session = DA_NULL; + SoupMessage *msg = DA_NULL; + + DA_LOG_FUNC_START(HTTPManager); + + if (DA_FALSE == _pi_http_is_valid_input_for_tranx(input_for_tranx)) { + DA_LOG_ERR(HTTPManager,"input_for_tranx is invalid"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } else { + queue = input_for_tranx->queue; + pi_http_method = input_for_tranx->http_method; + url = input_for_tranx->http_msg_request->url; + } + + session_table_entry = _pi_http_get_avaiable_session_table_entry(); + if (session_table_entry == -1) { + ret = DA_ERR_ALREADY_MAX_DOWNLOAD; + goto ERR; + } + DA_LOG(HTTPManager,"session_table_entry = %d", session_table_entry); + + if (DA_FALSE == _pi_http_register_queue_to_session_table( + session_table_entry, queue)) { + _pi_http_destroy_session_table_entry(session_table_entry); + ret = DA_ERR_ALREADY_MAX_DOWNLOAD; + goto ERR; + } + + /* modified by keunsoon.lee 2010-09-20 use sync_new() instead of async_new() for make different soup thread from UI main thread*/ + session = soup_session_sync_new(); + /* session=soup_session_async_new(); */ + if (!session) { + DA_LOG_ERR(HTTPManager,"Fail to create session"); + return DA_ERR_INVALID_URL; + } + DA_LOG(HTTPManager,"session[%p]", session); +/* + SoupLogger* logger = soup_logger_new(SOUP_LOGGER_LOG_BODY, -1); + soup_logger_attach(logger, session); + g_object_unref(logger); +*/ + if (DA_FALSE == _pi_http_register_session_to_session_table( + session_table_entry, session)) { + _pi_http_init_session_table_entry(session_table_entry); + ret = DA_ERR_ALREADY_MAX_DOWNLOAD; + goto ERR; + } + + g_object_set(session, SOUP_SESSION_MAX_CONNS, MAX_SESSION_COUNT, NULL); + /* Set timeout unlimited time to resume a download which has ETag when the network is re-connected + * => This is changed to 180 seconds due to limitation of max downloading items. + */ + g_object_set(session, SOUP_SESSION_TIMEOUT, MAX_TIMEOUT, NULL); + + _set_proxy_on_soup_session(session, input_for_tranx->proxy_addr); + + switch (pi_http_method) { + case PI_HTTP_METHOD_GET: + msg = soup_message_new(METHOD_GET, url); + break; + case PI_HTTP_METHOD_POST: + msg = soup_message_new(METHOD_POST, url); + break; + case PI_HTTP_METHOD_HEAD: + msg = soup_message_new(METHOD_HEAD, url); + break; + default: + DA_LOG_ERR(HTTPManager,"Cannot enter here"); + break; + } + DA_LOG(HTTPManager,"msg[%p]", msg); + /* if it is failed to create a msg, the url can be invalid, becasue of the input argument of soup_message_new API */ + if (msg == NULL) { + DA_LOG_ERR(HTTPManager,"Fail to create message"); + ret = DA_ERR_INVALID_URL; + goto ERR; + } + + _fill_soup_msg_header(msg, input_for_tranx); + + g_signal_connect(msg, "restarted", G_CALLBACK(_pi_http_restarted_cb), + NULL); /* for redirection case */ + g_signal_connect(msg, "got-headers", + G_CALLBACK(_pi_http_gotheaders_cb), NULL); + g_signal_connect(msg, "got-chunk", G_CALLBACK(_pi_http_gotchunk_cb), + NULL); + + if (using_content_sniffing) { + soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_SNIFFER); + g_signal_connect(msg, "content-sniffed", + G_CALLBACK(_pi_http_contentsniffed_cb), NULL); + } else { + soup_message_disable_feature(msg, SOUP_TYPE_CONTENT_SNIFFER); + } + + soup_session_queue_message(session, msg, _pi_http_finished_cb, NULL); +// g_signal_connect(msg, "finished", G_CALLBACK(_pi_http_finished_cb), NULL); + + if (DA_FALSE == _pi_http_register_msg_to_session_table( + session_table_entry, msg)) { + _pi_http_destroy_session_table_entry(session_table_entry); + ret = DA_ERR_ALREADY_MAX_DOWNLOAD; + goto ERR; + } + + *out_tranx_id = session_table_entry; + DA_LOG(HTTPManager,"*out_tranx_id = %d", *out_tranx_id); + +ERR: + return ret; +} + +da_result_t PI_http_disconnect_transaction(int in_tranx_id) +{ + da_result_t ret = DA_RESULT_OK; + int session_table_entry = -1; + + DA_LOG_FUNC_START(HTTPManager); + + DA_LOG(HTTPManager,"in_tranx_id = %d", in_tranx_id); + + session_table_entry = in_tranx_id; + + _pi_http_destroy_session_table_entry(session_table_entry); + + return ret; +} + +da_result_t PI_http_cancel_transaction(int in_tranx_id, da_bool_t abort_option) +{ + da_result_t ret = DA_RESULT_OK; + SoupSession *session; + SoupMessage *msg; + int session_table_entry = -1; + + DA_LOG_FUNC_START(HTTPManager); + + DA_LOG(HTTPManager,"in_tranx_id = %d", in_tranx_id); + + session_table_entry = in_tranx_id; + if (!_pi_http_is_this_session_table_entry_using(session_table_entry)) { + DA_LOG_CRITICAL(HTTPManager,"not using session"); + return ret; + } + session = GET_SESSION_FROM_TABLE_ENTRY(session_table_entry); + msg = GET_MSG_FROM_TABLE_ENTRY(session_table_entry); + + if (DA_NULL == session) { + DA_LOG_ERR(HTTPManager,"invalid session = %p", session); + goto ERR; + } + + if (DA_NULL == msg) { + DA_LOG_ERR(HTTPManager,"invalid message = %p", msg); + goto ERR; + } + DA_LOG(HTTPManager,"Call soup cancel API : abort option[%d]",abort_option); + if (abort_option) + soup_session_abort(session); + else + soup_session_cancel_message(session, msg, SOUP_STATUS_CANCELLED); + DA_LOG(HTTPManager,"Call soup cancel API-Done"); +ERR: + return ret; +} + +void PI_http_pause_transaction(int transaction_id) +{ + int session_table_entry = -1; + pthread_mutex_t *mutex; + pthread_cond_t *cond; + + DA_LOG_FUNC_START(HTTPManager); + + DA_LOG(HTTPManager,"in_tranx_id = %d", transaction_id); + + session_table_entry = transaction_id; + + if (!_pi_http_is_this_session_table_entry_using(session_table_entry)) + return; + + mutex = &(pi_session_table[session_table_entry].mutex); + cond = &(pi_session_table[session_table_entry].cond); + + _da_thread_mutex_lock (mutex); + + if (pi_session_table[session_table_entry].is_paused == DA_FALSE) { + DA_LOG_CRITICAL(HTTPManager,"paused!"); + pi_session_table[session_table_entry].is_paused = DA_TRUE; + _da_thread_cond_wait(cond, mutex); + } else { + DA_LOG_CRITICAL(HTTPManager,"NOT paused!"); + } + + _da_thread_mutex_unlock (mutex); + +} + +void PI_http_unpause_transaction(int transaction_id) +{ + int session_table_entry = -1; + pthread_mutex_t* mutex; + pthread_cond_t* cond; + + /* DA_LOG_FUNC_START(Default); */ + + session_table_entry = transaction_id; + + if (!_pi_http_is_this_session_table_entry_using(session_table_entry)) + return; + + mutex = &(pi_session_table[session_table_entry].mutex); + cond = &(pi_session_table[session_table_entry].cond); + + _da_thread_mutex_lock (mutex); + + if (pi_session_table[session_table_entry].is_paused == DA_TRUE) { + DA_LOG_CRITICAL(HTTPManager,"wake up!"); + pi_session_table[session_table_entry].is_paused = DA_FALSE; + _da_thread_cond_signal(cond); + } + + _da_thread_mutex_unlock (mutex); + +} + +da_bool_t _pi_http_is_valid_input_for_tranx( + const input_for_tranx_t *input_for_tranx) +{ + if (!(input_for_tranx->http_msg_request)) { + DA_LOG_ERR(HTTPManager,"http_msg_request is NULL"); + return DA_FALSE; + } + + if (!((input_for_tranx->http_method == PI_HTTP_METHOD_GET) || + (input_for_tranx->http_method == PI_HTTP_METHOD_POST) || + (input_for_tranx->http_method == PI_HTTP_METHOD_HEAD))) { + DA_LOG_ERR(HTTPManager,"http_method is neither GET or POST or HEAD"); + return DA_FALSE; + } + + return DA_TRUE; +} + +da_bool_t _pi_http_is_this_session_table_entry_using( + const int in_session_table_entry) +{ + da_bool_t is_using = DA_FALSE; + + if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(in_session_table_entry)) + return DA_FALSE; + + _da_thread_mutex_lock (&mutex_for_session_table); + + is_using = pi_session_table[in_session_table_entry].is_using; + + _da_thread_mutex_unlock (&mutex_for_session_table); + + return is_using; +} + +void _pi_http_init_session_table_entry(const int in_session_table_entry) +{ + int entry = in_session_table_entry; + + if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) + return; + +// _da_thread_mutex_lock (&mutex_for_session_table); + + pi_session_table[entry].is_using = DA_TRUE; + pi_session_table[entry].msg = NULL; + pi_session_table[entry].session = NULL; + pi_session_table[entry].queue = NULL; + + _da_thread_mutex_init(&(pi_session_table[entry].mutex), DA_NULL); + _da_thread_cond_init(&(pi_session_table[entry].cond), NULL); + pi_session_table[entry].is_paused = DA_FALSE; + +// _da_thread_mutex_unlock (&mutex_for_session_table); + + return; +} + +void _pi_http_destroy_session_table_entry(const int in_session_table_entry) +{ + int entry = in_session_table_entry; + + if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) + return; + + _da_thread_mutex_lock (&mutex_for_session_table); + + if (pi_session_table[entry].is_paused == DA_TRUE) + PI_http_unpause_transaction(entry); + + /* Warning! Do not g_object_unref(msg) here! + * soup_session_queue_message() steals msg's reference count, + * so, we don't need to do anything for memory management. + * + * But, if using soup_session_send_message(), MUST call g_object_unref(msg). */ + /* if (pi_session_table[entry].msg) + g_object_unref(pi_session_table[entry].msg); */ + + pi_session_table[entry].msg = NULL; + + /* FIXME Cannot g_object_unref(session) here, + * because msg inside this session is not destoryed yet. + * The msg's reference count is stealed by soup_session_queue_message(), + * and it will be destroyed when _pi_http_finished_cb() is returned. + * For now, this _pi_http_destroy_session_table_entry() is called inside + * _pi_http_finished_cb(), so, g_object_unref(session) is not working. + * Should find out call this function after _pi_http_finished_cb(). */ + if (pi_session_table[entry].session) + g_object_unref(pi_session_table[entry].session); + else + DA_LOG_ERR(HTTPManager,"session is NULL. Cannot unref this."); + DA_LOG(HTTPManager,"unref session [%p]",pi_session_table[entry].session); + + pi_session_table[entry].session = NULL; + + pi_session_table[entry].queue = NULL; + pi_session_table[entry].is_paused = DA_FALSE; + pi_session_table[entry].is_using = DA_FALSE; + + _da_thread_mutex_destroy(&(pi_session_table[entry].mutex)); + _da_thread_cond_destroy(&(pi_session_table[entry].cond)); + + _da_thread_mutex_unlock (&mutex_for_session_table); + + return; +} + +int _pi_http_get_avaiable_session_table_entry(void) +{ + int i; + int avaiable_entry = -1; + + _da_thread_mutex_lock (&mutex_for_session_table); + + for (i = 0; i < MAX_SESSION_COUNT; i++) { + if (pi_session_table[i].is_using == DA_FALSE) { + /* pi_session_table[i].is_using = DA_TRUE; */ + DA_LOG(HTTPManager,"available entry = %d", i); + + avaiable_entry = i; + + break; + } + } + _pi_http_init_session_table_entry(avaiable_entry); + _da_thread_mutex_unlock (&mutex_for_session_table); + + return avaiable_entry; +} + +da_bool_t _pi_http_register_queue_to_session_table( + const int in_session_table_entry, const queue_t *in_queue) +{ + int entry = in_session_table_entry; + queue_t *queue = (queue_t *) in_queue; + da_bool_t ret = DA_FALSE; + + if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) { + DA_LOG_ERR(HTTPManager,"invalid entry = %d", entry); + return DA_FALSE; + } + + _da_thread_mutex_lock (&mutex_for_session_table); + + if (pi_session_table[entry].is_using == DA_FALSE) { + DA_LOG_ERR(HTTPManager,"this entry [%d] is not using", entry); + ret = DA_FALSE; + } else { + pi_session_table[entry].queue = queue; + DA_LOG(HTTPManager,"queue = %p", pi_session_table[entry].queue); + ret = DA_TRUE; + } + + _da_thread_mutex_unlock (&mutex_for_session_table); + + return ret; +} + +da_bool_t _pi_http_register_session_to_session_table( + const int in_session_table_entry, SoupSession *session) +{ + int entry = in_session_table_entry; + da_bool_t ret = DA_FALSE; + + if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) { + DA_LOG_ERR(HTTPManager,"invalid entry = %d", entry); + return DA_FALSE; + } + + if (DA_NULL == session) { + DA_LOG_ERR(HTTPManager,"invalid session = %p",session); + return DA_FALSE; + } + + _da_thread_mutex_lock (&mutex_for_session_table); + + if (pi_session_table[entry].is_using == DA_FALSE) { + ret = DA_FALSE; + } else { + pi_session_table[entry].session = session; + ret = DA_TRUE; + } + + _da_thread_mutex_unlock (&mutex_for_session_table); + + return ret; +} + +da_bool_t _pi_http_register_msg_to_session_table( + const int in_session_table_entry, SoupMessage *msg) +{ + int entry = in_session_table_entry; + da_bool_t ret = DA_FALSE; + + if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) { + DA_LOG_ERR(HTTPManager,"invalid entry = %d", entry); + return DA_FALSE; + } + + if (DA_NULL == msg) { + DA_LOG_ERR(HTTPManager,"invalid msg = %p",msg); + return DA_FALSE; + } + + _da_thread_mutex_lock (&mutex_for_session_table); + + if (pi_session_table[entry].is_using == DA_FALSE) { + ret = DA_FALSE; + } else { + pi_session_table[entry].msg = msg; + ret = DA_TRUE; + } + + _da_thread_mutex_unlock (&mutex_for_session_table); + + return ret; +} + +queue_t *_pi_http_get_queue_from_session_table_entry( + const int in_session_table_entry) +{ + int entry = in_session_table_entry; + queue_t *out_queue = NULL; + + if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) { + DA_LOG_ERR(HTTPManager,"invalid entry = %d", entry); + return out_queue; + } + + _da_thread_mutex_lock (&mutex_for_session_table); + + out_queue = pi_session_table[entry].queue; + _da_thread_mutex_unlock (&mutex_for_session_table); + + return out_queue; +} + +void _pi_http_store_read_header_to_queue(SoupMessage *msg, const char *sniffedType) +{ + da_result_t ret = DA_RESULT_OK; + + queue_t *da_queue = NULL; + q_event_t *da_event = NULL; + q_event_type_data da_event_type_data; + + int session_table_entry = -1; + SoupMessageHeadersIter headers_iter; + + const char *header_name; + const char *header_value; + + http_msg_response_t *http_msg_response = NULL; + + /* DA_LOG_FUNC_START(Default); */ + + if (msg->response_headers) { + ret = http_msg_response_create(&http_msg_response); + if (ret != DA_RESULT_OK) + return; + + http_msg_response_set_status_code(http_msg_response, + msg->status_code); + + DA_LOG(HTTPManager,"\n----raw header---------------------------------------------"); + DA_LOG_CRITICAL(HTTPManager,"status code = %d", msg->status_code); + soup_message_headers_iter_init(&headers_iter, + msg->response_headers); + while (soup_message_headers_iter_next(&headers_iter, + &header_name, &header_value)) { + if ((header_name != DA_NULL) && (header_value + != DA_NULL)) { + http_msg_response_add_field(http_msg_response, + header_name, header_value); + } + } + DA_LOG(HTTPManager,"\n-------------------------------------------------------------\n"); + + } + + if (using_content_sniffing && sniffedType) + http_msg_response_set_content_type(http_msg_response, sniffedType); + + session_table_entry + = _pi_http_get_session_table_entry_from_message(msg); + if (session_table_entry == -1) { + DA_LOG_ERR(HTTPManager,"Fail to find matched session table entry.."); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + da_event_type_data = Q_EVENT_TYPE_DATA_PACKET; + + da_queue = _pi_http_get_queue_from_session_table_entry( + session_table_entry); + + ret = Q_make_http_data_event(da_event_type_data, &da_event); + if (ret != DA_RESULT_OK) { + DA_LOG_ERR(HTTPManager,"fail to make da_event"); + goto ERR; + } else { + Q_set_status_code_on_http_data_event(da_event, msg->status_code); + da_event->type.q_event_data_http.http_response_msg + = http_msg_response; + + Q_push_event(da_queue, da_event); + } + return; + +ERR: + if (DA_RESULT_OK != ret) + http_msg_response_destroy(&http_msg_response); + + return; +} + +void _pi_http_store_read_data_to_queue(SoupMessage *msg, const char* body_data, + int received_body_len) +{ + da_result_t ret = DA_RESULT_OK; + da_bool_t b_ret = DA_FALSE; + + char *body_buffer = NULL; + queue_t *da_queue = NULL; + q_event_t *da_event = NULL; + q_event_type_data da_event_type_data; + int session_table_entry = -1; + int http_status = -1; + + /* DA_LOG_FUNC_START(Default); */ + + http_status = msg->status_code; + + session_table_entry + = _pi_http_get_session_table_entry_from_message(msg); + if (session_table_entry == -1) { + DA_LOG_ERR(HTTPManager,"Fail to find matched session table entry.."); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + if (received_body_len == 0) { + DA_LOG(HTTPManager,"Q_EVENT_TYPE_DATA_FINAL"); + da_event_type_data = Q_EVENT_TYPE_DATA_FINAL; + } else { + da_event_type_data = Q_EVENT_TYPE_DATA_PACKET; + if (received_body_len > 0) { + body_buffer = (char*) calloc(1, received_body_len); + DA_LOG(HTTPManager,"body_buffer[%p]msg[%p]",body_buffer,msg); + if (body_buffer == DA_NULL) { + DA_LOG_ERR(HTTPManager,"DA_ERR_FAIL_TO_MEMALLOC"); + goto ERR; + } + memcpy(body_buffer, body_data, received_body_len); + } + } + + da_queue = _pi_http_get_queue_from_session_table_entry( + session_table_entry); + + ret = Q_make_http_data_event(da_event_type_data, &da_event); + if (ret != DA_RESULT_OK) { + DA_LOG_ERR(HTTPManager,"fail to make da_event"); + goto ERR; + } else { + Q_set_status_code_on_http_data_event(da_event, http_status); + Q_set_http_body_on_http_data_event(da_event, received_body_len, + body_buffer); + + _da_thread_mutex_lock (&(da_queue->mutex_queue)); + b_ret = Q_push_event_without_lock(da_queue, da_event); + if (b_ret == DA_FALSE) { + DA_LOG_CRITICAL(HTTPManager,"----------------------------------------fail to push!"); + + pthread_mutex_t *session_mutex = NULL; + pthread_cond_t *session_cond = NULL; + + session_mutex + = &(pi_session_table[session_table_entry].mutex); + session_cond + = &(pi_session_table[session_table_entry].cond); + + /* MUST keep this order for these mutexes */ + _da_thread_mutex_lock (session_mutex); + _da_thread_mutex_unlock (&(da_queue->mutex_queue)); + + if (pi_session_table[session_table_entry].is_paused + == DA_FALSE) { + DA_LOG_CRITICAL(HTTPManager,"paused!"); + pi_session_table[session_table_entry].is_paused + = DA_TRUE; + _da_thread_cond_wait(session_cond, session_mutex); + } else { + DA_LOG_CRITICAL(HTTPManager,"NOT paused!"); + } + + _da_thread_mutex_unlock (session_mutex); + + DA_LOG_CRITICAL(HTTPManager,"wake up! push again"); + Q_push_event(da_queue, da_event); + } else { + _da_thread_mutex_unlock (&(da_queue->mutex_queue)); + } + + } + + return; + +ERR: + if (DA_RESULT_OK != ret) { + if (DA_NULL != body_buffer) { + free(body_buffer); + } + } + + return; +} + +int _translate_error_code(int soup_error) +{ + switch (soup_error) { + case SOUP_STATUS_CANT_RESOLVE: + case SOUP_STATUS_CANT_RESOLVE_PROXY: + case SOUP_STATUS_CANT_CONNECT: + case SOUP_STATUS_CANT_CONNECT_PROXY: + case SOUP_STATUS_IO_ERROR: + case SOUP_STATUS_MALFORMED: + case SOUP_STATUS_TRY_AGAIN: + case SOUP_STATUS_TOO_MANY_REDIRECTS: + return DA_ERR_NETWORK_FAIL; + + case SOUP_STATUS_SSL_FAILED: + return DA_ERR_SSL_FAIL; + + default: + return DA_RESULT_OK; + } +} + +void _pi_http_store_neterr_to_queue(SoupMessage *msg) +{ + da_result_t ret = DA_RESULT_OK; + int error_type = -1; + queue_t *da_queue = NULL; + q_event_t *da_event = NULL; + int session_table_entry = -1; + + DA_LOG_FUNC_START(HTTPManager); + + error_type = _translate_error_code(msg->status_code); + + session_table_entry + = _pi_http_get_session_table_entry_from_message(msg); + if (session_table_entry == -1) { + DA_LOG_ERR(HTTPManager,"Fail to find matched session table entry.."); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + + da_queue = _pi_http_get_queue_from_session_table_entry( + session_table_entry); + + DA_LOG_CRITICAL(HTTPManager,"Q_EVENT_TYPE_DATA_ABORT"); + ret = Q_make_http_data_event(Q_EVENT_TYPE_DATA_ABORT, &da_event); + if (ret != DA_RESULT_OK) { + DA_LOG_ERR(HTTPManager,"fail to make da_event"); + goto ERR; + } else { + Q_set_error_type_on_http_data_event(da_event, error_type); + + Q_push_event(da_queue, da_event); + } + +ERR: + return; +} + +int _pi_http_get_session_table_entry_from_message(SoupMessage *msg) +{ + + int out_entry = -1; + int i; + + if (DA_NULL == msg) { + DA_LOG_ERR(HTTPManager,"invalid message = %p", msg); + return out_entry; + } + + _da_thread_mutex_lock (&mutex_for_session_table); + + for (i = 0; i < MAX_SESSION_COUNT; i++) { + if (pi_session_table[i].is_using == DA_TRUE) { + if (pi_session_table[i].msg == msg) { + out_entry = i; + break; + } + } + } + + _da_thread_mutex_unlock (&mutex_for_session_table); + + if (i == MAX_SESSION_COUNT) { + DA_LOG_ERR(HTTPManager,"fail to find message = %p", msg); + } + + return out_entry; + +} + +void _pi_http_finished_cb(SoupSession *session, SoupMessage *msg, gpointer data) +{ + char *url = NULL; + + DA_LOG_FUNC_START(HTTPManager); + + url = soup_uri_to_string(soup_message_get_uri(msg), DA_FALSE); + + DA_LOG(HTTPManager,"status_code[%d], reason[%s], url[%s]",msg->status_code,msg->reason_phrase,url); + + if (url) { + free(url); + url = NULL; + } + + if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)) { + if (msg->status_code == SOUP_STATUS_CANCELLED) { + _pi_http_store_read_data_to_queue(msg, DA_NULL, 0); + } else { + _pi_http_store_neterr_to_queue(msg); + } + } else { + _pi_http_store_read_data_to_queue(msg, DA_NULL, 0); + } + +} + +/* this callback is called in case of redirection */ +void _pi_http_restarted_cb(SoupMessage *msg, gpointer data) +{ + DA_LOG_FUNC_START(HTTPManager); + /* Location URL is needed when extracting the file name from url. + * So, the response header should be handled by http mgr.*/ + _pi_http_store_read_header_to_queue(msg, NULL); +} + +void _pi_http_gotheaders_cb(SoupMessage *msg, gpointer data) +{ + DA_LOG_FUNC_START(HTTPManager); + + if (SOUP_STATUS_IS_REDIRECTION(msg->status_code)) { + DA_LOG(HTTPManager,"Redirection !!"); + if (SOUP_STATUS_NOT_MODIFIED != msg->status_code) + return; + } + + soup_message_body_set_accumulate(msg->response_body, FALSE); + + if (!using_content_sniffing) + _pi_http_store_read_header_to_queue(msg, NULL); + else + DA_LOG(HTTPManager,"ignore because content sniffing is turned on"); +} + +void _pi_http_contentsniffed_cb(SoupMessage *msg, const char *sniffedType, + GHashTable *params, gpointer data) +{ + DA_LOG_FUNC_START(HTTPManager); + + if (SOUP_STATUS_IS_REDIRECTION(msg->status_code)) { + DA_LOG(HTTPManager,"Redirection !!"); + if (SOUP_STATUS_NOT_MODIFIED != msg->status_code) + return; + } + + if (using_content_sniffing) + _pi_http_store_read_header_to_queue(msg, sniffedType); +} + +void _pi_http_gotchunk_cb(SoupMessage *msg, SoupBuffer *chunk, gpointer data) +{ + DA_LOG_FUNC_START(HTTPManager); + + if (SOUP_STATUS_IS_REDIRECTION(msg->status_code)) + return; + + if (chunk->data && chunk->length > 0) { + _pi_http_store_read_data_to_queue(msg, chunk->data, + chunk->length); + } +} + diff --git a/src/agent/download-agent-utils-dl-req-id-history.c b/src/agent/download-agent-utils-dl-req-id-history.c new file mode 100644 index 0000000..35ab700 --- /dev/null +++ b/src/agent/download-agent-utils-dl-req-id-history.c @@ -0,0 +1,79 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-utils-dl-req-id-history.c + * @brief Including operations for dl-req-id-history + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + +#include "download-agent-type.h" +#include "download-agent-utils.h" +#include "download-agent-utils-dl-req-id-history.h" + +da_result_t init_dl_req_id_history(dl_req_id_history_t *dl_req_id_history) +{ + da_result_t ret = DA_RESULT_OK; + + /* Initial dl_req_id_history will be starting number for dl_req_id. + * dl_req_id will be sequentially increased from the dl_req_id_history, + * then dl_req_id_history will be updated. */ + _da_thread_mutex_init(&(dl_req_id_history->mutex), DA_NULL); + _da_thread_mutex_lock(&(dl_req_id_history->mutex)); + get_random_number(&(dl_req_id_history->starting_num)); + dl_req_id_history->cur_dl_req_id = DA_INVALID_ID; + _da_thread_mutex_unlock(&(dl_req_id_history->mutex)); + + DA_LOG_CRITICAL(Default,"starting num = %d", dl_req_id_history->starting_num); + return ret; +} + +da_result_t deinit_dl_req_id_history(dl_req_id_history_t *dl_req_id_history) +{ + da_result_t ret = DA_RESULT_OK; + + _da_thread_mutex_lock(&(dl_req_id_history->mutex)); + dl_req_id_history->starting_num = DA_INVALID_ID; + dl_req_id_history->cur_dl_req_id = DA_INVALID_ID; + _da_thread_mutex_unlock(&(dl_req_id_history->mutex)); + + _da_thread_mutex_destroy(&(dl_req_id_history->mutex)); + + return ret; +} + +int get_available_dl_req_id(dl_req_id_history_t *dl_req_id_history) +{ + int dl_req_id = 0; + + _da_thread_mutex_lock(&(dl_req_id_history->mutex)); + + if (dl_req_id_history->cur_dl_req_id == DA_INVALID_ID) + dl_req_id_history->cur_dl_req_id = dl_req_id_history->starting_num; + else if (dl_req_id_history->cur_dl_req_id > 254) + dl_req_id_history->cur_dl_req_id = 1; + else + dl_req_id_history->cur_dl_req_id++; + + dl_req_id = dl_req_id_history->cur_dl_req_id; + + _da_thread_mutex_unlock(&(dl_req_id_history->mutex)); + + DA_LOG_CRITICAL(Default,"dl_req_id = %d", dl_req_id); + return dl_req_id; +} diff --git a/src/agent/download-agent-utils.c b/src/agent/download-agent-utils.c new file mode 100644 index 0000000..5843ef8 --- /dev/null +++ b/src/agent/download-agent-utils.c @@ -0,0 +1,404 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-utils.c + * @brief Including some utilitis + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + ***/ + +#include <sys/vfs.h> +#include <sys/stat.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <glib.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#include "download-agent-client-mgr.h" +#include "download-agent-debug.h" +#include "download-agent-dl-mgr.h" +#include "download-agent-file.h" +#include "download-agent-http-misc.h" +#include "download-agent-mime-util.h" +#include "download-agent-utils.h" +#include "download-agent-plugin-conf.h" +#include "download-agent-plugin-install.h" +#include "download-agent-dl-info-util.h" + +#define DA_HTTP_HEADER_CONTENT_TYPE "Content-Type" +#define DA_HTTP_HEADER_CONTENT_LENGTH "Content-Length" +#define DA_FILE_NUMBER_LIMIT (1024*1024) +// Addition or deletion of entries in this list should be in sync with the +// enumaration download_content_t defined in download-agent-dl-mgr.h + +typedef struct _da_descriptor_mime_table_t { + char* content_type; + da_mime_type_id_t mime_type; +} da_descriptor_mime_table_t; + +da_descriptor_mime_table_t + descriptor_mime_table[] = { + {"", DA_MIME_TYPE_NONE}, + /* DRM1.0 */ + {"application/vnd.oma.drm.message", + DA_MIME_TYPE_DRM1_MESSATE}, /* drm1.0 FL.CD*/ + {"application/vnd.ms-playready.initiator+xml", + DA_MIME_PLAYREADY_INIT}, // 17 + {"", DA_MIME_TYPE_END}}; + +void get_random_number(int *out_num) +{ + int temp = DA_INVALID_ID; + unsigned int seed = (unsigned)time(0); + + temp = (int)(rand_r(&seed) % 100 + 1.0); + *out_num = temp; +} + +da_bool_t is_content_drm_dm(char *content_type) +{ + if (content_type == DA_NULL) + return DA_FALSE; + + if (0 == strcmp(content_type, MIME_DRM_MESSAGE)) { + DA_LOG(Default,"DRM_DM content"); + return DA_TRUE; + } else { + return DA_FALSE; + } +} + +da_result_t get_extension_from_mime_type(char *mime_type, char **extension) +{ + da_result_t ret = DA_RESULT_OK; + char *ext = DA_NULL; + + DA_LOG_FUNC_START(Default); + if (DA_NULL == mime_type || DA_NULL == extension) { + DA_LOG_ERR(Default,"received mime_type is null"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + DA_LOG(Default,"input mime type = %s", mime_type); + if (DA_RESULT_OK != (ret = da_mime_get_ext_name(mime_type, &ext))) { + DA_LOG_ERR(Default,"can't find proper extension!"); + goto ERR; + } + *extension = ext; + DA_LOG(Default,"found extension = %s", *extension); + +ERR: + return ret; +} + +int read_data_from_file(char *file, char **out_buffer) +{ + FILE *fd; + int file_size = -1; + char *buffer = NULL; + int buffer_len = 0; + int read_len = 0; + + *out_buffer = NULL; + + if (!file) + return 0; + + /* open file with "rb", because fread() handles the file as binary mode */ + fd = fopen(file, "rb"); + if (!fd) { + DA_LOG_ERR(FileManager,"File open err! received file path = [%s]", file); + return 0; + } + + get_file_size(file, &file_size); + if (file_size <= 0) { + DA_LOG_ERR(FileManager,"file size is [%d]", file_size); + fclose(fd); + return 0; + } + + /* A guide from www.securecoding.cert.org + * : FIO17-C. Do not rely on an ending null character when using fread() + * + * buffer is initialized with null through calloc(), so, it is always null-terminated even if fread() failed. + * allocate memory one more byte to ensure null-terminated even if the file is not null-terminated. + */ + buffer_len = sizeof(char) * file_size; + buffer = (char *)calloc(1, buffer_len + 1); + if (buffer) { + read_len = fread(buffer, sizeof(char), file_size, fd); + if (read_len == file_size) { + *out_buffer = buffer; + } else { + DA_LOG_ERR(FileManager,"File Read Not Complete read length = %d", read_len); + free(buffer); + buffer = NULL; + buffer_len = 0; + } + } else { + buffer_len = 0; + } + + fclose(fd); + + return buffer_len; +} + +da_result_t check_enough_storage(stage_info *stage) +{ + da_result_t ret = DA_RESULT_OK; + unsigned long cont_size = 0; + da_storage_size_t avail_memory = {0, }; + da_storage_type_t type = DA_STORAGE_PHONE; + + DA_LOG_FUNC_START(Default); + + /* check enough storage here because of multiple download */ + ret = get_storage_type(&type); + if (DA_RESULT_OK != ret) + return ret; + + cont_size + = GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)); + + DA_LOG(Default,"cont_size [%d]", cont_size); + if (cont_size) { + ret = get_available_memory(DA_STORAGE_PHONE, &avail_memory); + if (DA_RESULT_OK == ret && (avail_memory.b_available + < ((cont_size + SAVE_FILE_BUFFERING_SIZE_5MB) + / avail_memory.b_size))) /* 5MB buffering */ + { + DA_LOG_ERR(Default,"There is no space for content in Phone memory"); + return DA_ERR_DISK_FULL; + } else if (DA_RESULT_OK != ret) { + return ret; + } + /* If default memeory type is mmc, + * it need to check phone memroy for temproary folder + * and mmc memory for actual install folder */ + if (type == DA_STORAGE_MMC) { + DA_LOG(Default,"Storage type == DA_STORAGE_MMC\n"); + ret = get_available_memory(type, &avail_memory); + if (DA_RESULT_OK == ret && (avail_memory.b_available + < ((cont_size + SAVE_FILE_BUFFERING_SIZE_50KB) + / avail_memory.b_size))) /* 50KB buffering */ + { + DA_LOG_ERR(Default,"There is no space for content in MMC memory"); + return DA_ERR_DISK_FULL; + } else if (DA_RESULT_OK != ret) { + return ret; + } + } + } + + return ret; +} + +da_result_t get_available_memory( + da_storage_type_t storage_type, + da_storage_size_t *avail_memory) +{ + int fs_ret = 0; + struct statfs filesys_info = {0, }; + + DA_LOG_FUNC_START(Default); + + if (!avail_memory) + return DA_ERR_INVALID_ARGUMENT; + + if (storage_type == DA_STORAGE_PHONE) { + fs_ret = statfs(DA_DEFAULT_TMP_FILE_DIR_PATH, &filesys_info); + } else if (storage_type == DA_STORAGE_MMC) { + char *default_install_dir = NULL; + default_install_dir = PI_get_default_install_dir(); + if (default_install_dir) { + fs_ret = statfs(default_install_dir, &filesys_info); + } else { + return DA_ERR_FAIL_TO_ACCESS_STORAGE; + } + } else { + DA_LOG_ERR(Default,"Invalid storage type"); + return DA_ERR_INVALID_ARGUMENT; + } + + if (fs_ret != 0) { + DA_LOG_ERR(Default,"Phone file path :statfs error - [%d]", errno); + return DA_ERR_FAIL_TO_ACCESS_FILE; + } + + avail_memory->b_available = filesys_info.f_bavail; + avail_memory->b_size = filesys_info.f_bsize; + + DA_LOG(Default, "Memory type : %d", storage_type); + DA_LOG(Default, "Available Memory(f_bavail) : %lu", filesys_info.f_bavail); + DA_LOG(Default, "Available Memory(f_bsize) : %d", filesys_info.f_bsize); + DA_LOG(Default, "Available Memory(kbytes) : %lu", (filesys_info.f_bavail/1024)*filesys_info.f_bsize); + + return DA_RESULT_OK; +} + +da_mime_type_id_t get_mime_type_id(char* content_type) +{ + int i = 0; + + DA_LOG_FUNC_START(Default); + + DA_LOG(Default,"received content_type = %s", content_type); + + if (content_type == NULL) { + DA_LOG_ERR(Default, "No Mime Type\n"); + return DA_MIME_TYPE_NONE; + } + + while(descriptor_mime_table[i].mime_type != DA_MIME_TYPE_END) + { + if (!strcmp(descriptor_mime_table[i].content_type, content_type)) { + break; + } + i++; + } + DA_LOG(Default, "dd mime type check: index[%d] type[%d]", i, descriptor_mime_table[i].mime_type); + return descriptor_mime_table[i].mime_type; +} + + + +da_bool_t is_valid_url(const char* url, da_result_t *err_code) +{ + da_result_t ret = DA_RESULT_OK; + da_bool_t b_ret = DA_FALSE; + + int wanted_str_len = 0; + char *wanted_str = NULL; + char *wanted_str_start = NULL; + char *wanted_str_end = NULL; + + if ((DA_NULL == url) || (1 > strlen(url))) { + ret = DA_ERR_INVALID_URL; + goto ERR; + } + + wanted_str_start = (char*)url; + wanted_str_end = strstr(url, "://"); + if (!wanted_str_end) { + DA_LOG_ERR(Default,"No protocol on this url"); + ret = DA_ERR_INVALID_URL; + goto ERR; + } + + wanted_str_len = wanted_str_end - wanted_str_start; + wanted_str = (char*)calloc(1, wanted_str_len + 1); + if (!wanted_str) { + DA_LOG_ERR(Default,"DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + strncpy(wanted_str, wanted_str_start, wanted_str_len); + + b_ret = is_supporting_protocol(wanted_str); + if (!b_ret) { + ret = DA_ERR_UNSUPPORTED_PROTOCAL; + goto ERR; + } + +ERR: + if (wanted_str) { + free(wanted_str); + wanted_str = NULL; + } + + if (err_code) + *err_code = ret; + + return b_ret; +} + +da_result_t move_file(const char *from_path, const char *to_path) +{ + da_result_t ret = DA_RESULT_OK; + + if (!from_path || !to_path) + return DA_ERR_INVALID_ARGUMENT; + + if (rename(from_path, to_path) != 0) { + DA_LOG_CRITICAL(FileManager,"rename failed : syserr[%d]",errno); + if (errno == EXDEV) { + DA_LOG_CRITICAL(FileManager,"File system is diffrent. Try to copy a file"); + ret = copy_file(from_path, to_path); + if (ret == DA_RESULT_OK) { + remove_file(from_path); + } else { + if (is_file_exist(to_path)) + remove_file(to_path); + ret = DA_ERR_FAIL_TO_INSTALL_FILE; + } + } else { + ret = DA_ERR_FAIL_TO_INSTALL_FILE; + } + } + return ret; +} + +void remove_file(const char *file_path) +{ + DA_LOG_FUNC_START(FileManager); + + if (file_path) { + DA_LOG(FileManager,"remove file [%s]", file_path); + if (unlink(file_path) < 0) { + DA_LOG_ERR(FileManager,"file removing failed."); + } + } +} + +char *print_dl_state(da_state state) +{ + switch (state) { + case DA_STATE_WAITING: + return "DA_STATE_WAITING"; + case DA_STATE_DOWNLOAD_STARTED: + return "DA_STATE_DOWNLOAD_STARTED"; + case DA_STATE_DOWNLOADING: + return "DA_STATE_DOWNLOADING"; + case DA_STATE_DOWNLOAD_COMPLETE: + return "DA_STATE_DOWNLOAD_COMPLETE"; + case DA_STATE_FINISHED: + return "DA_STATE_FINISHED"; + case DA_STATE_CANCELED: + return "DA_STATE_CANCELED"; + case DA_STATE_CANCELED_ALL: + return "DA_STATE_CANCELED_ALL"; + case DA_STATE_SUSPENDED: + return "DA_STATE_SUSPENDED"; + case DA_STATE_SUSPENDED_ALL: + return "DA_STATE_SUSPENDED_ALL"; + case DA_STATE_RESUMED: + return "DA_STATE_RESUMED"; + case DA_STATE_FAILED: + return "DA_STATE_FAILED"; + default: + return "STATE ERROR"; + + } +} + diff --git a/src/agent/include/download-agent-basic.h b/src/agent/include/download-agent-basic.h new file mode 100644 index 0000000..7c27dec --- /dev/null +++ b/src/agent/include/download-agent-basic.h @@ -0,0 +1,45 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-basic.h + * @brief + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + +#ifndef _Download_Agent_Basic_H +#define _Download_Agent_Basic_H + +#include <string.h> + +#include "download-agent-type.h" +#include "download-agent-interface.h" +#include "download-agent-dl-mgr.h" + +typedef struct _extension_data_t { + const char **request_header; + const int *request_header_count; + const char *install_path; + const char *file_name; + void *user_data; +} extension_data_t; + +da_result_t start_download(const char* url, da_handle_t *dl_req_id); +da_result_t start_download_with_extension(const char *url , da_handle_t *dl_req_id, extension_data_t *extension_data); + +#endif diff --git a/src/agent/include/download-agent-client-mgr.h b/src/agent/include/download-agent-client-mgr.h new file mode 100644 index 0000000..2ac50ee --- /dev/null +++ b/src/agent/include/download-agent-client-mgr.h @@ -0,0 +1,102 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-client-mgr.h + * @brief + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + +#ifndef _Download_Agent_Client_Mgr_H +#define _Download_Agent_Client_Mgr_H + +#include <string.h> + +#include "download-agent-type.h" +#include "download-agent-interface.h" + +#include "download-agent-pthread.h" + +typedef enum { + Q_CLIENT_NOTI_TYPE_UPDATE_DL_INFO, + Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO, + Q_CLIENT_NOTI_TYPE_SEND_STATE, + Q_CLIENT_NOTI_TYPE_TERMINATE, +} client_noti_type; + +typedef struct _client_noti_t client_noti_t; +struct _client_noti_t { + int download_id; + void *user_data; + client_noti_type noti_type; + union _client_type { + user_download_info_t update_dl_info ; + user_downloading_info_t update_downloading_info ; + user_notify_info_t da_state_info ; + } type; + + client_noti_t *next; +}; + +typedef struct _client_queue_t { + da_bool_t having_data; + client_noti_t *client_q_head; + pthread_mutex_t mutex_client_queue; + pthread_cond_t cond_client_queue; +} client_queue_t; + +typedef struct _client_app_info_t { + da_bool_t is_using; + da_bool_t is_manual_download; + da_client_cb_t client_callback; + char *client_user_agent; +} client_app_info_t; + +typedef struct _client_app_mgr_t { + da_bool_t is_init; + da_bool_t is_manual_download; + client_queue_t client_queue; + client_app_info_t client_app_info; + pthread_t thread_id; + da_bool_t is_thread_init; + pthread_mutex_t mutex_client_mgr; +} client_app_mgr_t; + +da_result_t init_client_app_mgr(void); +da_bool_t is_client_app_mgr_init(void); + +da_result_t reg_client_app(da_client_cb_t *da_client_callback, + da_download_managing_method download_method); +da_result_t dereg_client_app(void); + +da_result_t send_client_da_state (int download_id, da_state state, int err); +da_result_t send_client_update_dl_info (int download_id, int dl_req_id, + char *file_type, unsigned long int file_size, char *tmp_saved_path, + char *http_response_header, char *http_raw_data); +da_result_t send_client_update_downloading_info (int download_id, int dl_req_id, + unsigned long int total_received_size, char *saved_path); + +da_result_t get_client_download_path(char **out_path); +char *get_client_user_agent_string(void); + +da_bool_t is_this_client_available(void); +da_bool_t is_this_client_manual_download_type(void); + +void push_client_noti(client_noti_t *client_noti); + +#endif diff --git a/src/agent/include/download-agent-debug.h b/src/agent/include/download-agent-debug.h new file mode 100644 index 0000000..aa569ad --- /dev/null +++ b/src/agent/include/download-agent-debug.h @@ -0,0 +1,103 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-debug.h + * @brief Including some debug utilitis + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + +#ifndef _Download_Agent_Debug_H +#define _Download_Agent_Debug_H + +#include "download-agent-type.h" + +#define DA_DEBUG_ENV_KEY "DOWNLOAD_AGENT_DEBUG" +#define DA_DEBUG_CONFIG_FILE_PATH "/tmp/.download_agent.conf" + +#define IS_LOG_ON(channel) (DALogBitMap & (0x1<<(channel))) + +typedef enum { + Soup, + HTTPManager, + InstallManager, + FileManager, + DRMManager, + DownloadManager, + ClientNoti, + HTTPMessageHandler, + Encoding, + QueueManager, + Parsing, + Thread, + Default, + DA_LOG_CHANNEL_MAX +} da_log_channel; + +extern int DALogBitMap; + +da_result_t init_log_mgr(void); + +#ifdef NODEBUG + #define DA_LOG(channel, format, ...) ((void)0) + #define DA_LOG_CRITICAL(channel, format, ...) ((void)0) + #define DA_LOG_VERBOSE(channel, format, ...) ((void)0) + #define DA_LOG_ERR(channel, format, ...) ((void)0) + #define DA_LOG_FUNC_START(channel, ...) ((void)0) + +#else /* NODEBUG */ +#include <stdio.h> +#include <stdarg.h> +#include <pthread.h> + +#ifdef DA_DEBUG_USING_DLOG + #include <dlog.h> + #ifdef LOG_TAG + #undef LOG_TAG + #endif /* LOG_TAG */ + #define LOG_TAG "DownloadAgent" + + #define DA_LOG(channel, format, ...) LOGD_IF(IS_LOG_ON(channel), "[%s] "format"\n", __FUNCTION__, ##__VA_ARGS__); + #define DA_LOG_CRITICAL(channel, format, ...) LOGE_IF(IS_LOG_ON(channel), "[%s] "format"\n", __FUNCTION__, ##__VA_ARGS__); + #define DA_LOG_VERBOSE(channel, format, ...) LOGV_IF(IS_LOG_ON(channel), "[%s] "format"\n", __FUNCTION__, ##__VA_ARGS__); + #define DA_LOG_ERR(channel, format, ...) LOGE_IF(IS_LOG_ON(channel), "[%s] ERR! "format"\n", __FUNCTION__, ##__VA_ARGS__); + #define DA_LOG_FUNC_START(channel, ...) LOGV_IF(IS_LOG_ON(channel), "[%s] starting... \n", __FUNCTION__); +#else /* DA_DEBUG_USING_DLOG */ + #include <unistd.h> + #include <syscall.h> + + #define DA_LOG(channel, format, ...) do {\ + IS_LOG_ON(channel) \ + ? fprintf(stderr, "[DA][%u][%s(): %d] "format"\n",(unsigned int)syscall(__NR_gettid), __FUNCTION__,__LINE__, ##__VA_ARGS__) \ + : ((void)0);\ + }while(0) + #define DA_LOG_ERR(channel, format, ...) do {\ + IS_LOG_ON(channel) \ + ? fprintf(stderr, "[DA][%u][ERR][%s(): %d]\n",(unsigned int)syscall(__NR_gettid), __FUNCTION__,__LINE__, ##__VA_ARGS__) \ + : ((void)0); \ + }while(0) + #define DA_LOG_FUNC_START(channel, ...) do {\ + IS_LOG_ON(channel) \ + ? fprintf(stderr, "[DA][%u][%s(): %d] starting\n",(unsigned int)syscall(__NR_gettid), __FUNCTION__,__LINE__) \ + : ((void)0); \ + }while(0) + #define DA_LOG_CRITICAL DA_LOG + #define DA_LOG_VERBOSE DA_LOG +#endif /* DA_DEBUG_USING_DLOG */ +#endif /* NDEBUG */ +#endif /* _Download_Agent_Debug_H */ diff --git a/src/agent/include/download-agent-defs.h b/src/agent/include/download-agent-defs.h new file mode 100644 index 0000000..0d4c9af --- /dev/null +++ b/src/agent/include/download-agent-defs.h @@ -0,0 +1,328 @@ +/** + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-defs.h + * @brief including types and defines for Download Agent + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + */ + +#ifndef _Download_Agent_Defs_H +#define _Download_Agent_Defs_H + +/** + * @{ + */ +#ifndef DEPRECATED +#define DEPRECATED __attribute__((deprecated)) +#endif + +/** + * @ingroup Reference + */ +typedef int da_handle_t; + +/** + * @ingroup Reference + * Max count to download files simultaneously. \n + * Main reason for this restriction is because of Network bandwidth. + */ +#define DA_MAX_DOWNLOAD_REQ_AT_ONCE 5 + +/** + * @ingroup Reference + */ +#define DA_RESULT_OK 0 + +#define DA_TRUE 1 +#define DA_FALSE 0 +#define DA_NULL 0 +#define DA_INVALID_ID -1 + +/** + * @ingroup Reference + * special \c dl_req_id to indicate all \c dl_req_id on current status \n\n + * If client wants to do something (cancel/suspend/resume) for all \c dl_req_id, simply use this. \n + * This sends a command to all downloading threads on current status without any changes on state notification. \n + * That is, it is same with calling each dl_req_id separately. + * @see DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI + */ +#define DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS -1 +/** + * @ingroup Reference + * This is also indicates all \c dl_req_id, but it will not send state notification for each \c dl_req_id. \n + * Instead, DA_STATE_XXX_ALL will be sent. + * @see DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS + */ +#define DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI -2 +/** + * @} + */ + +/** + * @ingroup Reference + * @addtogroup ExtensionFeatures Extension features + * @{ + * @brief Download Agent's extension features using by da_start_download_with_extension() + * + * When calling \a da_start_download_with_extension function, use these defines for property name. \n + * +*/ +/** + * @fn DA_FEATURE_REQUEST_HEADER + * @brief receiving reqeust header for requesting URL on \a da_start_download_with_extension. + * @remarks + * property value type for this is 'char**'. + * value is valid if it has the string array which consist the name of http header field and the value of http header. + * ex) Cookie: SID=1234 + * @see da_start_download_with_extension + */ +#define DA_FEATURE_REQUEST_HEADER "request_header" + +/** + * @def DA_FEATURE_USER_DATA + * @brief receiving user data for requesting URL on \a da_start_download_with_extension. + * @remarks + * property value type for this is 'void*'. + * @details + * Every client callback will convey this value. + * @see da_start_download_with_extension + */ +#define DA_FEATURE_USER_DATA "user_data" + +/** + * @def DA_FEATURE_INSTALL_PATH + * @brief Downloaded file will be installed on designated path. + * @remarks + * property value type for this is 'char*'. + * @warning + * If the path is invalid, DA_ERR_INVALID_INSTALL_PATH will be returned. \n + * No file name accepts, but only path does. + * @see da_start_download_with_extension + */ +#define DA_FEATURE_INSTALL_PATH "install_path" + +/** + * @def DA_FEATURE_FILE_NAME + * @brief Downloaded file will be stored with the designated name. + * @remarks + * property value type for this is 'char*'. + * @warning + * No path accepts, but only file name dose. \n\n + * If the designated file name does not include extension, DA will extract an extension automatically and use it. \n + * If the designated file name includes extension, DA will use the extension without any check. \n\n + * <b>It is not guaranteed to play or execute the stored file if client designates wrong extension. </b><br> + * <b>If you are not confident of extension, DO NOT designate extension, but send just pure file name. </b><br><br> + * <b>Client MUST check \a saved_path of \a user_download_info_t. </b><br> + * <b>Because really decided file name can be different from the designated one. </b><br> + * For example, actual file name can have numbering postfix if another file has same name is exist on storing directory. \n + * (e.g. abc.mp3 to abc_1.mp3) \n\n + * This feature is ignored in case of OMA/Midlet download. \n + * @see da_start_download_with_extension + * @see user_download_info_t + */ +#define DA_FEATURE_FILE_NAME "file_name" +/** +*@} +*/ + +/** + * @ingroup Reference + * DA_DOWNLOAD_MANAGING_METHOD_MANUAL means that DA pass chunked packetes and response header data to the client in direct. + * This is only availalbe in case of A link download (HTTP) + * Please refer to sample code (da-test/md-sample.c) + */ +typedef enum { + DA_DOWNLOAD_MANAGING_METHOD_AUTO = 0, // DA handle all download progress including install a content. Support A link(HTTP) / OMA / MIDP download. + DA_DOWNLOAD_MANAGING_METHOD_MANUAL, // DA pass only chuncked packets, response header data, state and error code to the client. Support only A link (HTTP) download + DA_DOWNLOAD_MANAGING_METHOD_MAX +} da_download_managing_method; + +/** + * @warning depricated + */ +typedef enum { + DA_INSTALL_FAIL_REASON_OK = 0, // install is succeed + DA_INSTALL_FAIL_REASON_INSUFFICIENT_MEMORY, // There is no sufficient memory on target + DA_INSTALL_FAIL_REASON_USER_CANCELED, // user canceled installation + DA_INSTALL_FAIL_REASON_MAX +} da_install_fail_reason; + + +/** + * @ingroup Reference + * Download Agent notifies these states to client with \a da_notify_cb, when it is changed. \n + * Most of these value are informative, except for DA_STATE_WAITING_USER_CONFIRM. \n + * @remark Guarantee that one of following state is the final one. + * @li DA_STATE_FINISHED + * @li DA_STATE_CANCELED + * @li DA_STATE_FAILED + * @see user_notify_info_t + * @see da_notify_cb + * @par + @li For default download + \n DA_STATE_DOWNLOAD_STARTED, + DA_STATE_DOWNLOADING, + DA_STATE_DOWNLOAD_COMPLETE, + + @li For cancel, suspend, resume + \n DA_STATE_CANCELED, + DA_STATE_SUSPENDED, + DA_STATE_RESUMED, + + @li Last notification for all case + \n DA_STATE_FINISHED, + DA_STATE_FAILED, + */ +typedef enum { + DA_STATE_WAITING = 0, + /// Requested download to Web server for designated URL + DA_STATE_DOWNLOAD_STARTED, // 1 + /// Started to receiving HTTP body data + DA_STATE_DOWNLOADING, // 2 + /// Completed to download from Web server. Not yet registered to system. + DA_STATE_DOWNLOAD_COMPLETE, // 3 + /// Suspended download + DA_STATE_SUSPENDED, // 4 + /// Suspended all download. Emitted only if receiving DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI. + DA_STATE_SUSPENDED_ALL, // 5 + /// Resumed download which was suspended + DA_STATE_RESUMED, // 6 + /// Resumed all download. Emitted only if receiving DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI. + DA_STATE_RESUMED_ALL, // 7 + /// Finished all process to download. + DA_STATE_FINISHED, // 8 + /// Canceled download + DA_STATE_CANCELED, // 9 + /// Canceled all download. Emitted only if receiving DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI. + DA_STATE_CANCELED_ALL, // 10 + /// Failed to download + DA_STATE_FAILED // 11 +} da_state; + + +/** + * @ingroup Reference + * @addtogroup ErrorCodes Error codes + * @{ + */ + +/** + * @{ + */ +// 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_CLIENT -102 +#define DA_ERR_INVALID_DD -103 +#define DA_ERR_INVALID_URL -104 +#define DA_ERR_INVALID_HANDLE -105 +#define DA_ERR_INVALID_INSTALL_PATH -106 +#define DA_ERR_INVALID_MIME_TYPE -107 + +// Client passed correct parameter, but Download Agent rejects the request because of internal policy. +#define DA_ERR_MISMATCH_CLIENT_DD -150 +#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_WAITING_USER_CONFIRM -180 +#define DA_ERR_WAITING_INSTALL_RESULT -181 +#define DA_ERR_INVALID_STATE -190 +#define DA_ERR_ALREADY_MAX_DOWNLOAD -191 +#define DA_ERR_UNSUPPORTED_PROTOCAL -192 +#define DA_ERR_CLIENT_IS_ALREADY_REGISTERED -193 +/** + * @} + */ + +/** + * @{ + */ +// System error (-200 ~ -299) +#define DA_ERR_FAIL_TO_MEMALLOC -200 +#define DA_ERR_FAIL_TO_CREATE_THREAD -210 +#define DA_ERR_FAIL_TO_OBTAIN_MUTEX -220 +#define DA_ERR_FAIL_TO_ACCESS_FILE -230 +#define DA_ERR_DISK_FULL -240 +/** + * @} + */ + +/** + * @{ + */ +// Platform error (-300 ~ -399) +#define DA_ERR_FAIL_TO_GET_CONF_VALUE -300 +#define DA_ERR_FAIL_TO_ACCESS_STORAGE -310 +#define DA_ERR_DLOPEN_FAIL -330 +/** + * @} + */ + +/** + * @{ + */ +// Network error (-400 ~ -499) +#define DA_ERR_NETWORK_FAIL -400 +#define DA_ERR_UNREACHABLE_SERVER -410 +#define DA_ERR_HTTP_TIMEOUT -420 +#define DA_ERR_SSL_FAIL -430 +/** + * @} + */ + +/** + * @{ + */ +// HTTP error - not conforming with HTTP spec (-500 ~ -599) +#define DA_ERR_MISMATCH_CONTENT_TYPE -500 +#define DA_ERR_MISMATCH_CONTENT_SIZE -501 +#define DA_ERR_SERVER_RESPOND_BUT_SEND_NO_CONTENT -502 +/** + * @} + */ + + +/** + * @{ + */ +// DRM error - not conforming with DRM spec (-700 ~ -799) +#define DA_ERR_DRM_FAIL -700 +#define DA_ERR_DRM_FILE_FAIL -710 +/** + * @} + */ + +/** + * @{ + */ +// install error (-800 ~ -899) +#define DA_ERR_FAIL_TO_INSTALL_FILE -800 +/** +*@} +*/ + +/** +*@} +*/ +#endif + diff --git a/src/agent/include/download-agent-dl-info-util.h b/src/agent/include/download-agent-dl-info-util.h new file mode 100644 index 0000000..f17715d --- /dev/null +++ b/src/agent/include/download-agent-dl-info-util.h @@ -0,0 +1,294 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-dl-info-util.h + * @brief + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + +#ifndef _Download_Agent_Dl_Info_Util_H +#define _Download_Agent_Dl_Info_Util_H + +#include "download-agent-type.h" +#include "download-agent-http-queue.h" +#include "download-agent-utils-dl-req-id-history.h" + +#define DA_MAX_DOWNLOAD_ID DA_MAX_DOWNLOAD_REQ_AT_ONCE +#define DA_MAX_TYPE_COUNT 10 + +#define DOWNLOAD_NOTIFY_LIMIT (1024*32) //bytes +extern pthread_mutex_t mutex_download_state[]; + +typedef enum { + DOWNLOAD_STATE_IDLE = 0, + DOWNLOAD_STATE_NEW_DOWNLOAD = 20, /* stage */ + + DOWNLOAD_STATE_READY_TO_INSTAL = 55, /* stage */ + + DOWNLOAD_STATE_FINISH = 60, /* stage */ + + DOWNLOAD_STATE_PAUSED = 70, /* http */ + DOWNLOAD_STATE_CANCELED, /* http */ + +} download_state_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_PAUSED = 10, + HTTP_STATE_RESUMED = 11, + HTTP_STATE_ABORTED = 12, + +} http_state_t; + +typedef struct _client_input_basic_t { + char *req_url; + char **user_request_header; + int user_request_header_count; +} client_input_basic_t; + + +typedef struct _client_input_t { + void *user_data; + char *install_path; + char *file_name; + client_input_basic_t client_input_basic; +} client_input_t; + +typedef struct _download_thread_input { + int download_id; + client_input_t *client_input; +} download_thread_input; + +typedef struct _source_info_basic_t { + int dl_id; + char *url; + char **user_request_header; + int user_request_header_count; +} source_info_basic_t; + +typedef struct _source_info_t { + union _source_info_type { + source_info_basic_t *source_info_basic; + } source_info_type; +} source_info_t; + +#define GET_SOURCE_TYPE(SOURCE) ((SOURCE)->source_type) +#define GET_SOURCE_BASIC(SOURCE) ((SOURCE)->source_info_type.source_info_basic) +#define GET_SOURCE_BASIC_URL(SOURCE) (GET_SOURCE_BASIC(SOURCE)->url) + +typedef struct _req_dl_info { + http_info_t http_info; + + /* This is just pointer assignment from stage source info. */ + char *destination_url; + /* The location url is assigned here in case of redirection. + * At this time, the pointer should be freed. */ + char *location_url; + char **user_request_header; + int user_request_header_count; + + http_state_t http_state; + pthread_mutex_t mutex_http_state; + + da_result_t result; + /*************** will be depreciated ***********************/ + /* ToDo : previous http_info should be saved in case of pause */ + char *content_type_from_header; /* calloced in set hdr fiels on download info */ + int content_len_from_header; + char *etag_from_header; + + unsigned long int downloaded_data_size; + + int invloved_transaction_id; +} req_dl_info; + +#define GET_REQUEST_HTTP_RESULT(REQUEST) (REQUEST->result) +#define GET_REQUEST_HTTP_TRANS_ID(REQUEST) (REQUEST->invloved_transaction_id) +#define GET_REQUEST_HTTP_REQ_URL(REQUEST) (REQUEST->destination_url) +#define GET_REQUEST_HTTP_REQ_LOCATION(REQUEST) (REQUEST->location_url) +#define GET_REQUEST_HTTP_USER_REQUEST_HEADER(REQUEST) (REQUEST->user_request_header) +#define GET_REQUEST_HTTP_USER_REQUEST_HEADER_COUNT(REQUEST) (REQUEST->user_request_header_count) +#define GET_REQUEST_HTTP_HDR_ETAG(REQUEST) (REQUEST->etag_from_header) +#define GET_REQUEST_HTTP_HDR_CONT_TYPE(REQUEST) (REQUEST->content_type_from_header) +#define GET_REQUEST_HTTP_HDR_CONT_LEN(REQUEST) (REQUEST->content_len_from_header) +#define GET_REQUEST_HTTP_CONTENT_OFFSET(REQUEST)(REQUEST->downloaded_data_size) +#define GET_REQUEST_HTTP_MUTEX_HTTP_STATE(STAGE) (GET_STAGE_TRANSACTION_INFO(STAGE)->mutex_http_state) +#define GET_HTTP_STATE_ON_STAGE(STAGE) (GET_STAGE_TRANSACTION_INFO(STAGE)->http_state) +#define CHANGE_HTTP_STATE(STATE,STAGE) {\ + _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(STAGE)));\ + GET_HTTP_STATE_ON_STAGE(STAGE) = STATE;\ + DA_LOG_CRITICAL(Default, "Changed http_state to - [%d] ", GET_HTTP_STATE_ON_STAGE(STAGE));\ + _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(STAGE)));\ +} + +typedef struct _file_info { + void *file_handle; + char *pure_file_name; + char *extension; + char *file_name_tmp; /* malloced in make file info. */ + char *file_name_final; /* malloced in set_file_path_for_final_saving */ + char *content_type; /* malloced in make file info. */ + char *add_to_buffer; + unsigned int file_size; /* http header's Content-Length has higher priority than DD's <size> */ + unsigned int total_bytes_written_to_file; /* current written file size */ + unsigned int bytes_written_to_file; + unsigned int current_buffer_len; +} file_info; + +#define GET_CONTENT_STORE_PURE_FILE_NAME(FILE_CNTXT) (FILE_CNTXT)->pure_file_name +#define GET_CONTENT_STORE_EXTENSION(FILE_CNTXT) (FILE_CNTXT)->extension +#define GET_CONTENT_STORE_TMP_FILE_NAME(FILE_CNTXT) (FILE_CNTXT)->file_name_tmp +#define GET_CONTENT_STORE_ACTUAL_FILE_NAME(FILE_CNTXT) (FILE_CNTXT)->file_name_final +#define GET_CONTENT_STORE_FILE_HANDLE(FILE_CNTXT) (FILE_CNTXT)->file_handle +#define GET_CONTENT_STORE_FILE_SIZE(FILE_CNTXT) (FILE_CNTXT)->file_size +#define GET_CONTENT_STORE_CURRENT_FILE_SIZE(FILE_CNTXT) (FILE_CNTXT)->total_bytes_written_to_file +#define IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(FILE_CNTXT) (FILE_CNTXT)->bytes_written_to_file +#define GET_CONTENT_STORE_FILE_BUFFER(FILE_CNTXT) (FILE_CNTXT)->add_to_buffer +#define GET_CONTENT_STORE_FILE_BUFF_LEN(FILE_CNTXT) ((FILE_CNTXT)->current_buffer_len) +#define GET_CONTENT_STORE_CONTENT_TYPE(FILE_CNTXT) (FILE_CNTXT)->content_type + +typedef struct _stage_info { + int dl_id; + source_info_t dl_request; + req_dl_info dl_tansaction_context; + file_info dl_content_storage; + struct _stage_info *next_stage_info; +} stage_info; + +#define GET_STAGE_DL_ID(STAGE) ((STAGE)->dl_id) +#define GET_STAGE_SOURCE_INFO(STAGE) (&((STAGE)->dl_request)) +#define GET_STAGE_TRANSACTION_INFO(STAGE) (&((STAGE)->dl_tansaction_context)) +#define GET_STAGE_CONTENT_STORE_INFO(STAGE) (&((STAGE)->dl_content_storage)) +#define GET_STAGE_INSTALLATION_INFO(STAGE) (&((STAGE)->post_dl_context)) + +typedef struct _download_info_t { + da_bool_t is_using; + int download_id; + int dl_req_id; + pthread_t active_dl_thread_id; + download_state_t state; + stage_info *download_stage_data; + da_state cur_da_state; + queue_t queue; + // FIXME have client_input itself, not to have each of them + char *user_install_path; + char *user_file_name; + void *user_data; +} download_info_t; + +#define GET_DL_THREAD_ID(ID) (download_mgr.download_info[ID].active_dl_thread_id) +#define GET_DL_STATE_ON_ID(ID) (download_mgr.download_info[ID].state) +#define GET_DL_STATE_ON_STAGE(STAGE) (GET_DL_STATE_ON_ID(GET_STAGE_DL_ID(STAGE))) +#define GET_DL_CURRENT_STAGE(ID) (download_mgr.download_info[ID].download_stage_data) +#define GET_DL_REQ_ID(ID) (download_mgr.download_info[ID].dl_req_id) +#define GET_DL_DA_STATE(ID) (download_mgr.download_info[ID].cur_da_state) +#define GET_DL_QUEUE(ID) &(download_mgr.download_info[ID].queue) +#define GET_DL_USER_INSTALL_PATH(ID) (download_mgr.download_info[ID].user_install_path) +#define GET_DL_USER_FILE_NAME(ID) (download_mgr.download_info[ID].user_file_name) +#define GET_DL_USER_DATA(ID) (download_mgr.download_info[ID].user_data) +#define IS_THIS_DL_ID_USING(ID) (download_mgr.download_info[ID].is_using) + +#define CHANGE_DOWNLOAD_STATE(STATE,STAGE) {\ + _da_thread_mutex_lock (&mutex_download_state[GET_STAGE_DL_ID(STAGE)]);\ + GET_DL_STATE_ON_STAGE(STAGE) = STATE;\ + DA_LOG_CRITICAL(Default, "Changed download_state to - [%d] ", GET_DL_STATE_ON_STAGE(STAGE));\ + _da_thread_mutex_unlock (&mutex_download_state[GET_STAGE_DL_ID(STAGE)]);\ + } + +typedef enum { + STATE_WATCHER_TYPE_NONE = 0, + STATE_WATCHER_TYPE_CANCEL, + STATE_WATCHER_TYPE_SUSPEND, + STATE_WATCHER_TYPE_RESUME +} state_watcher_type_t; + +typedef struct _state_watcher_t { + state_watcher_type_t type; + unsigned short state_watching_bitmap; + da_bool_t is_progressing_to_all; + pthread_mutex_t mutex; +} state_watcher_t; + +typedef struct _default_http_hdr_info_t { + char *user_agent_string; +} default_http_hdr_info_t; + +#define GET_USER_AGENT (download_mgr.default_hdr_info->user_agent_string) + +typedef struct _download_mgr_t { + da_bool_t is_init; + download_info_t download_info[DA_MAX_DOWNLOAD_ID]; + default_http_hdr_info_t *default_hdr_info; + state_watcher_t state_watcher; + + /* FIXME: This is temporary solution to prevent crash on following case; + * 1) OMA download(that is, DA's libsoup is using) is on progressing on Browser + * 2) User push END hard key + * 3) da_deinit() is called. - on UI thread + * 4) cancel_download(all) is called. + * 5) plugin-libsoup.c calls soup_session_cancel_message(). + * 6) da_deinit() is finished and process is over. + * 7) soup's callback for soup_session_cancel_message() is trying to be called - on UI thread + * 8) Browser crashed because the callback address is no longer exist. + * + * Here is a temporary solution; + * If cancel is from da_deinit(), plugin-libsoup.c will not call soup_session_cancel_message(). + * So, append following variable to recognize this. + **/ + //da_bool_t is_progressing_deinit; + + dl_req_id_history_t dl_req_id_history; +} download_mgr_t; + +extern download_mgr_t download_mgr; + +da_result_t init_download_mgr(); +da_result_t deinit_download_mgr(void); + +void init_download_info(int download_id); +void destroy_download_info(int download_id); + +void *Add_new_download_stage(int download_id); +void remove_download_stage(int download_id, stage_info *in_stage); + +void empty_stage_info(stage_info *in_stage); + +void clean_up_client_input_info(client_input_t *client_input); + +da_result_t get_available_download_id(da_handle_t *available_id); +da_result_t get_download_id_for_dl_req_id(da_handle_t dl_req_id , da_handle_t* download_id); +da_bool_t is_valid_dl_ID(int download_id); + +void state_watcher_flag_ON_for_download_id(state_watcher_t *state_watcher, + int download_id); +void state_watcher_flag_OFF_for_download_id(state_watcher_t *state_watcher, + int download_id); +da_bool_t state_watcher_need_redirect_Q(int download_id); +void state_watcher_redirect_state(int download_id, da_state state, int err); + +#endif /* _Download_Agent_Dl_Info_Util_H */ diff --git a/src/agent/include/download-agent-dl-mgr.h b/src/agent/include/download-agent-dl-mgr.h new file mode 100644 index 0000000..8ef36ef --- /dev/null +++ b/src/agent/include/download-agent-dl-mgr.h @@ -0,0 +1,47 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-dl-mgr.h + * @brief + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + +#ifndef _Download_Agent_Dl_Mgr_H +#define _Download_Agent_Dl_Mgr_H + +#include "download-agent-type.h" +#include "download-agent-dl-info-util.h" + +da_result_t cancel_download (int dl_req_id); +da_result_t cancel_download_all (int dl_req_id); + +da_result_t suspend_download (int dl_req_id); +da_result_t suspend_download_all (int dl_req_id); + +da_result_t resume_download (int dl_req_id); +da_result_t resume_download_all (int dl_req_id); + +da_result_t requesting_download(stage_info *stage); +da_result_t handle_after_download(stage_info *stage); +da_result_t process_install(stage_info *stage); +da_result_t send_user_noti_and_finish_download_flow(int download_id); + +da_result_t process_play_ready_initiator(stage_info *stage); + +#endif diff --git a/src/agent/include/download-agent-encoding.h b/src/agent/include/download-agent-encoding.h new file mode 100644 index 0000000..9453edd --- /dev/null +++ b/src/agent/include/download-agent-encoding.h @@ -0,0 +1,35 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-encoding.h + * @brief Utilities to manipulate encoding and charset + * @author Keunsoon Lee (keunsoon.lee@samsung.com) + */ + +#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_result_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/src/agent/include/download-agent-file.h b/src/agent/include/download-agent-file.h new file mode 100644 index 0000000..c15c046 --- /dev/null +++ b/src/agent/include/download-agent-file.h @@ -0,0 +1,65 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-file.h + * @brief + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + +#ifndef _Download_Agent_File_H +#define _Download_Agent_File_H + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "download-agent-type.h" +#include "download-agent-dl-mgr.h" + +#ifdef _TARGET +#define DA_DEFAULT_TMP_FILE_DIR_PATH "/opt/media/.tmp_download" +#else +// FIXME Later : temporary code +#define DA_DEFAULT_TMP_FILE_DIR_PATH "/tmp/.tmp_download" +#endif + +da_bool_t is_file_exist(const char *file_path); +da_bool_t is_dir_exist(char *dir_path); + +void get_file_size(char *file_path, int *out_file_size); + +da_result_t clean_files_from_dir(char* dir_path); +da_result_t create_temp_saved_dir(void); + +da_result_t file_write_ongoing(stage_info *stage, char *body, int body_len); +da_result_t file_write_complete(stage_info *stage); +da_result_t start_file_writing(stage_info *stage); +da_result_t start_file_writing_append(stage_info *stage); + +da_result_t get_mime_type(stage_info *stage, char **out_mime_type); +da_result_t discard_download(stage_info *stage) ; +void clean_paused_file(stage_info *stage); +da_result_t replace_content_file_in_stage(stage_info *stage, const char *dest_dd_file_path); +da_result_t decide_final_file_path(stage_info *stage); +char *get_full_path_avoided_duplication(char *in_dir, char *in_candidate_file_name, char * in_extension); + +da_result_t copy_file(const char *src, const char *dest); +da_result_t create_dir(const char *install_dir); + +#endif diff --git a/src/agent/include/download-agent-http-mgr.h b/src/agent/include/download-agent-http-mgr.h new file mode 100644 index 0000000..de661f2 --- /dev/null +++ b/src/agent/include/download-agent-http-mgr.h @@ -0,0 +1,56 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-http-mgr.h + * @brief Including functions regarding http mgr + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + + +#ifndef _Download_Agent_Http_Mgr_H +#define _Download_Agent_Http_Mgr_H + +#include <string.h> + +#include "download-agent-type.h" +#include "download-agent-dl-mgr.h" +#include "download-agent-http-queue.h" + +#define DA_MAX_SESSION_INFO DA_MAX_DOWNLOAD_ID +#define DA_MAX_TRANSACTION_INFO 10 +#define DA_MAX_TRANSACTION_MUTEX DA_MAX_SESSION_INFO*DA_MAX_TRANSACTION_INFO + +typedef struct _http_mgr_t +{ + da_bool_t is_init; + da_bool_t is_http_init; +}http_mgr_t; + +extern http_mgr_t http_mgr; + +da_result_t init_http_mgr(void); +void deinit_http_mgr(void); +da_result_t make_req_dl_info_http(stage_info *stage, req_dl_info *out_info); +da_result_t request_http_download(stage_info *stage); +da_result_t request_to_cancel_http_download(stage_info *stage); +da_result_t request_to_abort_http_download(stage_info *stage); +da_result_t request_to_suspend_http_download(stage_info *stage); +da_result_t request_to_resume_http_download(stage_info *stage); + +#endif diff --git a/src/agent/include/download-agent-http-misc.h b/src/agent/include/download-agent-http-misc.h new file mode 100644 index 0000000..b60cb23 --- /dev/null +++ b/src/agent/include/download-agent-http-misc.h @@ -0,0 +1,56 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-http-misc.h + * @brief Including miscellaneous functions for http + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + + +#ifndef _Download_Agent_Http_Misc_H +#define _Download_Agent_Http_Misc_H + +#include <string.h> + +#include "download-agent-type.h" + +#define SCHEME_HTTP "http://" +#define SCHEME_HTTPS "https://" +#define SCHEME_CID "cid:" + +#define METHOD_GET "GET" +#define METHOD_POST "POST" +#define METHOD_HEAD "HEAD" + +#define HTTP_TAG_UAGENT "User-Agent: " +#define HTTP_TAG_HOST "Host: " +#define HTTP_TAG_UAPROF "X-Wap-Profile: " +#define HTTP_TAG_CONTENT_LENGTH "Content-Length: " +#define HTTP_TAG_CONTENT_TYPE "Content-Type: " +#define HTTP_TAG_IF_MATCH "If-Match: " +#define HTTP_TAG_RANGE "Range: " +#define HTTP_TAG_IF_RANGE "If-Range: " + +#define END_OF_FIELD "\r\n" + +char* get_user_agent(); + +da_bool_t is_supporting_protocol(const char* protocol); + +#endif diff --git a/src/agent/include/download-agent-http-msg-handler.h b/src/agent/include/download-agent-http-msg-handler.h new file mode 100644 index 0000000..bcb9444 --- /dev/null +++ b/src/agent/include/download-agent-http-msg-handler.h @@ -0,0 +1,128 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-http-msg-handler.h + * @brief Utilities to manipulate HTTP messages + * @author Keunsoon Lee (keunsoon.lee@samsung.com) + */ + +#ifndef _Download_Agent_Http_Msg_Handler_H +#define _Download_Agent_Http_Msg_Handler_H + +#include "download-agent-type.h" + +#define HTTP_FIELD_UAGENT "User-Agent" +#define HTTP_FIELD_HOST "Host" +#define HTTP_FIELD_UAPROF "X-Wap-Profile" +#define HTTP_FIELD_CONTENT_LENGTH "Content-Length" +#define HTTP_FIELD_CONTENT_TYPE "Content-Type" +#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" + +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; +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 http_header_t* http_msg_iter_t; + + +typedef struct{ + http_msg_request_t* http_msg_request; + http_msg_response_t* http_msg_response; +}http_info_t; + + +da_result_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_result_t http_msg_request_set_method(http_msg_request_t* http_msg_request, const char* method); +da_result_t http_msg_request_get_method(http_msg_request_t* http_msg_request, const char** method); + +da_result_t http_msg_request_set_url(http_msg_request_t* http_msg_request, const char* url); +da_result_t http_msg_request_get_url(http_msg_request_t* http_msg_request, const char** url); + +da_result_t http_msg_request_set_body(http_msg_request_t* http_msg_request, const char* body); +da_result_t http_msg_request_get_body(http_msg_request_t* http_msg_request, const char** body); + +da_result_t http_msg_request_add_field(http_msg_request_t* http_msg_request, const char* field, const char* value); + + +da_result_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_result_t http_msg_response_set_status_code(http_msg_response_t* http_msg_response, int status_code); +da_result_t http_msg_response_get_status_code(http_msg_response_t* http_msg_response, int* status_code); + +da_result_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, int* 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); +// should be refactored later +da_result_t http_msg_response_get_boundary(http_msg_response_t* http_msg_response, char** out_val); + + +da_result_t http_msg_request_get_iter(http_msg_request_t* http_msg_request, http_msg_iter_t* http_msg_iter); +da_result_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); + +char *get_http_response_header_raw(http_msg_response_t *http_msg_response); + +da_bool_t extract_attribute_from_header(char* szHeadStr, const char* szFindStr, char** ppRtnValue); +#endif // _Download_Agent_Http_Msg_Handler_H diff --git a/src/agent/include/download-agent-http-queue.h b/src/agent/include/download-agent-http-queue.h new file mode 100644 index 0000000..cf3a0e5 --- /dev/null +++ b/src/agent/include/download-agent-http-queue.h @@ -0,0 +1,134 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-http-queue.h + * @brief Including functions regarding http queue + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + + +#ifndef _Download_Agent_Http_Queue_H +#define _Download_Agent_Http_Queue_H + + +#include "download-agent-type.h" +#include "download-agent-http-msg-handler.h" + +#include <pthread.h> +#include <stdlib.h> + +#define MAX_QUEUE_SIZE 1024*64 + +typedef enum +{ + Q_EVENT_TYPE_DATA_HTTP, + Q_EVENT_TYPE_DATA_DRM, + Q_EVENT_TYPE_CONTROL, +}q_event_type; + +typedef enum +{ + Q_EVENT_TYPE_CONTROL_CANCEL, + Q_EVENT_TYPE_CONTROL_SUSPEND, + Q_EVENT_TYPE_CONTROL_RESUME, + Q_EVENT_TYPE_CONTROL_NET_DISCONNECTED, + Q_EVENT_TYPE_CONTROL_ABORT, +// [090205][jungki]not used yet. +// Q_EVENT_TYPE_CONTROL_USER_CONFIRM_RESULT, +// Q_EVENT_TYPE_CONTROL_INSTALL_RESULT, +}q_event_type_control; + +typedef enum +{ + Q_EVENT_TYPE_DATA_PACKET, + Q_EVENT_TYPE_DATA_FINAL, + Q_EVENT_TYPE_DATA_ABORT, +}q_event_type_data; + +typedef struct _q_event_data_http_t +{ + q_event_type_data data_type; + + int status_code; + + http_msg_response_t* http_response_msg; + + int body_len; + char *body_data; + + da_result_t error_type; +}q_event_data_http_t; + +typedef struct _q_event_control_t +{ + q_event_type_control control_type; +}q_event_control_t; + +typedef struct _q_event_t q_event_t; +struct _q_event_t +{ + int size; + q_event_type event_type; + union _type + { + q_event_data_http_t q_event_data_http; + q_event_control_t q_event_control; + } type; + + q_event_t *next; +}; + +typedef struct _queue_t +{ + da_bool_t having_data; + + q_event_t *control_head; + q_event_t *data_head; + + pthread_mutex_t mutex_queue; + pthread_cond_t cond_queue; + + int queue_size; +}queue_t; + +void Q_init_queue(queue_t *queue); +void Q_destroy_queue(queue_t *queue); + +void Q_init_q_event(q_event_t *q_event); +void Q_destroy_q_event(q_event_t **q_event); + +da_result_t Q_make_control_event(q_event_type_control control_type, q_event_t **out_event); + +da_result_t Q_make_http_data_event(q_event_type_data data_type, q_event_t **out_event); +da_result_t Q_set_status_code_on_http_data_event(q_event_t *q_event, int status_code); +da_result_t Q_set_http_body_on_http_data_event(q_event_t *q_event, int body_len, char *body_data); +da_result_t Q_set_error_type_on_http_data_event(q_event_t *q_event, int error_type); + + +da_bool_t Q_push_event(const queue_t *in_queue, const q_event_t *in_event); +da_bool_t Q_push_event_without_lock(const queue_t *in_queue, const q_event_t *in_event); +void Q_pop_event(const queue_t *in_queue, q_event_t **out_event); + +#define GET_IS_Q_HAVING_DATA(QUEUE) (QUEUE->having_data) + +void Q_goto_sleep(const queue_t *in_queue); +void Q_wake_up(const queue_t *in_queue); + + +#endif diff --git a/src/agent/include/download-agent-installation.h b/src/agent/include/download-agent-installation.h new file mode 100644 index 0000000..5cf8dbf --- /dev/null +++ b/src/agent/include/download-agent-installation.h @@ -0,0 +1,36 @@ +/*
+ * Download Agent
+ *
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @file download-agent-installation.h
+ * @brief Functions Declaration for Content Installation
+ * @author Keunsoon Lee(keunsoon.lee@samsung.com)
+ * @author Jungki Kwak(jungki.kwak@samsung.com)
+ ***/
+
+
+#ifndef _Download_Agent_Installation_H
+#define _Download_Agent_Installation_H
+
+#include "download-agent-utils.h"
+#include "download-agent-debug.h"
+#include "download-agent-dl-mgr.h"
+
+da_result_t install_content(stage_info *stage);
+
+#endif
diff --git a/src/agent/include/download-agent-interface.h b/src/agent/include/download-agent-interface.h new file mode 100644 index 0000000..8ceee58 --- /dev/null +++ b/src/agent/include/download-agent-interface.h @@ -0,0 +1,611 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-interface.h + * @brief Interface for Download Agent. + * @author Keunsoon Lee (keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + * + */ + +#ifndef _Download_Agent_Interface_H +#define _Download_Agent_Interface_H + +#ifdef __cplusplus + extern "C" + { +#endif + +#include "download-agent-defs.h" +#include <stdarg.h> + +/** + * @ingroup Internet_FW + * @addtogroup DownloadAgent Download Agent + * @{ + * @brief Download Agent is a UI-less shared library to download files from Internet. + * @par Details + * Download Agent is a module to download stuffs through HTTP. \n + * Download Agent can download several files simultaneously using multi-thread. \n\n + * If any application wants to download something from Internet, then use this like following. \n + * 1) Be a client for Download Agent. \n + * 2) Pass a URL which you want to download to Download Agent. \n + * 3) Get notifications and result from Download Agent. \n + */ + +/** + * @ingroup DownloadAgent + * @addtogroup QuickGuide Quick Guide + * @{ + * @par Step 1. To implement required callbacks to receive notifications + * \c da_notify_cb and \c da_update_download_info_cb are required almost all cases. \n + * @remark Do not free anything on the callbacks. DA will take care of them. + * @remark If you want to use \a user_param, set it with \a DA_FEATURE_USER_DATA + * @remark You can free user_param when receiving one of following \a da_state. + * @li DA_STATE_FINISHED + * @li DA_STATE_FAILED + * @li DA_STATE_CANCELED + * @par + * @code + * // main.c + * #include <download-agent-interface.h> + * + * void notify_cb(user_notify_info_t *notify_info, void* user_param) + * { + * if (!notify_info) + * return; + * printf("id [%d], state [%d]", notify_info->da_dl_req_id, notify_info->state); + * if (notify_info->state == DA_STATE_FAILED) + * printf("error code [%d]", notify_info->err); + * } + * + * void update_download_info_cb(user_download_info_t *download_info, void* user_param) + * { + * if (!download_info) + * return; + * printf("id [%d], file size [%d/%d]", download_info->da_dl_req_id, + * download_info->file_size); + * } + * + * void update_downloading_info_cb(user_downloading_info_t *downloading_info, void* user_param) + * { + * if (!downloading_info) + * return; + * printf("id [%d], received size [%d]", downloading_info->da_dl_req_id, + * downloading_info->total_received_size); + * } + * @endcode + * @endcode + * + * @par Step 2. To register the callbacks + * set NULL for callbacks you do not want to know. + * @code + * // continued after Step 1 + * + * void download_initialize() + * { + * int da_ret; + * da_client_cb_t da_cb = { notify_cb, NULL, update_download_info_cb, update_downloading_info_cb, NULL }; + * + * da_ret = da_init (&da_cb, 0); + * if(da_ret == DA_RESULT_OK) + * printf("successed\n"); + * else + * printf("failed with error code %d\n", da_ret); + * } + * @endcode + * + * @par Step 3. To request a download + * You can meet the da_req_id on Step 1 callbacks again. \n + * Downloaded file is automatically registered to system. (e.g. File DB) \n + * If there is another file has same name on registering directory, new one's name would have numbering postfix. \n + * (e.g. abc.mp3 to abc_1.mp3) + * @see da_start_download_with_extension + * @code + * // continued after Step 2 + * void start_download() + * { + * int da_ret; + * da_handle_t da_req_id; + * char *url = "http://www.test.com/sample.mp3"; + * da_ret = da_start_download(url, &da_req_id); + * if(da_ret == DA_RESULT_OK) + * printf("successed\n"); + * else + * printf("failed with error code %d\n", da_ret); + * } + * @endcode + * + * @par Step 4. To do whatever client wants with information obtained from callbacks + * + * @par Step 5. To de-initialize when client does not use Download Agent anymore + * @code + * // continued after Step 3 + * void download_deinit() + * { + * int da_ret; + * da_ret = da_deinit(); + * if(da_ret == DA_RESULT_OK) + * printf("successed\n"); + * else + * printf("failed with error code %d\n", da_ret); + * } + * @endcode + * @} + */ + + /** + * @ingroup DownloadAgent + * @addtogroup Reference + * @{ + */ + +/** + * @ingroup Reference + * @addtogroup NotificationCallbacks Notification callbacks for client + * @brief Download Agent notifies many information with these callbacks to client. + * @{ + */ +/** + * @struct user_notify_info_t + * @brief Download Agent will send its state through this structure. + * @see da_notify_cb + * @par + * This is used only by callback /a user_notify_info_t. \n + */ +typedef struct { + /// download request id for this notification + da_handle_t da_dl_req_id; + /// Download Agent's current state corresponding to the da_dl_req_id + da_state state; + /// convey error code if necessary, or it is zero. + int err; +} user_notify_info_t; + +/** + * @struct user_downloading_info_t + * @brief Download Agent will send current downloading file's information through this structure. + * @see da_update_downloading_info_cb + * @par + * This is used only by callback /a da_update_downloading_info_cb. \n + */ +typedef struct { + /// download request id for this updated download information + da_handle_t da_dl_req_id; + /// received size of chunked data. + unsigned long int total_received_size; + /// This has only file name for now. + char *saved_path; +} user_downloading_info_t; + +/** + * @struct user_download_info_t + * @brief Download Agent will send current download's information through this structure. + * @see da_update_download_info_cb + * @par + * This is used only by callback /a da_update_download_info_cb. \n + */ +typedef struct { + /// download request id for this updated download information + da_handle_t da_dl_req_id; + /// file's mime type from http header. + char *file_type; + /// file size from http header. + unsigned long int file_size; + /// This is same with 'saved_path' for now. + char *tmp_saved_path; + /// This is raw data of response header + char *http_response_header; + /// This is raw data of chunked data + char *http_chunked_data; +} user_download_info_t; + +/** + * @typedef da_notify_cb + * @brief Download Agent will call this function to notify its state. + * + * This is user callback function registered on \a da_init. \n + * + * @remarks For the most of time, this state is just informative, so, user doesn't need to do any action back to Download Agent. + * @remarks But, Download Agent will wait for user's specific action after notifying some states. + * + * @warning Download will be holding until getting user confirmation result through the function. + * + * @param[in] state state from Download Agent + * @param[in] user_param user parameter which is set with \a DA_FEATURE_USER_DATA + * + * @see da_init + * @see da_client_cb_t + */ +typedef void (*da_notify_cb) (user_notify_info_t *notify_info, void* user_param); + +/** + * @brief Download Agent will call this function to update received size of download-requested file. + * + * This is user callback function registered on \a da_init. \n + * This is informative, so, user doesn't need to do any action back to Download Agent.\n + * + * @param[in] downloading_info updated downloading information + * @param[in] user_param user parameter which is set with \a DA_FEATURE_USER_DATA + * + * @see da_init + * @see da_client_cb_t + */ +typedef void (*da_update_downloading_info_cb) (user_downloading_info_t *downloading_info, void* user_param); + +/** + * @brief Download Agent will call this function to update mime type, temp file name, total file sizeand installed path. + * + * This is user callback function registered on \a da_init. \n + * This is informative, so, user doesn't need to do any action back to Download Agent.\n + * + * @param[in] download_info updated download information + * @param[in] user_param user parameter which is set with \a DA_FEATURE_USER_DATA + * + * @see da_init + * @see da_client_cb_t + */ +typedef void (*da_update_download_info_cb) (user_download_info_t *download_info, void* user_param); + + /** + * @struct da_client_cb_t + * @brief This structure convey User's callback functions for \a da_init + * @see da_init + */ +typedef struct { + /// callback to convey \a da_state and error code + da_notify_cb user_noti_cb; + /// callback to convey download information + da_update_download_info_cb update_dl_info_cb; + /// callback to convey downloading information while downloading including received file size + da_update_downloading_info_cb update_progress_info_cb; +} da_client_cb_t; +/** + * @} + */ + +/** + * @fn int da_init (da_client_cb_t *da_client_callback,da_download_managing_method download_method) + * @ingroup Reference + * @brief This function initiates Download Agent and registers user callback functions. + * @warning This should be called at once when client application is initialized before using other Download Agent APIs + * @warning This function is paired with da_deinit function. + * + * @pre None. + * @post None. + * + * @param[in] da_client_callback User callback function structure. The type is struct data pointer. + * @param[in] download_method Application can choose to manage download manually or automatically.The Enum data da_download_managing_method is defined at download-agent-defs.h. + * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail. DA_ERR_XXX is defined at download-agent-def.h. + * @remarks User MUST call this function first rather than any other DA APIs. \n + * Please do not call UI code at callback function in direct. \n + * It is better that it returns as soon as copying the data of callback functon. \n + * @see da_deinit + * @par Example + * @code + * #include <download-agent-interface.h> + * + * void da_notify_cb(user_notify_info_t *notify_info, void *user_param); + * void da_update_download_info_cb(user_download_info_t *download_info,void* user_param); + * void da_update_downloading_info_cb(user_downloading_info_t *downloading_info,void* user_param); + * + * + * int download_initialize() + * { + * int da_ret; + * da_client_cb_t da_cb = {0}; + * + * da_cb.user_noti_cb = ¬ify_cb; + * da_cb.update_dl_info_cb = &update_download_info_cb; + * da_cb.update_progress_info_cb = &update_downloading_info_cb; + * + * da_ret = da_init (&da_cb, 0); + * if (da_ret == DA_RESULT_OK) { + * // printf("successed\n"); + * return true; + * } else { + * // printf("failed with error code %d\n", da_ret); + * return fail; + * } + * } + * @endcode + */ +int da_init ( + da_client_cb_t *da_client_callback, + da_download_managing_method download_method +); + + + /** + * @fn int da_deinit () + * @ingroup Reference + * @brief This function deinitiates Download Agent. + * + * This function destroys all infomation for client manager. + * When Download Agent is not used any more, please call this function. + * Usually when client application is destructed, this is needed. + * + * @remarks This is paired with da_init. \n + * The client Id should be the one from /a da_init(). \n + * Otherwise, it cannot excute to deinitialize. \n + * + * @pre da_init() must be called in advance. + * @post None. + * + * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail. DA_ERR_XXX is defined at download-agent-def.h. + * @see da_init + * @par Example + * @code + * #include <download-agent-interface.h> + * + * + * int download_deinitialize() + * { + * int da_ret; + * da_ret = da_deinit(); + * if(da_ret == DA_RESULT_OK) { + * // printf("successed\n"); + * return true; + * } else { + * // printf("failed with error code %d\n", da_ret); + * return fail; + * } + * } + @endcode + */ +int da_deinit (); + + + /** + * @fn int da_start_download(const char *url, da_handle_t *da_dl_req_id) + * @ingroup Reference + * @brief This function starts to download a content on passed URL. + * + * Useful information and result are conveyed through following callbacks. + * @li da_notify_cb + * @li da_update_download_info_cb + * + * @pre da_init() must be called in advance. + * @post None. + * @remarks + * Downloaded file is automatically registered to system. (e.g. File DB) \n + * If there is another file has same name on registering directory, new one's name would have numbering postfix. \n + * (e.g. abc.mp3 to abc_1.mp3) + * + * @param[in] url url to start download + * @param[out] da_dl_req_id assigned download request id for this URL + * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail. DA_ERR_XXX is defined at download-agent-def.h. + * + * @see None. + * + * @par Example + * @code + * #include <download-agent-interface.h> + * + * int da_ret; + * int da_dl_req_id; + * char* url = "http://www.test.com/sample.mp3"; + * + * da_ret = da_start_download(url,&da_dl_req_id); + * if (da_ret == DA_RESULT_OK) + * printf("download requesting is successed\n"); + * else + * printf("download requesting is failed with error code %d\n", da_ret); + * @endcode + */ +int da_start_download( + const char *url, + da_handle_t *da_dl_req_id +); + +/** +* @fn int da_start_download_with_extension(const char *url, da_handle_t *da_dl_req_id, ...) +* @ingroup Reference +* @brief This function starts to download a content on passed URL with passed extension. +* +* Useful information and result are conveyed through following callbacks. +* @li da_notify_cb +* @li da_update_download_info_cb +* +* @pre da_init() must be called in advance. +* @post None. +* @remarks This API operation is exactly same with da_start_download(), except for input properties. \n +* Input properties' count is unlimited, but they MUST be a pair(name and value) and terminated by NULL. \n +* Refer to following for property name and value type. \n +* +* @li DA_FEATURE_REQUEST_HEADER : char** int * \n +* @li DA_FEATURE_USER_DATA : void* \n +* @li DA_FEATURE_INSTALL_PATH : char* \n +* @li DA_FEATURE_FILE_NAME : char* \n +* +* @see ExtensionFeatures +* +* @param[in] url url to start download +* @param[out] da_dl_req_id assigned download request id for this URL +* @param[in] first_property_name first property name to supply +* @param[in] first_property_value first property value to supply. This value's type can be int, char* or void*, which is up to first_property_name. +* @param[in] ... +* @return DA_RESULT_OK for success, or DA_ERR_XXX for fail. DA_ERR_XXX is defined at download-agent-def.h. +* +* +* @par Example +* @code + #include <download-agent-interface.h> + + int da_ret; + int da_dl_req_id; + const char *url = "https://www.test.com/sample.mp3"; + const char *install_path = "/myFiles/music"; + const char *my_data = strdup("data"); // should free after getting DA_STATE_FINISHED or DA_STATE_FAILED or DA_STATE_CANCELED + + da_ret = da_start_download_with_extension(url, &da_dl_req_id, DA_FEATURE_INSTALL_PATH, install_path + , DA_FEATURE_USER_DATA, (void*)my_data, NULL); + if (da_ret == DA_RESULT_OK) + printf("download requesting is successed\n"); + else + printf("download requesting is failed with error code %d\n", da_ret); + @endcode +*/ +int da_start_download_with_extension( + const char *url, + da_handle_t *da_dl_req_id, + ... +); + + +/** + * @fn int da_cancel_download(da_handle_t da_dl_req_id) + * @ingroup Reference + * @brief This function cancels a download for passed da_dl_req_id. + * + * Client can use this function if user wants to cancel already requested download. + * + * @remarks Should check return value. \n + * If return value is not DA_RESULT_OK, then previous requested download can be keep downloading. + * @remarks After calling this function, all information for the da_dl_req_id will be deleted. So, client cannot request anything for the da_dl_req_id. + * + * @pre There should be exist ongoing or suspended download for da_dl_req_id. + * @post None. + * + * @param[in] da_dl_req_id download request id + * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail + * + * @see None. + * + * @par Example + * @code + #include <download-agent-interface.h> + + int da_ret; + int da_dl_req_id; + + da_ret = da_cancel_download(da_dl_req_id); + if(da_ret == DA_RESULT_OK) { + // printf("download with [%d] is successfully canceled.\n", da_dl_req_id); + } + else { + // in this case, downloading with da_dl_req_id is keep ongoing. + printf("failed to cancel with error code %d\n", da_ret); + } + @endcode + */ +int da_cancel_download( + da_handle_t da_dl_req_id +); + + +/** + * @fn int da_suspend_download(da_handle_t da_dl_req_id) + * @ingroup Reference + * @brief This function suspends downloading for passed da_dl_req_id. + * + * Client can use this function if user wants to suspend already requested download. + * + * @remarks Should check return value. \n + * If return value is not DA_RESULT_OK, then previous requested download can be keep downloading. + * @remarks After calling this function, all information for the da_dl_req_id will be remained. So, client can request resume for the da_dl_req_id. + * @remarks Client should cancel or resume for this da_dl_req_id, or all information for the da_dl_req_id will be leaved forever. + * + * @pre There should be exist ongoing download for da_dl_req_id. + * @post None. + * + * @param[in] da_dl_req_id download request id + * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail + * + * @see da_resume_download() + * @see da_cancel_download() + * + * @par Example + * @code + #include <download-agent-interface.h> + + int da_ret; + int da_dl_req_id; + + da_ret = da_suspend_download(da_dl_req_id); + if(da_ret == DA_RESULT_OK) { + // printf("download with [%d] is successfully suspended.\n", da_dl_req_id); + } + else { + // in this case, downloading with da_dl_req_id is keep ongoing. + printf("failed to suspend with error code %d\n", da_ret); + } + @endcode + */ +int da_suspend_download( + da_handle_t da_dl_req_id +); + + + +/** + * @fn int da_resume_download(da_handle_t da_dl_req_id) + * @ingroup Reference + * @brief This function resumes downloading for passed da_dl_req_id. + * + * Client can use this function if user wants to resume suspended download. + * + * @remarks Should check return value. \n + * If return value is not DA_RESULT_OK, then requested download can be not to resume. + * + * @pre There should be exist suspended download for da_dl_req_id. + * @post None. + * + * @param[in] da_dl_req_id download request id + * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail + * + * @see da_suspend_download() + * + * @par Example + * @code + #include <download-agent-interface.h> + + int da_ret; + int da_dl_req_id; + + da_ret = da_resume_download(da_dl_req_id); + if(da_ret == DA_RESULT_OK) { + // printf("download with [%d] is successfully resumed.\n", da_dl_req_id); + } + else { + // in this case, downloading with da_dl_req_id is keep suspended. + printf("failed to resume with error code %d\n", da_ret); + } + @endcode + */ +int da_resume_download( + da_handle_t da_dl_req_id +); + + +/** +* @} +*/ + +/** +*@} +*/ + +#ifdef __cplusplus + } +#endif + +#endif //_Download_Agent_Interface_H + + diff --git a/src/agent/include/download-agent-mime-util.h b/src/agent/include/download-agent-mime-util.h new file mode 100644 index 0000000..4eb5382 --- /dev/null +++ b/src/agent/include/download-agent-mime-util.h @@ -0,0 +1,43 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-mime-util.h + * @brief + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + * @author Jungki Kwak(jungki.kwak@samsung.com) + ***/ + +#ifndef _Download_Agent_Mime_Table_H +#define _Download_Agent_Mime_Table_H + +#include "download-agent-type.h" + +#define NO_EXTENSION_NAME_STR "dat" + +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_result_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); +#endif diff --git a/src/agent/include/download-agent-plugin-conf.h b/src/agent/include/download-agent-plugin-conf.h new file mode 100644 index 0000000..8baad4c --- /dev/null +++ b/src/agent/include/download-agent-plugin-conf.h @@ -0,0 +1,36 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-plugin-conf.h + * @brief Including some functions to get configuration data from platform + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + +#ifndef _Download_Agent_Plugin_Conf_H +#define _Download_Agent_Plugin_Conf_H + +#include "download-agent-type.h" +#include "download-agent-interface.h" +#include "download-agent-utils.h" + +da_result_t get_user_agent_string(char **uagent_str); +da_result_t get_storage_type(da_storage_type_t *type); +char *get_proxy_address(void); + +#endif diff --git a/src/agent/include/download-agent-plugin-drm.h b/src/agent/include/download-agent-plugin-drm.h new file mode 100644 index 0000000..ff5df1b --- /dev/null +++ b/src/agent/include/download-agent-plugin-drm.h @@ -0,0 +1,39 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-plugin-drm.h + * @brief Including plugin functions for emerald DRM from SISO + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + + +#ifndef _Download_Agent_Plugin_Drm_H +#define _Download_Agent_Plugin_Drm_H + +#include "download-agent-type.h" + +da_bool_t EDRM_check_dcf_file(const char *file_path); +da_bool_t EDRM_has_vaild_ro(const char *file_path); +da_bool_t EDRM_open_convert (const char *file_path, void **fd); +da_bool_t EDRM_write_convert (void *fd, unsigned char *buffer, int buffer_size); +da_bool_t EDRM_close_convert (void **fd); +da_result_t EDRM_wm_get_license (char *rights_url, char **out_content_url); + + +#endif diff --git a/src/agent/include/download-agent-plugin-http-interface.h b/src/agent/include/download-agent-plugin-http-interface.h new file mode 100644 index 0000000..0cd733b --- /dev/null +++ b/src/agent/include/download-agent-plugin-http-interface.h @@ -0,0 +1,60 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-plugin-http-interface.h + * @brief Including functions regarding http plugin interface + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + + +#ifndef _Download_Agent_Plugin_Http_Interface_H +#define _Download_Agent_Plugin_Http_Interface_H + +#include "download-agent-type.h" +#include "download-agent-http-msg-handler.h" + +typedef enum { + PI_HTTP_METHOD_GET = 1, + PI_HTTP_METHOD_POST = 2, + PI_HTTP_METHOD_HEAD = 3 +} pi_http_method_t; + + +typedef struct _input_for_tranx_t { + pi_http_method_t http_method; + + char *proxy_addr; + queue_t *queue; + + http_msg_request_t* http_msg_request; +} input_for_tranx_t; + + + +da_result_t PI_http_init(void); +void PI_http_deinit(void); + +da_result_t PI_http_start_transaction(const input_for_tranx_t *input_for_tranx, int *out_tranx_id); +da_result_t PI_http_cancel_transaction(int in_tranx_id, da_bool_t abort_option); +da_result_t PI_http_disconnect_transaction(int in_tranx_id); +void PI_http_pause_transaction(int transaction_id); +void PI_http_unpause_transaction(int transaction_id); + +#endif + diff --git a/src/agent/include/download-agent-plugin-install.h b/src/agent/include/download-agent-plugin-install.h new file mode 100644 index 0000000..cdf48fe --- /dev/null +++ b/src/agent/include/download-agent-plugin-install.h @@ -0,0 +1,33 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-plugin-install.h + * @brief Including functions for installing a content + * @author Jungki,Kwak(jungki.kwak@samsung.com) + ***/ + + +#ifndef _Download_Agent_Plugin_Install_H +#define _Download_Agent_Plugin_Install_H + +#include "download-agent-type.h" + +char *PI_get_default_install_dir(void); + +#endif diff --git a/src/agent/include/download-agent-plugin-libsoup.h b/src/agent/include/download-agent-plugin-libsoup.h new file mode 100644 index 0000000..a8a7284 --- /dev/null +++ b/src/agent/include/download-agent-plugin-libsoup.h @@ -0,0 +1,84 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-plugin-libsoup.h + * @brief Including functions regarding libsoup plugin + * @author Jungki Kwak (jungki.kwak@samsung.com) + ***/ + + +#ifndef _Download_Agent_Plugin_Libsoup_H +#define _Download_Agent_Plugin_Libsoup_H + +#include <string.h> +#include <libsoup/soup.h> + +#include "download-agent-http-queue.h" +#include "download-agent-pthread.h" +#include "download-agent-plugin-http-interface.h" + +typedef struct _pi_session_table_t { + da_bool_t is_using; + SoupSession *session; + SoupMessage *msg; + queue_t *queue; + pthread_mutex_t mutex; + pthread_cond_t cond; + da_bool_t is_paused; +} pi_session_table_t; + +extern pi_session_table_t pi_session_table[]; + +#define MAX_SESSION_COUNT DA_MAX_DOWNLOAD_REQ_AT_ONCE +#define MAX_TIMEOUT 180 // second + +#define IS_VALID_SESSION_TABLE_ENTRY(ENTRY) ((((ENTRY) < 0) || ((ENTRY) > MAX_SESSION_COUNT-1)) ? 0 : 1) + + +#define GET_SESSION_FROM_TABLE_ENTRY(ENTRY) (pi_session_table[ENTRY].session) +#define GET_MSG_FROM_TABLE_ENTRY(ENTRY) (pi_session_table[ENTRY].msg) +#define GET_QUEUE_FROM_TABLE_ENTRY(ENTRY) (pi_session_table[ENTRY].queue) + + +da_bool_t _pi_http_is_valid_input_for_tranx(const input_for_tranx_t *input_for_tranx); + +void _pi_http_init_session_table_entry(const int in_session_table_entry); +void _pi_http_destroy_session_table_entry(const int in_session_table_entry); +int _pi_http_get_avaiable_session_table_entry(void); + +da_bool_t _pi_http_register_queue_to_session_table(const int session_table_entry, const queue_t *in_queue); +da_bool_t _pi_http_register_session_to_session_table(const int in_session_table_entry, SoupSession *session); +da_bool_t _pi_http_register_msg_to_session_table(const int in_session_table_entry, SoupMessage *msg); + +queue_t * _pi_http_get_queue_from_session_table_entry(const int in_session_table_entry); +int _pi_http_get_session_table_entry_from_message(SoupMessage *msg); + +void _pi_http_store_read_data_to_queue(SoupMessage *msg,const char* body_data, int received_body_len); +void _pi_http_store_read_header_to_queue(SoupMessage *msg, const char *sniffedType); +void _pi_http_store_neterr_to_queue(SoupMessage *msg); + + +void _pi_http_finished_cb(SoupSession *session, SoupMessage* msg, gpointer data); +void _pi_http_restarted_cb(SoupMessage* msg, gpointer data); +void _pi_http_gotheaders_cb(SoupMessage* msg, gpointer data); +void _pi_http_contentsniffed_cb(SoupMessage* msg, const char* sniffedType, GHashTable *params, gpointer data); +void _pi_http_gotchunk_cb(SoupMessage* msg, SoupBuffer* chunk, gpointer data); + + +#endif diff --git a/src/agent/include/download-agent-pthread.h b/src/agent/include/download-agent-pthread.h new file mode 100644 index 0000000..cc43b06 --- /dev/null +++ b/src/agent/include/download-agent-pthread.h @@ -0,0 +1,156 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-pthread.h + * @brief Wrapping pthread functions + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + + +#ifndef _Download_Agent_Pthread_H +#define _Download_Agent_Pthread_H + +#include <pthread.h> +#include <errno.h> +#include <time.h> + +#include "download-agent-type.h" +#include "download-agent-debug.h" + +#define _da_thread_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_LOG_ERR(Default, "pthread_mutex_init FAIL with EINVAL."); \ + break; \ + } \ + else if(ENOMEM == ret){ \ + DA_LOG_ERR(Default, "pthread_mutex_init FAIL with ENOMEM."); \ + break; \ + } \ + else{ \ + DA_LOG_ERR(Default, "pthread_mutex_init FAIL with %d.", ret); \ + break; \ + } \ + }while(1); \ + } + +#define _da_thread_cond_init(cond_add, attr) do{ \ + if (0 != pthread_cond_init(cond_add, attr)){\ + DA_LOG_ERR(Default, "pthread_cond_init FAIL");} \ + }while(0) + + + +#define _da_thread_mutex_lock(mutex_add) {\ + int ret = 0;\ + do{\ + ret = pthread_mutex_lock(mutex_add);\ + if (0 == ret){\ + break;\ + }\ + else if(EINVAL == ret){\ + DA_LOG_ERR(Default, "pthread_mutex_lock FAIL with EINVAL.");\ + break;\ + }\ + else if(EDEADLK == ret){\ + DA_LOG_ERR(Default, "pthread_mutex_lock FAIL with EDEADLK.");\ + break;\ + }\ + else{\ + DA_LOG_ERR(Default, "pthread_mutex_lock FAIL with %d.", ret);\ + break;\ + }\ + }while(1);\ + } + + +#define _da_thread_mutex_unlock(mutex_add) {\ + int ret = 0;\ + do{\ + ret = pthread_mutex_unlock(mutex_add);\ + if (0 == ret){\ + break;\ + }\ + else if(EINVAL == ret){\ + DA_LOG_ERR(Default, "pthread_mutex_unlock FAIL with EINVAL.");\ + break;\ + }\ + else if(EPERM == ret){\ + DA_LOG_ERR(Default, "pthread_mutex_unlock FAIL with EPERM.");\ + break;\ + }\ + else{\ + DA_LOG_ERR(Default, "pthread_mutex_unlock FAIL with %d.", ret);\ + break;\ + }\ + }while(1);\ + } + + +#define _da_thread_cond_signal(cond_add) do{ \ + if (0 != pthread_cond_signal(cond_add)){\ + DA_LOG_ERR(Default, "pthread_cond_signal FAIL");} \ + }while(0) + + + +#define _da_thread_cond_wait(cond_add, mutex_add) do{ \ + if (0 != pthread_cond_wait(cond_add, mutex_add)){\ + DA_LOG_ERR(Default, "pthread_cond_wait FAIL");} \ + }while(0) + +#define _da_thread_cond_timed_wait(cond_add, mutex_add, time) do{ \ + if (0 != pthread_cond_timedwait(cond_add, mutex_add, time)){\ + DA_LOG_ERR(Default, "pthread_cond_wait FAIL");} \ + }while(0) + + +#define _da_thread_cond_destroy(cond_add) do{ \ + if (0 != pthread_cond_destroy(cond_add)){\ + DA_LOG_ERR(Default, "pthread_cond_destroy FAIL");} \ + }while(0) + +#define _da_thread_mutex_destroy(mutex_add) {\ + int ret = 0;\ + do{\ + ret = pthread_mutex_destroy(mutex_add);\ + if (0 == ret){\ + break;\ + }\ + else if(EINVAL == ret){\ + DA_LOG_ERR(Default, "pthread_mutex_destroy FAIL with EINVAL.");\ + break;\ + }\ + else if(EBUSY == ret){\ + DA_LOG_ERR(Default, "pthread_mutex_destroy FAIL with EBUSY.");\ + break;\ + }\ + else{\ + DA_LOG_ERR(Default, "pthread_mutex_destroy FAIL with %d.", ret);\ + break;\ + }\ + }while(1);\ + } + +#endif diff --git a/src/agent/include/download-agent-type.h b/src/agent/include/download-agent-type.h new file mode 100644 index 0000000..0bdb753 --- /dev/null +++ b/src/agent/include/download-agent-type.h @@ -0,0 +1,44 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-type.h + * @brief including types and defines for Download Agent. This is internally used + * @author Jungki Kwak (jungki.kwak@samsung.com) + */ + +#ifndef _Download_Agent_Types_H +#define _Download_Agent_Types_H + +#include "download-agent-defs.h" + +typedef int da_result_t; +typedef int da_bool_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 + + +#endif + diff --git a/src/agent/include/download-agent-utils-dl-req-id-history.h b/src/agent/include/download-agent-utils-dl-req-id-history.h new file mode 100644 index 0000000..d255b42 --- /dev/null +++ b/src/agent/include/download-agent-utils-dl-req-id-history.h @@ -0,0 +1,44 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-utils-dl-req-id-history.h + * @brief Including operations for dl-req-id-history + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + + +#ifndef _Download_Agent_Utils_Hash_Table_H +#define _Download_Agent_Utils_Hash_Table_H + +#include "download-agent-pthread.h" + +typedef struct _dl_req_id_history_t dl_req_id_history_t; +struct _dl_req_id_history_t { + int starting_num; + int cur_dl_req_id; + pthread_mutex_t mutex; +}; + +da_result_t init_dl_req_id_history(dl_req_id_history_t *dl_req_id_history); +da_result_t deinit_dl_req_id_history(dl_req_id_history_t *dl_req_id_history); + +int get_available_dl_req_id(dl_req_id_history_t *dl_req_id_history); + + +#endif /* _Download_Agent_Utils_Hash_Table_H */ diff --git a/src/agent/include/download-agent-utils.h b/src/agent/include/download-agent-utils.h new file mode 100644 index 0000000..ccf053d --- /dev/null +++ b/src/agent/include/download-agent-utils.h @@ -0,0 +1,94 @@ +/* + * Download Agent + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file download-agent-utils.h + * @brief Including some utilitis + * @author Keunsoon Lee(keunsoon.lee@samsung.com) + ***/ + + +#ifndef _Download_Agent_Utils_H +#define _Download_Agent_Utils_H + +#include <time.h> +#include "download-agent-defs.h" +#include "download-agent-interface.h" +#include "download-agent-dl-mgr.h" + +/* Todo : move these to mime-util.c */ +#define MIME_DRM_MESSAGE "application/vnd.oma.drm.message" +#define MIME_ODF "application/vnd.oasis.opendocument.formula" +#define MIME_OMA_DD "application/vnd.oma.dd+xml" +#define MIME_MIDP_JAR "application/vnd.sun.j2me.java-archive" +#define MIME_MULTIPART_MESSAGE "multipart/related" +#define MIME_TEXT_PLAIN "text/plain" +#define MIME_PLAYREADY_INIT "application/vnd.ms-playready.initiator+xml" + +#define SAVE_FILE_BUFFERING_SIZE_50KB (50*1024) +#define SAVE_FILE_BUFFERING_SIZE_5MB (5*1024*1024) + +#define DA_SLEEP(x) \ + do \ + { \ + struct timespec interval,remainder; \ + interval.tv_sec = (unsigned int)((x)/1000); \ + interval.tv_nsec = (((x)-(interval.tv_sec*1000))*1000000); \ + nanosleep(&interval,&remainder); \ + } while(0) + +typedef enum { + DA_STORAGE_PHONE, /*To Store in Phone memory*/ + DA_STORAGE_MMC, /*To Store in MMC */ + DA_STORAGE_SYSTEM /*To Store in both Phone and MMC*/ +} da_storage_type_t; + +typedef struct _da_storage_size_t { + unsigned long b_available; + unsigned long b_size; +} da_storage_size_t; + +typedef enum { + DA_MIME_TYPE_NONE, + DA_MIME_TYPE_DRM1_MESSATE, + DA_MIME_PLAYREADY_INIT, + DA_MIME_TYPE_END +} da_mime_type_id_t; + +void get_random_number(int *out_num); +da_result_t get_available_dd_id(da_handle_t *available_id); + +da_result_t get_extension_from_mime_type(char *mime_type, char **extension); +da_mime_type_id_t get_mime_type_id(char* content_type); + +da_result_t get_available_memory(da_storage_type_t storage_type, da_storage_size_t *avail_memory); +da_result_t check_enough_storage(stage_info *stage); + +da_bool_t is_valid_url(const char* url, da_result_t *err_code); +da_bool_t is_content_drm_dm(char *content_type); + +int read_data_from_file(char *file, char**out_buffer); + +da_result_t move_file(const char *from_path, const char *to_path); +void remove_file(const char *file_path); + +char* print_dl_state(da_state state); + +char* _stristr(const char* long_str, const char* find_str); + +#endif diff --git a/src/download-provider-dateTime.cpp b/src/download-provider-dateTime.cpp deleted file mode 100644 index 8f6edd3..0000000 --- a/src/download-provider-dateTime.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-dateTime.cpp - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief data and utility APIs for Date and Time - */ - -#include "runtime_info.h" -#include "download-provider-dateTime.h" - -#define MAX_SKELETON_BUFFER_LEN 8 -#define MAX_PATTERN_BUFFER_LEN 128 - -DateGroup::DateGroup() - : count(0) - , type(DATETIME::DATE_TYPE_NONE) - , m_glGroupItem(NULL) -{ -} - -DateGroup::~DateGroup() -{ -} - -void DateGroup::initData() -{ - count = 0; - m_glGroupItem = NULL; -} - -DateUtil::DateUtil() - : m_todayStandardTime(0) - , dateShortFormat(NULL) - , dateMediumFormat(NULL) - , dateFullFormat(NULL) - , timeFormat12H(NULL) - , timeFormat24H(NULL) -{ -} - -DateUtil::~DateUtil() -{ - deinitLocaleData(); -} - -void DateUtil::deinitLocaleData() -{ - if (dateShortFormat) - udat_close(dateShortFormat); - if (dateMediumFormat) - udat_close(dateMediumFormat); - if (dateFullFormat) - udat_close(dateFullFormat); - if (timeFormat12H) - udat_close(timeFormat12H); - if (timeFormat24H) - udat_close(timeFormat24H); - dateShortFormat = NULL; - dateMediumFormat = NULL; - dateFullFormat = NULL; - timeFormat12H = NULL; - timeFormat24H = NULL; -} - -int DateUtil::getDiffDaysFromToday() -{ - time_t now = time(NULL); - DP_LOGD("todayStandardTime[%ld]", m_todayStandardTime); - if (m_todayStandardTime == 0) - return 0; - else - return getDiffDays(now, m_todayStandardTime); -} - -int DateUtil::getDiffDays(time_t nowTime,time_t refTime) -{ - int diffDays = 0; - int nowYear = 0; - int nowYday = 0; - int refYday = 0; - int refYear = 0; - struct tm *nowDate = localtime(&nowTime); - nowYday = nowDate->tm_yday; - nowYear = nowDate->tm_year; - struct tm *finishedDate = localtime(&refTime); - refYday = finishedDate->tm_yday; - refYear = finishedDate->tm_year; - diffDays = nowYday - refYday; - /*DP_LOGD("refDate[%d/%d/%d]refTime[%ld]yday[%d]", - (finishedDate->tm_year + 1900), (finishedDate->tm_mon + 1), - finishedDate->tm_mday, refTime, refYday);*/ - if ((nowYear-refYear)>0 && diffDays < 0) { - int year = nowDate->tm_year; - diffDays = diffDays + 365; - /* leap year */ - if ((year%4 == 0 && year%100 != 0) || year%400 == 0) - diffDays++; - } - DP_LOGD("diffDays[%d]",diffDays); - return diffDays; -} - -UDateFormat *DateUtil::getBestPattern(const char *patternStr, - UDateTimePatternGenerator *generator, const char *locale) -{ - UDateFormat *format = NULL; - UChar customSkeleton[MAX_SKELETON_BUFFER_LEN] = {0,}; - UChar bestPattern[MAX_PATTERN_BUFFER_LEN] = {0,}; - UErrorCode status = U_ZERO_ERROR; - int32_t patternLen = 0; - - if (patternStr) { - u_uastrncpy(customSkeleton, patternStr, strlen(patternStr)); - patternLen = udatpg_getBestPattern(generator, customSkeleton, - u_strlen(customSkeleton), bestPattern, MAX_PATTERN_BUFFER_LEN, - &status); - DP_LOGD("udatpg_getBestPattern status[%d] bestPattern[%s]", status, - bestPattern); - if (patternLen < 1) { - format = udat_open(UDAT_SHORT, UDAT_NONE, locale, NULL, -1, - NULL, -1, &status); - return format; - } - } - format = udat_open(UDAT_IGNORE, UDAT_NONE, locale, NULL, -1, - bestPattern, -1, &status); - return format; -} - -void DateUtil::updateLocale() -{ - UDateTimePatternGenerator *generator = NULL; - UErrorCode status = U_ZERO_ERROR; - const char *locale = NULL; - - DP_LOGD_FUNC(); - - deinitLocaleData(); - - uloc_setDefault(getenv("LC_TIME"), &status); - DP_LOGD("uloc_setDefault status[%d]",status); - - locale = uloc_getDefault(); - generator = udatpg_open(locale,&status); - DP_LOGD("udatpg_open status[%d]",status); - - timeFormat12H = getBestPattern("hm", generator, locale); - timeFormat24H = getBestPattern("Hm", generator, locale); - - dateShortFormat = udat_open(UDAT_NONE, UDAT_SHORT, locale, NULL, -1, NULL, - -1, &status); - dateMediumFormat = udat_open(UDAT_NONE, UDAT_MEDIUM, locale, NULL, -1, NULL, - -1, &status); - dateFullFormat = getBestPattern("yMMMEEEd", generator, locale); - udatpg_close(generator); -} - -void DateUtil::getDateStr(int style, double time, string &outBuf) -{ - UDateFormat *format = NULL; - UErrorCode status = U_ZERO_ERROR; - UChar str[MAX_BUF_LEN] = {0,}; - bool value = false; - - DP_LOGD_FUNC(); - switch (style) { - case LOCALE_STYLE::TIME: - if (runtime_info_get_value_bool( - RUNTIME_INFO_KEY_24HOUR_CLOCK_FORMAT_ENABLED,&value) != 0) { - DP_LOGE("runtime_info_get_value_bool is failed"); - format = timeFormat12H; - } else { - if (value) - format = timeFormat24H; - else - format = timeFormat12H; - } - break; - case LOCALE_STYLE::SHORT_DATE: - format = dateShortFormat; - break; - case LOCALE_STYLE::MEDIUM_DATE: - format = dateMediumFormat; - break; - case LOCALE_STYLE::FULL_DATE: - format = dateFullFormat; - break; - default : - DP_LOGE("Critical: cannot enter here"); - format = timeFormat12H; - } - if (format) { - char tempBuf[MAX_BUF_LEN] = {0,}; - udat_format(format, time, str, MAX_BUF_LEN - 1, NULL, &status); - DP_LOGD("udat_format : status[%d]", status); - u_austrncpy(tempBuf, str, MAX_BUF_LEN-1); - outBuf = string(tempBuf); - } else { - DP_LOGE("Critical: fail to get time value"); - outBuf = string(S_("IDS_COM_POP_ERROR")); - } -} - diff --git a/src/download-provider-db.c b/src/download-provider-db.c new file mode 100644 index 0000000..edf02cc --- /dev/null +++ b/src/download-provider-db.c @@ -0,0 +1,868 @@ +#include <db-util.h> + +#include <string.h> +#include <errno.h> + +#include "download-provider-config.h" +#include "download-provider-db.h" +#include "download-provider-log.h" + +__thread sqlite3 *g_download_provider_db = 0; + +void __download_provider_db_close() +{ + if (g_download_provider_db) { + db_util_close(g_download_provider_db); + } + g_download_provider_db = 0; +} + +int __download_provider_db_open() +{ + if (db_util_open(DOWNLOAD_PROVIDER_DOWNLOADING_DB_NAME, + &g_download_provider_db, + DB_UTIL_REGISTER_HOOK_METHOD) != SQLITE_OK) { + TRACE_DEBUG_MSG("failed db_util_open [%s][%s]", + DOWNLOAD_PROVIDER_DOWNLOADING_DB_NAME, + sqlite3_errmsg(g_download_provider_db)); + __download_provider_db_close(); + return -1; + } + return g_download_provider_db ? 0 : -1; +} + +void _download_provider_sql_close(sqlite3_stmt *stmt) +{ + if (sqlite3_finalize(stmt) != SQLITE_OK) + TRACE_DEBUG_MSG("failed sqlite3_finalize [%s]", + sqlite3_errmsg(g_download_provider_db)); + + __download_provider_db_close(); +} + +int _download_provider_sql_open() +{ + __download_provider_db_close(); + return __download_provider_db_open(); +} + +int download_provider_db_requestinfo_remove(int uniqueid) +{ + int errorcode; + sqlite3_stmt *stmt; + + if (uniqueid <= 0) { + TRACE_DEBUG_MSG("[NULL-CHECK]"); + return -1; + } + + if (_download_provider_sql_open() < 0) { + TRACE_DEBUG_MSG("db_util_open is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + return -1; + } + + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "delete from downloading where uniqueid = ?", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (sqlite3_bind_int(stmt, 1, uniqueid) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { + _download_provider_sql_close(stmt); + return 0; + } + TRACE_DEBUG_MSG("sqlite3_step is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + __download_provider_db_close(); + return -1; +} + +int download_provider_db_requestinfo_new(download_clientinfo *clientinfo) +{ + int errorcode; + sqlite3_stmt *stmt; + + if (!clientinfo || !clientinfo->requestinfo + || clientinfo->requestinfo->requestid <= 0) { + TRACE_DEBUG_MSG("[NULL-CHECK]"); + return -1; + } + + if (_download_provider_sql_open() < 0) { + TRACE_DEBUG_MSG("db_util_open is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + return -1; + } + + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "INSERT INTO downloading (uniqueid, packagename, notification, installpath, filename, creationdate, state, url, mimetype, savedpath) VALUES (?, ?, ?, ?, ?, DATETIME('now'), ?, ?, ?, ?)", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (sqlite3_bind_int(stmt, 1, clientinfo->requestinfo->requestid) != + SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (clientinfo->requestinfo->client_packagename.length > 0) { + if (sqlite3_bind_text + (stmt, 2, clientinfo->requestinfo->client_packagename.str, + -1, NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + } + // notification + if (sqlite3_bind_int(stmt, 3, clientinfo->requestinfo->notification) != + SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (clientinfo->downloadinfo && clientinfo->downloadinfo->content_name) { + if (sqlite3_bind_text + (stmt, 5, clientinfo->downloadinfo->content_name, -1, + NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + } + if (sqlite3_bind_int(stmt, 6, clientinfo->state) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (clientinfo->requestinfo->url.length > 0) { + if (sqlite3_bind_text + (stmt, 7, clientinfo->requestinfo->url.str, -1, + NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + } + if (clientinfo->downloadinfo && clientinfo->downloadinfo->mime_type) { + if (sqlite3_bind_text + (stmt, 8, clientinfo->downloadinfo->mime_type, -1, + NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + } + if (clientinfo->tmp_saved_path) { + if (sqlite3_bind_text + (stmt, 9, clientinfo->tmp_saved_path, -1, + NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + } + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { + _download_provider_sql_close(stmt); + return 0; + } + TRACE_DEBUG_MSG("sqlite3_step is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + __download_provider_db_close(); + return -1; +} + +int download_provider_db_requestinfo_update_column(download_clientinfo *clientinfo, + download_db_column_type type) +{ + int errorcode; + sqlite3_stmt *stmt; + + if (!clientinfo || !clientinfo->requestinfo + || clientinfo->requestinfo->requestid <= 0) { + TRACE_DEBUG_MSG("[NULL-CHECK]"); + return -1; + } + + if (_download_provider_sql_open() < 0) { + TRACE_DEBUG_MSG("db_util_open is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + return -1; + } + + switch (type) { + case DOWNLOAD_DB_PACKAGENAME: + if (clientinfo->requestinfo->client_packagename.length <= 0 + || !clientinfo->requestinfo->client_packagename.str) { + TRACE_DEBUG_MSG("[NULL-CHECK] type [%d]", type); + _download_provider_sql_close(stmt); + return -1; + } + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "UPDATE downloading SET packagename = ? WHERE uniqueid = ?", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (sqlite3_bind_text + (stmt, 1, clientinfo->requestinfo->client_packagename.str, + -1, NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + break; + case DOWNLOAD_DB_NOTIFICATION: + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "UPDATE downloading SET notification = ? WHERE uniqueid = ?", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (sqlite3_bind_int + (stmt, 1, + clientinfo->requestinfo->notification) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + break; + case DOWNLOAD_DB_STATE: + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "UPDATE downloading SET state = ? WHERE uniqueid = ?", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (sqlite3_bind_int(stmt, 1, clientinfo->state) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + break; + case DOWNLOAD_DB_MIMETYPE: + if (!clientinfo->downloadinfo) { + TRACE_DEBUG_MSG("[NULL-CHECK] type [%d]", type); + _download_provider_sql_close(stmt); + return -1; + } + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "UPDATE downloading SET mimetype = ? WHERE uniqueid = ?", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (sqlite3_bind_text + (stmt, 1, clientinfo->downloadinfo->mime_type, -1, + NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + break; + case DOWNLOAD_DB_FILENAME: + if (!clientinfo->downloadinfo + || !clientinfo->downloadinfo->content_name) { + TRACE_DEBUG_MSG("[NULL-CHECK] type [%d]", type); + _download_provider_sql_close(stmt); + return -1; + } + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "UPDATE downloading SET filename = ? WHERE uniqueid = ?", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (sqlite3_bind_text + (stmt, 1, clientinfo->downloadinfo->content_name, -1, + NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + break; + case DOWNLOAD_DB_SAVEDPATH: + if (!clientinfo->tmp_saved_path) { + TRACE_DEBUG_MSG("[NULL-CHECK] type [%d]", type); + _download_provider_sql_close(stmt); + return -1; + } + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "UPDATE downloading SET savedpath = ? WHERE uniqueid = ?", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (sqlite3_bind_text + (stmt, 1, clientinfo->tmp_saved_path, -1, + NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + break; + default: + TRACE_DEBUG_MSG("Wrong type [%d]", type); + return -1; + } + + if (sqlite3_bind_int(stmt, 2, clientinfo->requestinfo->requestid) != + SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { + _download_provider_sql_close(stmt); + return 0; + } + TRACE_DEBUG_MSG("sqlite3_step is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + __download_provider_db_close(); + return -1; +} + +download_dbinfo_list *download_provider_db_get_list(int state) +{ + int errorcode; + int listcount; + int i = 0; + int buffer_length = 0; + sqlite3_stmt *stmt; + char *buffer; + download_dbinfo_list *m_list = NULL; + + listcount = download_provider_db_list_count(state); + if (listcount <= 0) + return NULL; + + if (_download_provider_sql_open() < 0) { + TRACE_DEBUG_MSG("db_util_open is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + return NULL; + } + + if (state != DOWNLOAD_STATE_NONE) { + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "SELECT uniqueid, packagename, notification, installpath, filename, creationdate, state, url, mimetype, savedpath FROM downloading WHERE state = ?", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return NULL; + } + if (sqlite3_bind_int(stmt, 1, state) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return NULL; + } + } else { + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "SELECT uniqueid, packagename, notification, installpath, filename, creationdate, state, url, mimetype, savedpath FROM downloading", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return NULL; + } + } + m_list = (download_dbinfo_list *) calloc(1, sizeof(download_dbinfo_list)); + m_list->item = + (download_dbinfo *) calloc(listcount, sizeof(download_dbinfo)); + m_list->count = listcount; + + while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW + && (i < listcount)) { + m_list->item[i].requestid = sqlite3_column_int(stmt, 0); + buffer = (char *)(sqlite3_column_text(stmt, 1)); + m_list->item[i].packagename = NULL; + if (buffer) { + buffer_length = strlen(buffer); + m_list->item[i].packagename + = (char *)calloc(buffer_length + 1, sizeof(char)); + memcpy(m_list->item[i].packagename, buffer, + buffer_length * sizeof(char)); + m_list->item[i].packagename[buffer_length] = '\0'; + } + m_list->item[i].notification = sqlite3_column_int(stmt, 2); + buffer = (char *)(sqlite3_column_text(stmt, 3)); + m_list->item[i].installpath = NULL; + if (buffer) { + buffer_length = strlen(buffer); + m_list->item[i].installpath + = (char *)calloc(buffer_length + 1, sizeof(char)); + memcpy(m_list->item[i].installpath, buffer, + buffer_length * sizeof(char)); + m_list->item[i].installpath[buffer_length] = '\0'; + } + buffer = (char *)(sqlite3_column_text(stmt, 4)); + m_list->item[i].filename = NULL; + if (buffer) { + buffer_length = strlen(buffer); + m_list->item[i].filename + = (char *)calloc(buffer_length + 1, sizeof(char)); + memcpy(m_list->item[i].filename, buffer, + buffer_length * sizeof(char)); + m_list->item[i].filename[buffer_length] = '\0'; + } + buffer = (char *)(sqlite3_column_text(stmt, 5)); + m_list->item[i].createdate = NULL; + if (buffer) { + buffer_length = strlen(buffer); + m_list->item[i].createdate + = (char *)calloc(buffer_length + 1, sizeof(char)); + memcpy(m_list->item[i].createdate, buffer, + buffer_length * sizeof(char)); + m_list->item[i].createdate[buffer_length] = '\0'; + } + m_list->item[i].state = sqlite3_column_int(stmt, 6); + buffer = (char *)(sqlite3_column_text(stmt, 7)); + m_list->item[i].url = NULL; + if (buffer) { + buffer_length = strlen(buffer); + m_list->item[i].url + = (char *)calloc(buffer_length + 1, sizeof(char)); + memcpy(m_list->item[i].url, buffer, + buffer_length * sizeof(char)); + m_list->item[i].url[buffer_length] = '\0'; + } + buffer = (char *)(sqlite3_column_text(stmt, 8)); + m_list->item[i].mimetype = NULL; + if (buffer) { + buffer_length = strlen(buffer); + m_list->item[i].mimetype + = (char *)calloc(buffer_length + 1, sizeof(char)); + memcpy(m_list->item[i].mimetype, buffer, + buffer_length * sizeof(char)); + m_list->item[i].mimetype[buffer_length] = '\0'; + } + buffer = (char *)(sqlite3_column_text(stmt, 9)); + m_list->item[i].saved_path = NULL; + if (buffer) { + buffer_length = strlen(buffer); + m_list->item[i].saved_path + = (char *)calloc(buffer_length + 1, sizeof(char)); + memcpy(m_list->item[i].saved_path, buffer, + buffer_length * sizeof(char)); + m_list->item[i].saved_path[buffer_length] = '\0'; + } + i++; + } + m_list->count = i; + + if (i <= 0) { + TRACE_DEBUG_MSG("sqlite3_step is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + __download_provider_db_close(); + download_provider_db_list_free(m_list); + return NULL; + } + _download_provider_sql_close(stmt); + return m_list; +} + +int download_provider_db_list_count(int state) +{ + int errorcode; + int count = 0; + sqlite3_stmt *stmt; + + if (_download_provider_sql_open() < 0) { + TRACE_DEBUG_MSG("db_util_open is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + return -1; + } + + if (state != DOWNLOAD_STATE_NONE) { + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "SELECT count(*) FROM downloading WHERE state = ?", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (sqlite3_bind_int(stmt, 1, state) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + } else { + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "SELECT count(*) FROM downloading", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + } + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_ROW) { + count = sqlite3_column_int(stmt, 0); + _download_provider_sql_close(stmt); + return count; + } + TRACE_DEBUG_MSG("sqlite3_step is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + __download_provider_db_close(); + return 0; +} + +void download_provider_db_list_free(download_dbinfo_list *list) +{ + TRACE_DEBUG_MSG(""); + + int i = 0; + if (!list) + return; + + if (list->count > 0 && list->item) { + for (i = 0; i < list->count; i++) { + list->item[i].requestid = 0; + if (list->item[i].packagename) + free(list->item[i].packagename); + list->item[i].packagename = NULL; + if (list->item[i].installpath) + free(list->item[i].installpath); + list->item[i].installpath = NULL; + if (list->item[i].filename) + free(list->item[i].filename); + list->item[i].filename = NULL; + if (list->item[i].createdate) + free(list->item[i].createdate); + list->item[i].createdate = NULL; + if (list->item[i].url) + free(list->item[i].url); + list->item[i].url = NULL; + if (list->item[i].mimetype) + free(list->item[i].mimetype); + list->item[i].mimetype = NULL; + if (list->item[i].etag) + free(list->item[i].etag); + list->item[i].etag = NULL; + if (list->item[i].saved_path) + free(list->item[i].saved_path); + list->item[i].saved_path = NULL; + } + free(list->item); + list->item = NULL; + } + free(list); + list = NULL; +} + +download_request_info *download_provider_db_get_requestinfo(download_dbinfo *dbinfo) +{ + if (!dbinfo || dbinfo->requestid <= 0) + return NULL; + + download_request_info *requestinfo = + (download_request_info *) calloc(1, sizeof(download_request_info)); + requestinfo->requestid = dbinfo->requestid; + if (dbinfo->packagename) { + requestinfo->client_packagename.length = + strlen(dbinfo->packagename); + if (requestinfo->client_packagename.length > 0) { + requestinfo->client_packagename.str + = + (char *) + calloc((requestinfo->client_packagename.length + 1), + sizeof(char)); + memcpy(requestinfo->client_packagename.str, + dbinfo->packagename, + requestinfo->client_packagename.length * + sizeof(char)); + requestinfo->client_packagename.str[requestinfo-> + client_packagename. + length] = '\0'; + } + } + if (dbinfo->url) { + requestinfo->url.length = strlen(dbinfo->url); + if (requestinfo->url.length > 0) { + requestinfo->url.str + = + (char *)calloc((requestinfo->url.length + 1), + sizeof(char)); + memcpy(requestinfo->url.str, dbinfo->url, + requestinfo->url.length * sizeof(char)); + requestinfo->url.str[requestinfo->url.length] = '\0'; + } + } + if (dbinfo->installpath) { + requestinfo->install_path.length = strlen(dbinfo->installpath); + if (requestinfo->install_path.length > 0) { + requestinfo->install_path.str + = + (char *) + calloc((requestinfo->install_path.length + 1), + sizeof(char)); + memcpy(requestinfo->install_path.str, + dbinfo->installpath, + requestinfo->install_path.length * sizeof(char)); + requestinfo->install_path.str[requestinfo->install_path. + length] = '\0'; + } + } + if (dbinfo->filename) { + requestinfo->filename.length = strlen(dbinfo->filename); + if (requestinfo->filename.length > 0) { + requestinfo->filename.str + = + (char *)calloc((requestinfo->filename.length + 1), + sizeof(char)); + memcpy(requestinfo->filename.str, dbinfo->filename, + requestinfo->filename.length * sizeof(char)); + requestinfo->filename.str[requestinfo->filename. + length] = '\0'; + } + } + // disable callback. + memset(&requestinfo->callbackinfo, 0x00, sizeof(callback_info)); + requestinfo->notification = dbinfo->notification; + return requestinfo; +} + +int download_provider_db_history_new(download_clientinfo *clientinfo) +{ + int errorcode; + sqlite3_stmt *stmt; + + if (!clientinfo || !clientinfo->requestinfo + || clientinfo->requestinfo->requestid <= 0) { + TRACE_DEBUG_MSG("[NULL-CHECK]"); + return -1; + } + + if (_download_provider_sql_open() < 0) { + TRACE_DEBUG_MSG("db_util_open is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + return -1; + } + + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "INSERT INTO history (uniqueid, packagename, filename, creationdate, state, mimetype, savedpath) VALUES (?, ?, ?, DATETIME('now'), ?, ?, ?)", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (sqlite3_bind_int(stmt, 1, clientinfo->requestinfo->requestid) != + SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (clientinfo->requestinfo->client_packagename.length > 0) { + if (sqlite3_bind_text + (stmt, 2, clientinfo->requestinfo->client_packagename.str, + -1, NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + } + if (clientinfo->downloadinfo && clientinfo->downloadinfo->content_name) { + if (sqlite3_bind_text + (stmt, 3, clientinfo->downloadinfo->content_name, -1, + NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + } + if (sqlite3_bind_int(stmt, 4, clientinfo->state) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (clientinfo->downloadinfo && clientinfo->downloadinfo->mime_type) { + if (sqlite3_bind_text + (stmt, 5, clientinfo->downloadinfo->mime_type, -1, + NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + } + if (clientinfo->tmp_saved_path) { + if (sqlite3_bind_text + (stmt, 6, clientinfo->tmp_saved_path, -1, + NULL) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + } + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { + _download_provider_sql_close(stmt); + download_provider_db_history_limit_rows(); + return 0; + } + TRACE_DEBUG_MSG("sqlite3_step is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + __download_provider_db_close(); + return -1; +} + +int download_provider_db_history_remove(int uniqueid) +{ + int errorcode; + sqlite3_stmt *stmt; + + if (uniqueid <= 0) { + TRACE_DEBUG_MSG("[NULL-CHECK]"); + return -1; + } + + if (_download_provider_sql_open() < 0) { + TRACE_DEBUG_MSG("db_util_open is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + return -1; + } + + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "delete from history where uniqueid = ?", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (sqlite3_bind_int(stmt, 1, uniqueid) != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { + _download_provider_sql_close(stmt); + return 0; + } + TRACE_DEBUG_MSG("sqlite3_step is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + __download_provider_db_close(); + return -1; +} + +int download_provider_db_history_limit_rows() +{ + int errorcode; + sqlite3_stmt *stmt; + + if (_download_provider_sql_open() < 0) { + TRACE_DEBUG_MSG("db_util_open is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + return -1; + } + + errorcode = + sqlite3_prepare_v2(g_download_provider_db, + "DELETE FROM history where uniqueid NOT IN (SELECT uniqueid FROM history ORDER BY id DESC LIMIT ?)", + -1, &stmt, NULL); + if (errorcode != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + if (sqlite3_bind_int(stmt, 1, DOWNLOAD_PROVIDER_HISTORY_DB_LIMIT_ROWS) + != SQLITE_OK) { + TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", + sqlite3_errmsg(g_download_provider_db)); + _download_provider_sql_close(stmt); + return -1; + } + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { + _download_provider_sql_close(stmt); + return 0; + } + TRACE_DEBUG_MSG("sqlite3_step is failed [%s]", + sqlite3_errmsg(g_download_provider_db)); + __download_provider_db_close(); + return -1; +} diff --git a/src/download-provider-downloadItem.cpp b/src/download-provider-downloadItem.cpp deleted file mode 100644 index de3df50..0000000 --- a/src/download-provider-downloadItem.cpp +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-downloadItem.cpp - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief download item class for interface of download agent - */ - -#include "download-provider-downloadItem.h" - -#include "download-provider-common.h" -#include <Ecore.h> -#include <iostream> - -/* Download Agent CallBacks */ -static void __notify_cb(user_notify_info_t *notify_info, void *user_data); -static void __update_download_info_cb(user_download_info_t *download_info, void *user_data); -static void __get_dd_info_cb(user_dd_info_t *dd_info, void *user_data); - -static Ecore_Pipe *ecore_pipe = NULL; -static void __ecore_cb_pipe_update(void *data, void *buffer, unsigned int nbyte); - -namespace DA_CB { -enum TYPE { - NOTIFY = 1, - UPDATE, - DD_INFO -}; -} - -class CbData { -public: - CbData() {} - ~CbData() {} - - void updateDownloadItem(); - - inline void setType(DA_CB::TYPE type) { m_type = type; } - inline void setUserData(void *userData) { m_userData = userData; } - inline void setDownloadId(int id) { m_da_req_id = id; } - inline void setReceivedFileSize(unsigned long int size) { m_receivedFileSize = size; } - inline void setFileSize(unsigned long int size) { m_fileSize = size; } - inline void setFilePath(const char *path) { if (path) m_filePath = path; } - inline void setRegisteredFilePath(const char *path) { if (path) m_registeredFilePath = path; } - inline void setMimeType(const char *mime) { m_mimeType = mime; } - inline void setState(da_state state) { m_da_state = state; } - inline void setErrorCode(int err) { m_da_error = err; } - inline void setIsMidletInstalled(bool b) { m_isMidletInstalled = b; } - inline void setIsJad(bool b) { m_isJad = b;} - inline void setContentName(const char *name) { m_contentName = name; } - inline void setVendorName(const char *name) { m_vendorName = name; } - -private: - DA_CB::TYPE m_type; - void *m_userData; - da_handle_t m_da_req_id; - da_state m_da_state; - int m_da_error; - unsigned long int m_receivedFileSize; - unsigned long int m_fileSize; - string m_filePath; - string m_registeredFilePath; - string m_mimeType; - bool m_isMidletInstalled; - bool m_isJad; - string m_contentName; - string m_vendorName; -}; - -struct pipe_data_t { - CbData *cbData; -}; - -DownloadEngine::DownloadEngine() -{ -} - -DownloadEngine::~DownloadEngine() -{ - DP_LOG_FUNC(); -} - -void DownloadEngine::initEngine(void) -{ - da_client_cb_t da_cb = { - __notify_cb, /* da_notify_cb */ - __get_dd_info_cb, /* da_send_dd_info_cb */ - __update_download_info_cb, /* da_update_download_info_cb */ - NULL /* da_go_to_next_url_cb */ - }; - - int da_ret = da_init(&da_cb, DA_DOWNLOAD_MANAGING_METHOD_AUTO); - if (DA_RESULT_OK == da_ret) { - ecore_pipe = ecore_pipe_add(__ecore_cb_pipe_update, NULL); - } -} - -void DownloadEngine::deinitEngine(void) -{ - da_deinit(); - if (ecore_pipe) { - ecore_pipe_del(ecore_pipe); - ecore_pipe = NULL; - } -} - -void CbData::updateDownloadItem() -{ -// DP_LOGD_FUNC(); - - if (!m_userData) { - DP_LOGE("download item is NULL"); - return; - } - - - DownloadItem *downloadItem = static_cast<DownloadItem*>(m_userData); - if (downloadItem->state() == DL_ITEM::FAILED) { - DP_LOGE("download item is already failed"); - return; - } - - switch(m_type) { - case DA_CB::NOTIFY: - { - DP_LOGD("DA_CB::NOTIFY"); - downloadItem->setDownloadId(m_da_req_id); - DL_ITEM::STATE dl_state = downloadItem->_convert_da_state_to_download_state(m_da_state); - DP_LOG("DL_ITEM::STATE [%d]", dl_state); - //if (dl_state != DL_ITEM::IGNORE) - if (dl_state == DL_ITEM::IGNORE) - return; - downloadItem->setState(dl_state); - - if (dl_state == DL_ITEM::FAILED) - downloadItem->setErrorCode(downloadItem->_convert_da_error(m_da_error)); - } - break; - - case DA_CB::UPDATE: - DP_LOGD("DA_CB::UPDATE"); - DP_LOGD("DA_CB::UPDATE state[%d] receivedFileSize[%d]", downloadItem->state(), m_receivedFileSize); -// downloadItem->setDownloadId(m_da_req_id); - downloadItem->setState(DL_ITEM::UPDATING); - downloadItem->setReceivedFileSize(m_receivedFileSize); - downloadItem->setFileSize(m_fileSize); - - if (!m_mimeType.empty()) - downloadItem->setMimeType(m_mimeType); - - if (!m_filePath.empty()) - downloadItem->setFilePath(m_filePath); - - if (!m_registeredFilePath.empty()) { - DP_LOGD("registeredFilePath[%s]", m_registeredFilePath.c_str()); - downloadItem->setRegisteredFilePath(m_registeredFilePath); - } - break; - - case DA_CB::DD_INFO: - DP_LOG("DA_CB::DD_INFO"); - downloadItem->setDownloadId(m_da_req_id); - downloadItem->setFileSize(m_fileSize); - downloadItem->setIsMidletInstalled(m_isMidletInstalled); - if (m_isJad) - downloadItem->setDownloadType(DL_TYPE::MIDP_DOWNLOAD); - else - downloadItem->setDownloadType(DL_TYPE::OMA_DOWNLOAD); - downloadItem->setContentName(m_contentName); - downloadItem->setVendorName(m_vendorName); - downloadItem->setState(DL_ITEM::WAITING_CONFIRM); - break; - - default: - break; - } - - downloadItem->notify(); -} - -void __ecore_cb_pipe_update(void *data, void *buffer, unsigned int nbyte) -{ -// DP_LOGD_FUNC(); - - if (!buffer) - return; - pipe_data_t *pipe_data = static_cast<pipe_data_t *>(buffer); - CbData *cbData = pipe_data->cbData; - if (!cbData) - return; - - cbData->updateDownloadItem(); - delete cbData; -} - -void __notify_cb(user_notify_info_t *notify_info, void* user_data) -{ - DP_LOGD_FUNC(); - - if (!notify_info || !user_data) - return; - - DP_LOGD("__notify_cb: id[%d] state[%d] err[%d]", notify_info->da_dl_req_id, notify_info->state, notify_info->err); - - CbData *cbData = new CbData(); - cbData->setType(DA_CB::NOTIFY); - cbData->setDownloadId(notify_info->da_dl_req_id); - cbData->setUserData(user_data); - cbData->setState(notify_info->state); - cbData->setErrorCode(notify_info->err); - - pipe_data_t pipe_data; - pipe_data.cbData = cbData; - ecore_pipe_write(ecore_pipe, &pipe_data, sizeof(pipe_data_t)); -} - -void __update_download_info_cb(user_download_info_t *download_info, void *user_data) -{ -// DP_LOGD_FUNC(); - - if (!download_info || !user_data) - return; - - CbData *cbData = new CbData(); - cbData->setType(DA_CB::UPDATE); - cbData->setDownloadId(download_info->da_dl_req_id); - cbData->setUserData(user_data); - cbData->setFileSize(download_info->file_size); - cbData->setReceivedFileSize(download_info->total_received_size); - -// DP_LOGD("tmp path [%s] path [%s] type [%s]", download_info->tmp_saved_path, download_info->saved_path, download_info->file_type); - DownloadItem *item = static_cast<DownloadItem*>(user_data); - if(download_info->file_type && item->mimeType().empty()) - cbData->setMimeType(download_info->file_type); - - if(download_info->tmp_saved_path && item->filePath().empty()) - cbData->setFilePath(download_info->tmp_saved_path); - - if(download_info->saved_path && item->registeredFilePath().empty()) - cbData->setRegisteredFilePath(download_info->saved_path); - - pipe_data_t pipe_data; - pipe_data.cbData = cbData; - ecore_pipe_write(ecore_pipe, &pipe_data, sizeof(pipe_data_t)); -} - -void __get_dd_info_cb(user_dd_info_t *dd_info, void *user_data) -{ - DP_LOGD_FUNC(); - - if (!dd_info || !user_data) - return; - - CbData *cbData = new CbData(); - cbData->setType(DA_CB::DD_INFO); - cbData->setDownloadId(dd_info->da_dl_req_id); - cbData->setUserData(user_data); - cbData->setIsMidletInstalled(dd_info->is_installed); - cbData->setIsJad(dd_info->is_jad); - cbData->setFileSize(dd_info->size); - - if (dd_info->name) - cbData->setContentName(dd_info->name); - if (dd_info->vendor) - cbData->setVendorName(dd_info->vendor); - if (dd_info->type) - cbData->setMimeType(dd_info->type); - - pipe_data_t pipe_data; - pipe_data.cbData = cbData; - ecore_pipe_write(ecore_pipe, &pipe_data, sizeof(pipe_data_t)); -} - -DownloadItem::DownloadItem() - : m_da_req_id(DA_INVALID_ID) - , m_state(DL_ITEM::IGNORE) - , m_errorCode(ERROR::NONE) - , m_receivedFileSize(0) - , m_fileSize(0) - , m_downloadType(DL_TYPE::HTTP_DOWNLOAD) - , m_isMidletInstalled(false) -{ -} - -DownloadItem::DownloadItem(auto_ptr<DownloadRequest> request) - : m_aptr_request(request) - , m_da_req_id(DA_INVALID_ID) - , m_state(DL_ITEM::IGNORE) - , m_errorCode(ERROR::NONE) - , m_receivedFileSize(0) - , m_fileSize(0) - , m_downloadType(DL_TYPE::HTTP_DOWNLOAD) - , m_isMidletInstalled(false) -{ -} - -DownloadItem::~DownloadItem() -{ - DP_LOGD_FUNC(); -} - -void DownloadItem::start(void) -{ - int da_ret = 0; - DP_LOGD_FUNC(); - - if (m_aptr_request->getCookie().empty()) { - da_ret = da_start_download_with_extension( - m_aptr_request->getUrl().c_str(), - &m_da_req_id, - DA_FEATURE_USER_DATA, - static_cast<void*>(this), - NULL); - } else { - char *requestHeader[1] = {NULL,}; - int reqHeaderCount = 1; - string reqHeaderStr = string("Cookie:"); - reqHeaderStr.append(m_aptr_request->getCookie().c_str()); - requestHeader[0] = strdup(reqHeaderStr.c_str()); - da_ret = da_start_download_with_extension( - m_aptr_request->getUrl().c_str(), - &m_da_req_id, - DA_FEATURE_REQUEST_HEADER, - requestHeader, - &reqHeaderCount, - DA_FEATURE_USER_DATA, - static_cast<void*>(this), - NULL); - if (requestHeader[0]) { - free(requestHeader[0]); - requestHeader[0] = NULL; - } - } - if (da_ret != DA_RESULT_OK) { - m_state = DL_ITEM::FAILED; - m_errorCode = ERROR::ENGINE_FAIL; - notify(); - } -} - -DL_ITEM::STATE DownloadItem::_convert_da_state_to_download_state(int da_state) -{ - switch (da_state) { - case DA_STATE_DOWNLOAD_STARTED: - return DL_ITEM::STARTED; -// case DA_STATE_DOWNLOADING: -// return DL_ITEM::UPDATING; - case DA_STATE_DOWNLOAD_COMPLETE: - return DL_ITEM::COMPLETE_DOWNLOAD; - case DA_STATE_WAITING_USER_CONFIRM: - return DL_ITEM::WAITING_CONFIRM; - case DA_STATE_START_INSTALL_NOTIFY: - return DL_ITEM::INSTALL_NOTIFY; - case DA_STATE_DRM_JOIN_LEAVE_DOMAIN_START: - return DL_ITEM::START_DRM_DOMAIN; - case DA_STATE_DRM_JOIN_LEAVE_DOMAIN_FINISH: - return DL_ITEM::FINISH_DRM_DOMAIN; - case DA_STATE_WAITING_RO: - return DL_ITEM::WAITING_RO; - case DA_STATE_SUSPENDED: - return DL_ITEM::SUSPENDED; - case DA_STATE_RESUMED: - return DL_ITEM::RESUMED; - case DA_STATE_CANCELED: - return DL_ITEM::CANCELED; - case DA_STATE_FINISHED: - return DL_ITEM::FINISHED; - case DA_STATE_FAILED: - return DL_ITEM::FAILED; - case DA_STATE_DOWNLOADING: - case DA_STATE_DONE_INSTALL_NOTIFY: - case DA_STATE_DRM_ROAP_START: - case DA_STATE_DRM_ROAP_FINISH: - default: - return DL_ITEM::IGNORE; - } -} - -ERROR::CODE DownloadItem::_convert_da_error(int da_err) -{ - DP_LOGD("download agent error[%d]", da_err); - - switch (da_err) { - case DA_ERR_NETWORK_FAIL: - case DA_ERR_HTTP_TIMEOUT: - case DA_ERR_UNREACHABLE_SERVER : - return ERROR::NETWORK_FAIL; - - case DA_ERR_INVALID_URL: - return ERROR::INVALID_URL; - - case DA_ERR_DISK_FULL: - return ERROR::NOT_ENOUGH_MEMORY; - - case DA_ERR_FAIL_TO_INSTALL_FILE: - case DA_ERR_DLOPEN_FAIL: - return ERROR::FAIL_TO_INSTALL; - - case DA_ERR_USER_RESPONSE_WAITING_TIME_OUT: - return ERROR::OMA_POPUP_TIME_OUT; - - case DA_ERR_PARSE_FAIL: - return ERROR::FAIL_TO_PARSE_DESCRIPTOR; - - default : - return ERROR::UNKNOWN; - } - -} - -void DownloadItem::cancel() -{ - DP_LOGD("DownloadItem::cancel"); - if (m_state == DL_ITEM::CANCELED) { - DP_LOGD("It is already canceled"); - notify(); - return; - } - int da_ret = da_cancel_download(m_da_req_id); - if (da_ret != DA_RESULT_OK) { - DP_LOGE("Fail to cancel download : reqId[%d] reason[%d]", - m_da_req_id, da_ret); - m_state = DL_ITEM::FAILED; - m_errorCode = ERROR::ENGINE_FAIL; - notify(); - } - return; -} - -void DownloadItem::retry() -{ - DP_LOGD_FUNC(); - m_da_req_id = DA_INVALID_ID; - m_state = DL_ITEM::IGNORE; - m_errorCode = ERROR::NONE; - m_receivedFileSize = 0; - m_fileSize = 0; - m_downloadType = DL_TYPE::HTTP_DOWNLOAD; - m_isMidletInstalled = false; - start(); -} - -bool DownloadItem::sendUserResponse(bool res) -{ - int da_ret = da_send_back_user_confirm(m_da_req_id, res); - if (da_ret != DA_RESULT_OK) { - DP_LOGE("Fail to send back user confirm : reqId[%d] reason[%d]", - m_da_req_id, da_ret); - m_state = DL_ITEM::FAILED; - m_errorCode = ERROR::ENGINE_FAIL; - notify(); - return false; - } - return true; -} - -void DownloadItem::suspend() -{ - int da_ret = DA_RESULT_OK; - da_ret = da_suspend_download(m_da_req_id); - if (da_ret != DA_RESULT_OK) { - DP_LOGE("Fail to suspend download : reqId[%d] err[%d]", m_da_req_id, da_ret); - m_state = DL_ITEM::FAILED; - m_errorCode = ERROR::ENGINE_FAIL; - notify(); - } -} - -void DownloadItem::resume() -{ - int da_ret = DA_RESULT_OK; - da_ret = da_resume_download(m_da_req_id); - if (da_ret != DA_RESULT_OK) { - DP_LOGE("Fail to resume download : reqId[%d] err[%d]", m_da_req_id, da_ret); - m_state = DL_ITEM::FAILED; - m_errorCode = ERROR::ENGINE_FAIL; - notify(); - } -} diff --git a/src/download-provider-downloadRequest.cpp b/src/download-provider-downloadRequest.cpp deleted file mode 100644 index 4c1608c..0000000 --- a/src/download-provider-downloadRequest.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provier-downloadRequest.cpp - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief download request data class - */ -#include "download-provider-downloadRequest.h" - -/*DownloadRequest::DownloadRequest() - : m_url(NULL) - , m_cookie(NULL) -{ -}*/ - -DownloadRequest::DownloadRequest(string url, string cookie) - : m_url(url) - , m_cookie(cookie) -{ -} - -DownloadRequest::DownloadRequest(DownloadRequest &rRequest) -{ - m_url.assign(rRequest.getUrl()); - m_cookie.assign(rRequest.getCookie()); -} - -DownloadRequest::~DownloadRequest() -{ -// DP_LOG_FUNC(); -} - -string &DownloadRequest::getUrl() -{ - return m_url; -} - -string &DownloadRequest::getCookie() -{ - return m_cookie; -} - -bool DownloadRequest::isUrlEmpty() -{ - return m_url.empty(); -} - -bool DownloadRequest::isCookieEmpty() -{ - return m_cookie.empty(); -} - -void DownloadRequest::setUrl(string url) -{ - m_url.assign(url); -} - -void DownloadRequest::setCookie(string cookie) -{ - m_cookie.assign(cookie); -} diff --git a/src/download-provider-event.cpp b/src/download-provider-event.cpp deleted file mode 100644 index 1484727..0000000 --- a/src/download-provider-event.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-event.cpp - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief download event class for event flow - */ -#include "download-provider-event.h" -#include "download-provider-common.h" - -#include <iostream> - -void Subject::attach(Observer *o) -{ - _observers.push_back(o); -} - -void Subject::detach(Observer *o) -{ - vector<Observer*>::iterator it; - for(it = _observers.begin() ; it < _observers.end() ; it++) { - if (*it == o) { - _observers.erase(it); - break; - } - } -} - -void Subject::notify(void) -{ - vector<Observer*>::iterator it; - Observer *curObserver; - it = _observers.begin(); - while (it < _observers.end()) { - curObserver = *it; - - DP_LOGD("[%s] Call Update",curObserver->name().c_str()); - (*it)->update(this); - - if (curObserver != *it) - continue; - - it++; - } -} - -void Observer::update(Subject *s) -{ - call(); -} - -//Observer::Observer(updateFunction uf, void *data) -/* For debug */ -Observer::Observer(updateFunction uf, void *data, const char *name) - : m_updateFunction(uf) - , m_userData(data) -{ - observerName = name; -} - -void Observer::set(updateFunction uf, void *data) -{ - m_updateFunction = uf; - m_userData = data; -} - -void Observer::clear(void) -{ - m_updateFunction = 0; - m_userData = 0; -} - -void Observer::call(void) -{ - if (m_updateFunction) - m_updateFunction(m_userData); -} diff --git a/src/download-provider-history-db.cpp b/src/download-provider-history-db.cpp deleted file mode 100644 index 7772ac8..0000000 --- a/src/download-provider-history-db.cpp +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-history-db.cpp - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief Manager for a download history DB - */ - -#include <sstream> -#include "download-provider-common.h" -#include "download-provider-history-db.h" - -#define FINALIZE_ON_ERROR( stmt ) { \ - DP_LOG("SQL error: %d", ret);\ - if (sqlite3_finalize(stmt) != SQLITE_OK)\ - DP_LOGE("sqlite3_finalize is failed.");\ - close();\ - return false; \ -} - -sqlite3 *DownloadHistoryDB::historyDb = NULL; - -DownloadHistoryDB::DownloadHistoryDB() -{ -} - -DownloadHistoryDB::~DownloadHistoryDB() -{ -} - -bool DownloadHistoryDB::open() -{ - int ret = 0; - - DP_LOGD_FUNC(); - - close(); - - ret = db_util_open(DBDATADIR"/"HISTORYDB, &historyDb, - DB_UTIL_REGISTER_HOOK_METHOD); - - if (ret != SQLITE_OK) { - DP_LOGE("open fail"); - db_util_close(historyDb); - historyDb = NULL; - return false; - } - - return isOpen(); -} - -void DownloadHistoryDB::close() -{ - DP_LOGD_FUNC(); - if (historyDb) { - db_util_close(historyDb); - historyDb = NULL; - } -} - -/* FIXME : Hitory entry limitation ?? */ -bool DownloadHistoryDB::addToHistoryDB(Item *item) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - const char *name = NULL; - - DP_LOG_FUNC(); - - if (!item) { - DP_LOGE("Item is NULL"); - return false; - } - - if (item->historyId() < 0) { - DP_LOGE("Cannot add to DB. Because historyId is invaild"); - return false; - } - - if (!open()) { - DP_LOGE("historyDB is NULL"); - return false; - } - - const string statement = "insert into history (historyid, downloadtype,\ - contenttype, state, err, name, vendor, path, url, cookie, date) \ - values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - - ret = sqlite3_prepare_v2(historyDb, statement.c_str(), -1, &stmt, NULL); - - if (ret != SQLITE_OK) - FINALIZE_ON_ERROR(stmt); - /* binding values */ - if (sqlite3_bind_int(stmt, 1, item->historyId()) != SQLITE_OK) - DP_LOGE("sqlite3_bind_int is failed."); - if (sqlite3_bind_int(stmt, 2, item->downloadType()) != SQLITE_OK) - DP_LOGE("sqlite3_bind_int is failed."); - if (sqlite3_bind_int(stmt, 3, item->contentType()) != SQLITE_OK) - DP_LOGE("sqlite3_bind_int is failed."); - if (sqlite3_bind_int(stmt, 4, item->state()) != SQLITE_OK) - DP_LOGE("sqlite3_bind_int is failed."); - if (sqlite3_bind_int(stmt, 5, item->errorCode()) != SQLITE_OK) - DP_LOGE("sqlite3_bind_int is failed."); - if (item->downloadType() == DL_TYPE::MIDP_DOWNLOAD) - name = item->contentName().c_str(); - else - name = item->title().c_str(); - if (sqlite3_bind_text(stmt, 6, name, -1, NULL) != SQLITE_OK) - DP_LOGE("sqlite3_bind_text is failed."); - if (sqlite3_bind_text(stmt, 7, item->vendorName().c_str(), -1, NULL) != - SQLITE_OK) - DP_LOGE("sqlite3_bind_int is failed."); - if (sqlite3_bind_text( - stmt, 8, item->registeredFilePath().c_str(), -1, NULL) != SQLITE_OK) - DP_LOGE("sqlite3_bind_text is failed."); - if (sqlite3_bind_text(stmt, 9, item->url().c_str(), -1, NULL) != SQLITE_OK) - DP_LOGE("sqlite3_bind_text is failed."); - if (sqlite3_bind_text(stmt, 10, item->cookie().c_str(), -1, NULL) != SQLITE_OK) - DP_LOGE("sqlite3_bind_text is failed."); - if (sqlite3_bind_double(stmt, 11, item->finishedTime()) != SQLITE_OK) - DP_LOGE("sqlite3_bind_double is failed."); - ret = sqlite3_step(stmt); - - DP_LOGD("SQL return: %s", (ret == SQLITE_ROW || ret == SQLITE_OK)?"Success":"Fail"); - - close(); - - return ret == SQLITE_DONE; -} - -bool DownloadHistoryDB::getCountOfHistory(int *count) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - - DP_LOG_FUNC(); - - if (!open()) { - DP_LOGE("historyDB is NULL"); - return false; - } - ret = sqlite3_prepare_v2(historyDb, "select COUNT(*) from history", -1, &stmt, NULL); - if (ret != SQLITE_OK) - FINALIZE_ON_ERROR(stmt); - - ret = sqlite3_step(stmt); - DP_LOGD("SQL return: %s", (ret == SQLITE_ROW || ret == SQLITE_OK)?"Success":"Fail"); - if (ret == SQLITE_ROW) { - *count = sqlite3_column_int(stmt,0); - DP_LOGD("count[%d]",*count); - } else { - DP_LOGE("SQL query error"); - *count = 0; - } - - if (sqlite3_finalize(stmt) != SQLITE_OK) - DP_LOGE("sqlite3_finalize is failed."); - close(); - return true; -} - -bool DownloadHistoryDB::createRemainedItemsFromHistoryDB(int limit, int offset) -{ - int ret = 0; - stringstream limitStr; - stringstream offsetStr; - sqlite3_stmt *stmt = NULL; - string tmp; - - DP_LOG_FUNC(); - - if (!open()) { - DP_LOGE("historyDB is NULL"); - return false; - } - limitStr << limit; - offsetStr << offset; - - tmp.append("select historyid, downloadtype, contenttype, state, err, "); - tmp.append("name, vendor, path, url, cookie, date from history order by "); - tmp.append("date DESC limit "); - tmp.append(limitStr.str()); - tmp.append(" offset "); - tmp.append(offsetStr.str()); - ret = sqlite3_prepare_v2(historyDb, tmp.c_str(), -1, &stmt, NULL); - if (ret != SQLITE_OK) - FINALIZE_ON_ERROR(stmt); - - for (;;) { - ret = sqlite3_step(stmt); - if (ret == SQLITE_ROW) { - const char *tempStr = NULL; - string arg; - string url; - string cookie; - Item *item = Item::createHistoryItem(); - if (!item) { - DP_LOGE("Fail to create item"); - break; - } - item->setHistoryId(sqlite3_column_int(stmt,0)); - item->setDownloadType((DL_TYPE::TYPE)sqlite3_column_int(stmt,1)); - item->setContentType(sqlite3_column_int(stmt,2)); - item->setState((ITEM::STATE)sqlite3_column_int(stmt,3)); - item->setErrorCode((ERROR::CODE)sqlite3_column_int(stmt,4)); - tempStr = (const char *)(sqlite3_column_text(stmt,5)); - if (tempStr) { - arg = tempStr; - if (item->downloadType() == DL_TYPE::MIDP_DOWNLOAD) - item->setContentName(arg); - item->setTitle(arg); - } - tempStr = (const char *)(sqlite3_column_text(stmt,6)); - if (tempStr) - arg = tempStr; - else - arg = string(); - item->setVendorName(arg); - tempStr = (const char *)(sqlite3_column_text(stmt,7)); - if (tempStr) - arg = tempStr; - else - arg = string(); - item->setRegisteredFilePath(arg); - tempStr = (const char *)(sqlite3_column_text(stmt,8)); - if (tempStr) - url = tempStr; - else - url = string(); - tempStr = (const char *)(sqlite3_column_text(stmt,9)); - if (tempStr) - cookie = tempStr; - else - cookie = string(); - item->setFinishedTime(sqlite3_column_double(stmt,10)); - item->attachHistoryItem(); - item->setRetryData(url, cookie); - } else - break; - } - DP_LOGD("SQL error: %d", ret); - - if (sqlite3_finalize(stmt) != SQLITE_OK) - DP_LOGE("sqlite3_finalize is failed."); - - close(); - - if (ret == SQLITE_DONE || ret == SQLITE_ROW) - return true; - else - return false; -} - -bool DownloadHistoryDB::createItemsFromHistoryDB() -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - string tmp; - stringstream limitStr; - - DP_LOG_FUNC(); - - if (!open()) { - DP_LOGE("historyDB is NULL"); - return false; - } - limitStr << LOAD_HISTORY_COUNT; - tmp.append("select historyid, downloadtype, contenttype, state, err, "); - tmp.append("name, vendor, path, url, cookie, date from history order by "); - tmp.append("date DESC limit "); - tmp.append(limitStr.str()); - ret = sqlite3_prepare_v2(historyDb, tmp.c_str(), -1, &stmt, NULL); - if (ret != SQLITE_OK) - FINALIZE_ON_ERROR(stmt); - - for (;;) { - ret = sqlite3_step(stmt); - if (ret == SQLITE_ROW) { - const char *tempStr = NULL; - string arg = string(); - string url = string(); - string cookie = string(); - Item *item = Item::createHistoryItem(); - if (!item) { - DP_LOGE("Fail to create item"); - break; - } - item->setHistoryId(sqlite3_column_int(stmt,0)); - item->setDownloadType((DL_TYPE::TYPE)sqlite3_column_int(stmt,1)); - item->setContentType(sqlite3_column_int(stmt,2)); - item->setState((ITEM::STATE)sqlite3_column_int(stmt,3)); - item->setErrorCode((ERROR::CODE)sqlite3_column_int(stmt,4)); - tempStr = (const char *)(sqlite3_column_text(stmt,5)); - if (tempStr) { - arg = tempStr; - if (item->downloadType() == DL_TYPE::MIDP_DOWNLOAD) - item->setContentName(arg); - item->setTitle(arg); - } - tempStr = (const char *)(sqlite3_column_text(stmt,6)); - if (tempStr) - arg = tempStr; - item->setVendorName(arg); - tempStr = (const char *)(sqlite3_column_text(stmt,7)); - if (tempStr) - arg = tempStr; - item->setRegisteredFilePath(arg); - tempStr = (const char *)(sqlite3_column_text(stmt,8)); - if (tempStr) - url = tempStr; - tempStr = (const char *)(sqlite3_column_text(stmt,9)); - if (tempStr) - cookie = tempStr; - item->setFinishedTime(sqlite3_column_double(stmt,10)); - item->attachHistoryItem(); - item->setRetryData(url, cookie); - } else - break; - } - DP_LOGD("SQL error: %d", ret); - - if (sqlite3_finalize(stmt) != SQLITE_OK) - DP_LOGE("sqlite3_finalize is failed."); - close(); - - if (ret == SQLITE_DONE || ret == SQLITE_ROW) - return true; - else - return false; -} - -bool DownloadHistoryDB::deleteItem(unsigned int historyId) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - - DP_LOG_FUNC(); - - if (!open()) { - DP_LOGE("historyDB is NULL"); - return false; - } - - ret = sqlite3_prepare_v2(historyDb, "delete from history where historyid=?", - -1, &stmt, NULL); - - if (ret != SQLITE_OK) - FINALIZE_ON_ERROR(stmt); - if (sqlite3_bind_int(stmt, 1, historyId) != SQLITE_OK) - DP_LOGE("sqlite3_bind_int is failed."); - ret = sqlite3_step(stmt); - if (ret != SQLITE_OK && ret != SQLITE_DONE) - FINALIZE_ON_ERROR(stmt); - - if (sqlite3_finalize(stmt) != SQLITE_OK) - DP_LOGE("sqlite3_finalize is failed."); - close(); - return true; -} - -bool DownloadHistoryDB::deleteMultipleItem(queue <unsigned int> &q) -{ - int ret = 0; - unsigned int historyId = -1; - sqlite3_stmt *stmt = NULL; - char *errmsg = NULL; - - DP_LOG_FUNC(); - - if (!open()) { - DP_LOGE("historyDB is NULL"); - return false; - } - ret = sqlite3_exec(historyDb, "PRAGMA synchronous=OFF;\ - PRAGMA count_changes=OFF; PRAGMA temp_store=memory;", - NULL, NULL, &errmsg); - if (SQLITE_OK != ret) { - sqlite3_free(errmsg); - close(); - return false; - } - - DP_LOGD("queue size[%d]",q.size()); - while (!q.empty()) { - ret = sqlite3_prepare_v2(historyDb, "delete from history where historyid=?", - -1, &stmt, NULL); - if (ret != SQLITE_OK) - FINALIZE_ON_ERROR(stmt); - historyId = q.front(); - q.pop(); - if (sqlite3_bind_int(stmt, 1, historyId) != SQLITE_OK) - DP_LOGE("sqlite3_bind_int is failed."); - ret = sqlite3_step(stmt); - if (ret != SQLITE_OK && ret != SQLITE_DONE) - FINALIZE_ON_ERROR(stmt); - } - - if (sqlite3_finalize(stmt) != SQLITE_OK) - DP_LOGE("sqlite3_finalize is failed."); - close(); - return true; -} - -bool DownloadHistoryDB::clearData(void) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - - DP_LOG_FUNC(); - - if (!open()) { - DP_LOGE("historyDB is NULL"); - return false; - } - - ret = sqlite3_prepare_v2(historyDb, "delete from history", -1, &stmt, NULL); - if (ret != SQLITE_OK) - FINALIZE_ON_ERROR(stmt); - - ret = sqlite3_step(stmt); - if (ret != SQLITE_DONE) - FINALIZE_ON_ERROR(stmt); - - if (sqlite3_finalize(stmt) != SQLITE_OK) - DP_LOGE("sqlite3_finalize is failed."); - close(); - return true; -} - diff --git a/src/download-provider-ipc.c b/src/download-provider-ipc.c new file mode 100644 index 0000000..66e94ad --- /dev/null +++ b/src/download-provider-ipc.c @@ -0,0 +1,269 @@ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <errno.h> + +#include "download-provider-ipc.h" +#include "download-provider-log.h" + +int ipc_receive_header(int fd) +{ + if (fd <= 0) + return -1; + + download_controls msgheader = 0; + if (read(fd, &msgheader, sizeof(download_controls)) < 0) { + TRACE_DEBUG_MSG("failed to read message header (%s)", + strerror(errno)); + return -1; + } + return msgheader; +} + +int ipc_send_stateinfo(download_clientinfo *clientinfo) +{ + if (!clientinfo || clientinfo->clientfd <= 0) + return -1; + + download_state_info stateinfo; + download_controls type = DOWNLOAD_CONTROL_GET_STATE_INFO; + memset(&stateinfo, 0x00, sizeof(download_state_info)); + stateinfo.state = clientinfo->state; + stateinfo.err = clientinfo->err; + + // send control + if (send(clientinfo->clientfd, &type, sizeof(download_controls), 0) < 0) { + TRACE_DEBUG_MSG("failed to send message header (%s)", + strerror(errno)); + return -1; + } + if (send(clientinfo->clientfd, &stateinfo, sizeof(download_state_info), 0) < 0) { + TRACE_DEBUG_MSG("failed to send message header (%s)", + strerror(errno)); + return -1; + } + return type; +} + +int ipc_send_request_stateinfo(download_clientinfo *clientinfo) +{ + if (!clientinfo || clientinfo->clientfd <= 0) + return -1; + + download_request_state_info requeststateinfo; + download_controls type = DOWNLOAD_CONTROL_GET_REQUEST_STATE_INFO; + memset(&requeststateinfo, 0x00, sizeof(download_request_state_info)); + requeststateinfo.stateinfo.state = clientinfo->state; + requeststateinfo.stateinfo.err = clientinfo->err; + if (clientinfo->requestinfo) + requeststateinfo.requestid = clientinfo->requestinfo->requestid; + + // send control + if (send(clientinfo->clientfd, &type, sizeof(download_controls), 0) < 0) { + TRACE_DEBUG_MSG("failed to send message header (%s)", + strerror(errno)); + return -1; + } + if (send + (clientinfo->clientfd, &requeststateinfo, sizeof(download_request_state_info), + 0) < 0) { + TRACE_DEBUG_MSG("failed to send message header (%s)", + strerror(errno)); + return -1; + } + return type; +} + +int ipc_send_downloadinfo(download_clientinfo *clientinfo) +{ + if (!clientinfo || clientinfo->clientfd <= 0 + || !clientinfo->downloadinfo) + return -1; + + download_controls type = DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO; + // send control + if (send(clientinfo->clientfd, &type, sizeof(download_controls), 0) < 0) { + TRACE_DEBUG_MSG("failed to send message header (%s)", + strerror(errno)); + return -1; + } + if (send + (clientinfo->clientfd, clientinfo->downloadinfo, + sizeof(download_content_info), 0) < 0) { + TRACE_DEBUG_MSG("failed to send message header (%s)", + strerror(errno)); + return -1; + } + return type; +} + +int ipc_send_downloadinginfo(download_clientinfo *clientinfo) +{ + if (!clientinfo || clientinfo->clientfd <= 0 + || !clientinfo->downloadinginfo) + return -1; + + download_controls type = DOWNLOAD_CONTROL_GET_DOWNLOADING_INFO; + // send control + if (send(clientinfo->clientfd, &type, sizeof(download_controls), 0) < 0) { + TRACE_DEBUG_MSG("failed to send message header (%s)", + strerror(errno)); + return -1; + } + if (send + (clientinfo->clientfd, clientinfo->downloadinginfo, + sizeof(downloading_state_info), 0) < 0) { + TRACE_DEBUG_MSG("failed to send message header (%s)", + strerror(errno)); + return -1; + } + return type; +} + +int ipc_receive_request_msg(download_clientinfo *clientinfo) +{ + if (!clientinfo || clientinfo->clientfd <= 0) + return -1; + + if (!clientinfo->requestinfo) + clientinfo->requestinfo = + (download_request_info *) calloc(1, sizeof(download_request_info)); + + if (!clientinfo->requestinfo) + return -1; + + // read reqeust structure + if (read + (clientinfo->clientfd, clientinfo->requestinfo, + sizeof(download_request_info)) < 0) { + TRACE_DEBUG_MSG("failed to read message header"); + return -1; + } + if (clientinfo->requestinfo->client_packagename.length > 0) { + clientinfo->requestinfo->client_packagename.str = + (char *) + calloc((clientinfo->requestinfo->client_packagename.length + + 1), sizeof(char)); + if (read + (clientinfo->clientfd, + clientinfo->requestinfo->client_packagename.str, + clientinfo->requestinfo->client_packagename.length * + sizeof(char)) < 0) { + TRACE_DEBUG_MSG + ("failed to read message header client_app_id(%s)", + strerror(errno)); + return -1; + } + clientinfo->requestinfo->client_packagename.str[clientinfo-> + requestinfo-> + client_packagename. + length] = '\0'; + TRACE_DEBUG_MSG("request client_packagename [%s]", + clientinfo->requestinfo->client_packagename. + str); + } + if (clientinfo->requestinfo->url.length > 0) { + clientinfo->requestinfo->url.str = + (char *)calloc((clientinfo->requestinfo->url.length + 1), + sizeof(char)); + if (read + (clientinfo->clientfd, clientinfo->requestinfo->url.str, + clientinfo->requestinfo->url.length * sizeof(char)) < 0) { + TRACE_DEBUG_MSG("failed to read message header url(%s)", + strerror(errno)); + return -1; + } + clientinfo->requestinfo->url.str[clientinfo->requestinfo->url. + length] = '\0'; + TRACE_DEBUG_MSG("request url [%s]", + clientinfo->requestinfo->url.str); + } + if (clientinfo->requestinfo->install_path.length > 0) { + clientinfo->requestinfo->install_path.str = + (char *) + calloc((clientinfo->requestinfo->install_path.length + 1), + sizeof(char)); + if (read + (clientinfo->clientfd, + clientinfo->requestinfo->install_path.str, + clientinfo->requestinfo->install_path.length * + sizeof(char)) < 0) { + TRACE_DEBUG_MSG + ("failed to read message header install_path(%s)", + strerror(errno)); + return -1; + } + clientinfo->requestinfo->install_path.str[clientinfo-> + requestinfo-> + install_path.length] = + '\0'; + TRACE_DEBUG_MSG("request install_path [%s]", + clientinfo->requestinfo->install_path.str); + } + if (clientinfo->requestinfo->filename.length > 0) { + clientinfo->requestinfo->filename.str = + (char *) + calloc((clientinfo->requestinfo->filename.length + 1), + sizeof(char)); + if (read + (clientinfo->clientfd, + clientinfo->requestinfo->filename.str, + clientinfo->requestinfo->filename.length * sizeof(char)) < + 0) { + TRACE_DEBUG_MSG + ("failed to read message header filename(%s)", + strerror(errno)); + return -1; + } + clientinfo->requestinfo->filename.str[clientinfo->requestinfo-> + filename.length] = '\0'; + TRACE_DEBUG_MSG("request filename [%s]", + clientinfo->requestinfo->filename.str); + } + if (clientinfo->requestinfo->headers.rows) { + clientinfo->requestinfo->headers.str = + (download_flexible_string *) calloc(clientinfo->requestinfo->headers. + rows, sizeof(download_flexible_string)); + int i = 0; + for (i = 0; i < clientinfo->requestinfo->headers.rows; i++) { + if (read + (clientinfo->clientfd, + &clientinfo->requestinfo->headers.str[i], + sizeof(download_flexible_string)) < 0) { + TRACE_DEBUG_MSG + ("failed to read message header headers(%s)", + strerror(errno)); + return -1; + } + if (clientinfo->requestinfo->headers.str[i].length > 0) { + TRACE_DEBUG_MSG("headers[%d] length[%d]", i, + clientinfo->requestinfo-> + headers.str[i].length); + clientinfo->requestinfo->headers.str[i].str = + (char *) + calloc((clientinfo->requestinfo->headers. + str[i].length + 1), sizeof(char)); + if (read + (clientinfo->clientfd, + clientinfo->requestinfo->headers.str[i]. + str, + clientinfo->requestinfo->headers.str[i]. + length * sizeof(char)) < 0) { + TRACE_DEBUG_MSG + ("failed to read message header headers(%s)", + strerror(errno)); + return -1; + } + clientinfo->requestinfo->headers.str[i]. + str[clientinfo->requestinfo->headers.str[i]. + length] = '\0'; + TRACE_DEBUG_MSG("headers[%d][%s]", i, + clientinfo->requestinfo-> + headers.str[i].str); + } + } + } + return 0; +} diff --git a/src/download-provider-item.cpp b/src/download-provider-item.cpp deleted file mode 100644 index df3d892..0000000 --- a/src/download-provider-item.cpp +++ /dev/null @@ -1,653 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-item.cpp - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief item class for saving download data - */ -// FIXME later : move to util clas -#include "download-provider-item.h" -#include "download-provider-common.h" -#include "download-provider-items.h" -#include "download-provider-viewItem.h" -#include "download-provider-history-db.h" -#include "download-provider-network.h" -#include <iostream> -#include <time.h> - -Item::Item() - : m_state(ITEM::IDLE) - , m_errorCode(ERROR::NONE) - , m_historyId(-1) - , m_contentType(DP_CONTENT_UNKOWN) - , m_finishedTime(0) - , m_downloadType(DL_TYPE::TYPE_NONE) - , m_gotFirstData(false) -{ -// FIXME Later : init private members -} - -Item::Item(DownloadRequest &rRequest) - : m_state(ITEM::IDLE) - , m_errorCode(ERROR::NONE) - , m_historyId(-1) - , m_contentType(DP_CONTENT_UNKOWN) - , m_finishedTime(0) - , m_downloadType(DL_TYPE::TYPE_NONE) - , m_gotFirstData(false) -{ - m_title = S_("IDS_COM_BODY_NO_NAME"); - m_iconPath = DP_UNKNOWN_ICON_PATH; - m_aptr_request = auto_ptr<DownloadRequest>(new DownloadRequest(rRequest)); // FIXME ??? -} - -Item::~Item() -{ - DP_LOGD_FUNC(); -} - -void Item::create(DownloadRequest &rRequest) -{ -// DP_LOGD_FUNC(); - - Item *newItem = new Item(rRequest); - - Items &items = Items::getInstance(); - items.attachItem(newItem); - - ViewItem::create(newItem); - DP_LOGD("newItem[%p]",newItem); - - newItem->download(); -} - -Item *Item::createHistoryItem() -{ - string url = string(); - string cookie = string(); - DownloadRequest request(url,cookie); - Item *newItem = new Item(request); -// DP_LOGD_FUNC(); - - DP_LOGD("new History Item[%p]",newItem); - - return newItem; -} - -void Item::attachHistoryItem() -{ - Items &items = Items::getInstance(); - - DP_LOGD("attach History Item[%p]",this); - items.attachItem(this); - ViewItem::create(this); - extractIconPath(); -} - -void Item::destroy() -{ -// DP_LOG_FUNC(); - // FIXME prohibit to destroy if downloading - if (!isFinished()) { - DP_LOGE("Cannot delete this item. State[%d]",m_state); - return; - } - DP_LOGD("Item::destroy() notify()"); - - setState(ITEM::DESTROY); - notify(); -// DP_LOG("Item::destroy() notify()... END"); - m_aptr_downloadItem->deSubscribe(m_aptr_downloadObserver.get()); - if (m_aptr_downloadObserver.get()) - m_aptr_downloadObserver->clear(); - else - DP_LOGE("download observer pointer is NULL"); - /* When deleting item after download is failed */ - if (m_aptr_netEventObserver.get()) { - NetMgr &netMgrInstance = NetMgr::getInstance(); - netMgrInstance.deSubscribe(m_aptr_netEventObserver.get()); - } - Items::getInstance().detachItem(this); -} - -void Item::deleteFromDB() -{ - DownloadHistoryDB::deleteItem(m_historyId); -} - -void Item::download() -{ - NetMgr &netMgrInstance = NetMgr::getInstance(); - -// DP_LOGD_FUNC(); - - setState(ITEM::REQUESTING); - - createSubscribeData(); - - netMgrInstance.subscribe(m_aptr_netEventObserver.get()); - - m_aptr_downloadItem->start(); - - DP_LOG("Item::download() notify()"); - notify(); -} - -void Item::createSubscribeData() // autoptr's variable of this class. -{ - m_aptr_downloadObserver = auto_ptr<Observer>( - new Observer(updateCBForDownloadObserver, this, "downloadItemObserver")); - m_aptr_netEventObserver = auto_ptr<Observer>( - new Observer(netEventCBObserver, this, "netMgrObserver")); - m_aptr_downloadItem = auto_ptr<DownloadItem>(new DownloadItem(m_aptr_request)); - if (!m_aptr_downloadItem.get()) { - DP_LOGE("Fail to create download item"); - return; - } - m_aptr_downloadItem->subscribe(m_aptr_downloadObserver.get()); -} - -void Item::startUpdate(void) -{ - if (m_gotFirstData) { - setState(ITEM::DOWNLOADING); - if (!registeredFilePath().empty()) - /* need to parse title again, because installed path can be changed */ - extractTitle(); - return; - } - - DP_LOGD_FUNC(); - - if (!m_aptr_downloadItem.get()) { - DP_LOGE("Fail to get download item"); - return; - } - m_gotFirstData = true; -// setState(ITEM::DOWNLOADING); - setState(ITEM::RECEIVING_DOWNLOAD_INFO); - - extractTitle(); - DownloadUtil &util = DownloadUtil::getInstance(); - m_contentType = util.getContentType( - m_aptr_downloadItem->mimeType().c_str(), filePath().c_str()); - extractIconPath(); -} - -void Item::updateFromDownloadItem(void) -{ -// DP_LOGD_FUNC(); - - switch (m_aptr_downloadItem->state()) { - case DL_ITEM::STARTED: - break; - case DL_ITEM::UPDATING: - startUpdate(); - break; - case DL_ITEM::COMPLETE_DOWNLOAD: - setState(ITEM::REGISTERING_TO_SYSTEM); - /* need to parse title again, because installed path can be changed */ - //extractTitle(); - break; - case DL_ITEM::INSTALL_NOTIFY: - setState(ITEM::NOTIFYING_TO_SERVER); - break; - case DL_ITEM::START_DRM_DOMAIN: - setState(ITEM::PROCESSING_DOMAIN); - break; - case DL_ITEM::FINISH_DRM_DOMAIN: - setState(ITEM::FINISH_PROCESSING_DOMAIN); - break; - case DL_ITEM::WAITING_RO: - setState(ITEM::ACTIVATING); - break; - case DL_ITEM::SUSPENDED: - setState(ITEM::SUSPEND); - m_aptr_downloadItem->resume(); - break; - case DL_ITEM::RESUMED: - //setState(ITEM::RESUMED); - break; - case DL_ITEM::FINISHED: - setState(ITEM::FINISH_DOWNLOAD); - handleFinishedItem(); - break; - case DL_ITEM::CANCELED: - /* Already update for cancel state in case of cancellation from user Response popup */ - if (state() == ITEM::CANCEL) { - DP_LOGD("Already cancelled when closing OMA download popup"); - return; - } else { - setState(ITEM::CANCEL); - handleFinishedItem(); - } - break; - case DL_ITEM::FAILED: - setState(ITEM::FAIL_TO_DOWNLOAD); - setErrorCode(m_aptr_downloadItem->errorCode()); - handleFinishedItem(); - break; - case DL_ITEM::WAITING_CONFIRM: - setState(ITEM::WAITING_USER_RESPONSE); - break; - default: - break; - } - - DP_LOGD("Item[%p]::updateFromDownloadItem() notify() dl_state[%d]state[%d]", this, m_aptr_downloadItem->state(), state()); - notify(); -} -void Item::handleFinishedItem() -{ - createHistoryId(); - m_finishedTime = time(NULL); - DownloadHistoryDB::addToHistoryDB(this); - /* If download is finished, it is not need to get network event */ - if (m_aptr_netEventObserver.get()) { - NetMgr &netMgrInstance = NetMgr::getInstance(); - netMgrInstance.deSubscribe(m_aptr_netEventObserver.get()); - } -} - -const char *Item::getErrorMessage(void) -{ - switch (m_errorCode) { - case ERROR::NETWORK_FAIL: - return S_("IDS_COM_POP_CONNECTION_FAILED"); - - case ERROR::INVALID_URL: - return S_("IDS_COM_POP_INVALID_URL"); - - case ERROR::NOT_ENOUGH_MEMORY: - return S_("IDS_COM_POP_NOT_ENOUGH_MEMORY"); - - case ERROR::FAIL_TO_INSTALL: - return __("IDS_BR_POP_INSTALLATION_FAILED"); - - case ERROR::OMA_POPUP_TIME_OUT: - return S_("IDS_COM_POP_CANCELLED") ; - - case ERROR::FAIL_TO_PARSE_DESCRIPTOR: - return __("IDS_BR_POP_INVALIDDESCRIPTOR") ; - - case ERROR::UNKNOWN: - case ERROR::ENGINE_FAIL: - return S_("IDS_COM_POP_FAILED") ; - default: - return NULL; - } -} - -void Item::extractTitle(void) -{ - if (!m_aptr_downloadItem.get()) { - DP_LOGE("Fail to get download item"); - return; - } - DP_LOGD("title [%s] filePath [%s]", m_title.c_str(), filePath().c_str()); - if ((m_aptr_downloadItem->downloadType() == DL_TYPE::OMA_DOWNLOAD || - m_aptr_downloadItem->downloadType() == DL_TYPE::MIDP_DOWNLOAD) && - !m_aptr_downloadItem->contentName().empty()) { - m_title = m_aptr_downloadItem->contentName(); - } else { - size_t found = 0; - string path; - if (!registeredFilePath().empty()) - path = registeredFilePath(); - else - path = filePath(); - found = path.find_last_of("/"); - if (found != string::npos) - m_title = path.substr(found+1); - } -} - -void Item::extractIconPath() -{ - // FIXME Later : change 2 dimension array?? - switch(m_contentType) { - case DP_CONTENT_IMAGE : - m_iconPath = DP_IMAGE_ICON_PATH; - break; - case DP_CONTENT_VIDEO : - m_iconPath = DP_VIDEO_ICON_PATH; - break; - case DP_CONTENT_MUSIC: - m_iconPath = DP_MUSIC_ICON_PATH; - break; - case DP_CONTENT_PDF: - m_iconPath = DP_PDF_ICON_PATH; - break; - case DP_CONTENT_WORD: - m_iconPath = DP_WORD_ICON_PATH; - break; - case DP_CONTENT_PPT: - m_iconPath = DP_PPT_ICON_PATH; - break; - case DP_CONTENT_EXCEL: - m_iconPath = DP_EXCEL_ICON_PATH; - break; - case DP_CONTENT_HTML: - m_iconPath = DP_HTML_ICON_PATH; - break; - case DP_CONTENT_TEXT: - m_iconPath = DP_TEXT_ICON_PATH; - break; - case DP_CONTENT_RINGTONE: - m_iconPath = DP_RINGTONE_ICON_PATH; - break; - case DP_CONTENT_DRM: - m_iconPath = DP_DRM_ICON_PATH; - break; - case DP_CONTENT_JAVA: - m_iconPath = DP_JAVA_ICON_PATH; - break; - case DP_CONTENT_UNKOWN: - default: - m_iconPath = DP_UNKNOWN_ICON_PATH; - } -} - -void Item::updateCBForDownloadObserver(void *data) -{ - DP_LOGD_FUNC(); - if (data) - static_cast<Item*>(data)->updateFromDownloadItem(); -} - -void Item::netEventCBObserver(void *data) -{ - /* It is only considerd that there is one network event which is suspend now. - * If other network evnet is added, - * it is needed to add function accroding to what kinds of network event is - **/ - DP_LOG_FUNC(); - if (data) - static_cast<Item*>(data)->suspend(); -} - -void Item::sendUserResponse(bool res) -{ - bool ret = false; - DP_LOG_FUNC(); - if (!m_aptr_downloadItem.get()) { - DP_LOGE("Fail to get download item"); - return; - } - ret = m_aptr_downloadItem->sendUserResponse(res); - if (ret) { - /* Update UI at once if the user cancel the oma download - * But this is really needed?? - */ - if (!res) { - setState(ITEM::CANCEL); - handleFinishedItem(); - notify(); - } else { - setState(ITEM::RECEIVING_DOWNLOAD_INFO); - } - } -} - -bool Item::play() -{ - if (m_contentType == DP_CONTENT_JAVA && - m_aptr_downloadItem->downloadType() == DL_TYPE::MIDP_DOWNLOAD) { - string pkgName; - DownloadUtil &util = DownloadUtil::getInstance(); - pkgName = util.getMidletPkgName(m_contentName, m_vendorName); - return m_fileOpener.openApp(pkgName); - } else { - return m_fileOpener.openFile(registeredFilePath(), m_contentType); - } -} - -/* Test code */ -const char *Item::stateStr(void) -{ - switch((int)state()) { - case ITEM::IDLE: - return "IDLE"; - case ITEM::REQUESTING: - return "REQUESTING"; - case ITEM::PREPARE_TO_RETRY: - return "PREPARE_TO_RETRY"; - case ITEM::WAITING_USER_RESPONSE: - return "WAITING_USER_RESPONSE"; - case ITEM::RECEIVING_DOWNLOAD_INFO: - return "RECEIVING_DOWNLOAD_INFO"; - case ITEM::DOWNLOADING: - return "DOWNLOADING"; - case ITEM::REGISTERING_TO_SYSTEM: - return "REGISTERING_TO_SYSTEM"; - case ITEM::PROCESSING_DOMAIN: - return "PROCESSING_DOMAIN"; - case ITEM::FINISH_PROCESSING_DOMAIN: - return "FINISH_PROCESSING_DOMAIN"; - case ITEM::ACTIVATING: - return "ACTIVATING"; - case ITEM::NOTIFYING_TO_SERVER: - return "NOTIFYING_TO_SERVER"; - case ITEM::SUSPEND: - return "SUSPEND"; - case ITEM::FINISH_DOWNLOAD: - return "FINISH_DOWNLOAD"; - case ITEM::FAIL_TO_DOWNLOAD: - return "FAIL_TO_DOWNLOAD"; - case ITEM::CANCEL: - return "CANCEL"; - case ITEM::PLAY: - return "PLAY"; - case ITEM::DESTROY: - return "DESTROY"; - } - return "Unknown State"; -} - -DL_TYPE::TYPE Item::downloadType() -{ - if (m_downloadType == DL_TYPE::TYPE_NONE) { - if (!m_aptr_downloadItem.get()) { - DP_LOGE("Fail to get download item"); - return DL_TYPE::TYPE_NONE; - } - m_downloadType = m_aptr_downloadItem->downloadType(); - } - return m_downloadType; -} - -string &Item::contentName() -{ - if (m_contentName.empty()) { - if (!m_aptr_downloadItem.get()) { - DP_LOGE("Fail to get download item"); - return m_emptyString; - } - m_contentName = m_aptr_downloadItem->contentName(); - } - return m_contentName; -} - -string &Item::vendorName() -{ - if (m_vendorName.empty()) { - if (!m_aptr_downloadItem.get()) { - DP_LOGE("Fail to get download item"); - return m_emptyString; - } - m_vendorName = m_aptr_downloadItem->vendorName(); - } - return m_vendorName; -} - -string &Item::registeredFilePath() -{ - if (m_registeredFilePath.empty()) { - if (!m_aptr_downloadItem.get()) { - DP_LOGE("Fail to get download item"); - return m_emptyString; - } - m_registeredFilePath = m_aptr_downloadItem->registeredFilePath(); - } - return m_registeredFilePath; -} - -string &Item::url() -{ - if (m_url.empty()) { - if (!m_aptr_downloadItem.get()) { - DP_LOGE("Fail to get download item"); - return m_emptyString; - } - m_url = m_aptr_downloadItem->url(); - } - return m_url; -} - -string &Item::cookie() -{ - if (m_cookie.empty()) { - if (!m_aptr_downloadItem.get()) { - DP_LOGE("Fail to get download item"); - return m_emptyString; - } - m_cookie = m_aptr_downloadItem->cookie(); - } - return m_cookie; -} - - -void Item::createHistoryId() -{ - int count = 0; - unsigned tempId = time(NULL); - while (isExistedHistoryId(tempId)) { - srand((unsigned)(time(NULL))); - tempId = rand(); - count++; - if (count > 100) { - DP_LOGE("Fail to create unique ID"); - tempId = -1; - break; - } - DP_LOGD("random historyId[%ld]", m_historyId); - } - m_historyId = tempId; -} - -bool Item::isExistedHistoryId(unsigned int id) -{ - Items &items = Items::getInstance(); - return items.isExistedHistoryId(id); -} - -void Item::setRetryData(string &url, string &cookie) -{ - - m_url = url; - m_cookie = cookie; - m_aptr_request->setUrl(url); - m_aptr_request->setCookie(cookie); - - createSubscribeData(); - -} - -bool Item::retry() -{ - DP_LOG_FUNC(); - if (m_aptr_downloadItem.get()) { - NetMgr &netMgrInstance = NetMgr::getInstance(); - setState(ITEM::PREPARE_TO_RETRY); - notify(); - DownloadHistoryDB::deleteItem(m_historyId); - netMgrInstance.subscribe(m_aptr_netEventObserver.get()); - m_historyId = -1; - m_aptr_downloadItem->retry(); - return true; - } else { - m_state = ITEM::FAIL_TO_DOWNLOAD; - return false; - } -} - -void Item::clearForRetry() -{ - m_state = ITEM::IDLE; - m_errorCode = ERROR::NONE; - m_contentType = DP_CONTENT_UNKOWN; - m_finishedTime = 0; - m_downloadType = DL_TYPE::TYPE_NONE; - m_gotFirstData = false; -} - -bool Item::isFinished() -{ - bool ret = false; - switch (m_state) { - case ITEM::FINISH_DOWNLOAD: - case ITEM::FAIL_TO_DOWNLOAD: - case ITEM::CANCEL: - case ITEM::PLAY: - case ITEM::DESTROY: - ret = true; - break; - default: - ret = false; - } - return ret; -} - -bool Item::isFinishedWithErr() -{ - bool ret = false; - switch (m_state) { - case ITEM::FAIL_TO_DOWNLOAD: - case ITEM::CANCEL: - ret = true; - break; - default: - ret = false; - } - return ret; -} - -bool Item::isPreparingDownload() -{ - bool ret = false; - switch (m_state) { - case ITEM::IDLE: - case ITEM::REQUESTING: - case ITEM::PREPARE_TO_RETRY: - case ITEM::WAITING_USER_RESPONSE: - ret = true; - break; - default: - ret = false; - } - return ret; - -} - -bool Item::isCompletedDownload() -{ - if (isPreparingDownload() || m_state == ITEM::DOWNLOADING) - return false; - else - return true; -} - diff --git a/src/download-provider-items.cpp b/src/download-provider-items.cpp deleted file mode 100644 index 7fe1141..0000000 --- a/src/download-provider-items.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-items.cpp - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief Interface API with item list - */ -#include "download-provider-items.h" - -void Items::attachItem(Item *item) -{ - m_items.push_back(item); -} - -void Items::detachItem(Item *item) -{ - vector<Item *>::iterator it; - for (it = m_items.begin() ; it < m_items.end() ; it++) { - if (*it == item) { - m_items.erase(it); - delete item; - } - } -} - -bool Items::isExistedHistoryId(unsigned int id) -{ - vector <Item *>::iterator it; - for (it = m_items.begin(); it < m_items.end(); it++) { - if ((*it)->historyId() == id ) { - DP_LOGD("historyId[%ld],title[%s]", - (*it)->historyId(), (*it)->title().c_str()); - return true; - } - } - return false; -} - diff --git a/src/download-provider-main.c b/src/download-provider-main.c new file mode 100644 index 0000000..907a22e --- /dev/null +++ b/src/download-provider-main.c @@ -0,0 +1,98 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <glib.h> +#include <glib-object.h> +#include <pthread.h> + +#include "download-provider-config.h" +#include "download-provider-log.h" + +GMainLoop *gMainLoop = 0; // need for libsoup, decided the life-time by mainloop. +pthread_t gRequestThreadPid; + +int lock_download_provider_pid(char *path); +void *run_manage_download_server(void *args); + +void TerminateDaemon(int signo) +{ + TRACE_DEBUG_MSG("Received SIGTERM"); + if (g_main_loop_is_running(gMainLoop)) + g_main_loop_quit(gMainLoop); +} + +static gboolean CreateThreadFunc(void *data) +{ + pthread_attr_t thread_attr; + if (pthread_attr_init(&thread_attr) != 0) { + TRACE_DEBUG_MSG("failed to init pthread attr"); + if (g_main_loop_is_running(gMainLoop)) + g_main_loop_quit(gMainLoop); + return FALSE; + } + // create thread for receiving the client request. + if (pthread_create + (&gRequestThreadPid, &thread_attr, run_manage_download_server, + data) != 0) { + TRACE_DEBUG_MSG + ("failed to create pthread for run_manage_download_server"); + if (g_main_loop_is_running(gMainLoop)) + g_main_loop_quit(gMainLoop); + } + return FALSE; +} + +int main() +{ + if (chdir("/") < 0) { + TRACE_DEBUG_MSG("failed to call setsid or chdir"); + exit(EXIT_FAILURE); + } +#if 0 + // close all console I/O + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); +#endif + + if (signal(SIGTERM, TerminateDaemon) == SIG_ERR) { + TRACE_DEBUG_MSG("failed to register signal callback"); + exit(EXIT_FAILURE); + } + // write IPC_FD_PATH. and lock + if (lock_download_provider_pid(DOWNLOAD_PROVIDER_LOCK_PID) < 0) { + TRACE_DEBUG_MSG + ("It need to check download-provider is already alive"); + TRACE_DEBUG_MSG("Or fail to create pid file in (%s)", + DOWNLOAD_PROVIDER_LOCK_PID); + exit(EXIT_FAILURE); + } + // if exit socket file, delete it + if (access(DOWNLOAD_PROVIDER_IPC, F_OK) == 0) { + unlink(DOWNLOAD_PROVIDER_IPC); + } + // libsoup need mainloop. + + gMainLoop = g_main_loop_new(NULL, 0); + + g_type_init(); + + g_idle_add(CreateThreadFunc, gMainLoop); + + g_main_loop_run(gMainLoop); + + TRACE_DEBUG_MSG("Download-Provider will be terminated."); + + pthread_cancel(gRequestThreadPid); + pthread_join(gRequestThreadPid, NULL); + + // if exit socket file, delete it + if (access(DOWNLOAD_PROVIDER_IPC, F_OK) == 0) { + unlink(DOWNLOAD_PROVIDER_IPC); + } + // delete pid file + if (access(DOWNLOAD_PROVIDER_LOCK_PID, F_OK) == 0) { + unlink(DOWNLOAD_PROVIDER_LOCK_PID); + } + exit(EXIT_SUCCESS); +} diff --git a/src/download-provider-network.cpp b/src/download-provider-network.cpp deleted file mode 100644 index 6c6fa90..0000000 --- a/src/download-provider-network.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-network.cpp - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief Download netowkr manager - */ - -#include <stdlib.h> -#include "download-provider-common.h" -#include "download-provider-network.h" - -enum { - NET_INACTIVE = 0, - NET_WIFI_ACTIVE, - NET_CELLULAR_ACTIVE -}; - -NetMgr::NetMgr() -{ - m_netStatus = getConnectionState(); - if (m_netStatus == NET_WIFI_ACTIVE || - m_netStatus == NET_CELLULAR_ACTIVE) { - getProxy(); - getIPAddress(); - } -} - -NetMgr::~NetMgr() -{ -} - -void NetMgr::initNetwork() -{ - if (vconf_notify_key_changed(VCONFKEY_NETWORK_STATUS, - netStatusChangedCB, NULL) < 0) - DP_LOGE("Fail to register network status callback"); - if (vconf_notify_key_changed(VCONFKEY_NETWORK_CONFIGURATION_CHANGE_IND, - netConfigChangedCB, NULL) < 0) - DP_LOGE("Fail to register network config change callback"); -} - -void NetMgr::deinitNetwork() -{ - if (vconf_ignore_key_changed(VCONFKEY_NETWORK_STATUS, - netStatusChangedCB) < 0) - DP_LOGE("Fail to ignore network status callback"); - if (vconf_ignore_key_changed(VCONFKEY_NETWORK_CONFIGURATION_CHANGE_IND, - netConfigChangedCB) < 0) - DP_LOGE("Fail to ignore network config change callback"); -} - -int NetMgr::getConnectionState() -{ - int status = VCONFKEY_NETWORK_OFF; - int ret = 0; - - ret = vconf_get_int(VCONFKEY_NETWORK_STATUS, &status); - if (ret < 0) { - DP_LOGE(" Fail to get network status : err[%d]",ret); - return NET_INACTIVE; - } - switch (status) { - case VCONFKEY_NETWORK_OFF: - DP_LOG("VCONFKEY_NETWORK_OFF"); - ret = NET_INACTIVE; - break; - case VCONFKEY_NETWORK_CELLULAR: - DP_LOG("VCONFKEY_NETWORK_CELLULAR"); - ret = getCellularStatus(); - break; - case VCONFKEY_NETWORK_WIFI: - DP_LOG("VCONFKEY_NETWORK_WIFI"); - ret = getWifiStatus(); - break; - default: - DP_LOGE("Cannot enter here"); - ret = NET_INACTIVE; - } - return ret; -} - -int NetMgr::getCellularStatus() -{ - int status = VCONFKEY_NETWORK_CELLULAR_NO_SERVICE; - int ret = 0; - - ret = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_STATE, &status); - - if (ret < 0) { - DP_LOGE(" Fail to get cellular status : err[%d]",ret); - return NET_INACTIVE; - } - - switch(status) { - case VCONFKEY_NETWORK_CELLULAR_ON: - DP_LOG("VCONFKEY_NETWORK_CELLULAR_ON"); - ret = NET_CELLULAR_ACTIVE; - break; - case VCONFKEY_NETWORK_CELLULAR_3G_OPTION_OFF: - DP_LOG("VCONFKEY_NETWORK_CELLULAR_3G_OPTION_OFF"); - ret = NET_INACTIVE; - break; - case VCONFKEY_NETWORK_CELLULAR_ROAMING_OFF: - DP_LOG("VCONFKEY_NETWORK_CELLULAR_ROAMING_OFF"); - ret = NET_INACTIVE; - break; - case VCONFKEY_NETWORK_CELLULAR_FLIGHT_MODE: - DP_LOG("VCONFKEY_NETWORK_CELLULAR_FLIGHT_MODE"); - ret = NET_INACTIVE; - break; - case VCONFKEY_NETWORK_CELLULAR_NO_SERVICE: - DP_LOG("VCONFKEY_NETWORK_CELLULAR_NO_SERVICE"); - ret = NET_INACTIVE; - break; - default: - DP_LOGE("Cannot enter here"); - ret = NET_INACTIVE; - } - return ret; - -} - -int NetMgr::getWifiStatus() -{ - int status = VCONFKEY_NETWORK_WIFI_OFF; - int ret = 0; - - ret = vconf_get_int(VCONFKEY_NETWORK_WIFI_STATE, &status); - - if (ret < 0) { - DP_LOGE(" Fail to get wifi status : err[%d]",ret); - return NET_INACTIVE; - } - - switch(status) { - case VCONFKEY_NETWORK_WIFI_CONNECTED: - DP_LOG("VCONFKEY_NETWORK_WIFI_CONNECTED"); - ret = NET_WIFI_ACTIVE; - break; - case VCONFKEY_NETWORK_WIFI_NOT_CONNECTED: - DP_LOG("VCONFKEY_NETWORK_WIFI_NOT_CONNECTED"); - ret = NET_INACTIVE; - break; - case VCONFKEY_NETWORK_WIFI_OFF: - DP_LOG("VCONFKEY_NETWORK_WIFI_OFF"); - ret = NET_INACTIVE; - break; - default: - DP_LOGE("Cannot enter here"); - ret = NET_INACTIVE; - } - return ret; -} - -void NetMgr::netStatusChanged() -{ - int changedStatus = NET_INACTIVE; - changedStatus = getConnectionState(); - DP_LOG("Previous[%d] Changed[%d]", m_netStatus, changedStatus); - if (m_netStatus != changedStatus) { - if (changedStatus == NET_INACTIVE) - DP_LOG("Netowrk is disconnected"); - else - DP_LOG("Network is connected"); - m_netStatus = changedStatus; - } else { - DP_LOGE("Network status is not changed. Cannot enter here"); - } -} - -void NetMgr::netConfigChanged() -{ - int status = 0; - int ret = 0; - - DP_LOG_FUNC(); - - ret = vconf_get_int(VCONFKEY_NETWORK_CONFIGURATION_CHANGE_IND, &status); - if (ret < 0) { - DP_LOGE("Fail to get network configuration change ind : err[%d]",ret); - return; - } - DP_LOG("netConfigChanged:status[%d]", status); - - - if (status) { /* true */ - getProxy(); - getIPAddress(); - /* This notify is only for suspend event. - * If othere network event is added, it is needed to save event types - * and get function for it - **/ - notify(); - } else { - DP_LOGE("Network connection is disconnected"); - } -} - -void NetMgr::getProxy() -{ - char *proxy = NULL; - proxy = vconf_get_str(VCONFKEY_NETWORK_PROXY); - if (proxy) { - DP_LOG("===== Proxy address[%s] =====", proxy); - free(proxy); - proxy = NULL; - } -} - -void NetMgr::getIPAddress() -{ - char *ipAddr = NULL; - ipAddr = vconf_get_str(VCONFKEY_NETWORK_IP); - if (ipAddr) { - DP_LOG("===== IP address[%s] =====", ipAddr); - free(ipAddr); - ipAddr= NULL; - } -} - -void NetMgr::netStatusChangedCB(keynode_t *keynode, void *data) -{ - NetMgr inst = NetMgr::getInstance(); - inst.netStatusChanged(); -} - -void NetMgr::netConfigChangedCB(keynode_t *keynode, void *data) -{ - NetMgr inst = NetMgr::getInstance(); - inst.netConfigChanged(); -} - diff --git a/src/download-provider-notification.c b/src/download-provider-notification.c new file mode 100644 index 0000000..ba38bb1 --- /dev/null +++ b/src/download-provider-notification.c @@ -0,0 +1,375 @@ +#include <app.h> +#include <app_ui_notification.h> +#include <app_service.h> + +#include <time.h> +#include <sys/time.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "download-provider-notification.h" +#include "download-provider-utils.h" +#include "download-provider-log.h" + +#include <libintl.h> + +#define S_(s) dgettext("sys_string", s) + +#define DP_NOTIFICATION_ICON_PATH IMAGE_DIR"/Q02_Notification_Download_failed.png" + +void print_app_error_message(int ret) +{ + switch (ret) { + case APP_ERROR_NONE: + TRACE_DEBUG_MSG("APP_ERROR_NONE"); + break; + case APP_ERROR_INVALID_PARAMETER: + TRACE_DEBUG_MSG("APP_ERROR_INVALID_PARAMETER"); + break; + case APP_ERROR_OUT_OF_MEMORY: + TRACE_DEBUG_MSG("APP_ERROR_OUT_OF_MEMORY"); + break; + case APP_ERROR_INVALID_CONTEXT: + TRACE_DEBUG_MSG("APP_ERROR_INVALID_CONTEXT"); + break; + case APP_ERROR_NO_SUCH_FILE: + TRACE_DEBUG_MSG("APP_ERROR_NO_SUCH_FILE"); + break; + case APP_ERROR_ALREADY_RUNNING: + TRACE_DEBUG_MSG("APP_ERROR_ALREADY_RUNNING"); + break; + default: + TRACE_DEBUG_MSG("Unknown error"); + break; + } +} + +void print_notification_error_message(int ret) +{ + switch (ret) { + case UI_NOTIFICATION_ERROR_NONE: + TRACE_DEBUG_MSG("UI_NOTIFICATION_ERROR_NONE"); + break; + case UI_NOTIFICATION_ERROR_INVALID_PARAMETER: + TRACE_DEBUG_MSG("UI_NOTIFICATION_ERROR_INVALID_PARAMETER"); + break; + case UI_NOTIFICATION_ERROR_OUT_OF_MEMORY: + TRACE_DEBUG_MSG("UI_NOTIFICATION_ERROR_OUT_OF_MEMORY"); + break; + case UI_NOTIFICATION_ERROR_DB_FAILED: + TRACE_DEBUG_MSG("UI_NOTIFICATION_ERROR_DB_FAILED"); + break; + case UI_NOTIFICATION_ERROR_NO_SUCH_FILE: + TRACE_DEBUG_MSG("UI_NOTIFICATION_ERROR_NO_SUCH_FILE"); + break; + case UI_NOTIFICATION_ERROR_INVALID_STATE: + TRACE_DEBUG_MSG("UI_NOTIFICATION_ERROR_INVALID_STATE"); + break; + default: + TRACE_DEBUG_MSG("Unknown error"); + break; + } +} + +char *__get_string_status(int state) +{ + char *message = NULL; + switch (state) { + case DOWNLOAD_STATE_INSTALLING: + message = S_("IDS_COM_POP_INSTALLING_ING"); + break; + case DOWNLOAD_STATE_FINISHED: + message = strdup("Completed"); + break; + case DOWNLOAD_STATE_STOPPED: + message = S_("IDS_COM_POP_CANCELLED"); + break; + case DOWNLOAD_STATE_FAILED: + message = S_("IDS_COM_POP_FAILED"); + break; + default: + break; + } + return message; +} + +bool download_provider_appfw_notification_cb(ui_notification_h notification, + void *user_data) +{ + if (!user_data) + return false; + download_clientinfo *clientinfo = (download_clientinfo *) user_data; + if (!clientinfo->downloadinfo) + return false; + + bool checkInfo = false; + char *title = NULL; + char *content = NULL; + ui_notification_get_title(notification, &title); + ui_notification_get_content(notification, &content); + + TRACE_DEBUG_MSG("title [%s]", title); + TRACE_DEBUG_MSG("content [%s]", content); + + // relatively unique + if (title && clientinfo->downloadinfo->content_name) { + int title_length = strlen(title); + int content_name_length = + strlen(clientinfo->downloadinfo->content_name); + if (title_length == content_name_length) + if (strncmp + (title, clientinfo->downloadinfo->content_name, + title_length) == 0) + checkInfo = true; + } + // Only when matched title. + if (checkInfo && content) { + char *failed_content = + __get_string_status(DOWNLOAD_STATE_FAILED); + if (failed_content) { + int content_length = strlen(content); + int content_name_length = strlen(failed_content); + if (content_length == content_name_length) + if (strncmp + (content, failed_content, + content_length) == 0) + checkInfo = true; + free(failed_content); + } + if (!checkInfo) { + char *stopped_content = + __get_string_status(DOWNLOAD_STATE_STOPPED); + if (stopped_content) { + int content_length = strlen(content); + int content_name_length = + strlen(stopped_content); + if (content_length == content_name_length) + if (strncmp + (content, stopped_content, + content_length) == 0) + checkInfo = true; + free(stopped_content); + } + } + } + + if (title) + free(title); + if (content) + free(content); + + if (checkInfo) { // compare info with noti info. + TRACE_DEBUG_MSG("ui_notification_cancel"); + ui_notification_cancel(notification); + return false; // do not search noti item anymore. + } + return true; +} + +int destroy_appfw_service(download_clientinfo *clientinfo) +{ + if (!clientinfo) + return -1; + + if (clientinfo->service_handle) { + service_destroy(clientinfo->service_handle); + } + clientinfo->service_handle = NULL; + return 0; +} + +int create_appfw_service(download_clientinfo *clientinfo) +{ + if (!clientinfo) + return -1; + + if (!clientinfo->service_handle) + destroy_appfw_service(clientinfo); + if (service_create(&clientinfo->service_handle) < 0) { + TRACE_DEBUG_MSG("failed service_create (%s)", strerror(errno)); + return false; + } + + if (clientinfo->requestinfo + && clientinfo->requestinfo->client_packagename.str) { + if (service_set_package(clientinfo->service_handle, + clientinfo->requestinfo-> + client_packagename.str) < 0) + TRACE_DEBUG_MSG("failed service_set_package (%s)", + strerror(errno)); + } + return 0; +} + +int destroy_appfw_notification(download_clientinfo *clientinfo) +{ + if (!clientinfo) + return -1; + + destroy_appfw_service(clientinfo); + if (clientinfo->ui_notification_handle) { + bool ongoing = 0; + ui_notification_is_ongoing(clientinfo->ui_notification_handle, + &ongoing); + if (ongoing) { + if (ui_notification_cancel + (clientinfo->ui_notification_handle) < 0) + TRACE_DEBUG_MSG("Fail ui_notification_cancel"); + } + ui_notification_destroy(clientinfo->ui_notification_handle); + } + clientinfo->ui_notification_handle = NULL; + return 0; +} + +int create_appfw_notification(download_clientinfo *clientinfo, bool ongoing) +{ + if (!clientinfo) + return -1; + + int ret = 0; + + if (ui_notification_create(ongoing, &clientinfo->ui_notification_handle) + < 0) { + TRACE_DEBUG_MSG("Fail to create notification handle"); + return -1; + } + + if (clientinfo->downloadinfo) { + if (clientinfo->downloadinfo->content_name) { + if (ui_notification_set_title + (clientinfo->ui_notification_handle, + clientinfo->downloadinfo->content_name) < 0) { + TRACE_DEBUG_MSG + ("failed ui_notification_set_title (%s)", + strerror(errno)); + destroy_appfw_notification(clientinfo); + return -1; + } + } + } + + if (ui_notification_set_icon + (clientinfo->ui_notification_handle, + DP_NOTIFICATION_ICON_PATH) < 0) { + TRACE_DEBUG_MSG("Fail ui_notification_set_icon (%s)", + strerror(errno)); + destroy_appfw_notification(clientinfo); + return -1; + } + + create_appfw_service(clientinfo); + + if (clientinfo->service_handle) { + if (!ongoing) { + // view the special viewer by contents + if (clientinfo->service_handle + && clientinfo->downloadinginfo + && clientinfo->downloadinginfo->saved_path + && clientinfo->state == DOWNLOAD_STATE_FINISHED) { + if (service_set_operation + (clientinfo->service_handle, + SERVICE_OPERATION_VIEW) < 0) { + TRACE_DEBUG_MSG + ("Fail service_set_operation"); + destroy_appfw_service(clientinfo); + } + if (service_set_uri(clientinfo->service_handle, + clientinfo->downloadinginfo->saved_path) + < 0) { + TRACE_DEBUG_MSG("Fail service_set_uri"); + destroy_appfw_service(clientinfo); + } + } + } + if (ui_notification_set_service + (clientinfo->ui_notification_handle, + clientinfo->service_handle) < 0) { + TRACE_DEBUG_MSG("Fail ui_notification_set_service"); + destroy_appfw_service(clientinfo); + } + } + + if ((ret = + ui_notification_post(clientinfo->ui_notification_handle)) != + UI_NOTIFICATION_ERROR_NONE) { + TRACE_DEBUG_MSG("Fail to post [%d]", ret); + print_notification_error_message(ret); + destroy_appfw_notification(clientinfo); + return -1; + } + + return 0; +} + +int set_downloadinginfo_appfw_notification(download_clientinfo *clientinfo) +{ + if (!clientinfo || !clientinfo->downloadinginfo) + return -1; + + if (!clientinfo->ui_notification_handle) { + create_appfw_notification(clientinfo, true); + } + + if (!clientinfo->ui_notification_handle) + return -1; + + if (clientinfo->downloadinfo && clientinfo->downloadinfo->file_size > 0) { + double progress = + (double)clientinfo->downloadinginfo->received_size / + (double)clientinfo->downloadinfo->file_size; + if (ui_notification_update_progress + (clientinfo->ui_notification_handle, + UI_NOTIFICATION_PROGRESS_TYPE_PERCENTAGE, progress) < 0) { + TRACE_DEBUG_MSG("Fail to update progress"); + destroy_appfw_notification(clientinfo); + return -1; + } + } else { + if (ui_notification_update_progress + (clientinfo->ui_notification_handle, + UI_NOTIFICATION_PROGRESS_TYPE_SIZE, + (double)(clientinfo->downloadinginfo->received_size)) < + 0) { + TRACE_DEBUG_MSG("Fail to update size"); + destroy_appfw_notification(clientinfo); + return -1; + } + } + + return 0; +} + +int set_downloadedinfo_appfw_notification(download_clientinfo *clientinfo) +{ + if (!clientinfo) + return -1; + + destroy_appfw_notification(clientinfo); + + if (!clientinfo->ui_notification_handle) + create_appfw_notification(clientinfo, false); + + // fill downloaded info to post to notification bar. + char *message = __get_string_status(clientinfo->state); + TRACE_DEBUG_MSG("message : [%s]", message); + if (message) { + if (ui_notification_set_content + (clientinfo->ui_notification_handle, message) < 0) + TRACE_DEBUG_MSG("Fail to set content"); + } + + time_t tt = time(NULL); + struct tm *localTime = localtime(&tt); + + if (ui_notification_set_time + (clientinfo->ui_notification_handle, localTime) < 0) + TRACE_DEBUG_MSG("Fail to set time"); + + if (ui_notification_update(clientinfo->ui_notification_handle) < 0) + TRACE_DEBUG_MSG("Fail to ui_notification_update"); + + destroy_appfw_notification(clientinfo); + return 0; +} diff --git a/src/download-provider-pid.c b/src/download-provider-pid.c new file mode 100644 index 0000000..b580ae9 --- /dev/null +++ b/src/download-provider-pid.c @@ -0,0 +1,14 @@ +#include <unistd.h> +#include <fcntl.h> + +int lock_download_provider_pid(char *path) +{ + int lockfd = 0; + if ((lockfd = open(path, O_WRONLY | O_CREAT, (0666 & (~000)))) < 0) { + return -1; + } else if (lockf(lockfd, F_TLOCK, 0) < 0) { + close(lockfd); + return -1; + } + return 0; +} diff --git a/src/download-provider-receiver.c b/src/download-provider-receiver.c new file mode 100644 index 0000000..63e656b --- /dev/null +++ b/src/download-provider-receiver.c @@ -0,0 +1,1095 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <sys/stat.h> +#include <time.h> +#include <sys/time.h> + +#include <glib.h> + +#include <net_connection.h> + +#include "download-provider-config.h" +#include "download-provider-log.h" +#include "download-provider-pthread.h" +#include "download-provider-notification.h" +#include "download-provider-ipc.h" +#include "download-provider-db.h" +#include "download-provider-utils.h" + +#include "download-agent-defs.h" +#include "download-agent-interface.h" + +int _init_agent(void); +void _deinit_agent(void); +static void __downloading_info_cb(user_downloading_info_t *download_info, + void *user_data); +static void __download_info_cb(user_download_info_t *download_info, + void *user_data); +static void __notify_cb(user_notify_info_t *notify_info, void *user_data); +static int __change_error(int err); +static int __change_state(da_state state); + +void TerminateDaemon(int signo); + +pthread_attr_t g_download_provider_thread_attr; +fd_set g_download_provider_socket_readset; +fd_set g_download_provider_socket_exceptset; + +void *_start_download(void *args) +{ + int da_ret = -1; + int req_dl_id = -1; + + download_clientinfo_slot *clientinfoslot = + (download_clientinfo_slot *) args; + if (!clientinfoslot) { + TRACE_DEBUG_MSG("[NULL-CHECK] download_clientinfo_slot"); + return 0; + } + download_clientinfo *clientinfo = + (download_clientinfo *) clientinfoslot->clientinfo; + if (!clientinfo) { + TRACE_DEBUG_MSG("[NULL-CHECK] download_clientinfo"); + return 0; + } + + CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); + clientinfo->state = DOWNLOAD_STATE_READY; + clientinfo->err = DOWNLOAD_ERROR_NONE; + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); + + // call start_download() of download-agent + if (clientinfo->requestinfo->headers.rows > 0) { + int len = 0; + int i = 0; + char **req_header = NULL; + len = clientinfo->requestinfo->headers.rows; + req_header = calloc(len, sizeof(char *)); + if (!req_header) { + TRACE_DEBUG_MSG("fail to calloc"); + return 0; + } + for (i = 0; i < len; i++) + req_header[i] = + strdup(clientinfo->requestinfo->headers.str[i].str); + if (clientinfo->requestinfo->install_path.length > 0) + da_ret = + da_start_download_with_extension(clientinfo->requestinfo-> + url.str, &req_dl_id, + DA_FEATURE_REQUEST_HEADER, + req_header, &len, + DA_FEATURE_INSTALL_PATH, + clientinfo->requestinfo->install_path.str, + DA_FEATURE_USER_DATA, + (void *)clientinfoslot, + NULL); + else + da_ret = + da_start_download_with_extension(clientinfo->requestinfo-> + url.str, &req_dl_id, + DA_FEATURE_REQUEST_HEADER, + req_header, &len, + DA_FEATURE_USER_DATA, + (void *)clientinfoslot, + NULL); + for (i = 0; i < len; i++) { + if (req_header[i]) + free(req_header[i]); + } + } else { + if (clientinfo->requestinfo->install_path.length > 0) + da_ret = + da_start_download_with_extension(clientinfo->requestinfo-> + url.str, &req_dl_id, + DA_FEATURE_INSTALL_PATH, + clientinfo->requestinfo->install_path.str, + DA_FEATURE_USER_DATA, + (void *)clientinfoslot, + NULL); + else + da_ret = + da_start_download_with_extension(clientinfo->requestinfo-> + url.str, &req_dl_id, + DA_FEATURE_USER_DATA, + (void *)clientinfoslot, + NULL); + } + + // if start_download() return error cause of maximun download limitation, set state to DOWNLOAD_STATE_PENDED. + if (da_ret == DA_ERR_ALREADY_MAX_DOWNLOAD) { + TRACE_DEBUG_MSG("change to pended request [%d]", da_ret); + CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); + clientinfo->state = DOWNLOAD_STATE_PENDED; + clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS; + download_provider_db_requestinfo_update_column(clientinfo, + DOWNLOAD_DB_STATE); + ipc_send_request_stateinfo(clientinfo); + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); + return 0; + } else if (da_ret != DA_RESULT_OK) { + TRACE_DEBUG_MSG("Fail to request start [%d]", da_ret); + /* FIXME : need to seperate in detail according to error return values */ + CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); + clientinfo->state = DOWNLOAD_STATE_FAILED; + clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; + download_provider_db_requestinfo_remove(clientinfo-> + requestinfo->requestid); + ipc_send_request_stateinfo(clientinfo); + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); + clear_clientinfoslot(clientinfoslot); + return 0; + } + + CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); + + TRACE_DEBUG_MSG("started download [%d]", da_ret); + + clientinfo->req_id = req_dl_id; + clientinfo->state = DOWNLOAD_STATE_DOWNLOADING; + clientinfo->err = DOWNLOAD_ERROR_NONE; + + download_provider_db_requestinfo_update_column(clientinfo, + DOWNLOAD_DB_STATE); + + // sync return // client should be alive till this line at least. + ipc_send_request_stateinfo(clientinfo); + + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); + return 0; +} + +int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_clientinfo *request_clientinfo) +{ + uint searchslot = 0; + + // NULL - checking + if (!clientinfo_list || !request_clientinfo ) { + TRACE_DEBUG_MSG("NULL-CHECK"); + return -1; + } + + CLIENT_MUTEX_INIT(&(request_clientinfo->client_mutex), NULL); + +#ifdef SO_PEERCRED + socklen_t cr_len = + sizeof(request_clientinfo->credentials); + if (getsockopt + (request_clientinfo->clientfd, SOL_SOCKET, + SO_PEERCRED, &request_clientinfo->credentials, + &cr_len) == 0) { + TRACE_DEBUG_MSG + ("Client Info : pid=%d, uid=%d, gid=%d\n", + request_clientinfo->credentials.pid, + request_clientinfo->credentials.uid, + request_clientinfo->credentials.gid); + } +#endif + + download_controls type = + ipc_receive_header(request_clientinfo->clientfd); + TRACE_DEBUG_MSG("[ACCEPT] HEADER : [%d] ", type); + // first of all, receive requestinfo . + if (type <= 0 || ipc_receive_request_msg(request_clientinfo) < 0) { + TRACE_DEBUG_MSG("Ignore this connection, Invalid command"); + clear_clientinfo(request_clientinfo); + return -1; + } + + if (type == DOWNLOAD_CONTROL_STOP + || type == DOWNLOAD_CONTROL_GET_STATE_INFO) { + // get requestid from socket. + if (request_clientinfo->requestinfo + && request_clientinfo->requestinfo->requestid > 0) { + // search requestid in slots. + int searchindex = get_same_request_slot_index + (clientinfo_list, + request_clientinfo->requestinfo->requestid); + if (type == DOWNLOAD_CONTROL_STOP) { + TRACE_DEBUG_MSG("Request : DOWNLOAD_CONTROL_STOP"); + // remove info from downloading table. + download_provider_db_requestinfo_remove + (request_clientinfo->requestinfo->requestid); + if (searchindex >= 0) { + CLIENT_MUTEX_LOCK(& + (clientinfo_list[searchindex].clientinfo->client_mutex)); + if (da_cancel_download + (clientinfo_list[searchindex].clientinfo->req_id) + == DA_RESULT_OK) { + request_clientinfo->state = DOWNLOAD_STATE_STOPPED; + request_clientinfo->err = DOWNLOAD_ERROR_NONE; + } else { + request_clientinfo->state = DOWNLOAD_STATE_FAILED; + request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; + } + ipc_send_stateinfo(request_clientinfo); + CLIENT_MUTEX_UNLOCK(& + (clientinfo_list[searchindex].clientinfo->client_mutex)); + } + } else if (type == DOWNLOAD_CONTROL_GET_STATE_INFO) + { + // not implemented yet + // search slots/downloading db/history db + // estabilish the spec of return value. + } + } + clear_clientinfo(request_clientinfo); + return 0; + } + + if (type != DOWNLOAD_CONTROL_START) { + TRACE_DEBUG_MSG + ("Now, DOWNLOAD_CONTROL_START is only supported"); + clear_clientinfo(request_clientinfo); + return -1; + } + + // check whether requestinfo has requestid or not. + if (request_clientinfo->requestinfo + && request_clientinfo->requestinfo->requestid > 0) { + // search same request id. + int searchindex = get_same_request_slot_index(clientinfo_list, + request_clientinfo->requestinfo->requestid); + if (searchindex < 0) { + CLIENT_MUTEX_LOCK(&(request_clientinfo->client_mutex)); + TRACE_DEBUG_MSG("Not Found Same Request ID"); + request_clientinfo->requestinfo->requestid = 0; + // Invalid id + request_clientinfo->state = DOWNLOAD_STATE_FAILED; + request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; + ipc_send_request_stateinfo(request_clientinfo); + CLIENT_MUTEX_UNLOCK(&(request_clientinfo->client_mutex)); + clear_clientinfo(request_clientinfo); + return 0; + } else { // found request id. // how to deal etag ? + // connect to slot. + TRACE_DEBUG_MSG("Found Same Request ID slot[%d]", searchindex); + CLIENT_MUTEX_LOCK(&(request_clientinfo->client_mutex)); + // close previous socket. + if (clientinfo_list[searchindex].clientinfo->clientfd > 0) + close(clientinfo_list[searchindex].clientinfo->clientfd); + // change to new socket. + clientinfo_list[searchindex].clientinfo->clientfd = + request_clientinfo->clientfd; + ipc_send_request_stateinfo(clientinfo_list[searchindex].clientinfo); + // update some info. + clientinfo_list[searchindex].clientinfo->requestinfo->callbackinfo = + request_clientinfo->requestinfo->callbackinfo; + clientinfo_list[searchindex].clientinfo->requestinfo->notification = + request_clientinfo->requestinfo->notification; + request_clientinfo->clientfd = 0; // prevent to not be disconnected. + CLIENT_MUTEX_UNLOCK(&(request_clientinfo->client_mutex)); + clear_clientinfo(request_clientinfo); + return 0; + } + } + + // new request. + searchslot = get_empty_slot_index(clientinfo_list); + if (searchslot < 0) { + TRACE_DEBUG_MSG("download-provider is busy, try later"); + clear_clientinfo(request_clientinfo); + sleep(5); // provider need the time of refresh. + return -1; + } + // create new unique id, and insert info to DB. + if (request_clientinfo->requestinfo + && request_clientinfo->requestinfo->requestid <= 0) { + request_clientinfo->requestinfo->requestid = + get_download_request_id(); + if (download_provider_db_requestinfo_new + (request_clientinfo) < 0) { + clear_clientinfo(request_clientinfo); + sleep(5); // provider need the time of refresh. + return -1; + } + } + + clientinfo_list[searchslot].clientinfo = request_clientinfo; + + TRACE_DEBUG_MSG("New Connection slot [%d] max [%d] max once [%d]", + searchslot, + MAX_CLIENT, + DA_MAX_DOWNLOAD_REQ_AT_ONCE); + + if (get_downloading_count(clientinfo_list) >= + DA_MAX_DOWNLOAD_REQ_AT_ONCE) { + CLIENT_MUTEX_LOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex)); + // deal as pended job. + clientinfo_list[searchslot].clientinfo->state = DOWNLOAD_STATE_PENDED; + clientinfo_list[searchslot].clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS; + download_provider_db_requestinfo_update_column + (clientinfo_list[searchslot].clientinfo, + DOWNLOAD_DB_STATE); + ipc_send_request_stateinfo(clientinfo_list[searchslot].clientinfo); + TRACE_DEBUG_MSG ("Pended Request is saved to [%d/%d]", + searchslot, MAX_CLIENT); + CLIENT_MUTEX_UNLOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex)); + sleep(5); // provider need the time of refresh. + } else { + // create thread for receiving the reqeust info from client. + // and if possible, it will create the thread for listening the event. + if (pthread_create + (&clientinfo_list[searchslot].clientinfo->thread_pid, + &g_download_provider_thread_attr, _start_download, + &clientinfo_list[searchslot]) != 0) { + TRACE_DEBUG_MSG("failed to call pthread_create for client"); + TRACE_DEBUG_MSG("Change to pended job"); + CLIENT_MUTEX_LOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex)); + clientinfo_list[searchslot].clientinfo->state = + DOWNLOAD_STATE_PENDED; + clientinfo_list[searchslot].clientinfo->err = + DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS; + download_provider_db_requestinfo_update_column + (clientinfo_list[searchslot].clientinfo, + DOWNLOAD_DB_STATE); + ipc_send_request_stateinfo(clientinfo_list[searchslot].clientinfo); + CLIENT_MUTEX_UNLOCK(&(clientinfo_list[searchslot].clientinfo->client_mutex)); + sleep(5); // provider need the time of refresh. + } + } + return 0; +} + +int _handle_client_request(download_clientinfo* clientinfo) +{ + int da_ret = 0; + int msgType = 0; + + // NULL - checking + if (!clientinfo) { + TRACE_DEBUG_MSG("NULL-CHECK"); + return -1; + } + + CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); + switch (msgType = ipc_receive_header(clientinfo->clientfd)) { + case DOWNLOAD_CONTROL_STOP: + TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_STOP"); + da_ret = da_cancel_download(clientinfo->req_id); + if (da_ret != DA_RESULT_OK) { + /* FIXME : need to seperate in detail according to error return values */ + clientinfo->state = DOWNLOAD_STATE_FAILED; + clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; + TRACE_DEBUG_MSG("Fail to request cancel [%d]", da_ret); + } else { + clientinfo->state = DOWNLOAD_STATE_STOPPED; + clientinfo->err = DOWNLOAD_ERROR_NONE; + } + ipc_send_stateinfo(clientinfo); + break; + case DOWNLOAD_CONTROL_PAUSE: + TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_PAUSE"); + da_ret = da_suspend_download(clientinfo->req_id); + if (da_ret != DA_RESULT_OK) { + /* FIXME : need to seperate in detail according to error return values */ + clientinfo->state = DOWNLOAD_STATE_FAILED; + clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; + TRACE_DEBUG_MSG("Fail to request suspend [%d]", da_ret); + } else { + clientinfo->state = DOWNLOAD_STATE_PAUSE_REQUESTED; + clientinfo->err = DOWNLOAD_ERROR_NONE; + } + ipc_send_stateinfo(clientinfo); + break; + case DOWNLOAD_CONTROL_RESUME: + TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_RESUME"); + da_ret = da_resume_download(clientinfo->req_id); + if (da_ret != DA_RESULT_OK) { + /* FIXME : need to seperate in detail according to error return values */ + clientinfo->state = DOWNLOAD_STATE_FAILED; + clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; + TRACE_DEBUG_MSG("Fail to request resume [%d]", da_ret); + } else { + clientinfo->state = DOWNLOAD_STATE_DOWNLOADING; + clientinfo->err = DOWNLOAD_ERROR_NONE; + } + ipc_send_stateinfo(clientinfo); + break; + case DOWNLOAD_CONTROL_GET_STATE_INFO: // sync call + TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_GET_STATE_INFO"); + ipc_send_stateinfo(clientinfo); + break; + case DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO: // sync call + TRACE_DEBUG_MSG("DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO"); + ipc_send_downloadinfo(clientinfo); + break; + case -1: + case 0: + TRACE_DEBUG_MSG("(Closed Socket ) terminate event thread (%d)", + msgType); + // bloken socket... it seems the client is dead or closed by agent thread. + // close socket, this will break the loop. and terminate this thread. + clear_socket(clientinfo); + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); + return -1; + default: + TRACE_DEBUG_MSG("Unknow message [%d]", msgType); + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); + return -1; + } + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); + return 0; +} + +void *run_manage_download_server(void *args) +{ + int listenfd = 0; // main socket to be albe to listen the new connection + int maxfd; + int ret = 0; + fd_set rset, exceptset; + struct timeval timeout; + long flexible_timeout; + download_clientinfo_slot *clientinfo_list; + uint searchslot = 0; + uint count_downloading_threads = 0; + download_clientinfo *request_clientinfo; + int check_retry = 1; + int i = 0; + + socklen_t clientlen; + struct sockaddr_un listenaddr, clientaddr; + + GMainLoop *mainloop = (GMainLoop *) args; + + ret = _init_agent(); + if (ret != DOWNLOAD_ERROR_NONE) { + TRACE_DEBUG_MSG("failed to init agent"); + TerminateDaemon(SIGTERM); + return 0; + } + + if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + TRACE_DEBUG_MSG("failed to create socket"); + TerminateDaemon(SIGTERM); + return 0; + } + + bzero(&listenaddr, sizeof(listenaddr)); + listenaddr.sun_family = AF_UNIX; + strcpy(listenaddr.sun_path, DOWNLOAD_PROVIDER_IPC); + + if (bind(listenfd, (struct sockaddr *)&listenaddr, sizeof listenaddr) != + 0) { + TRACE_DEBUG_MSG("failed to call bind"); + TerminateDaemon(SIGTERM); + return 0; + } + + if (chmod(listenaddr.sun_path, 0777) < 0) { + TRACE_DEBUG_MSG + ("failed to change the permission of socket file"); + TerminateDaemon(SIGTERM); + return 0; + } + + if (listen(listenfd, MAX_CLIENT) != 0) { + TRACE_DEBUG_MSG("failed to call listen"); + TerminateDaemon(SIGTERM); + return 0; + } + + maxfd = listenfd; + TRACE_DEBUG_MSG("Ready to listen IPC [%d][%s]", listenfd, + DOWNLOAD_PROVIDER_IPC); + + // allocation the array structure for managing the clients. + clientinfo_list = + (download_clientinfo_slot *) calloc(MAX_CLIENT, + sizeof(download_clientinfo_slot)); + if (clientinfo_list == NULL) { + TRACE_DEBUG_MSG("failed to allocate the memory for client list"); + TerminateDaemon(SIGTERM); + return 0; + } + + if (pthread_attr_init(&g_download_provider_thread_attr) != 0) { + TRACE_DEBUG_MSG("failed to call pthread_attr_init for client"); + TerminateDaemon(SIGTERM); + return 0; + } + if (pthread_attr_setdetachstate(&g_download_provider_thread_attr, + PTHREAD_CREATE_DETACHED) != 0) { + TRACE_DEBUG_MSG("failed to set detach option"); + TerminateDaemon(SIGTERM); + return 0; + } + + flexible_timeout = DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL; + + FD_ZERO(&g_download_provider_socket_readset); + FD_ZERO(&g_download_provider_socket_exceptset); + FD_SET(listenfd, &g_download_provider_socket_readset); + FD_SET(listenfd, &g_download_provider_socket_exceptset); + + while (g_main_loop_is_running(mainloop)) { + + // clean slots + for (i=0; i < MAX_CLIENT; i++) { + if (!clientinfo_list[i].clientinfo) + continue; + CLIENT_MUTEX_LOCK(&(clientinfo_list[i].clientinfo->client_mutex)); + // clear slot. + if (clientinfo_list[i].clientinfo->state >= DOWNLOAD_STATE_FINISHED) { + CLIENT_MUTEX_UNLOCK(&(clientinfo_list[i].clientinfo->client_mutex)); + clear_clientinfoslot(&clientinfo_list[i]); + continue; + } + CLIENT_MUTEX_UNLOCK(&(clientinfo_list[i].clientinfo->client_mutex)); + } + + rset = g_download_provider_socket_readset; + exceptset = g_download_provider_socket_exceptset; + + timeout.tv_sec = flexible_timeout; + + if (select((maxfd + 1), &rset, 0, &exceptset, &timeout) < 0) { + TRACE_DEBUG_MSG + ("select error, provider can't receive any request from client."); + TerminateDaemon(SIGTERM); + break; + } + + for (i=0; i < MAX_CLIENT; i++) { // find the socket received the packet. + if (!clientinfo_list[i].clientinfo) + continue; + // ignore if finished + //if (clientinfo_list[i].clientinfo->state >= DOWNLOAD_STATE_FINISHED) + //continue; + //Even if no socket, downloading should be progressed. + if (clientinfo_list[i].clientinfo->clientfd <= 0) + continue; + if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &rset) > 0) { + TRACE_DEBUG_MSG("FD_ISSET [%d] readset slot[%d]", + clientinfo_list[i].clientinfo->clientfd, i); + _handle_client_request(clientinfo_list[i].clientinfo); + } else if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &exceptset) > 0) { + TRACE_DEBUG_MSG("FD_ISSET [%d] exceptset slot[%d]", clientinfo_list[i].clientinfo->clientfd, i); + clear_clientinfoslot(&clientinfo_list[i]); + } + } // MAX_CLIENT + + if (FD_ISSET(listenfd, &exceptset) > 0) { + TRACE_DEBUG_MSG("meet listenfd Exception of socket"); + TerminateDaemon(SIGTERM); + break; + } else if (FD_ISSET(listenfd, &rset) > 0) { // new connection + TRACE_DEBUG_MSG("FD_ISSET listenfd rset"); + // reset timeout. + flexible_timeout = + DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL; + // ready the buffer. + request_clientinfo = + (download_clientinfo *) calloc(1, + sizeof(download_clientinfo)); + if (!request_clientinfo) { + TRACE_DEBUG_MSG + ("download-provider can't allocate the memory, try later"); + clientlen = sizeof(clientaddr); + int clientfd = accept(listenfd, + (struct sockaddr *)&clientaddr, &clientlen); + close(clientfd); // disconnect. + sleep(5); // provider need the time of refresh. + continue; + } + // accept client. + clientlen = sizeof(clientaddr); + request_clientinfo->clientfd = accept(listenfd, + (struct sockaddr*)&clientaddr, + &clientlen); + if (request_clientinfo->clientfd < 0) { + clear_clientinfo(request_clientinfo); + sleep(5); // provider need the time of refresh. + continue; + } + FD_SET(request_clientinfo->clientfd, &g_download_provider_socket_readset); // add new descriptor to set + FD_SET(request_clientinfo->clientfd, &g_download_provider_socket_exceptset); + if (request_clientinfo->clientfd > maxfd ) + maxfd = request_clientinfo->clientfd; /* for select */ + + if (_handle_new_connection(clientinfo_list, request_clientinfo) < 0) { + sleep(1); + continue; + } + } + + if (i >= MAX_CLIENT) { // timeout + // If there is better solution to be able to know + // the number of downloading threads, replace below rough codes. + count_downloading_threads = + get_downloading_count(clientinfo_list); + // check whether the number of downloading is already maximum. + if (count_downloading_threads >= + DA_MAX_DOWNLOAD_REQ_AT_ONCE) + continue; + + // search pended request + for (searchslot = 0; searchslot < MAX_CLIENT; + searchslot++) { + if (clientinfo_list[searchslot].clientinfo) { + if (clientinfo_list[searchslot].clientinfo->state == + DOWNLOAD_STATE_PENDED) { + TRACE_DEBUG_MSG + ("Retry Pended Request [%d/%d] state [%d/%d]", + searchslot, MAX_CLIENT, + count_downloading_threads, + DA_MAX_DOWNLOAD_REQ_AT_ONCE); + // create thread for restarting the pended download. + if (pthread_create + (&clientinfo_list[searchslot].clientinfo->thread_pid, + &g_download_provider_thread_attr, + _start_download, + &clientinfo_list[searchslot]) != 0) { + TRACE_DEBUG_MSG + ("failed to call pthread_create for client"); + } + count_downloading_threads++; + usleep(1000); // sleep in busy state. + break; + } + } + } + + if (check_retry + && count_downloading_threads < + DA_MAX_DOWNLOAD_REQ_AT_ONCE) { + // Auto re-download feature. ethernet may be connected with other downloading items. + connection_h network_handle = NULL; + connection_ethernet_state_e system_network_state + = CONNECTION_ETHERNET_STATE_DISCONNECTED; + if (connection_create(&network_handle) < 0) { + TRACE_DEBUG_MSG + ("Failed connection_create"); + continue; + } + if (connection_get_ethernet_state(network_handle, + &system_network_state) != + CONNECTION_ERROR_NONE) + TRACE_DEBUG_MSG + ("Failed connection_get_ethernet_state"); + if (connection_destroy(network_handle) != + CONNECTION_ERROR_NONE) + TRACE_DEBUG_MSG + ("Failed connection_destroy"); + if (system_network_state != + CONNECTION_ETHERNET_STATE_CONNECTED) + continue; + // check auto-retrying list regardless state. pended state is also included to checking list. + int i = 0; + download_dbinfo_list *db_list = + download_provider_db_get_list(DOWNLOAD_STATE_NONE); + if (!db_list || db_list->count <= 0) { + TRACE_DEBUG_MSG + ("provider does not need to check DB anymore. in this life."); + check_retry = 0; // provider does not need to check DB anymore. in this life. + if (db_list) + download_provider_db_list_free(db_list); + continue; + } + for (i = 0; + count_downloading_threads < + DA_MAX_DOWNLOAD_REQ_AT_ONCE + && i < db_list->count; i++) { + if (db_list->item[i].requestid <= 0) + continue; + if (get_same_request_slot_index + (clientinfo_list,db_list->item[i].requestid) < 0) { + // not found requestid in memory + TRACE_DEBUG_MSG + ("Retry download [%d]", + db_list->item[i].requestid); + //search empty slot. copy db info to slot. + searchslot = + get_empty_slot_index(clientinfo_list); + if (searchslot < 0) { + TRACE_DEBUG_MSG + ("download-provider is busy, try later"); + flexible_timeout = + flexible_timeout * 2; + break; + } + // allocte requestinfo to empty slot. + request_clientinfo = + (download_clientinfo *) + calloc(1, sizeof(download_clientinfo)); + if (!request_clientinfo) + continue; + request_clientinfo->requestinfo + = + download_provider_db_get_requestinfo + (&db_list->item[i]); + if (!request_clientinfo->requestinfo) { + free(request_clientinfo); + request_clientinfo = NULL; + continue; + } + + clientinfo_list[searchslot].clientinfo = + request_clientinfo; + + TRACE_DEBUG_MSG + ("Retry download [%d/%d][%d/%d]", + searchslot, MAX_CLIENT, + count_downloading_threads, + DA_MAX_DOWNLOAD_REQ_AT_ONCE); + if (pthread_create + (&clientinfo_list[searchslot].clientinfo->thread_pid, + &g_download_provider_thread_attr, + _start_download, + &clientinfo_list[searchslot]) + != 0) { + TRACE_DEBUG_MSG + ("failed to call pthread_create for client"); + clientinfo_list[searchslot].clientinfo->state = + DOWNLOAD_STATE_PENDED; + clientinfo_list[searchslot].clientinfo->err = + DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS; + sleep(5); + } + count_downloading_threads++; + usleep(1000); // sleep in busy state. + } + } + if (i >= db_list->count) // do not search anymore. + check_retry = 0; + download_provider_db_list_free(db_list); + } + + // save system resource (CPU) + if (check_retry == 0 && count_downloading_threads == 0 + && flexible_timeout < + DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL) + flexible_timeout = flexible_timeout * 2; + if (flexible_timeout > + DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL) + flexible_timeout = + DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL; + TRACE_DEBUG_MSG("Next Timeout after [%ld] sec", + flexible_timeout); + + } // if (i >= MAX_CLIENT) { // timeout + } + + FD_CLR(listenfd, &rset); + FD_CLR(listenfd, &exceptset); + FD_CLR(listenfd, &g_download_provider_socket_readset); + FD_CLR(listenfd, &g_download_provider_socket_exceptset); + + // close accept socket. + if (listenfd) + close(listenfd); + + _deinit_agent(); + + // close all sockets for client. .. + // client thread will terminate by itself through catching this closing. + for (searchslot = 0; searchslot < MAX_CLIENT; searchslot++) + if (clientinfo_list[searchslot].clientinfo) + clear_clientinfoslot(&clientinfo_list[searchslot]); + + if (clientinfo_list) + free(clientinfo_list); + + pthread_exit(NULL); + return 0; +} + +void __download_info_cb(user_download_info_t *download_info, void *user_data) +{ + int len = 0; + if (!user_data) { + TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL"); + return; + } + download_clientinfo_slot *clientinfoslot = + (download_clientinfo_slot *) user_data; + download_clientinfo *clientinfo = + (download_clientinfo *) clientinfoslot->clientinfo; + if (!clientinfo) { + TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL"); + return; + } + TRACE_DEBUG_MSG("id[%d],size[%lu]", + download_info->da_dl_req_id, download_info->file_size) + + if (clientinfo->req_id != download_info->da_dl_req_id) { + TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}", + clientinfo->req_id, + download_info->da_dl_req_id); + return; + } + CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); + if (!clientinfo->downloadinfo) + clientinfo->downloadinfo = + (download_content_info *) calloc(1, sizeof(download_content_info)); + if (clientinfo->downloadinfo) + clientinfo->downloadinfo->file_size = download_info->file_size; + if (download_info->file_type) { + TRACE_DEBUG_MSG("mime[%s]", download_info->file_type); + + len = strlen(download_info->file_type); + if (len > (DP_MAX_STR_LEN - 1)) + len = DP_MAX_STR_LEN - 1; + if (clientinfo->downloadinfo) { + strncpy(clientinfo->downloadinfo->mime_type, + download_info->file_type, len); + download_provider_db_requestinfo_update_column + (clientinfo, DOWNLOAD_DB_MIMETYPE); + } + } + if (download_info->tmp_saved_path) { + char *str = NULL; + TRACE_DEBUG_MSG("tmp path[%s]", download_info->tmp_saved_path); + clientinfo->tmp_saved_path = + strdup(download_info->tmp_saved_path); + download_provider_db_requestinfo_update_column(clientinfo, + DOWNLOAD_DB_SAVEDPATH); + str = strrchr(download_info->tmp_saved_path, '/'); + if (str) { + str++; + len = strlen(str); + if (len > (DP_MAX_STR_LEN - 1)) + len = DP_MAX_STR_LEN - 1; + if (clientinfo->downloadinfo) { + strncpy(clientinfo->downloadinfo->content_name, + str, len); + download_provider_db_requestinfo_update_column + (clientinfo, DOWNLOAD_DB_FILENAME); + TRACE_DEBUG_MSG("content_name[%s]", + clientinfo->downloadinfo-> + content_name); + } + } + } + + if (clientinfo->requestinfo->callbackinfo.started) + ipc_send_downloadinfo(clientinfo); + + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); +} + +void __downloading_info_cb(user_downloading_info_t *download_info, + void *user_data) +{ + int len = 0; + if (!user_data) { + TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL"); + return; + } + download_clientinfo_slot *clientinfoslot = + (download_clientinfo_slot *) user_data; + download_clientinfo *clientinfo = + (download_clientinfo *) clientinfoslot->clientinfo; + if (!clientinfo) { + TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL"); + return; + } + CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); + if (clientinfo->req_id != download_info->da_dl_req_id) { + TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}", + clientinfo->req_id, + download_info->da_dl_req_id); + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); + return; + } + if (!clientinfo->downloadinginfo) + clientinfo->downloadinginfo = (downloading_state_info *) calloc(1, + sizeof(downloading_state_info)); + if (clientinfo->downloadinginfo) + clientinfo->downloadinginfo->received_size = + download_info->total_received_size; + if (download_info->saved_path) { + TRACE_DEBUG_MSG("tmp path[%s]", download_info->saved_path); + len = strlen(download_info->saved_path); + if (len > (DP_MAX_PATH_LEN - 1)) + len = DP_MAX_PATH_LEN - 1; + if (clientinfo->downloadinginfo) + strncpy(clientinfo->downloadinginfo->saved_path, + download_info->saved_path, len); + } + + static size_t updated_second; + time_t tt = time(NULL); + struct tm *localTime = localtime(&tt); + + if (updated_second != localTime->tm_sec || download_info->saved_path) { // every 1 second. + if (clientinfo->requestinfo + && clientinfo->requestinfo->notification) + set_downloadinginfo_appfw_notification(clientinfo); + if (clientinfo->requestinfo->callbackinfo.progress) + ipc_send_downloadinginfo(clientinfo); + updated_second = localTime->tm_sec; + } + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); +} + +void __notify_cb(user_notify_info_t *notify_info, void *user_data) +{ + if (!user_data) { + TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL"); + return; + } + download_clientinfo_slot *clientinfoslot = + (download_clientinfo_slot *) user_data; + download_clientinfo *clientinfo = + (download_clientinfo *) clientinfoslot->clientinfo; + if (!clientinfo) { + TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL"); + return; + } + CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); + TRACE_DEBUG_MSG("id[%d],state[%d],err[%d]", + notify_info->da_dl_req_id, + notify_info->state, notify_info->err); + if (clientinfo->req_id != notify_info->da_dl_req_id) { + TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}", + clientinfo->req_id, notify_info->da_dl_req_id); + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); + return; + } + + clientinfo->state = __change_state(notify_info->state); + clientinfo->err = __change_error(notify_info->err); + if (clientinfo->state >= DOWNLOAD_STATE_FINISHED) { + if (clientinfo->requestinfo) { + if (clientinfo->requestinfo->notification) + set_downloadedinfo_appfw_notification(clientinfo); + download_provider_db_requestinfo_remove(clientinfo-> + requestinfo->requestid); + } + download_provider_db_history_new(clientinfo); + TRACE_DEBUG_MSG("[TEST]Finish clientinfo[%p],fd[%d]", + clientinfo, clientinfo->clientfd); + } + + TRACE_DEBUG_MSG("state[%d]", clientinfo->state); + ipc_send_stateinfo(clientinfo); + + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); +} + +int __change_state(da_state state) +{ + int ret = DOWNLOAD_STATE_NONE; + switch (state) { + case DA_STATE_WAITING: + case DA_STATE_DOWNLOAD_STARTED: + TRACE_DEBUG_MSG("DA_STATE_DOWNLOAD_STARTED"); + ret = DOWNLOAD_STATE_READY; + break; + case DA_STATE_DOWNLOADING: + TRACE_DEBUG_MSG("DA_STATE_DOWNLOADING"); + ret = DOWNLOAD_STATE_DOWNLOADING; + break; + case DA_STATE_DOWNLOAD_COMPLETE: + TRACE_DEBUG_MSG("DA_STATE_COMPLETE"); + ret = DOWNLOAD_STATE_INSTALLING; + break; + case DA_STATE_CANCELED: + TRACE_DEBUG_MSG("DA_STATE_CANCELED"); + ret = DOWNLOAD_STATE_STOPPED; + break; + case DA_STATE_CANCELED_ALL: + TRACE_DEBUG_MSG("DA_STATE_CANCELED_ALL"); + break; + case DA_STATE_SUSPENDED: + TRACE_DEBUG_MSG("DA_STATE_SUSPENDED"); + ret = DOWNLOAD_STATE_PAUSED; + break; + case DA_STATE_SUSPENDED_ALL: + TRACE_DEBUG_MSG("DA_STATE_SUSPENDED_ALL"); + break; + case DA_STATE_RESUMED: + TRACE_DEBUG_MSG("DA_STATE_RESUMED"); + ret = DOWNLOAD_STATE_DOWNLOADING; + break; + case DA_STATE_RESUMED_ALL: + TRACE_DEBUG_MSG("DA_STATE_RESUMED_ALL"); + break; + case DA_STATE_FINISHED: + TRACE_DEBUG_MSG("DA_STATE_FINISHED"); + ret = DOWNLOAD_STATE_FINISHED; + break; + case DA_STATE_FAILED: + TRACE_DEBUG_MSG("DA_STATE_FAILED"); + ret = DOWNLOAD_STATE_FAILED; + break; + default: + break; + } + return ret; +} + +int __change_error(int err) +{ + int ret = DOWNLOAD_ERROR_UNKOWN; + switch (err) { + case DA_RESULT_OK: + ret = DOWNLOAD_ERROR_NONE; + break; + case DA_ERR_INVALID_ARGUMENT: + ret = DOWNLOAD_ERROR_INVALID_PARAMETER; + break; + case DA_ERR_FAIL_TO_MEMALLOC: + ret = DOWNLOAD_ERROR_OUT_OF_MEMORY; + break; + case DA_ERR_UNREACHABLE_SERVER: + ret = DOWNLOAD_ERROR_NETWORK_UNREACHABLE; + break; + case DA_ERR_HTTP_TIMEOUT: + ret = DOWNLOAD_ERROR_CONNECTION_TIMED_OUT; + break; + case DA_ERR_DISK_FULL: + ret = DOWNLOAD_ERROR_NO_SPACE; + break; + case DA_ERR_INVALID_STATE: + ret = DOWNLOAD_ERROR_INVALID_STATE; + break; + case DA_ERR_NETWORK_FAIL: + ret = DOWNLOAD_ERROR_CONNECTION_FAILED; + break; + case DA_ERR_INVALID_URL: + ret = DOWNLOAD_ERROR_INVALID_URL; + break; + case DA_ERR_INVALID_INSTALL_PATH: + ret = DOWNLOAD_ERROR_INVALID_DESTINATION; + break; + case DA_ERR_ALREADY_MAX_DOWNLOAD: + ret = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS; + break; + case DA_ERR_FAIL_TO_INSTALL_FILE: + ret = DOWNLOAD_ERROR_INSTALL_FAIL; + break; + case DA_ERR_FAIL_TO_CREATE_THREAD: + case DA_ERR_FAIL_TO_OBTAIN_MUTEX: + case DA_ERR_FAIL_TO_ACCESS_FILE: + case DA_ERR_FAIL_TO_GET_CONF_VALUE: + case DA_ERR_FAIL_TO_ACCESS_STORAGE: + case DA_ERR_DLOPEN_FAIL: + ret = DOWNLOAD_ERROR_IO_ERROR; + break; + } + return ret; +} + +int _init_agent() +{ + int da_ret = 0; + da_client_cb_t da_cb = { + __notify_cb, + __download_info_cb, + __downloading_info_cb + }; + da_ret = da_init(&da_cb, DA_DOWNLOAD_MANAGING_METHOD_AUTO); + if (da_ret != DA_RESULT_OK) { + return DOWNLOAD_ERROR_FAIL_INIT_AGENT; + } + return DOWNLOAD_ERROR_NONE; +} + +void _deinit_agent() +{ + da_deinit(); +} diff --git a/src/download-provider-util.cpp b/src/download-provider-util.cpp deleted file mode 100644 index cc4ba40..0000000 --- a/src/download-provider-util.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * @file download-provider-util.cpp - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief Utility APIs and interface with content player - */ - -#include <stdio.h> -#include <string.h> -#include <dlfcn.h> -#include "aul.h" -#include "xdgmime.h" -#include "app_service.h" - -#include "download-provider-util.h" - -#define JAVA_ENG_PATH "/usr/lib/libjava-installer.so" - -struct MimeTableType -{ - const char *mime; - int contentType; -}; - -#define MAX_MIME_TABLE_NUM 22 -const char *ambiguousMIMETypeList[] = { - "text/plain", - "application/octet-stream" -}; - -struct MimeTableType MimeTable[]={ - // 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/palin",DP_CONTENT_TEXT}, - // ringtone - {"text/x-iMelody",DP_CONTENT_RINGTONE},//10 - {"application/x-smaf",DP_CONTENT_RINGTONE}, - {"audio/midi",DP_CONTENT_RINGTONE}, - {"audio/AMR",DP_CONTENT_RINGTONE}, - {"audio/AMR-WB",DP_CONTENT_RINGTONE}, - {"audio/x-xmf",DP_CONTENT_RINGTONE}, - // DRM - {"application/vnd.oma.drm.content",DP_CONTENT_DRM}, - {"application/vnd.oma.drm.message",DP_CONTENT_DRM}, - // JAVA - {"application/x-java-archive",DP_CONTENT_JAVA}, - {"application/java-archive",DP_CONTENT_JAVA}, - // SVG - {"image/svg+xml",DP_CONTENT_SVG}, //20 - // FLASH - {"application/x-shockwave-flash",DP_CONTENT_FLASH} -}; - -bool FileOpener::openFile(string &path, int contentType) -{ - service_h handle = NULL; - string filePath; - DP_LOG_FUNC(); - - if (path.empty()) - return false; - - DP_LOG("path [%s]", path.c_str()); - if (service_create(&handle) < 0) { - DP_LOGE("Fail to create service handle"); - return false; - } - - if (!handle) { - DP_LOGE("service handle is null"); - return false; - } - - if (service_set_operation(handle, SERVICE_OPERATION_VIEW) < 0) { - DP_LOGE("Fail to set service operation"); - service_destroy(handle); - return false; - } - - if (contentType == DP_CONTENT_HTML) { - filePath = "file://"; - filePath.append(path.c_str()); - } else { - filePath = path; - } - if (service_set_uri(handle, filePath.c_str()) < 0) { - DP_LOGE("Fail to set uri"); - service_destroy(handle); - return false; - } - - if (service_send_launch_request(handle, NULL, NULL) < 0) { - DP_LOGE("Fail to launch service"); - service_destroy(handle); - return false; - } - - service_destroy(handle); - - return true; -} - -bool FileOpener::openApp(string &pkgName) -{ - service_h handle = NULL; - DP_LOG_FUNC(); - if (pkgName.empty()) - return false; - - if (service_create(&handle) < 0) { - DP_LOGE("Fail to create service handle"); - return false; - } - - if (!handle) { - DP_LOGE("service handle is null"); - return false; - } - - if (service_set_package(handle, pkgName.c_str()) < 0) { - DP_LOGE("Fail to set service operation"); - service_destroy(handle); - return false; - } - - if (service_send_launch_request(handle, NULL, NULL) < 0) { - DP_LOGE("Fail to aul open"); - service_destroy(handle); - return false; - } - - service_destroy(handle); - - return true; -} - - -DownloadUtil::DownloadUtil() -{ - initDrm(); -} - -string DownloadUtil::getMidletPkgName(string& name, string& vendor) -{ - string pkgName = string(); - char appName[MAX_FILE_PATH_LEN] = {0,}; - void *handle = NULL; - int (*java_get_pkgname )(char *,char *,char *) = NULL; - - if (name.length() < 1 || vendor.length() < 1) - return pkgName; - - handle = dlopen(JAVA_ENG_PATH, RTLD_LAZY); - if ( handle == NULL ) { - DP_LOGE("dlopen error\n"); - if(handle) - dlclose(handle); - return pkgName; - } - - java_get_pkgname = (int(*)(char *,char *,char *)) dlsym( handle, "jim_get_suite_pkgname_with_vendor_suite_name"); - if ( java_get_pkgname == NULL ) { - DP_LOGE("dlopen error2\n"); - dlclose(handle); - return pkgName; - } - DP_LOG("vendor name[%s] midlet name[%s]",vendor.c_str(),name.c_str()); - - if (java_get_pkgname((char *)vendor.c_str(), (char *)name.c_str(), appName)) { - DP_LOG("pkg name[%s]\n",appName); - pkgName = appName; - } - dlclose(handle); - return pkgName; -} - -void DownloadUtil::initDrm() -{ - DP_LOG_FUNC(); -} - -int DownloadUtil::getContentType(const char *mime, const char *filePath) -{ - int i = 0; - int type = DP_CONTENT_UNKOWN; - int ret = 0; - char tempMime[MAX_FILE_PATH_LEN] = {0,}; - DP_LOGD_FUNC(); - if (mime == NULL || strlen(mime) < 1) - return DP_CONTENT_UNKOWN; - - DP_LOG("mime[%s]",mime); - strncpy(tempMime, mime, MAX_FILE_PATH_LEN-1); - if (isAmbiguousMIMEType(mime)) { - if (filePath) { - memset(tempMime, 0x00, MAX_FILE_PATH_LEN); - ret = aul_get_mime_from_file(filePath,tempMime,sizeof(tempMime)); - if (ret < AUL_R_OK ) - strncpy(tempMime, mime, MAX_FILE_PATH_LEN-1); - else - DP_LOG("mime from extension name[%s]",tempMime); - } - } - - /* Search a content type from mime table. */ - for (i = 0; i < MAX_MIME_TABLE_NUM; i++) - { - //DP_LOG("TableMime[%d][%s]",i,MimeTable[i].mime); - if (strncmp(MimeTable[i].mime, tempMime, strlen(tempMime)) == 0){ - type = MimeTable[i].contentType; - break; - } - } - /* If there is no mime at mime table, check the category with the first - * domain of mime string - * ex) video/... => video type */ - if (type == DP_CONTENT_UNKOWN) - { - const char *unaliasedMime = NULL; - /* unaliased_mimetype means representative mime among similar types */ - unaliasedMime = xdg_mime_unalias_mime_type(tempMime); - - if (unaliasedMime != NULL) { - DP_LOG("unaliased mime type[%s]\n",unaliasedMime); - if (strstr(unaliasedMime,"video/") != NULL) - type = DP_CONTENT_VIDEO; - else if (strstr(unaliasedMime,"audio/") != NULL) - type = DP_CONTENT_MUSIC; - else if (strstr(unaliasedMime,"image/") != NULL) - type = DP_CONTENT_IMAGE; - } - } - DP_LOG("type[%d]\n",type); - return type; -} - -bool DownloadUtil::isAmbiguousMIMEType(const char *mimeType) -{ - - if (!mimeType) - return false; - - int index = 0; - int listSize = sizeof(ambiguousMIMETypeList) / sizeof(const char *); - for (index = 0; index < listSize; index++) { - if (0 == strncmp(mimeType, ambiguousMIMETypeList[index], - strlen(ambiguousMIMETypeList[index]))) { - DP_LOG("It is ambiguous! [%s]", ambiguousMIMETypeList[index]); - return true; - } - } - - return false; -} - diff --git a/src/download-provider-utils.c b/src/download-provider-utils.c new file mode 100644 index 0000000..8b43cd9 --- /dev/null +++ b/src/download-provider-utils.c @@ -0,0 +1,170 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <sys/time.h> +#include <sys/socket.h> + +#include "download-provider-config.h" +#include "download-provider-notification.h" +#include "download-provider-pthread.h" +#include "download-provider-log.h" + +extern fd_set g_download_provider_socket_readset; +extern fd_set g_download_provider_socket_exceptset; + +int get_download_request_id(void) +{ + int uniquetime = 0; + struct timeval tval; + static int last_uniquetime = 0; + + do { + uniquetime = (int)time(NULL); + gettimeofday(&tval, NULL); + if (tval.tv_usec == 0) + uniquetime = uniquetime + (tval.tv_usec + 1) % 0xfffff; + else + uniquetime = uniquetime + tval.tv_usec; + TRACE_DEBUG_MSG("ID : %d", uniquetime); + } while (last_uniquetime == uniquetime); + last_uniquetime = uniquetime; // store + return uniquetime; +} + +void clear_socket(download_clientinfo *clientinfo) +{ + if (!clientinfo) + return; + if (clientinfo->clientfd) { + FD_CLR(clientinfo->clientfd, &g_download_provider_socket_readset); + FD_CLR(clientinfo->clientfd, &g_download_provider_socket_exceptset); + shutdown(clientinfo->clientfd, 0); + fdatasync(clientinfo->clientfd); + close(clientinfo->clientfd); + clientinfo->clientfd = 0; + } +} + +void clear_clientinfo(download_clientinfo *clientinfo) +{ + TRACE_DEBUG_MSG("[TEST] clear [%p]",clientinfo); + // clear this slot + if (!clientinfo) + return; + + clear_socket(clientinfo); + + CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); + if (clientinfo->requestinfo) { + clientinfo->requestinfo->requestid = 0; + if (clientinfo->requestinfo->client_packagename.length > 0 + && clientinfo->requestinfo->client_packagename.str) + free(clientinfo->requestinfo->client_packagename.str); + clientinfo->requestinfo->client_packagename.str = NULL; + if (clientinfo->requestinfo->url.str) + free(clientinfo->requestinfo->url.str); + clientinfo->requestinfo->url.str = NULL; + if (clientinfo->requestinfo->install_path.str) + free(clientinfo->requestinfo->install_path.str); + clientinfo->requestinfo->install_path.str = NULL; + if (clientinfo->requestinfo->filename.str) + free(clientinfo->requestinfo->filename.str); + clientinfo->requestinfo->filename.str = NULL; + if (clientinfo->requestinfo->headers.rows) { + int i = 0; + for (i = 0; i < clientinfo->requestinfo->headers.rows; + i++) { + if (clientinfo->requestinfo->headers.str[i].str) + free(clientinfo->requestinfo->headers. + str[i].str); + clientinfo->requestinfo->headers.str[i].str = + NULL; + } + free(clientinfo->requestinfo->headers.str); + clientinfo->requestinfo->headers.str = NULL; + } + free(clientinfo->requestinfo); + clientinfo->requestinfo = NULL; + } + if (clientinfo->downloadinginfo) + free(clientinfo->downloadinginfo); + clientinfo->downloadinginfo = NULL; + if (clientinfo->downloadinfo) + free(clientinfo->downloadinfo); + clientinfo->downloadinfo = NULL; + if (clientinfo->tmp_saved_path) + free(clientinfo->tmp_saved_path); + clientinfo->tmp_saved_path = NULL; + if (clientinfo->ui_notification_handle || clientinfo->service_handle) + destroy_appfw_notification(clientinfo); + CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); + CLIENT_MUTEX_DESTROY(&(clientinfo->client_mutex)); + memset(clientinfo, 0x00, sizeof(download_clientinfo)); + free(clientinfo); + clientinfo = NULL; +} + +void clear_clientinfoslot(download_clientinfo_slot *clientinfoslot) +{ + TRACE_DEBUG_MSG(""); + // clear this slot + if (!clientinfoslot) + return; + download_clientinfo *clientinfo = + (download_clientinfo *) clientinfoslot->clientinfo; + clear_clientinfo(clientinfo); + clientinfoslot->clientinfo = NULL; +} + +int get_downloading_count(download_clientinfo_slot *clientinfo_list) +{ + int count = 0; + int i = 0; + for (i = 0; i < MAX_CLIENT; i++) { + if (clientinfo_list[i].clientinfo) { + if (clientinfo_list[i].clientinfo->state == + DOWNLOAD_STATE_DOWNLOADING + || clientinfo_list[i].clientinfo->state == + DOWNLOAD_STATE_INSTALLING + || clientinfo_list[i].clientinfo->state == + DOWNLOAD_STATE_READY) + count++; + } + } + return count; +} + +int get_same_request_slot_index(download_clientinfo_slot *clientinfo_list, + int requestid) +{ + int i = 0; + + if (!clientinfo_list || !requestid) + return -1; + + for (i = 0; i < MAX_CLIENT; i++) { + if (clientinfo_list[i].clientinfo + && clientinfo_list[i].clientinfo->requestinfo) { + if (clientinfo_list[i].clientinfo->requestinfo-> + requestid == requestid) { + return i; + } + } + } + return -1; +} + +int get_empty_slot_index(download_clientinfo_slot *clientinfo_list) +{ + int i = 0; + + if (!clientinfo_list) + return -1; + + for (i = 0; i < MAX_CLIENT; i++) + if (!clientinfo_list[i].clientinfo) + return i; + return -1; +} diff --git a/src/download-provider-view.cpp b/src/download-provider-view.cpp deleted file mode 100644 index 102d034..0000000 --- a/src/download-provider-view.cpp +++ /dev/null @@ -1,1174 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-view.cpp - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief UI manager class for download list view and delete view - */ -#include <sstream> -#include <queue> -#include "download-provider-view.h" -#include "download-provider-history-db.h" -#include "download-provider-downloadItem.h" - -static void destroy_window_cb(void *data, Evas_Object *obj, void *event); - -enum { - DOWNLOAD_NOTIFY_SELECTED, - DOWNLOAD_NOTIFY_DELETED -}; - -DownloadView::DownloadView(void) - : eoWindow(NULL) - , eoBackground(NULL) - , eoLayout(NULL) - , eoNaviBar(NULL) - , eoNaviBarItem(NULL) - , eoBackBtn(NULL) - , eoControlBar(NULL) - , eoCbItemDelete(NULL) - , eoCbItemCancel(NULL) - , eoCbItemEmpty(NULL) - , eoBoxLayout(NULL) - , eoBox(NULL) - , eoDldList(NULL) - , eoPopup(NULL) - , eoSelectAllLayout(NULL) - , eoAllCheckedBox(NULL) - , eoNotifyInfo(NULL) - , eoNotifyInfoLayout(NULL) - , m_allChecked(EINA_FALSE) - , m_viewItemCount(0) -{ -// FIXME Later : init private members - DownloadEngine &engine = DownloadEngine::getInstance(); - engine.initEngine(); - DateUtil &inst = DateUtil::getInstance(); - inst.updateLocale(); - dldGenlistGroupStyle.item_style = "grouptitle"; - dldGenlistGroupStyle.func.text_get = getGenlistGroupLabelCB; - dldGenlistGroupStyle.func.content_get = NULL; - dldGenlistGroupStyle.func.state_get = NULL; - dldGenlistGroupStyle.func.del = NULL; - - m_today.setType(DATETIME::DATE_TYPE_TODAY); - m_yesterday.setType(DATETIME::DATE_TYPE_YESTERDAY); - m_previousDay.setType(DATETIME::DATE_TYPE_PREVIOUS); -} - -DownloadView::~DownloadView() -{ - DP_LOG_FUNC(); - DownloadEngine &engine = DownloadEngine::getInstance(); - engine.deinitEngine(); -} - -Evas_Object *DownloadView::create(void) -{ - Evas_Object *window = NULL; - window = createWindow(PACKAGE); - if (!window) - return NULL; - - createBackground(window); - createLayout(window); - setIndicator(window); - createView(); - - return window; -} - -void DownloadView::show() -{ - DP_LOG_FUNC(); - elm_win_raise(eoWindow); - handleUpdateDateGroupType(NULL); -} - -void DownloadView::hide() -{ - DP_LOG_FUNC(); - removePopup(); - destroyNotifyInfo(); - if (isGenlistEditMode()) { - hideGenlistEditMode(); - } - elm_win_lower(eoWindow); -} - -void DownloadView::activateWindow() -{ - if (!eoWindow) - create(); - - show(); -} - -void DownloadView::showViewItem(int id, const char *title) -{ - DP_LOG_FUNC(); -} - -/* This is called by AUL view mode */ -void DownloadView::playContent(int id, const char *title) -{ - DP_LOG_FUNC(); -} - -void DownloadView::setIndicator(Evas_Object *window) -{ - elm_win_indicator_mode_set(window, ELM_WIN_INDICATOR_SHOW); -} - -Evas_Object *DownloadView::createWindow(const char *windowName) -{ - eoWindow = elm_win_add(NULL, windowName, ELM_WIN_BASIC); - if (eoWindow) { - elm_win_title_set(eoWindow, __("IDS_BR_HEADER_DOWNLOAD_MANAGER")); - elm_win_borderless_set(eoWindow, EINA_TRUE); - elm_win_conformant_set(eoWindow, 1); - evas_object_smart_callback_add(eoWindow, "delete,request", - destroy_window_cb, static_cast<void*>(this)); - } - return eoWindow; -} - -Evas_Object *DownloadView::createBackground(Evas_Object *window) -{ - if (!window) - return NULL; - - eoBackground = elm_bg_add(window); - if (eoBackground) { - evas_object_size_hint_weight_set(eoBackground, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_win_resize_object_add(window, eoBackground); - evas_object_show(eoBackground); - } else { - DP_LOGE("Fail to create bg object"); - } - return eoBackground; -} - -Evas_Object *DownloadView::createLayout(Evas_Object *parent) -{ - if (!parent) { - DP_LOGE("Invalid Paramter"); - return NULL; - } - - eoLayout = elm_layout_add(parent); - if (eoLayout) { - if (!elm_layout_theme_set(eoLayout, "layout", "application", "default" )) - DP_LOGE("Fail to set elm_layout_theme_set"); - - evas_object_size_hint_weight_set(eoLayout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_win_resize_object_add(parent, eoLayout); - - edje_object_signal_emit(elm_layout_edje_get(eoLayout), "elm,state,show,indicator", "elm"); - evas_object_show(eoLayout); - } else { - DP_LOGE("Fail to create layout"); - } - return eoLayout; -} - -void DownloadView::createView() -{ - DP_LOG_FUNC(); - createNaviBar(); - createList(); - if (m_viewItemCount < 1) - showEmptyView(); -} - -void DownloadView::createNaviBar() -{ - DP_LOGD_FUNC(); - eoNaviBar = elm_naviframe_add(eoLayout); - elm_object_part_content_set(eoLayout, "elm.swallow.content", eoNaviBar); - createBackBtn(); - createBox(); - eoNaviBarItem = elm_naviframe_item_push(eoNaviBar, - __("IDS_BR_HEADER_DOWNLOAD_MANAGER"),eoBackBtn, NULL, eoBoxLayout, NULL); - createControlBar(); - evas_object_show(eoNaviBar); - -} - -void DownloadView::createBackBtn() -{ - DP_LOGD_FUNC(); - eoBackBtn = elm_button_add(eoNaviBar); - elm_object_style_set(eoBackBtn, "naviframe/end_btn/default"); - evas_object_smart_callback_add(eoBackBtn, "clicked", backBtnCB,NULL); - evas_object_show(eoBackBtn); -} - -void DownloadView::createControlBar() -{ - DP_LOGD_FUNC(); - - eoControlBar = elm_toolbar_add(eoNaviBar); - if (eoControlBar == NULL) - return; - elm_toolbar_shrink_mode_set(eoControlBar, ELM_TOOLBAR_SHRINK_EXPAND); - eoCbItemDelete = elm_toolbar_item_append(eoControlBar, NULL, - S_("IDS_COM_OPT_DELETE"), cbItemDeleteCB, eoNaviBar); - eoCbItemEmpty = elm_toolbar_item_append(eoControlBar, NULL, NULL, NULL, NULL); - elm_object_item_part_content_set(eoNaviBarItem, "controlbar", - eoControlBar); - elm_object_item_disabled_set(eoCbItemDelete, EINA_TRUE); - elm_object_item_disabled_set(eoCbItemEmpty, EINA_TRUE); - evas_object_show(eoControlBar); -} - -void DownloadView::createBox() -{ - DP_LOGD_FUNC(); - eoBoxLayout = elm_layout_add(eoNaviBar); - elm_layout_theme_set(eoBoxLayout, "layout", "application", "noindicator"); - evas_object_size_hint_weight_set(eoBoxLayout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - - eoBox = elm_box_add(eoBoxLayout); - elm_object_part_content_set(eoBoxLayout, "elm.swallow.content", eoBox ); - - evas_object_show(eoBox); - evas_object_show(eoBoxLayout); -} - -void DownloadView::createList() -{ - //DP_LOGD_FUNC(); - eoDldList = elm_genlist_add(eoBoxLayout); - DP_LOGD("create::eoDldList[%p]",eoDldList); -/* When using ELM_LIST_LIMIT, the window size is broken at the landscape mode */ - evas_object_size_hint_weight_set(eoDldList, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(eoDldList, EVAS_HINT_FILL, EVAS_HINT_FILL); - elm_genlist_homogeneous_set(eoDldList, EINA_TRUE); - elm_genlist_block_count_set(eoDldList,8); - - elm_box_pack_end(eoBox, eoDldList); - evas_object_show(eoDldList); -} - -void destroy_window_cb(void *data, Evas_Object *obj, void *event) -{ - DP_LOG_FUNC(); - elm_exit(); -} - -void DownloadView::changedRegion() -{ - DateUtil &inst = DateUtil::getInstance(); - inst.updateLocale(); - elm_genlist_realized_items_update(eoDldList); -} - -void DownloadView::attachViewItem(ViewItem *viewItem) -{ - DP_LOG_FUNC(); - if (m_viewItemCount < 1) { - hideEmptyView(); - createList(); - } - if (viewItem) { - addViewItemToGenlist(viewItem); - m_viewItemCount++; - } -} - -void DownloadView::detachViewItem(ViewItem *viewItem) -{ - DP_LOG("delete viewItem[%p]",viewItem); - if (viewItem) { - delete viewItem; - m_viewItemCount--; - } - if (!isGenlistEditMode() && - (m_viewItemCount < 1)) - showEmptyView(); -} - -void DownloadView::update() -{ - Elm_Object_Item *it = NULL; - DP_LOG_FUNC(); - if (!eoDldList) { - DP_LOGE("download list is NULL"); - return; - } - it = elm_genlist_first_item_get(eoDldList); - while (it) { - DP_LOGD("glItem[%p]",it); - elm_genlist_item_update(it); - it = elm_genlist_item_next_get(it); - } -} - -void DownloadView::update(ViewItem *viewItem) -{ - if (!viewItem) - return; - - DP_LOG("DownloadView::update viewItem [%p]", viewItem); - elm_genlist_item_update(viewItem->genlistItem()); -} - -void DownloadView::update(Elm_Object_Item *glItem) -{ - if (!glItem) - return; - - DP_LOG("DownloadView::update glItem [%p]", glItem); - elm_genlist_item_update(glItem); -} - -void DownloadView::addViewItemToGenlist(ViewItem *viewItem) -{ - DP_LOG_FUNC(); - handleUpdateDateGroupType(viewItem); - createGenlistItem(viewItem); -} - -void DownloadView::createGenlistItem(ViewItem *viewItem) -{ - Elm_Object_Item *glItem = NULL; - Elm_Object_Item *glGroupItem = NULL; - /* EAPI Elm_Object_Item *elm_genlist_item_prepend( - * Evas_Object *obj, - * const Elm_Genlist_Item_Class *itc, - * const void *data, - * Elm_Object_Item *parent, - * Elm_Genlist_Item_Type flags, - * Evas_Smart_Cb func, - * const void *func_data) EINA_ARG_NONNULL(1); */ - glGroupItem = getGenlistGroupItem(viewItem->dateGroupType()); - DP_LOGD("group item[%p]",glGroupItem); - if (!glGroupItem) { - DateGroup *dateGrpObj = getDateGroupObj(viewItem->dateGroupType()); - if (!viewItem->isFinished()) { - glGroupItem = elm_genlist_item_prepend( - eoDldList, - &dldGenlistGroupStyle, - static_cast<const void*>(dateGrpObj), - NULL, - ELM_GENLIST_ITEM_GROUP, - NULL, - NULL); - } else { - /* Download History Item */ - glGroupItem = elm_genlist_item_append( - eoDldList, - &dldGenlistGroupStyle, - static_cast<const void*>(dateGrpObj), - NULL, - ELM_GENLIST_ITEM_GROUP, - NULL, - NULL); - } - if (!glGroupItem) - DP_LOGE("Fail to add a genlist group item"); - else - elm_genlist_item_select_mode_set(glGroupItem, - ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY); - setGenlistGroupItem(viewItem->dateGroupType(), glGroupItem); - } - increaseGenlistGroupCount(viewItem->dateGroupType()); - if (!viewItem->isFinished()) { - glItem = elm_genlist_item_insert_after( - eoDldList, - viewItem->elmGenlistStyle(), - static_cast<const void*>(viewItem), - glGroupItem, - glGroupItem, - ELM_GENLIST_ITEM_NONE, - genlistClickCB, - static_cast<const void*>(viewItem)); - } else { - /* Download History Item */ - glItem = elm_genlist_item_append( - eoDldList, - viewItem->elmGenlistStyle(), - static_cast<const void*>(viewItem), - glGroupItem, - ELM_GENLIST_ITEM_NONE, - genlistClickCB, - static_cast<const void*>(viewItem)); - } - if (!glItem) - DP_LOGE("Fail to add a genlist item"); - - DP_LOGD("genlist groupItem[%p] item[%p] viewItem[%p]", glGroupItem, glItem, viewItem); - viewItem->setGenlistItem(glItem); - /* Move scrollbar to top. - * When groupItem means today group in case of addtion of download link item - **/ - if (!viewItem->isFinished()) - elm_genlist_item_show(glGroupItem, ELM_GENLIST_ITEM_SCROLLTO_TOP); - -} - -void DownloadView::showEmptyView() -{ - DP_LOGD_FUNC(); - if (!eoEmptyNoContent) { - eoEmptyNoContent = elm_layout_add(eoLayout); - elm_layout_theme_set(eoEmptyNoContent, "layout", "nocontents", "text"); - evas_object_size_hint_weight_set(eoEmptyNoContent, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(eoEmptyNoContent, EVAS_HINT_FILL, EVAS_HINT_FILL); - elm_object_part_text_set(eoEmptyNoContent, "elm.text", - __("IDS_DL_BODY_NO_DOWNLOADS")); - evas_object_size_hint_weight_set (eoEmptyNoContent, - EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - - if (eoDldList) { - elm_box_unpack(eoBox,eoDldList); - /* Detection code */ - DP_LOGD("del::eoDldList[%p]",eoDldList); - evas_object_del(eoDldList); - eoDldList = NULL; - } - elm_box_pack_start(eoBox, eoEmptyNoContent); - } - evas_object_show(eoEmptyNoContent); - elm_object_item_disabled_set(eoCbItemDelete, EINA_TRUE); -} - -void DownloadView::hideEmptyView() -{ - DP_LOGD_FUNC(); - if(eoEmptyNoContent) { - elm_box_unpack(eoBox, eoEmptyNoContent); - evas_object_del(eoEmptyNoContent); - eoEmptyNoContent = NULL; - } - elm_object_item_disabled_set(eoCbItemDelete, EINA_FALSE); -} - -bool DownloadView::isGenlistEditMode() -{ - return (bool)elm_genlist_decorate_mode_get(eoDldList); -} - -void DownloadView::createSelectAllLayout() -{ - eoSelectAllLayout = elm_layout_add(eoBox); - elm_layout_theme_set(eoSelectAllLayout, "genlist", "item", - "select_all/default"); - evas_object_size_hint_weight_set(eoSelectAllLayout, EVAS_HINT_EXPAND, - EVAS_HINT_FILL); - evas_object_size_hint_align_set(eoSelectAllLayout, EVAS_HINT_FILL, - EVAS_HINT_FILL); - evas_object_event_callback_add(eoSelectAllLayout, EVAS_CALLBACK_MOUSE_DOWN, - selectAllClickedCB, NULL); - eoAllCheckedBox = elm_check_add(eoSelectAllLayout); - elm_check_state_pointer_set(eoAllCheckedBox, &m_allChecked); - evas_object_smart_callback_add(eoAllCheckedBox, "changed", - selectAllChangedCB, NULL); - evas_object_propagate_events_set(eoAllCheckedBox, EINA_FALSE); - elm_object_part_content_set(eoSelectAllLayout, "elm.icon", eoAllCheckedBox); - elm_object_text_set(eoSelectAllLayout, S_("IDS_COM_BODY_SELECT_ALL")); - elm_box_pack_start(eoBox, eoSelectAllLayout); - evas_object_show(eoSelectAllLayout); - m_allChecked = EINA_FALSE; -} - -void DownloadView::changeAllCheckedValue() -{ - m_allChecked = !m_allChecked; - elm_check_state_pointer_set(eoAllCheckedBox, &m_allChecked); - handleChangedAllCheckedState(); -} - -void DownloadView::destroyCheckedItem() -{ - Eina_List *list = NULL; - Elm_Object_Item *it = NULL; - ViewItem *item = NULL; - int checkedCount = 0; - queue <unsigned int> deleteQueue; - - DP_LOGD_FUNC(); - - it = elm_genlist_first_item_get(eoDldList); - - while (it) { - item = (ViewItem *)elm_object_item_data_get(it); - /* elm_genlist_item_select_mode_get is needed to check group item */ - if (elm_genlist_item_select_mode_get(it) != - ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY && - item && item->checkedValue()) { - list = eina_list_append(list, it); - } - it = elm_genlist_item_next_get(it); - } - - if (!list) { - DP_LOGD("There is no delete item"); - return; - } - - checkedCount = eina_list_count(list); - if (checkedCount < 1) - return; - DP_LOGD("checkedCount[%d]", checkedCount); - - for (int i = 0; i < checkedCount; i++) - { - it = (Elm_Object_Item *)eina_list_data_get(list); - if (it) - item = (ViewItem *)elm_object_item_data_get(it); - else - DP_LOGE("genlist item is null"); - list = eina_list_next(list); - if (item) { - deleteQueue.push(item->historyId()); - item->destroy(); - } else { - DP_LOGE("viewItem is null"); - } - } - if (list) - eina_list_free(list); - - DownloadHistoryDB::deleteMultipleItem(deleteQueue); - showNotifyInfo(DOWNLOAD_NOTIFY_DELETED, checkedCount); - hideGenlistEditMode(); -} - -void DownloadView::showGenlistEditMode() -{ - DP_LOG_FUNC(); - /* Initialize notify info widget */ - destroyNotifyInfo(); - elm_object_item_text_set(eoNaviBarItem, S_("IDS_COM_OPT_DELETE")); - /* Change layoutbackground color to edit mode color */ - elm_object_style_set(eoBackground, "edit_mode"); - /* Disable the back button of control bar */ - elm_object_item_part_content_unset(eoNaviBarItem, "prev_btn"); - destroyEvasObj(eoBackBtn); - - if (eoCbItemEmpty) - elm_object_item_del(eoCbItemEmpty); - eoCbItemCancel = elm_toolbar_item_append(eoControlBar, NULL, - S_("IDS_COM_SK_CANCEL"), cbItemCancelCB, eoNaviBar); - - /* Append 'Select All' layout */ - createSelectAllLayout(); - /* Set reorder end edit mode */ - elm_genlist_reorder_mode_set(eoDldList, EINA_TRUE); - elm_genlist_decorate_mode_set(eoDldList, EINA_TRUE); - /* This means even if the ouside of checked box is selected, - it is same to click a check box. */ - elm_genlist_select_mode_set(eoDldList, ELM_OBJECT_SELECT_MODE_ALWAYS); - - Elm_Object_Item *it = NULL; - ViewItem *viewItem = NULL; - it = elm_genlist_first_item_get(eoDldList); - while (it) { - viewItem = (ViewItem *)elm_object_item_data_get(it); - if (elm_genlist_item_select_mode_get(it) != - ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY && - viewItem && !(viewItem->isFinished())) - elm_object_item_disabled_set(it, EINA_TRUE); - it = elm_genlist_item_next_get(it); - } - elm_object_item_disabled_set(eoCbItemDelete, EINA_TRUE); -} - -void DownloadView::hideGenlistEditMode() -{ - DP_LOG_FUNC(); - - elm_object_item_text_set(eoNaviBarItem, __("IDS_BR_HEADER_DOWNLOAD_MANAGER")); - elm_object_style_set(eoBackground, "default"); - - /* Recreate back button */ - createBackBtn(); - elm_object_item_part_content_set(eoNaviBarItem, "prev_btn", eoBackBtn); - - if (eoCbItemCancel) { - elm_object_item_del(eoCbItemCancel); - eoCbItemCancel = NULL; - } - eoCbItemEmpty = elm_toolbar_item_append(eoControlBar, NULL, NULL, NULL, NULL); - elm_object_item_disabled_set(eoCbItemEmpty, EINA_TRUE); - - elm_box_unpack(eoBox, eoSelectAllLayout); - - destroyEvasObj(eoAllCheckedBox); - destroyEvasObj(eoSelectAllLayout); - - elm_genlist_reorder_mode_set(eoDldList, EINA_FALSE); - elm_genlist_decorate_mode_set(eoDldList, EINA_FALSE); - elm_genlist_select_mode_set(eoDldList, ELM_OBJECT_SELECT_MODE_DEFAULT); - - Elm_Object_Item *it = NULL; - ViewItem *viewItem = NULL; - it = elm_genlist_first_item_get(eoDldList); - while (it) { - viewItem = (ViewItem *)elm_object_item_data_get(it); - if (elm_genlist_item_select_mode_get(it) != - ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY && viewItem) { - if (elm_object_item_disabled_get(it)) - elm_object_item_disabled_set(it, EINA_FALSE); - viewItem->setCheckedValue(EINA_FALSE); - viewItem->setCheckedBtn(NULL); - } - it = elm_genlist_item_next_get(it); - } - - m_allChecked = EINA_FALSE; - - if (m_viewItemCount < 1) { - elm_object_item_disabled_set(eoCbItemDelete, EINA_TRUE); - showEmptyView(); - } else - elm_object_item_disabled_set(eoCbItemDelete, EINA_FALSE); -} - -void DownloadView::handleChangedAllCheckedState() -{ - int checkedCount = 0; - Elm_Object_Item *it = NULL; - ViewItem *viewItem = NULL; - it = elm_genlist_first_item_get(eoDldList); - while (it) { - viewItem = (ViewItem *)elm_object_item_data_get(it); - if (elm_genlist_item_select_mode_get(it) != - ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY && viewItem) { - if (viewItem->isFinished()) { - viewItem->setCheckedValue(m_allChecked); - viewItem->updateCheckedBtn(); - checkedCount++; - } - } - it = elm_genlist_item_next_get(it); - } - - if (m_allChecked && checkedCount > 0) { - elm_object_item_disabled_set(eoCbItemDelete, EINA_FALSE); - showNotifyInfo(DOWNLOAD_NOTIFY_SELECTED, checkedCount); - } else { - elm_object_item_disabled_set(eoCbItemDelete, EINA_TRUE); - showNotifyInfo(DOWNLOAD_NOTIFY_SELECTED, 0); - } -} - -void DownloadView::handleCheckedState() -{ - int checkedCount = 0; - int deleteAbleTotalCount = 0; - - DP_LOGD_FUNC(); - - Elm_Object_Item *it = NULL; - ViewItem *viewItem = NULL; - it = elm_genlist_first_item_get(eoDldList); - while (it) { - viewItem = (ViewItem *)elm_object_item_data_get(it); - if (elm_genlist_item_select_mode_get(it) != - ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY && viewItem) { - if (viewItem->checkedValue()) - checkedCount++; - if (viewItem->isFinished()) - deleteAbleTotalCount++; - } - it = elm_genlist_item_next_get(it); - } - - if (checkedCount == deleteAbleTotalCount) - m_allChecked = EINA_TRUE; - else - m_allChecked = EINA_FALSE; - elm_check_state_pointer_set(eoAllCheckedBox, &m_allChecked); - - if (checkedCount == 0) { - elm_object_item_disabled_set(eoCbItemDelete, EINA_TRUE); - destroyNotifyInfo(); - } else - elm_object_item_disabled_set(eoCbItemDelete, EINA_FALSE); - showNotifyInfo(DOWNLOAD_NOTIFY_SELECTED, checkedCount); -} -void DownloadView::createNotifyInfo() -{ - DP_LOGD_FUNC(); - eoNotifyInfo = elm_notify_add(eoBoxLayout); - elm_notify_orient_set(eoNotifyInfo, ELM_NOTIFY_ORIENT_BOTTOM); - evas_object_size_hint_weight_set(eoNotifyInfo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(eoNotifyInfo, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_event_callback_add(eoNotifyInfo, EVAS_CALLBACK_SHOW, showNotifyInfoCB, eoLayout); - evas_object_event_callback_add(eoNotifyInfo, EVAS_CALLBACK_HIDE, hideNotifyInfoCB, eoLayout); - eoNotifyInfoLayout = elm_layout_add(eoNotifyInfo); - elm_object_content_set(eoNotifyInfo, eoNotifyInfoLayout); -} - -void DownloadView::showNotifyInfo(int type, int selectedCount) -{ - string buf; - DP_LOGD_FUNC(); - - if (selectedCount == 0) { - destroyNotifyInfo(); - return; - } - - if (!eoNotifyInfo) - createNotifyInfo(); - - elm_layout_theme_set(eoNotifyInfoLayout, "standard", "selectioninfo", - "vertical/bottom_12"); - buf.append(" "); - if (type == DOWNLOAD_NOTIFY_SELECTED) { - stringstream countStr; - countStr << selectedCount; - buf = S_("IDS_COM_BODY_SELECTED"); - buf.append(" ("); - buf.append(countStr.str()); - buf.append(")"); - } else if (type == DOWNLOAD_NOTIFY_DELETED) { - buf = S_("IDS_COM_POP_DELETED"); - elm_notify_timeout_set(eoNotifyInfo, 3); - } - edje_object_part_text_set(_EDJ(eoNotifyInfoLayout), "elm.text", buf.c_str()); - evas_object_show(eoNotifyInfo); -} - -void DownloadView::destroyNotifyInfo() -{ - DP_LOGD_FUNC(); - destroyEvasObj(eoNotifyInfoLayout); - destroyEvasObj(eoNotifyInfo); - eoNotifyInfoLayout = NULL; - eoNotifyInfo = NULL; -} - -/* Static callback function */ -void DownloadView::showNotifyInfoCB(void *data, Evas *evas, Evas_Object *obj, - void *event) -{ - Evas_Object *layout = (Evas_Object *)data; - if (!data) { - DP_LOGE("data is NULL"); - return; - } - edje_object_signal_emit(_EDJ(layout), "elm,layout,content,bottom_padding", - "layout"); -} - -void DownloadView::hideNotifyInfoCB(void *data, Evas *evas, Evas_Object *obj, - void *event) -{ - Evas_Object *layout = (Evas_Object *)data; - if (!data) { - DP_LOGE("data is NULL"); - return; - } - edje_object_signal_emit(_EDJ(layout), "elm,layout,content,default", "layout"); -} - -void DownloadView::selectAllClickedCB(void *data, Evas *evas, Evas_Object *obj, - void *event_info) -{ - DownloadView &view = DownloadView::getInstance(); - DP_LOGD_FUNC(); - view.changeAllCheckedValue(); -} - -void DownloadView::selectAllChangedCB(void *data, Evas_Object *obj, - void *event_info) -{ - DownloadView &view = DownloadView::getInstance(); - DP_LOGD_FUNC(); - view.handleChangedAllCheckedState(); -} - -void DownloadView::backBtnCB(void *data, Evas_Object *obj, void *event_info) -{ - DownloadView& view = DownloadView::getInstance(); - view.hide(); -} - -void DownloadView::cbItemDeleteCB(void *data, Evas_Object *obj, void *event_info) -{ - - DownloadView& view = DownloadView::getInstance(); - if (!view.isGenlistEditMode()) - view.showGenlistEditMode(); - else - view.destroyCheckedItem(); -} - -void DownloadView::cbItemCancelCB(void *data, Evas_Object *obj, void *event_info) -{ - DownloadView& view = DownloadView::getInstance(); - view.destroyNotifyInfo(); - view.hideGenlistEditMode(); -} - -void DownloadView::genlistClickCB(void *data, Evas_Object *obj, void *event_info) -{ - ViewItem *item = reinterpret_cast<ViewItem *>(data); - DP_LOGD_FUNC(); - if (!data) { - DP_LOGE("data is NULL"); - return; - } - item->clickedGenlistItem(); -} - -void DownloadView::cancelClickCB(void *data, Evas_Object *obj, void *event_info) -{ - ViewItem *item = NULL; - - DP_LOGD_FUNC(); - - if (!data) { - DP_LOGE("data is NULL"); - return; - } - item = reinterpret_cast<ViewItem *>(data); - item->requestCancel(); - -} - -void DownloadView::showErrPopup(string &desc) -{ - removePopup(); - - eoPopup = elm_popup_add(eoWindow); - evas_object_size_hint_weight_set(eoPopup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_object_text_set(eoPopup, desc.c_str()); - elm_popup_timeout_set(eoPopup, 2); - evas_object_smart_callback_add(eoPopup, "response", errPopupResponseCB, NULL); - evas_object_show(eoPopup); -} - -void DownloadView::showOMAPopup(string &msg, ViewItem *viewItem) -{ - Evas_Object *btn1 = NULL; - Evas_Object *btn2 = NULL; - DP_LOGD_FUNC(); - /* If another popup is shown, delete it*/ - removePopup(); - eoPopup = elm_popup_add(eoWindow); - evas_object_size_hint_weight_set(eoPopup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_object_text_set(eoPopup, msg.c_str()); - elm_object_part_text_set(eoPopup, "title,text", __("IDS_BR_POP_DOWNLOAD_Q")); - btn1 = elm_button_add(eoPopup); - elm_object_text_set(btn1, S_("IDS_COM_SK_OK")); - elm_object_part_content_set(eoPopup, "button1", btn1); - evas_object_smart_callback_add(btn1, "clicked", omaPopupResponseOKCB, - viewItem); - btn2 = elm_button_add(eoPopup); - elm_object_text_set(btn2, S_("IDS_COM_POP_CANCEL")); - elm_object_part_content_set(eoPopup, "button2", btn2); - evas_object_smart_callback_add(btn2, "clicked", omaPopupResponseCancelCB, - viewItem); - evas_object_show(eoPopup); -} - -void DownloadView::errPopupResponseCB(void *data, Evas_Object *obj, void *event_info) -{ - DP_LOGD_FUNC(); - DownloadView& view = DownloadView::getInstance(); - view.removePopup(); -} - -void DownloadView::omaPopupResponseOKCB(void *data, Evas_Object *obj, - void *event_info) -{ - ViewItem *viewItem = (ViewItem *)data; - DownloadView& view = DownloadView::getInstance(); - - DP_LOGD_FUNC(); - if (viewItem) - viewItem->sendUserResponse(true); - else - DP_LOGE("No viewItem"); - view.removePopup(); -} - -void DownloadView::omaPopupResponseCancelCB(void *data, Evas_Object *obj, - void *event_info) -{ - ViewItem *viewItem = (ViewItem *)data; - DownloadView& view = DownloadView::getInstance(); - - DP_LOGD_FUNC(); - if (viewItem) - viewItem->sendUserResponse(false); - else - DP_LOGE("No viewItem"); - view.removePopup(); -} - -void DownloadView::removePopup() -{ - DP_LOGD_FUNC(); - destroyEvasObj(eoPopup); -} - -DateGroup *DownloadView::getDateGroupObj(int type) -{ - DateGroup *obj = NULL; - switch (type) { - case DATETIME::DATE_TYPE_LATER: - case DATETIME::DATE_TYPE_TODAY: - obj = &m_today; - break; - case DATETIME::DATE_TYPE_YESTERDAY: - obj = &m_yesterday; - break; - case DATETIME::DATE_TYPE_PREVIOUS: - obj = &m_previousDay; - break; - default: - obj = NULL; - DP_LOGE("Cannot enter here"); - } - return obj; -} - -Elm_Object_Item *DownloadView::getGenlistGroupItem(int type) -{ - DateGroup *obj = getDateGroupObj(type); - if (!obj) - return NULL; - return obj->glGroupItem(); -} - -void DownloadView::setGenlistGroupItem(int type, Elm_Object_Item *item) -{ - DateGroup *obj = getDateGroupObj(type); - if (!obj) - return; - obj->setGlGroupItem(item); -} - -void DownloadView::increaseGenlistGroupCount(int type) -{ - DateGroup *obj = getDateGroupObj(type); - if (!obj) - return; - if (type == DATETIME::DATE_TYPE_TODAY || type == DATETIME::DATE_TYPE_LATER) { - if (m_today.getCount() < 1) { - DateUtil &inst = DateUtil::getInstance(); - inst.setTodayStandardTime(); - } - } - obj->increaseCount(); - DP_LOGD("increased count[%d]",obj->getCount()); -} - -int DownloadView::getGenlistGroupCount(int type) -{ - DateGroup *obj = getDateGroupObj(type); - if (!obj) - return 0; - DP_LOGD("Group count[%d]",obj->getCount()); - return obj->getCount(); -} - -void DownloadView::handleGenlistGroupItem(int type) -{ - DateGroup *obj = getDateGroupObj(type); - if (!obj) - return; - obj->decreaseCount(); - DP_LOGD("count[%d]type[%d]",obj->getCount(),type); - if (obj->getCount() < 1) { - //DP_LOGD("Group Item[%p][%d]", obj->glGroupItem(),type); - elm_object_item_del(obj->glGroupItem()); - obj->setGlGroupItem(NULL); - } -} - -void DownloadView::handleUpdateDateGroupType(ViewItem *viewItem) -{ - int diffDays = 0; - DateUtil &inst = DateUtil::getInstance(); - DP_LOGD_FUNC(); - diffDays = inst.getDiffDaysFromToday(); - if (viewItem) { - /* Update a view item which is added now - * This should be only called when attaching item - **/ - viewItem->extractDateGroupType(); - } else if (diffDays != 0) { - /* FIXME later - * Now, it is recreated download items and group items. - * Consider to move only group item later. - * This should be only called from show() function - **/ -/* FIXME later - * Another problem is happend becuase eina list is used repacing with vector */ -#if 0 - cleanGenlistData(); - Elm_Object_Item *it = NULL; - ViewItem *viewItem = NULL; - it = elm_genlist_first_item_get(eoDldList); - while (it) { - viewItem = (ViewItem *)elm_object_item_data_get(it); - if (!viewItem || elm_genlist_item_select_mode_get(it) != - ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) - continue; - viewItem->extractDateGroupType(); - createGenlistItem(viewItem); - it = elm_genlist_item_next_get(it); - } -#endif - } - inst.setTodayStandardTime(); -} - -void DownloadView::moveRetryItem(ViewItem *viewItem) -{ - Elm_Object_Item *todayGroupItem = NULL; - Elm_Object_Item *firstItem = NULL; - DP_LOGD_FUNC(); - if (!viewItem) { - DP_LOGE("view item is NULL"); - return; - } - firstItem = elm_genlist_first_item_get(eoDldList); - if (firstItem) { - DP_LOGD("groupItem[%p] viewItem[%p]", firstItem, viewItem); - /* This is group item */ - if (elm_genlist_item_select_mode_get(firstItem) == - ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) { - /* The top item is the item after group item */ - firstItem = elm_genlist_item_next_get(firstItem); - DP_LOGD("firstItem[%p], present item[%p]", firstItem, viewItem->genlistItem()); - if (firstItem == viewItem->genlistItem()) { - DP_LOGD("This is already top item. Don't need to move"); - return; - } - } - } - elm_object_item_del(viewItem->genlistItem()); - viewItem->setGenlistItem(NULL); - handleGenlistGroupItem(viewItem->dateGroupType()); - todayGroupItem = getGenlistGroupItem(DATETIME::DATE_TYPE_TODAY); - if (!todayGroupItem) { - DateGroup *dateGrpObj = getDateGroupObj(DATETIME::DATE_TYPE_TODAY); - todayGroupItem = elm_genlist_item_prepend( - eoDldList, - &dldGenlistGroupStyle, - static_cast<const void*>(dateGrpObj), - NULL, - ELM_GENLIST_ITEM_GROUP, - NULL, - NULL); - setGenlistGroupItem(DATETIME::DATE_TYPE_TODAY, todayGroupItem); - if (!todayGroupItem) - DP_LOGE("Fail to add a genlist group item"); - else - elm_genlist_item_select_mode_set(todayGroupItem, - ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY); - } - increaseGenlistGroupCount(DATETIME::DATE_TYPE_TODAY); - Elm_Object_Item *glItem = elm_genlist_item_insert_after( - eoDldList, - viewItem->elmGenlistStyle(), - static_cast<const void*>(viewItem), - todayGroupItem, - todayGroupItem, - ELM_GENLIST_ITEM_NONE, - genlistClickCB, - static_cast<const void*>(viewItem)); - if (!glItem) - DP_LOGE("Fail to add a genlist item"); - DP_LOGD("genlist groupItem[%p] item[%p] viewItem[%p]", todayGroupItem, - glItem, viewItem); - viewItem->setGenlistItem(glItem); - elm_genlist_item_show(todayGroupItem, ELM_GENLIST_ITEM_SCROLLTO_TOP); - viewItem->extractDateGroupType(); -} - -char *DownloadView::getGenlistGroupLabel(void *data, Evas_Object *obj, const char *part) -{ - DateGroup *dateGrp = static_cast<DateGroup *>(data); - - if(!data || !obj || !part) - return NULL; - - DP_LOGD("ViewItem::getListGroupLabel:part[%s] groupDateType[%d] obj[%p]", part, dateGrp->getType(), obj); - if (strncmp(part, "elm.text", strlen("elm.text")) == 0) { - DateUtil &inst = DateUtil::getInstance(); - string msg; - string outBuf; - double udateTime = 0; - switch (dateGrp->getType()) { - case DATETIME::DATE_TYPE_PREVIOUS: - msg = S_("IDS_COM_BODY_PREVIOUS_DAYS"); - break; - case DATETIME::DATE_TYPE_YESTERDAY: - udateTime = inst.yesterdayTime()*1000; - msg = S_("IDS_COM_BODY_YESTERDAY"); - msg += " ("; - inst.getDateStr(LOCALE_STYLE::FULL_DATE, udateTime, outBuf); - msg += outBuf; - msg += ")"; - break; - case DATETIME::DATE_TYPE_LATER: - case DATETIME::DATE_TYPE_TODAY: - udateTime = inst.nowTime()*1000; - msg = S_("IDS_COM_BODY_TODAY"); - msg += " ("; - inst.getDateStr(LOCALE_STYLE::FULL_DATE, udateTime, outBuf); - msg += outBuf; - msg += ")"; - break; - default : - DP_LOGE("Cannot enter here"); - return NULL; - } - return strdup(msg.c_str()); - } - return NULL; -} - -char *DownloadView::getGenlistGroupLabelCB(void *data, Evas_Object *obj, const char *part) -{ -// DP_LOGD_FUNC(); - if(!data || !obj || !part) - return NULL; - - DownloadView &view = DownloadView::getInstance(); - return view.getGenlistGroupLabel(data, obj, part); -} - -void DownloadView::cleanGenlistData() -{ - Elm_Object_Item *grpItem = NULL; - DP_LOGD_FUNC(); - grpItem = m_today.glGroupItem(); - if (grpItem) - elm_object_item_del(grpItem); - m_today.initData(); - grpItem = m_yesterday.glGroupItem(); - if (grpItem) - elm_object_item_del(grpItem); - m_yesterday.initData(); - grpItem = m_previousDay.glGroupItem(); - if (grpItem) - elm_object_item_del(grpItem); - m_previousDay.initData(); - elm_genlist_clear(eoDldList); -} - diff --git a/src/download-provider-viewItem.cpp b/src/download-provider-viewItem.cpp deleted file mode 100644 index 2f4ca8a..0000000 --- a/src/download-provider-viewItem.cpp +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-viewItem.cpp - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief item data class for download view - */ -#include "download-provider-viewItem.h" -#include "download-provider-items.h" -#include "download-provider-view.h" - -ViewItem::ViewItem(Item *item) - : m_item(item) - , m_glItem(NULL) - , m_progressBar(NULL) - , m_checkedBtn(NULL) - , m_checked(EINA_FALSE) - , m_isRetryCase(false) - , m_dateGroupType(DATETIME::DATE_TYPE_NONE) -{ - // FIXME need to makes exchange subject?? not yet, but keep it in mind! - if (item) { - m_aptr_observer = auto_ptr<Observer>( - new Observer(updateCB, this, "viewItemObserver")); - item->subscribe(m_aptr_observer.get()); - } - - dldGenlistStyle.item_style = "3text.3icon"; - dldGenlistStyle.func.text_get = getGenlistLabelCB; - dldGenlistStyle.func.content_get = getGenlistIconCB; - dldGenlistStyle.func.state_get = NULL; - dldGenlistStyle.func.del = NULL; - dldGenlistStyle.decorate_all_item_style = "edit_default"; - - dldHistoryGenlistStyle.item_style = "3text.1icon.2"; - dldHistoryGenlistStyle.func.text_get = getGenlistLabelCB; - dldHistoryGenlistStyle.func.content_get = getGenlistIconCB; - dldHistoryGenlistStyle.func.state_get = NULL; - dldHistoryGenlistStyle.func.del = NULL; - dldHistoryGenlistStyle.decorate_all_item_style = "edit_default"; - - dldGenlistSlideStyle.item_style = "3text.1icon.2"; - dldGenlistSlideStyle.func.text_get = getGenlistLabelCB; - dldGenlistSlideStyle.func.content_get= getGenlistIconCB; - dldGenlistSlideStyle.func.state_get = NULL; - dldGenlistSlideStyle.func.del = NULL; - dldGenlistSlideStyle.decorate_all_item_style = "edit_default"; - -} - -ViewItem::~ViewItem() -{ - DP_LOGD_FUNC(); -} - -void ViewItem::create(Item *item) -{ - ViewItem *newViewItem = new ViewItem(item); - - DownloadView &view = DownloadView::getInstance(); - view.attachViewItem(newViewItem); -} - -void ViewItem::destroy() -{ - DP_LOGD("ViewItem::destroy"); - /* After item is destory, - view item also will be destroyed through event system */ - if (m_item) - m_item->destroy(); -} - -void ViewItem::updateCB(void *data) -{ - if (data) - static_cast<ViewItem*>(data)->updateFromItem(); -} - -void ViewItem::updateFromItem() -{ - DownloadView &view = DownloadView::getInstance(); - DP_LOGD("ViewItem::updateFromItem() ITEM::[%d]", state()); - if (state() == ITEM::DESTROY) { - int tempType = 0; - DP_LOGD("ViewItem::updateFromItem() ITEM::DESTROY"); - if (m_item) - m_item->deSubscribe(m_aptr_observer.get()); - m_aptr_observer->clear(); - elm_object_item_del(m_glItem); - m_glItem = NULL; - tempType = dateGroupType(); - view.detachViewItem(this); - view.handleGenlistGroupItem(tempType); - return; - } - - if (state() == ITEM::WAITING_USER_RESPONSE) { - string buf; - buf.append("Name : "); - buf.append(m_item->contentName()); - buf.append("<br>"); - buf.append("Size : "); - buf.append(getHumanFriendlyBytesStr(fileSize(), false)); - buf.append("<br>"); - buf.append("Vendor : "); - buf.append(m_item->vendorName()); - buf.append("<br>"); - if (m_item->isMidletInstalled()) { - buf.append("<br>"); - buf.append(S_("IDS_COM_POP_ALREDY_EXISTS")); - buf.append("<br>"); - buf.append("Want to update?"); - } - view.showOMAPopup(buf, this); - return; - } - - if (state() == ITEM::DOWNLOADING) { - if (fileSize() > 0 && m_progressBar) { - double percentageProgress = 0.0; - percentageProgress = (double)(receivedFileSize()) / - (double)(fileSize()); - DP_LOGD("progress value[%.2f]",percentageProgress); - elm_progressbar_value_set(m_progressBar, percentageProgress); - } - elm_genlist_item_fields_update(m_glItem,"elm.text.2", - ELM_GENLIST_ITEM_FIELD_TEXT); - } else if (m_isRetryCase && state() == ITEM::RECEIVING_DOWNLOAD_INFO) { - elm_genlist_item_item_class_update(m_glItem, &dldGenlistStyle); - } else if (!isFinished()) { - elm_genlist_item_update(m_glItem); - } else {/* finished state */ - if (state() == ITEM::FINISH_DOWNLOAD) - elm_genlist_item_item_class_update(m_glItem, &dldHistoryGenlistStyle); - else - elm_genlist_item_item_class_update(m_glItem, &dldGenlistSlideStyle); - if (view.isGenlistEditMode()) - elm_object_item_disabled_set(m_glItem, EINA_FALSE); - } -} - -char *ViewItem::getGenlistLabelCB(void *data, Evas_Object *obj, const char *part) -{ -// DP_LOGD_FUNC(); - - if(!data || !obj || !part) - return NULL; - - ViewItem *item = static_cast<ViewItem *>(data); - return item->getGenlistLabel(obj, part); -} - -char *ViewItem::getGenlistLabel(Evas_Object *obj, const char *part) -{ - DP_LOGD("ViewItem::getListLabel:part[%s]", part); - - if (strncmp(part, "elm.text.1", strlen("elm.text.1")) == 0) { - return strdup(getTitle()); - } else if (strncmp(part, "elm.text.2", strlen("elm.text.2")) == 0) { - return strdup(getMessage()); - } else if (strncmp(part, "elm.text.3", strlen("elm.text.3")) == 0) { - if (!isFinished()) { - return NULL; - } else { - string outBuf; - DateUtil &inst = DateUtil::getInstance(); - double udateTime = finishedTime() * 1000; - if (dateGroupType() == DATETIME::DATE_TYPE_PREVIOUS - || dateGroupType() == DATETIME::DATE_TYPE_LATER) - inst.getDateStr(LOCALE_STYLE::SHORT_DATE, udateTime, outBuf); - else - inst.getDateStr(LOCALE_STYLE::TIME, udateTime, outBuf); - return strdup(outBuf.c_str()); - } - } else { - DP_LOGD("No Implementation"); - return NULL; - } -} - -Evas_Object *ViewItem::getGenlistIconCB(void *data, Evas_Object *obj, - const char *part) -{ -// DP_LOGD_FUNC(); - if(!data || !obj || !part) { - DP_LOGE("parameter is NULL"); - return NULL; - } - - ViewItem *item = static_cast<ViewItem *>(data); - return item->getGenlistIcon(obj, part); -} - -Evas_Object *ViewItem::getGenlistIcon(Evas_Object *obj, const char *part) -{ - //DP_LOGD("ViewItem::getGenlistIcon:part[%s]state[%s]", part, stateStr()); - - if (elm_genlist_decorate_mode_get(obj) && isFinished()) { - if (strncmp(part,"elm.edit.icon.1", strlen("elm.edit.icon.1")) == 0) { - Evas_Object *checkBtn = elm_check_add(obj); - elm_check_state_pointer_set(checkBtn, &m_checked); - evas_object_smart_callback_add(checkBtn, "changed", checkChangedCB, - this); - m_checkedBtn = checkBtn; - return checkBtn; - } else if (strncmp(part,"elm.edit.icon.2", strlen("elm.edit.icon.2")) == - 0) { - return NULL; - } - - } - /* elm.icon.2 should be checked prior to elm.icon */ - if (strncmp(part,"elm.icon.2", strlen("elm.icon.2")) == 0) { - if (state() == ITEM::RECEIVING_DOWNLOAD_INFO || - state() == ITEM::PREPARE_TO_RETRY || - state() == ITEM::DOWNLOADING || - isPreparingDownload()) - return createCancelBtn(obj); - else - return NULL; - } else if (strncmp(part,"elm.icon.1", strlen("elm.icon.1")) == 0 || - strncmp(part, "elm.icon", strlen("elm.icon")) == 0) { -// if (strncmp(part,"elm.icon.1", strlen("elm.icon.1")) == 0) { - Evas_Object *icon = elm_icon_add(obj); - elm_icon_file_set(icon, getIconPath(), NULL); - evas_object_size_hint_aspect_set(icon, EVAS_ASPECT_CONTROL_VERTICAL,1,1); - return icon; - } else if (strcmp(part,"elm.swallow.progress") == 0) { - return createProgressBar(obj); - } else { - DP_LOGE("Cannot enter here"); - return NULL; - } -} - -void ViewItem::checkChangedCB(void *data, Evas_Object *obj, - void *event_info) -{ - DownloadView &view = DownloadView::getInstance(); - DP_LOGD_FUNC(); - //ViewItem *item = static_cast<ViewItem *>(data); - //DP_LOGD("checked[%d] viewItem[%p]",(bool)(item->checkedValue()),item); - view.handleCheckedState(); -} - -void ViewItem::clickedDeleteButton() -{ - DP_LOGD("ViewItem::clickedDeleteButton()"); - m_item->deleteFromDB(); - destroy(); -} - -void ViewItem::clickedCancelButton() -{ - DP_LOG("ViewItem::clickedCancelButton()"); - requestCancel(); -} - -void ViewItem::requestCancel() -{ - if (m_item) { - m_item->cancel(); - } -} - -void ViewItem::clickedRetryButton() -{ - DP_LOG_FUNC(); - retryViewItem(); -} - -void ViewItem::clickedGenlistItem() -{ - DownloadView &view = DownloadView::getInstance(); - DP_LOG_FUNC(); - if (!m_item) { - DP_LOGE("m_item is NULL"); - return; - } - if (view.isGenlistEditMode()) { - m_checked = !m_checked; - if (m_checkedBtn) - elm_genlist_item_fields_update(genlistItem(),"elm.edit.icon.1", - ELM_GENLIST_ITEM_FIELD_CONTENT); - else - DP_LOGE("m_checkedBtn is NULL"); - view.handleCheckedState(); - } else if (state() == ITEM::FINISH_DOWNLOAD) { - bool ret = m_item->play(); - if (ret == false) { - string desc = __("IDS_BR_POP_UNABLE_TO_OPEN_FILE"); - view.showErrPopup(desc); - } - } else if (isFinishedWithErr()) { - retryViewItem(); - } - elm_genlist_item_selected_set(genlistItem(), EINA_FALSE); -} - -Elm_Genlist_Item_Class *ViewItem::elmGenlistStyle() -{ - /* Change the genlist style class in case of download history item */ - if (state() == ITEM::FINISH_DOWNLOAD) - return &dldHistoryGenlistStyle; - else if (isFinishedWithErr()) - return &dldGenlistSlideStyle; - else - return &dldGenlistStyle; -} - -const char *ViewItem::getMessage() -{ - DP_LOGD("ViewItem state() ITEM::[%d]", state()); - const char *buff = NULL; - switch(state()) { - case ITEM::IDLE: - case ITEM::REQUESTING: - case ITEM::PREPARE_TO_RETRY: - case ITEM::WAITING_USER_RESPONSE: - case ITEM::RECEIVING_DOWNLOAD_INFO: - /* Do not display string and show only the progress bar */ -// buff = __("Check for download"); - buff = ""; - break; - case ITEM::DOWNLOADING: - buff = getHumanFriendlyBytesStr(receivedFileSize(), true); -// DP_LOGD("%s", buff); - break; - case ITEM::CANCEL: - buff = S_("IDS_COM_POP_CANCELLED"); - break; - case ITEM::FAIL_TO_DOWNLOAD: - buff = getErrMsg(); - break; - case ITEM::REGISTERING_TO_SYSTEM: - buff = S_("IDS_COM_POP_INSTALLING_ING"); - break; - case ITEM::ACTIVATING: - buff = S_("IDS_COM_POP_ACTIVATING"); - break; - case ITEM::NOTIFYING_TO_SERVER: - buff = __("IDS_BR_BODY_NOTIFYING_ING"); - break; - case ITEM::PROCESSING_DOMAIN: - buff = S_("IDS_COM_POP_PROCESSING"); - break; - case ITEM::FINISH_PROCESSING_DOMAIN: - buff = __("IDS_BR_BODY_PROCESSING_COMPLETED"); - break; - case ITEM::FINISH_DOWNLOAD: - buff = __("IDS_EMAIL_BODY_COMPLETE"); - break; - default: - buff = ""; - break; - } - return buff; -} - -const char *ViewItem::getHumanFriendlyBytesStr(unsigned long int bytes, - bool progressOption) -{ - double doubleTypeBytes = 0.0; - const char *unitStr[4] = {"B", "KB", "MB", "GB"}; - int unit = 0; - unsigned long int unitBytes = bytes; - - /* using bit operation to avoid floating point arithmetic */ - for (unit=0; (unitBytes > 1024 && unit < 4) ; unit++) { - unitBytes = unitBytes >> 10; - } - - unitBytes = 1 << (10*unit); - doubleTypeBytes = ((double)bytes / (double)(unitBytes)); - // FIXME following code should be broken into another function, but leave it now to save function call time.s - char str[32] = {0}; - if (progressOption && fileSize() != 0) { - /* using fixed point arithmetic to avoid floating point arithmetic */ - const int fixed_point = 6; - unsigned long long int receivedBytes = receivedFileSize() << fixed_point; - unsigned long long int result = (receivedBytes*100) / fileSize(); - unsigned long long int result_int = result >> fixed_point; - unsigned long long int result_fraction = result & - ~(0xFFFFFFFF << fixed_point); - if (unit == 0) - snprintf(str, sizeof(str), "%lu %s / %llu.%.2llu %%", - bytes, unitStr[unit], result_int, result_fraction); - else - snprintf(str, sizeof(str), "%.2f %s / %llu.%.2llu %%", - doubleTypeBytes, unitStr[unit], result_int, result_fraction); - } else { - if (unit == 0) - snprintf(str, sizeof(str), "%lu %s", bytes, unitStr[unit]); - else - snprintf(str, sizeof(str), "%.2f %s", doubleTypeBytes, unitStr[unit]); - } - return string(str).c_str(); -} - -unsigned long int ViewItem::receivedFileSize() -{ - if (m_item) - return m_item->receivedFileSize(); - - return 0; -} - -unsigned long int ViewItem::fileSize() -{ - if (m_item) - return m_item->fileSize(); - - return 0; -} - -const char *ViewItem::getTitle() -{ - const char *title = NULL; - if (m_item) - title = m_item->title().c_str(); - - if (!title) - return S_("IDS_COM_BODY_NO_NAME"); - - return title; -} - -Evas_Object *ViewItem::createProgressBar(Evas_Object *parent) -{ - Evas_Object *progress = NULL; - if (!parent) { - DP_LOGE("parent is NULL"); - return NULL; - } - progress = elm_progressbar_add(parent); - setProgressBar(progress); - if (isFinished()) { - DP_LOGE("Cannot enter here. finished item has othere genlist style"); - return NULL; - } - - if (fileSize() == 0 || isPreparingDownload()) { - //DP_LOGD("Pending style::progressBar[%p]",progress); - elm_object_style_set(progress, "pending_list"); - elm_progressbar_horizontal_set(progress, EINA_TRUE); - evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, - EVAS_HINT_EXPAND); - elm_progressbar_pulse(progress, EINA_TRUE); - } else { - //DP_LOGD("List style::progressBar[%p] fileSize[%d] state[%d]",progress, fileSize(),state()); - elm_object_style_set(progress, "list_progress"); - elm_progressbar_horizontal_set(progress, EINA_TRUE); - - if (isCompletedDownload()) - elm_progressbar_value_set(progress, 1.0); - /* When realized event is happened, the progress is created. - This is needed for that case */ - else if (state() == ITEM::DOWNLOADING) { - double percentageProgress = 0.0; - percentageProgress = (double)(receivedFileSize()) / - (double)(fileSize()); - elm_progressbar_value_set(progress, percentageProgress); - } - } - evas_object_show(progress); - return progress; -} - -void ViewItem::updateCheckedBtn() -{ - if (m_checkedBtn) - elm_check_state_pointer_set(m_checkedBtn,&m_checked); -} - -void ViewItem::deleteBtnClickedCB(void *data, Evas_Object *obj, void *event_info) -{ - DP_LOGD_FUNC(); - if (!data) { - DP_LOGE("data is NULL"); - return; - } - ViewItem *viewItem = static_cast<ViewItem *>(data); - viewItem->clickedDeleteButton(); -} - -void ViewItem::retryBtnClickedCB(void *data, Evas_Object *obj, void *event_info) -{ - DP_LOGD_FUNC(); - if (!data) { - DP_LOGE("data is NULL"); - return; - } - ViewItem *viewItem = static_cast<ViewItem *>(data); - viewItem->clickedRetryButton(); -} - -Evas_Object *ViewItem::createCancelBtn(Evas_Object *parent) -{ - DP_LOGD_FUNC(); - Evas_Object *button = elm_button_add(parent); - elm_object_part_content_set(parent, "btn_style1", button); - elm_object_style_set(button, "style1/auto_expand"); - evas_object_size_hint_aspect_set(button, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); - elm_object_text_set(button, S_("IDS_COM_SK_CANCEL")); - evas_object_propagate_events_set(button, EINA_FALSE); - evas_object_smart_callback_add(button,"clicked", cancelBtnClickedCB, this); - return button; -} - -void ViewItem::cancelBtnClickedCB(void *data, Evas_Object *obj, void *event_info) -{ - DP_LOGD_FUNC(); - if (!data) { - DP_LOGE("data is NULL"); - return; - } - ViewItem *viewItem = static_cast<ViewItem *>(data); - viewItem->clickedCancelButton(); -} - -void ViewItem::extractDateGroupType() -{ - DP_LOGD_FUNC(); - /* History Item */ - //DP_LOGD("state[%s],finishedTime[%ld]",stateStr(),finishedTime()); - if (isFinished() && finishedTime() > 0) { - int diffDay = 0; - DateUtil &inst = DateUtil::getInstance(); - double nowTime = inst.nowTime(); - double finishTime = finishedTime(); - diffDay = inst.getDiffDays((time_t)nowTime, (time_t)finishTime); - if (diffDay == 0) - m_dateGroupType = DATETIME::DATE_TYPE_TODAY; - else if (diffDay == 1) - m_dateGroupType = DATETIME::DATE_TYPE_YESTERDAY; - else if (diffDay > 1) - m_dateGroupType = DATETIME::DATE_TYPE_PREVIOUS; - else - m_dateGroupType = DATETIME::DATE_TYPE_LATER; - return; - } - /* Item which is added now or retrying item */ - m_dateGroupType = DATETIME::DATE_TYPE_TODAY; -} - - -void ViewItem::retryViewItem(void) -{ - DownloadView &view = DownloadView::getInstance(); - DP_LOGD_FUNC(); - if (m_item) { - m_isRetryCase = true; - m_item->clearForRetry(); - if (!m_item->retry()) { - DownloadView &view = DownloadView::getInstance(); - string desc = S_("IDS_COM_POP_FAILED"); - view.showErrPopup(desc); - m_item->deleteFromDB(); - m_item->destroy(); - return; - } - /* Move a item to Today group, if it is not included to Today group */ - view.moveRetryItem(this); - } -} diff --git a/src/include/download-provider-common.h b/src/include/download-provider-common.h deleted file mode 100644 index 4131c0d..0000000 --- a/src/include/download-provider-common.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-common.h - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief Common define and data - */ - -#ifndef DOWNLOAD_PROVIDER_DOWNLOAD_COMMON_H -#define DOWNLOAD_PROVIDER_DOWNLOAD_COMMON_H - -#include <libintl.h> -#include "download-provider-debug.h" - -#if !defined(PACKAGE) - #define PACKAGE "download-provider" -#endif - -#define _EDJ(o) elm_layout_edje_get(o) -#define __(s) dgettext(PACKAGE, s) -#define S_(s) dgettext("sys_string", s) - -#define ERROR_POPUP_LOW_MEM S_("IDS_COM_POP_NOT_ENOUGH_MEMORY") -#define ERROR_POPUP_UNKNOWN S_("IDS_COM_POP_INTERNAL_ERROR") -#define ERROR_POPUP_INVALID_URL S_("IDS_COM_POP_INVALID_URL") - -#define DP_DRM_ICON_PATH IMAGEDIR"/U06_icon_DRM.png" -#define DP_JAVA_ICON_PATH IMAGEDIR"/U06_icon_Java.png" -#define DP_UNKNOWN_ICON_PATH IMAGEDIR"/U06_icon_Unknown.png" -#define DP_EXCEL_ICON_PATH IMAGEDIR"/U06_icon_excel.png" -#define DP_HTML_ICON_PATH IMAGEDIR"/U06_icon_html.png" -#define DP_MUSIC_ICON_PATH IMAGEDIR"/U06_icon_music.png" -#define DP_PDF_ICON_PATH IMAGEDIR"/U06_icon_pdf.png" -#define DP_PPT_ICON_PATH IMAGEDIR"/U06_icon_ppt.png" -#define DP_RINGTONE_ICON_PATH IMAGEDIR"/U06_icon_ringtone.png" -#define DP_TEXT_ICON_PATH IMAGEDIR"/U06_icon_text.png" -#define DP_WORD_ICON_PATH IMAGEDIR"/U06_icon_word.png" -#define DP_VIDEO_ICON_PATH IMAGEDIR"/U06_icon_video.png" -#define DP_IMAGE_ICON_PATH IMAGEDIR"/U06_icon_image.png" - -#define MAX_FILE_PATH_LEN 256 -#define MAX_BUF_LEN 256 - -#define LOAD_HISTORY_COUNT 500 - -enum -{ - DP_CONTENT_NONE = 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_RINGTONE, - DP_CONTENT_DRM, // 10 - DP_CONTENT_JAVA, - DP_CONTENT_SVG, - DP_CONTENT_FLASH, - DP_CONTENT_UNKOWN -}; - -namespace DL_TYPE{ -enum TYPE { - TYPE_NONE, - HTTP_DOWNLOAD, - OMA_DOWNLOAD, - MIDP_DOWNLOAD -}; -} - -namespace ERROR { -enum CODE { - NONE, - INVALID_URL, - NETWORK_FAIL, - NOT_ENOUGH_MEMORY, - FAIL_TO_INSTALL, - FAIL_TO_PARSE_DESCRIPTOR, - OMA_POPUP_TIME_OUT, - ENGINE_FAIL, - UNKNOWN -}; -} - -#endif /* DOWNLOAD_PROVIDER_DOWNLOAD_COMMON_H */ diff --git a/src/include/download-provider-dateTime.h b/src/include/download-provider-dateTime.h deleted file mode 100644 index 87caf11..0000000 --- a/src/include/download-provider-dateTime.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-dateTime.h - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief data and utility APIs for Date and Time - */ - -#ifndef DOWNLOAD_PROVIDER_DATE_TIME_H -#define DOWNLOAD_PROVIDER_DATE_TIME_H - -#include <time.h> -#include <Elementary.h> -#include <unicode/udat.h> -#include <unicode/udatpg.h> -#include <unicode/ustring.h> - -#include "download-provider-common.h" - -using namespace std; - -namespace DATETIME { -enum { - DATE_TYPE_NONE = 0, - DATE_TYPE_LATER, - DATE_TYPE_TODAY, - DATE_TYPE_YESTERDAY, - DATE_TYPE_PREVIOUS, -}; -} - -namespace LOCALE_STYLE{ -enum { - TIME = 0, - SHORT_DATE, - MEDIUM_DATE, - FULL_DATE -}; -} - -class DateGroup { -public: - DateGroup(void); - ~DateGroup(void); - - Elm_Object_Item *glGroupItem() { return m_glGroupItem; } - void setGlGroupItem(Elm_Object_Item *i) { m_glGroupItem = i; } - void increaseCount(void) { count++; } - void decreaseCount(void) { count--; } - int getCount(void) { return count; } - void initData(void); - void setType(int t) { type = t; } - int getType(void) { return type; } - -private: - int count; - int type; - Elm_Object_Item *m_glGroupItem; -}; - -class DateUtil { -public: - static DateUtil& getInstance(void) { - static DateUtil inst; - return inst; - } - - inline void setTodayStandardTime(void) { m_todayStandardTime = time(NULL); } - int getDiffDaysFromToday(void); - int getDiffDays(time_t nowTime, time_t refTime); - void updateLocale(void); - void getDateStr(int style, double time, string &outBuf); - inline double nowTime(void) { return (double)(time(NULL)); } - /* yesterday is same to 24*60*60 seconds from now */ - inline double yesterdayTime(void) { return (double)(time(NULL)+24*60*60); } - -private: - DateUtil(void); - ~DateUtil(void); - - UDateFormat *getBestPattern(const char *patternStr, - UDateTimePatternGenerator *generator, const char *locale); - void deinitLocaleData(void); - /* Update this in case of follows - * 1. show main view. - * 2. add new item - * 3. create today group - **/ - time_t m_todayStandardTime; - UDateFormat *dateShortFormat; - UDateFormat *dateMediumFormat; - UDateFormat *dateFullFormat; - UDateFormat *timeFormat12H; - UDateFormat *timeFormat24H; -}; - -#endif /* DOWNLOAD_PROVIDER_DATE_TIME_H */ diff --git a/src/include/download-provider-debug.h b/src/include/download-provider-debug.h deleted file mode 100644 index 4c4552b..0000000 --- a/src/include/download-provider-debug.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-debug.h - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief debug function - */ - -#ifndef DOWNLOAD_PROVIDER_DEBUG_H -#define DOWNLOAD_PROVIDER_DEBUG_H - -#define _USE_DLOG 1 - -#ifdef _USE_DLOG -#include <dlog.h> - -#ifdef LOG_TAG -#undef LOG_TAG -#endif - -#define LOG_TAG "DownloadProvider" - -#define DP_LOG(format, args...) LOGI("[%s] "format, __func__, ##args) -#define DP_LOGD(format, args...) LOGD("[%s] "format, __func__, ##args) -#define DP_LOG_START(msg) LOGI("<<= [%s] Start =>>\n",msg) -#define DP_LOG_FUNC() LOGI("<<= [%s]=>>\n",__func__) -#define DP_LOGD_FUNC() LOGD("<<= [%s]=>>\n",__func__) -#define DP_LOG_END(msg) LOGI("<<= [%s] End [%d] =>>\n",msg) -#define DP_LOGE(format, args...) LOGE("[%s][ERR] "format, __func__, ##args) -#define DP_LOG_TEST(format, args...) LOGI("####TEST####[%s] "format, __func__, ##args) - -#else - -#include <stdio.h> -#include <pthread.h> - -#define DP_LOG(args...) do {\ - printf("[DP:%s][LN:%d][%lu]",__func__,__LINE__,pthread_self());\ - printf(args);printf("\n"); }while(0) -#define DP_LOGD(args...) do {\ - printf("[DP_D:%s][LN:%d][%lu]",__func__,__LINE__,pthread_self());\ - printf(args);printf("\n");}while(0) -#define DP_LOGE(args...) do {\ - printf("[DP_ERR:%s][LN:%d][%lu]",__func__,__LINE__,pthread_self());\ - printf(args);printf("\n");}while(0) -#define DP_LOG_FUNC() do {\ - printf("<<==[DP:%s][LN:%d][%lu] ==>> \n",__func__,__LINE__,pthread_self());\ - }while(0) -#define DP_LOGD_FUNC() do {\ - printf("<<==[DP_D:%s][LN:%d][%lu] ==>> \n",__func__,__LINE__,pthread_self());\ - }while(0) -#define DP_LOG_START(msg) do {\ - printf("<<==[DP:%s][LN:%d][%lu] Start ==>> \n",\ - __FUNCTION__,__LINE__,pthread_self());\ - }while(0) -#define DP_LOG_END(msg) do {\ - printf("<<==[DP:%s][LN:%d][%lu] End ==>> \n",\ - __FUNCTION__,__LINE__,pthread_self());\ - }while(0) -#endif /*_USE_DLOG*/ - -#endif /* DOWNLOAD_PROVIDER_DEBUG_H */ diff --git a/src/include/download-provider-downloadItem.h b/src/include/download-provider-downloadItem.h deleted file mode 100644 index 9421246..0000000 --- a/src/include/download-provider-downloadItem.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-downloadItem.h - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief download item class - */ - -#ifndef DOWNLOAD_PROVIDER_DOWNLOAD_ITEM_H -#define DOWNLOAD_PROVIDER_DOWNLOAD_ITEM_H - -#include "download-provider-common.h" -#include "download-provider-downloadRequest.h" -#include "download-provider-event.h" -#include "download-agent-interface.h" -#include <memory> - -namespace DL_ITEM { -enum STATE { - IGNORE, - STARTED, - WAITING_CONFIRM, - UPDATING, - COMPLETE_DOWNLOAD, - INSTALL_NOTIFY, - START_DRM_DOMAIN, - FINISH_DRM_DOMAIN, - WAITING_RO, - SUSPENDED, - RESUMED, - FINISHED, - CANCELED, - FAILED -}; -} - -class DownloadItem { -public: - DownloadItem(); /* FIXME remove after cleanup ecore_pipe */ - DownloadItem(auto_ptr<DownloadRequest> request); - ~DownloadItem(); - - void start(void); - void cancel(void); - void retry(void); - bool sendUserResponse(bool res); - void suspend(void); - void resume(void); - - inline int downloadId(void) { return m_da_req_id;} - inline void setDownloadId(int id) { m_da_req_id = id; } - - inline unsigned long int receivedFileSize(void) { return m_receivedFileSize; } - inline void setReceivedFileSize(unsigned long int size) { m_receivedFileSize = size; } - - inline unsigned long int fileSize(void) { return m_fileSize; } - inline void setFileSize(unsigned long int size) { m_fileSize = size; } - - inline string &filePath(void) { return m_filePath; } - inline void setFilePath(const char *path) { if (path) m_filePath = path; } - inline void setFilePath(string &path) { m_filePath = path; } - - inline string ®isteredFilePath(void) { return m_registeredFilePath; } - inline void setRegisteredFilePath(string &path) { m_registeredFilePath = path; } - - inline string &mimeType(void) { return m_mimeType; } - inline void setMimeType(const char *mime) { m_mimeType = mime; } - inline void setMimeType(string &mime) { m_mimeType = mime; } - - inline DL_ITEM::STATE state(void) { return m_state; } - inline void setState(DL_ITEM::STATE state) { m_state = state; } - - inline ERROR::CODE errorCode(void) { return m_errorCode; } - inline void setErrorCode(ERROR::CODE err) { m_errorCode = err; } - inline bool isMidletInstalled(void) { return m_isMidletInstalled; } - inline void setIsMidletInstalled(bool b) { m_isMidletInstalled = b; } - inline DL_TYPE::TYPE downloadType(void) { return m_downloadType; } - inline void setDownloadType(DL_TYPE::TYPE t) { m_downloadType = t;} - inline string &contentName(void) { return m_contentName; } - inline void setContentName(string &name) { m_contentName = name; } - inline string &vendorName(void) { return m_vendorName; } - inline void setVendorName(string &name) { m_vendorName = name; } - - inline void notify(void) { m_subject.notify(); } - inline void subscribe(Observer *o) { if (o) m_subject.attach(o); } - inline void deSubscribe(Observer *o) { if (o) m_subject.detach(o); } - inline string &url(void) { return m_aptr_request->getUrl(); } - inline string &cookie(void) { return m_aptr_request->getCookie(); } - - DL_ITEM::STATE _convert_da_state_to_download_state(int da_state); - ERROR::CODE _convert_da_error(int da_err); - -private: - auto_ptr<DownloadRequest> m_aptr_request; - Subject m_subject; - da_handle_t m_da_req_id; - DL_ITEM::STATE m_state; - ERROR::CODE m_errorCode; - unsigned long int m_receivedFileSize; - unsigned long int m_fileSize; - string m_filePath; - string m_registeredFilePath; - string m_mimeType; - DL_TYPE::TYPE m_downloadType; - bool m_isMidletInstalled; /* For MIDP */ - string m_contentName; /* For OMA & MIDP */ - string m_vendorName; /* For MIDP */ -}; - -class DownloadEngine { -public: - static DownloadEngine &getInstance(void) { - static DownloadEngine downloadEngine; - return downloadEngine; - } - - void initEngine(void); - void deinitEngine(void); -private: - DownloadEngine(void); - ~DownloadEngine(void); - -}; - - -#endif /* DOWNLOAD_PROVIDER_DOWNLOAD_ITEM_H */ diff --git a/src/include/download-provider-downloadRequest.h b/src/include/download-provider-downloadRequest.h deleted file mode 100644 index a21f7df..0000000 --- a/src/include/download-provider-downloadRequest.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-downloadRequest.h - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief Download Request class - */ - -#ifndef DOWNLOAD_PROVIDER_DOWNLOAD_REQUEST_H -#define DOWNLOAD_PROVIDER_DOWNLOAD_REQUEST_H - -#include <string> - -using namespace std; - -class DownloadRequest -{ -public: -// DownloadRequest(); - DownloadRequest(string url, string cookie); - DownloadRequest(DownloadRequest &rRequest); - ~DownloadRequest(); - - string &getUrl(); - string &getCookie(); - bool isUrlEmpty(); - bool isCookieEmpty(); - void setUrl(string url); - void setCookie(string cookie); -private: - string m_url; - string m_cookie; -}; - -#endif /* DOWNLOAD_PROVIDER_DOWNLOAD_REQUEST_H */ diff --git a/src/include/download-provider-event.h b/src/include/download-provider-event.h deleted file mode 100644 index e9378a6..0000000 --- a/src/include/download-provider-event.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-event.h - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief Download event class - */ -#ifndef DOWNLOAD_PROVIDER_EVENT_H -#define DOWNLOAD_PROVIDER_EVENT_H - -#include <vector> -/* For debug */ -#include <string> - -using namespace std; - -class Observer; -class Subject -{ -public: - Subject(){} - ~Subject(){} - - void attach(Observer *); - void detach(Observer *); - void notify(void); - -private: - vector<Observer*> _observers; -}; - -typedef void (*updateFunction)(void *data); - -class Observer -{ -public: - /* For debug */ - Observer(updateFunction uf, void *data, const char *name); - //Observer(updateFunction uf, void *data); - ~Observer(){} - - void update(Subject *s); - void set(updateFunction uf, void *data); - void clear(void); - void *getUserData(void) { return m_userData; } - /* For debug */ - string name(void) { return observerName; } - -private: - void call(void); - - updateFunction m_updateFunction; - void *m_userData; - /* For debug */ - string observerName; -}; - -#endif /* DOWNLOAD_PROVIDER_EVENT_H */ diff --git a/src/include/download-provider-history-db.h b/src/include/download-provider-history-db.h deleted file mode 100644 index b22883e..0000000 --- a/src/include/download-provider-history-db.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-history-db.h - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief Manager for a download history DB - */ - -#ifndef DOWNLOAD_PROVIDER_HISTORY_DB_H -#define DOWNLOAD_PROVIDER_HISTORY_DB_H - -#include <string> -#include <queue> -#include <db-util.h> -#include "download-provider-item.h" -extern "C" { -#include <unicode/utypes.h> -} - -using namespace std; - -class DownloadHistoryDB -{ -public: - static bool addToHistoryDB(Item *item); - static bool createRemainedItemsFromHistoryDB(int limit, int offset); - static bool createItemsFromHistoryDB(void); - static bool deleteItem(unsigned int historyId); - static bool deleteMultipleItem(queue <unsigned int> &q); - static bool clearData(void); - static bool getCountOfHistory(int *count); -private: - DownloadHistoryDB(void); - ~DownloadHistoryDB(void); - static sqlite3* historyDb; - static bool open(void); - static bool isOpen(void) { return historyDb ? true : false; } - static void close(void); -}; - -#endif /* DOWNLOAD_PROVIDER_HISTORY_DB_H */ - diff --git a/src/include/download-provider-item.h b/src/include/download-provider-item.h deleted file mode 100644 index 65ab1eb..0000000 --- a/src/include/download-provider-item.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-item.h - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief Item class - */ -#ifndef DOWNLOAD_PROVIDER_ITEM_H -#define DOWNLOAD_PROVIDER_ITEM_H - -#include <string> -#include <memory> -#include "download-provider-event.h" -#include "download-provider-downloadRequest.h" -#include "download-provider-downloadItem.h" -#include "download-provider-util.h" - -using namespace std; - -namespace ITEM { -enum STATE { - IDLE, - REQUESTING, - PREPARE_TO_RETRY, - WAITING_USER_RESPONSE, - RECEIVING_DOWNLOAD_INFO, - DOWNLOADING, - REGISTERING_TO_SYSTEM, - PROCESSING_DOMAIN, - FINISH_PROCESSING_DOMAIN, - ACTIVATING, - NOTIFYING_TO_SERVER, - SUSPEND, - FINISH_DOWNLOAD, - FAIL_TO_DOWNLOAD, - CANCEL, - PLAY, - DESTROY -}; -} - -class DownloadNoti; - -class Item { -public: - static void create(DownloadRequest &rRequest); - static Item *createHistoryItem(void); - ~Item(void); - - void attachHistoryItem(void); - void destroy(void); - /* SHOULD call this before destrying an item*/ - void deleteFromDB(void); - void download(void); - inline void cancel(void) - { - if (m_aptr_downloadItem.get()) - m_aptr_downloadItem->cancel(); - return; - } - void clearForRetry(void); - bool retry(void); - - void sendUserResponse(bool res); - bool play(void); - - inline void subscribe(Observer *o) { m_subjectForView.attach(o); } - inline void deSubscribe(Observer *o) { m_subjectForView.detach(o); } - - static void updateCBForDownloadObserver(void *data); - static void netEventCBObserver(void *data); - void updateFromDownloadItem(void); - inline void suspend(void) { m_aptr_downloadItem->suspend(); } - - inline int id(void) { - if (m_aptr_downloadItem.get()) - return m_aptr_downloadItem->downloadId(); - - return -1; - } // FIXME create Item's own id - - inline unsigned long int receivedFileSize(void) { - if (m_aptr_downloadItem.get()) - return m_aptr_downloadItem->receivedFileSize(); - return 0; - } - - inline unsigned long int fileSize(void) { - if (m_aptr_downloadItem.get()) - return m_aptr_downloadItem->fileSize(); - return 0; - } - - inline string &filePath(void) { - if (m_aptr_downloadItem.get()) - return m_aptr_downloadItem->filePath(); - return m_emptyString; - } - - inline bool isMidletInstalled(void) { - if (m_aptr_downloadItem.get()) - return m_aptr_downloadItem->isMidletInstalled(); - return false; - } - - inline void setHistoryId(unsigned int i) { m_historyId = i; } - inline unsigned int historyId(void) { return m_historyId; } // FIXME duplicated with m_id - inline string &title(void) {return m_title;} - inline void setTitle(string &title) { m_title = title; } - string &contentName(void); - inline void setContentName(string &c) { m_contentName = c; } - string &vendorName(void); - inline void setVendorName(string &v) { m_vendorName = v; } - string ®isteredFilePath(void); - inline void setRegisteredFilePath(string &r) { m_registeredFilePath = r; } - string &url(void); - string &cookie(void); - void setRetryData(string &url, string &cookie); - int contentType(void) { return m_contentType; } - inline void setContentType(int t) { m_contentType = t; } - DL_TYPE::TYPE downloadType(void); - inline void setDownloadType(DL_TYPE::TYPE t) { m_downloadType = t; } - -// string &getIconPath(void) {return m_iconPath; } - inline string &iconPath(void) { return m_iconPath; } - - inline void setState(ITEM::STATE state) { m_state = state; } - inline ITEM::STATE state(void) { return m_state; } - - inline void setErrorCode(ERROR::CODE err) { m_errorCode = err; } - inline ERROR::CODE errorCode(void) { return m_errorCode; } - const char *getErrorMessage(void); - inline void setFinishedTime(double t) { m_finishedTime = t; } - inline double finishedTime(void) { return m_finishedTime; } - - inline string getMidletPkgName(void) { - DownloadUtil &util = DownloadUtil::getInstance(); - return util.getMidletPkgName(m_contentName, m_vendorName); - } - - bool isFinished(void); /* include finish download state with error */ - bool isFinishedWithErr(void); - bool isPreparingDownload(void); /* Before downloading start */ - bool isCompletedDownload(void); /* After stating installation */ - - /* Test code */ - const char *stateStr(void); - -private: - Item(void); - Item(DownloadRequest &rRequest); - - inline void notify(void) { m_subjectForView.notify(); } - - void createSubscribeData(void); - void extractTitle(void); - void extractIconPath(void); - - void startUpdate(void); - void createHistoryId(void); - bool isExistedHistoryId(unsigned int id); - void handleFinishedItem(void); - - auto_ptr<DownloadRequest> m_aptr_request; - auto_ptr<DownloadItem> m_aptr_downloadItem; - FileOpener m_fileOpener; - - Subject m_subjectForView; - auto_ptr<Observer> m_aptr_downloadObserver; - auto_ptr<Observer> m_aptr_netEventObserver; - - ITEM::STATE m_state; - ERROR::CODE m_errorCode; - string m_title; - unsigned int m_historyId; - int m_contentType; - string m_iconPath; // FIXME Later:is it right to exist here? (ViewItem or not) - string m_emptyString; // FIXME this is temporary to avoid crash when filePath() is called if m_aptr_downloaditem points nothing - double m_finishedTime; - DL_TYPE::TYPE m_downloadType; - string m_contentName; - string m_vendorName; - string m_registeredFilePath; - string m_url; - string m_cookie; - - bool m_gotFirstData; -}; - -#endif /* DOWNLOAD_PROVIDER_ITEM_H */ diff --git a/src/include/download-provider-items.h b/src/include/download-provider-items.h deleted file mode 100644 index 8395719..0000000 --- a/src/include/download-provider-items.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * @file download-provider-items.h - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief item inventory class - */ -#ifndef DOWNLOAD_PROVIDER_ITEMS_H -#define DOWNLOAD_PROVIDER_ITEMS_H - -#include "download-provider-item.h" -#include <vector> - -class Items { -public: - static Items& getInstance(void) { - static Items inst; - return inst; - } - - void attachItem(Item *item); - void detachItem(Item *item); - bool isExistedHistoryId(unsigned int id); -private: - Items(){} - ~Items(){DP_LOGD_FUNC();} - - vector<Item*> m_items; -}; - -#endif /* DOWNLOAD_PROVIDER_ITEMS_H */ diff --git a/src/include/download-provider-network.h b/src/include/download-provider-network.h deleted file mode 100644 index 2d0f5eb..0000000 --- a/src/include/download-provider-network.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-network.h - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief Download netowkr manager - */ - -#ifndef DOWNLOAD_PROVIDER_NETWORK_H -#define DOWNLOAD_PROVIDER_NETWORK_H - -#include "vconf.h" -#include "vconf-keys.h" -#include "download-provider-event.h" - -class NetMgr { -public: - static NetMgr& getInstance(void) { - static NetMgr inst; - return inst; - } - void initNetwork(void); - void deinitNetwork(void); - void netStatusChanged(void); - void netConfigChanged(void); - inline void subscribe(Observer *o) { m_subject.attach(o); } - inline void deSubscribe(Observer *o) { m_subject.detach(o); } - static void netStatusChangedCB(keynode_t *keynode, void *data); - static void netConfigChangedCB(keynode_t *keynode, void *data); -private: - NetMgr(void); - ~NetMgr(void); - int getConnectionState(void); - int getCellularStatus(void); - int getWifiStatus(void); - void getProxy(void); - void getIPAddress(void); - inline void notify() { m_subject.notify(); } - int m_netStatus; - Subject m_subject; -}; - -#endif diff --git a/src/include/download-provider-util.h b/src/include/download-provider-util.h deleted file mode 100644 index 0ed6575..0000000 --- a/src/include/download-provider-util.h +++ /dev/null @@ -1,57 +0,0 @@ -/*
- * Copyright 2012 Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * @file download-provider-util.h
- * @author Jungki Kwak (jungki.kwak@samsung.com)
- * @brief Utility APIs and interface with content player
- */
-
-#ifndef DOWNLOAD_PROVIDER_UTIL_H
-#define DOWNLOAD_PROVIDER_UTIL_H
-
-#include <string>
-#include "download-provider-common.h"
-
-using namespace std;
-class FileOpener {
-public:
- FileOpener() {}
- ~FileOpener() {}
-
- bool openFile(string &path, int contentType);
- bool openApp(string &pkgName);
-};
-
-class DownloadUtil
-{
-public:
- static DownloadUtil& getInstance(void) {
- static DownloadUtil inst;
- return inst;
- }
-
- string getMidletPkgName(string& name, string& vendor);
- int getContentType(const char *mimem, const char *filePath);
-
-private:
- DownloadUtil(void);
- ~DownloadUtil(void) {}
- void initDrm(void);
- bool isAmbiguousMIMEType(const char *mimeType);
-};
-
-#endif//DOWNLOAD_PROVIDER_UTIL_H
diff --git a/src/include/download-provider-view.h b/src/include/download-provider-view.h deleted file mode 100644 index 4fdfab0..0000000 --- a/src/include/download-provider-view.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-view.h - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief Download UI View manager - */ - -#ifndef DOWNLOAD_PROVIDER_VIEW_H -#define DOWNLOAD_PROVIDER_VIEW_H - -#include <Elementary.h> -#include <libintl.h> - -#include <vector> -#include "download-provider-common.h" -#include "download-provider-viewItem.h" -#include "download-provider-dateTime.h" - -enum { - POPUP_EVENT_EXIT = 0, - POPUP_EVENT_ERR, -}; - -class DownloadView { -public: - static DownloadView& getInstance(void) { - static DownloadView inst; - return inst; - } - - Evas_Object *create(void); - void createView(void); - void activateWindow(void); - void show(void); - void hide(void); - - void attachViewItem(ViewItem *viewItem); - void detachViewItem(ViewItem *viewItem); - - void changedRegion(void); - void showErrPopup(string &desc); - void showOMAPopup(string &msg, ViewItem *viewItem); - void update(); - void update(ViewItem *viewItem); - void update(Elm_Object_Item *glItem); - void showViewItem(int id, const char *title); - void playContent(int id, const char *title); - void handleChangedAllCheckedState(void); - void handleCheckedState(void); - bool isGenlistEditMode(void); - void handleGenlistGroupItem(int type); - void moveRetryItem(ViewItem *viewItem); - static char *getGenlistGroupLabelCB(void *data, Evas_Object *obj, - const char *part); - -private: - static void showNotifyInfoCB(void *data, Evas *evas, Evas_Object *obj, void *event); - static void hideNotifyInfoCB(void *data, Evas *evas, Evas_Object *obj, void *event); - static void backBtnCB(void *data, Evas_Object *obj, void *event_info); - static void cbItemDeleteCB(void *data, Evas_Object *obj, void *event_info); - static void cbItemCancelCB(void *data, Evas_Object *obj, void *event_info); - static void selectAllClickedCB(void *data, Evas *evas, Evas_Object *obj, - void *event_info); - static void selectAllChangedCB(void *data, Evas_Object *obj, - void *event_info); - static void genlistClickCB(void *data, Evas_Object *obj, void *event_info); - static void cancelClickCB(void *data, Evas_Object *obj, void *event_info); - static void errPopupResponseCB(void *data, Evas_Object *obj, void *event_info); - static void omaPopupResponseOKCB(void *data, Evas_Object *obj, void *event_info); - static void omaPopupResponseCancelCB(void *data, Evas_Object *obj, void *event_info); - -private: - DownloadView(); - ~DownloadView(); - - inline void destroyEvasObj(Evas_Object *e) { if(e) evas_object_del(e); e = NULL;} - void setTheme(void); - void setIndicator(Evas_Object *window); - Evas_Object *createWindow(const char *windowName); - Evas_Object *createBackground(Evas_Object *window); - Evas_Object *createLayout(Evas_Object *parent); - void createTheme(void); - void createNaviBar(void); - void createBackBtn(void); - void createControlBar(void); - void createBox(void); - void createList(void); - - void removeTheme(void); - - void addViewItemToGenlist(ViewItem *viewItem); - void createGenlistItem(ViewItem *viewItem); - void showEmptyView(void); - void hideEmptyView(void); - - void removePopup(void); - void showGenlistEditMode(void); - void hideGenlistEditMode(void); - void createSelectAllLayout(void); - void changeAllCheckedValue(void); - void destroyCheckedItem(void); - void showNotifyInfo(int type, int selectedCount); - void destroyNotifyInfo(void); - void createNotifyInfo(void); - - DateGroup *getDateGroupObj(int type); - Elm_Object_Item *getGenlistGroupItem(int type); - int getGenlistGroupCount(int type); - void setGenlistGroupItem(int type, Elm_Object_Item *item); - void increaseGenlistGroupCount(int type); - void handleUpdateDateGroupType(ViewItem *viewItem); - void cleanGenlistData(); - char *getGenlistGroupLabel(void *data, Evas_Object *obj, const char *part); - - Evas_Object *eoWindow; - Evas_Object *eoBackground; - Evas_Object *eoLayout; - Elm_Theme *eoTheme; - - Evas_Object *eoEmptyNoContent; - Evas_Object *eoNaviBar; - Elm_Object_Item *eoNaviBarItem; - Evas_Object *eoBackBtn; - Evas_Object *eoControlBar; - Elm_Object_Item *eoCbItemDelete; - Elm_Object_Item *eoCbItemCancel; - Elm_Object_Item *eoCbItemEmpty; - Evas_Object *eoBoxLayout; - Evas_Object *eoBox; - Evas_Object *eoDldList; - Evas_Object *eoPopup; - Evas_Object *eoSelectAllLayout; - Evas_Object *eoAllCheckedBox; - Evas_Object *eoNotifyInfo; - Evas_Object *eoNotifyInfoLayout; - Elm_Genlist_Item_Class dldGenlistGroupStyle; - Eina_Bool m_allChecked; - - int m_viewItemCount; - DateGroup m_today; - DateGroup m_yesterday; - DateGroup m_previousDay; -}; - -#endif /* DOWNLOAD_PROVIDER_VIEW_H */ diff --git a/src/include/download-provider-viewItem.h b/src/include/download-provider-viewItem.h deleted file mode 100644 index 70e8ec5..0000000 --- a/src/include/download-provider-viewItem.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file download-provider-viewItem.h - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief Item class for Download view - */ - -#ifndef DOWNLOAD_PROVIDER_VIEW_ITEM_H -#define DOWNLOAD_PROVIDER_VIEW_ITEM_H - -#include "download-provider-event.h" -#include "download-provider-item.h" -#include <Elementary.h> -#include <memory> - -using namespace std; - -class ViewItem { -public: - ~ViewItem(); - static void create(Item *item); - void destroy(void); - inline void deleteFromDB(void) { m_item->deleteFromDB(); } - - inline void setItem(Item *item) { m_item = item; } - static void updateCB(void *); - - - static char *getGenlistLabelCB(void *data, Evas_Object *obj, - const char *part); - char *getGenlistLabel(Evas_Object *obj, const char *part); - - static Evas_Object *getGenlistIconCB(void *data, Evas_Object *obj, - const char *part); - Evas_Object *getGenlistIcon(Evas_Object *obj, const char *part); - - static void checkChangedCB(void *data, Evas_Object *obj, void *event_info); - - const char *getMessage(void); - const char *getBytesStr(void); - const char *getHumanFriendlyBytesStr(unsigned long int bytes, - bool progressOption); - - Elm_Genlist_Item_Class *elmGenlistStyle(void); - - inline Elm_Genlist_Item_Class *elmGenlistItemClass(void) - { return &dldGenlistStyle; } - inline Elm_Genlist_Item_Class *elmGenlistHistoryItemClass(void) - { return &dldHistoryGenlistStyle; } - inline Elm_Genlist_Item_Class *elmGenlistFailedItemClass(void) - { return &dldGenlistSlideStyle; } - inline ITEM::STATE state(void) { return m_item->state(); } - inline const char* stateStr(void) { return m_item->stateStr(); } - inline bool isFinished(void) { return m_item->isFinished(); } - inline bool isFinishedWithErr(void) { return m_item->isFinishedWithErr(); } - inline bool isPreparingDownload(void) { return m_item->isPreparingDownload(); } - inline bool isCompletedDownload(void) { return m_item->isCompletedDownload(); } - - unsigned long int receivedFileSize(void); - unsigned long int fileSize(void); - const char *getTitle(void); - inline const char *getErrMsg(void) { return m_item->getErrorMessage(); } - const char *getIconPath(void) { return m_item->iconPath().c_str(); } - - inline Elm_Object_Item *genlistItem(void) { return m_glItem; } - inline void setGenlistItem(Elm_Object_Item *glItem) { m_glItem = glItem; } - inline void setProgressBar(Evas_Object *p) { m_progressBar = p; } - - void clickedDeleteButton(void); - void clickedCancelButton(void); - void clickedRetryButton(void); - void clickedGenlistItem(void); - void requestCancel(void); - inline void sendUserResponse(bool res) - { - return m_item->sendUserResponse(res); - } - inline Eina_Bool checkedValue(void) { return m_checked; } - void setCheckedValue(Eina_Bool b) { m_checked = b; } - inline Evas_Object *checkedBtn(void) { return m_checkedBtn; } - void setCheckedBtn(Evas_Object *e) { m_checkedBtn = e; } - - void updateCheckedBtn(void); - - inline int dateGroupType(void) { return m_dateGroupType; } - void setDateGroupType (int t) { m_dateGroupType = t; } - - inline double finishedTime(void) { return m_item->finishedTime();} - void extractDateGroupType(void); - - inline unsigned int historyId(void) { return m_item->historyId(); } -private: - ViewItem(Item *item); - - void updateFromItem(void); - Evas_Object *createProgressBar(Evas_Object *parent); - Evas_Object *createCancelBtn(Evas_Object *parent); - void retryViewItem(void); - - static void deleteBtnClickedCB(void *data, Evas_Object *obj, - void *event_info); - static void cancelBtnClickedCB(void *data, Evas_Object *obj, - void *event_info); - static void retryBtnClickedCB(void *data, Evas_Object *obj, - void *event_info); - - auto_ptr<Observer> m_aptr_observer; - Item *m_item; - - Elm_Genlist_Item_Class dldGenlistStyle; - Elm_Genlist_Item_Class dldHistoryGenlistStyle; - Elm_Genlist_Item_Class dldGenlistSlideStyle; - Elm_Object_Item *m_glItem; - Evas_Object *m_progressBar; - Evas_Object *m_checkedBtn; - Eina_Bool m_checked; - bool m_isRetryCase; - int m_dateGroupType; -}; - -#endif /* DOWNLOAD_PROVIDER_VIEW_ITEM_H */ diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index c3748b6..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2012 Samsung Electronics Co., Ltd - * - * Licensed under the Flora License, Version 1.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.tizenopensource.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file main.cpp - * @author Jungki Kwak (jungki.kwak@samsung.com) - * @brief main file for download provider - */ - -#include <list> -#include <string> -#include <iostream> -#include <memory> - -#include "Ecore_X.h" -#include "aul.h" -#include "vconf.h" -#include "app.h" -#include "app_service.h" - -#include "download-provider-common.h" -#include "download-provider-view.h" -#include "download-provider-network.h" -#include "download-provider-downloadRequest.h" -#include "download-provider-history-db.h" - -using namespace std; - -struct app_data_t { - Ecore_Idler *idler; - int history_count; - int load_count; -}; - -static void __lang_changed_cb(void *data) -{ - DP_LOG("=== Language changed nofification ==="); - return; -} - -static void __region_changed_cb(void *data) -{ - DownloadView &view = DownloadView::getInstance(); - view.changedRegion(); - DP_LOG("=== Region changed nofification ==="); - return; -} - -static void __low_memory_cb(void *data) -{ - DP_LOG("=== Low memory nofification ==="); - return; -} - -static Eina_Bool __load_remained_history(void *data) -{ - struct app_data_t *app_data = (struct app_data_t *)data; - if (app_data && app_data->load_count <= app_data->history_count) { - app_data->load_count += LOAD_HISTORY_COUNT; - DownloadHistoryDB::createRemainedItemsFromHistoryDB( - LOAD_HISTORY_COUNT, app_data->load_count); - return ECORE_CALLBACK_RENEW; - } else - return ECORE_CALLBACK_CANCEL; -} - -static bool __app_create(void *data) -{ - int count = 0; - struct app_data_t *app_data = (struct app_data_t *)data; - DP_LOG_START("App Create"); - - DownloadView &view = DownloadView::getInstance(); - Evas_Object *window = view.create(); - if (!window) { - DP_LOGE("Fail to create main window"); - return false; - } - /* Init network */ - NetMgr &netObj = NetMgr::getInstance(); - netObj.initNetwork(); - - evas_object_show(window); - view.show(); - - DownloadHistoryDB::getCountOfHistory(&count); - if (count > 0) { - DownloadHistoryDB::createItemsFromHistoryDB(); - if (count > LOAD_HISTORY_COUNT) { - if (app_data) { - app_data->history_count = count; - app_data->idler = ecore_idler_add(__load_remained_history, app_data); - } - } - } - - DP_LOG_END("App Create"); - - return true; -} - -static void __app_terminate(void *data) -{ - struct app_data_t *app_data = (struct app_data_t *)data; - NetMgr &netObj = NetMgr::getInstance(); - netObj.deinitNetwork(); - if (app_data && app_data->idler) - ecore_idler_del(app_data->idler); - if (app_data) { - free(app_data); - app_data = NULL; - } - return; -} - -static void __app_pause(void *data) -{ - DP_LOG_FUNC(); - return; -} - -static void __app_resume(void *data) -{ - return; -} - -static void __app_service(service_h s, void *data) -{ - string s_url = std::string(); - string s_cookie = std::string(); - char *url = NULL; - char *cookie = NULL; - char *mode = NULL; - char *app_op = NULL; - DownloadView &view = DownloadView::getInstance(); - - DP_LOG_FUNC(); - - if (service_get_operation(s, &app_op) < 0) { - DP_LOGE("Fail to get service operation"); - return; - } - DP_LOG("operation[%s]", app_op); - - if (service_get_uri(s, &url) < 0) { - DP_LOGE("Invalid URL"); - } else { - DP_LOG("url[%s]",url); - if (url) - s_url = url; - } - - if (service_get_extra_data(s, "cookie", &cookie) < 0) { - DP_LOG("No cookie"); - } else { - DP_LOG("cookie[%s]",cookie); - if (cookie) - s_cookie = cookie; - } - - if (service_get_extra_data(s, "mode", &mode) < 0) { - DP_LOG("No mode"); - } else { - DP_LOG("mode[%s]",mode); - if ( 0 == strncmp(mode, "view", strlen("view"))) { - DP_LOG("View mode"); - view.activateWindow(); - return; - } - DP_LOGE("Invalid mode"); - view.activateWindow(); - return; - } - - DownloadRequest request(s_url, s_cookie); - Item::create(request); - view.activateWindow(); - - return; -} - -int main(int argc, char *argv[]) -{ - app_event_callback_s evt_cb = {0,}; - int ret = 0; - struct app_data_t *app_data = NULL; - - app_data = (struct app_data_t *)calloc(1, sizeof(struct app_data_t)); - if (!app_data) { - DP_LOGE("Fail to calloc of app data"); - return ret; - } - - evt_cb.create = __app_create; - evt_cb.terminate = __app_terminate; - evt_cb.pause = __app_pause; - evt_cb.resume = __app_resume; - evt_cb.service = __app_service; - evt_cb.low_memory = __low_memory_cb; - evt_cb.low_battery = NULL; - evt_cb.device_orientation = NULL; - evt_cb.language_changed = __lang_changed_cb; - evt_cb.region_format_changed = __region_changed_cb; - - ret = app_efl_main(&argc, &argv, &evt_cb, app_data); - - return ret; -} - |