Revert "Add send signal if there is not enough memory during web app installation"
[framework/web/wrt-installer.git] / src / jobs / widget_install / widget_unzip.cpp
index b8d0b98..d41b890 100644 (file)
  * @file    widget_unzip.cpp
  * @author  Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
  * @version 1.0
- * @brief   Implementation file for installer task unzip
+ * @brief   Implementation file for installer widget unzip
  */
 #include <widget_install/widget_unzip.h>
 #include <widget_install/widget_install_errors.h>
 #include <widget_install/widget_install_context.h>
 #include <widget_install/job_widget_install.h>
-#include <dpl/log/log.h>
 #include <dpl/copy.h>
 #include <dpl/file_output.h>
+#include "dpl/utils/path.h"
 #include <dpl/abstract_waitable_input_adapter.h>
 #include <dpl/wrt-dao-ro/global_config.h>
-#include <task_commons.h>
 #include <sys/stat.h>
-#include <drm_trusted_client.h>
+#include <dlfcn.h>
+#include <installer_log.h>
 
 using namespace WrtDB;
 
 namespace {
+const char *const DRM_LIB_PATH = "/usr/lib/libdrm-service-core-tizen.so";
+
 struct PathAndFilePair
 {
     std::string path;
     std::string file;
 
     PathAndFilePair(const std::string &p,
-            const std::string &f) :
+                    const std::string &f) :
         path(p),
         file(f)
-    {
-    }
+    {}
 };
 
 PathAndFilePair SplitFileAndPath(const std::string &filePath)
@@ -66,15 +67,8 @@ PathAndFilePair SplitFileAndPath(const std::string &filePath)
 
 namespace Jobs {
 namespace WidgetInstall {
-WidgetUnzip::WidgetUnzip(std::string source, std::string path) :
-    m_source(source),
-    m_destPath(path)
-{
-    LogDebug("WidgetUnzip");
-}
-
 void WidgetUnzip::ExtractFile(DPL::ZipInput::File *input,
-        const std::string &destFileName)
+                            const std::string &destFileName)
 {
     Try
     {
@@ -93,44 +87,11 @@ void WidgetUnzip::ExtractFile(DPL::ZipInput::File *input,
     }
 }
 
-void WidgetUnzip::UnzipWidget()
+void WidgetUnzip::unzipProgress(const std::string &destination)
 {
-    UnzipPrepare();
-    UnzipProgress();
-}
-
-void WidgetUnzip::UnzipPrepare()
-{
-    LogInfo("Prepare to unzip...");
-
-    Try
-    {
-        m_zip.reset(new DPL::ZipInput(m_source));
-        LogInfo("Widget package comment: " << m_zip->GetGlobalComment());
-
-        // Widget package must not be empty
-        if (m_zip->empty()) {
-            ThrowMsg(Exceptions::ZipEmpty, m_source);
-        }
-
-        // Set iterator to first file
-        m_zipIterator = m_zip->begin();
-    }
-    Catch(DPL::ZipInput::Exception::OpenFailed)
-    {
-        ReThrowMsg(Exceptions::OpenZipFailed, m_source);
-    }
-}
-
-void WidgetUnzip::UnzipProgress()
-{
-
     // Show file info
-    LogInfo("Unzipping: '" << m_zipIterator->name <<
-            "', Comment: '" << m_zipIterator->comment <<
-            "', Compressed size: " << m_zipIterator->compressedSize <<
-            ", Uncompressed size: " << m_zipIterator->uncompressedSize);
-
+    _D("Unzipping: '%s', Comment: '%s', Compressed size: %lld, Uncompressed size: %lld",
+            m_zipIterator->name.c_str(), m_zipIterator->comment.c_str(), m_zipIterator->compressedSize, m_zipIterator->uncompressedSize);
 
     // Normalize file paths
     // FIXME: Implement checking for invalid characters
@@ -140,27 +101,39 @@ void WidgetUnzip::UnzipProgress()
 
     if (fileName[fileName.size() - 1] == '/') {
         // This is path
-        std::string newPath = m_destPath + "/" +
+        std::string newPath = destination + "/" +
             fileName.substr(0, fileName.size() - 1);
-        LogPedantic("Path to extract: " << newPath);
+        _D("Path to extract: %s", newPath.c_str());
 
         // Create path in case of it is empty
-        createTempPath(newPath);
+        Try
+        {
+            DPL::Utils::MakeDir(DPL::Utils::Path(newPath));
+        }
+        Catch(DPL::Utils::Path::BaseException)
+        {
+            ThrowMsg(Exceptions::FileOperationFailed, "Failed to create temporary directory");
+        }
     } else {
         // This is regular file
-        std::string fileExtractPath = m_destPath + "/" + fileName;
+        std::string fileExtractPath = destination + "/" + fileName;
 
-        LogPedantic("File to extract: " << fileExtractPath);
+        _D("File to extract: %s", fileExtractPath.c_str());
 
         // Split into pat & file pair
         PathAndFilePair pathAndFile = SplitFileAndPath(fileExtractPath);
 
-        LogPedantic("Path and file: " <<
-                    pathAndFile.path <<
-                    " : " << pathAndFile.file);
+        _D("Path and file: %s : %s", pathAndFile.path.c_str(), pathAndFile.file.c_str());
 
         // First, ensure that path exists
-        createTempPath(pathAndFile.path);
+        Try
+        {
+            DPL::Utils::MakeDir(DPL::Utils::Path(pathAndFile.path));
+        }
+        Catch(DPL::Utils::Path::BaseException)
+        {
+            ThrowMsg(Exceptions::FileOperationFailed, "Failed to create temporary directory");
+        }
 
         Try
         {
@@ -179,32 +152,164 @@ void WidgetUnzip::UnzipProgress()
 
     // Check whether there are more files to extract
     if (++m_zipIterator == m_zip->end()) {
-        LogInfo("Unzip progress finished successfuly");
-        m_zip.reset();
+        _D("Unzip progress finished successfuly");
     } else {
-        UnzipProgress();
+        unzipProgress(destination);
+    }
+}
+
+bool WidgetUnzip::isDRMPackage(const std::string &source)
+{
+    _D("Enter : isDRMPackage()");
+    int ret = 0;
+    void* pHandle = NULL;
+    char* pErrorMsg = NULL;
+    int (*drm_oem_sapps_is_drm_file)(const char* pDcfPath, int dcfPathLen);
+
+    pHandle = dlopen(DRM_LIB_PATH, RTLD_LAZY | RTLD_GLOBAL);
+    if (!pHandle) {
+        _E("dlopen failed : %s [%s]", source.c_str(), dlerror());
+        return false;
+    }
+
+    // clear existing error
+    dlerror();
+
+    drm_oem_sapps_is_drm_file = reinterpret_cast <int (*)(const char*, int)>
+        (dlsym(pHandle, "drm_oem_sapps_is_drm_file"));
+
+    if ((pErrorMsg = dlerror()) != NULL) {
+        _E("dlsym failed : %s [%s]", source.c_str(), pErrorMsg);
+        dlclose(pHandle);
+        return false;
+    }
+
+    if (drm_oem_sapps_is_drm_file == NULL) {
+        _E("drm_oem_sapps_is_drm_file is NULL : %s", source.c_str());
+        dlclose(pHandle);
+        return false;
+    }
+
+    ret = drm_oem_sapps_is_drm_file(source.c_str(), source.length());
+    dlclose(pHandle);
+    if (1 == ret) {
+        _D("%s is DRM file", source.c_str());
+        return true;
     }
+    _D("%s isn't DRM file", source.c_str());
+    return false;
 }
 
-void WidgetUnzip::UnzipDRMWidget()
+bool WidgetUnzip::decryptDRMPackage(const std::string &source, const std::string
+        &decryptedSource)
 {
-    LogDebug("Decrypt drm widget");
-    drm_trusted_sapps_decrypt_package_info_s package_info;
+    _D("Enter : decryptDRMPackage()");
+    int ret = 0;
+    void* pHandle = NULL;
+    char* pErrorMsg = NULL;
+    int (*drm_oem_sapps_decrypt_package)(const char* pDcfPath, int dcfPathLen,
+            const char* pDecryptedFile, int decryptedFileLen);
+
+    pHandle = dlopen(DRM_LIB_PATH, RTLD_LAZY | RTLD_GLOBAL);
+    if (!pHandle) {
+        _E("dlopen failed : %s [%s]", source.c_str(), dlerror());
+        return false;
+    }
+
+    // clear existing error
+    dlerror();
+
+    drm_oem_sapps_decrypt_package = reinterpret_cast <int (*)(const char*, int,
+            const char*, int)>
+        (dlsym(pHandle, "drm_oem_sapps_decrypt_package"));
 
-    strncpy(package_info.sadcf_filepath, m_source.c_str(),
-            sizeof(package_info.sadcf_filepath));
-    strncpy(package_info.decrypt_filepath, m_destPath.c_str(),
-            sizeof(package_info.decrypt_filepath));
+    if ((pErrorMsg = dlerror()) != NULL) {
+        _E("dlsym failed : %s [%s]", source.c_str(), pErrorMsg);
+        dlclose(pHandle);
+        return false;
+    }
 
-    drm_trusted_request_type_e requestType =
-        DRM_TRUSTED_REQ_TYPE_SAPPS_DECRYPT_PACKAGE;
+    if (drm_oem_sapps_decrypt_package == NULL) {
+        _E("drm_oem_sapps_decrypt_package is NULL : %s", source.c_str());
+        dlclose(pHandle);
+        return false;
+    }
 
-    int ret = drm_trusted_handle_request(requestType,
-                                         (void *)&package_info, NULL);
-    if (DRM_TRUSTED_RETURN_SUCCESS != ret) {
-        LogDebug("Failed unzip drm widget");
-        ThrowMsg(Exceptions::ExtractFileFailed, m_destPath);
+    ret = drm_oem_sapps_decrypt_package(source.c_str(), source.length(),
+            decryptedSource.c_str(), decryptedSource.length());
+    dlclose(pHandle);
+    if (1 == ret) {
+        _D("%s is decrypted : %s", source.c_str(), decryptedSource.c_str());
+        return true;
     }
+    return false;
 }
+
+std::string WidgetUnzip::getDecryptedPackage(const std::string &source)
+{
+    _D("Check DRM...");
+    if (isDRMPackage(source)) {
+        std::string decryptedFile;
+        size_t found = source.find_last_of(".wgt");
+        if (found == std::string::npos) {
+            decryptedFile += source + "_tmp.wgt";
+        } else {
+            decryptedFile += source.substr(0, source.find_last_not_of(".wgt") +
+                    1) + "_tmp.wgt";
+        }
+
+        _D("decrypted file name : %s", decryptedFile.c_str());
+        if (!decryptDRMPackage(source, decryptedFile)) {
+            _E("Failed decrypt drm file");
+            ThrowMsg(Exceptions::DrmDecryptFailed, source);
+        }
+        return decryptedFile;
+    }
+    return source;
+}
+
+void WidgetUnzip::unzipWgtFile(const std::string &source, const std::string &destination)
+{
+    _D("Prepare to unzip...");
+    std::string wgtFile;
+    Try
+    {
+        wgtFile = getDecryptedPackage(source);
+        _D("wgtFile : %s", wgtFile.c_str());
+
+        m_zip.reset(new DPL::ZipInput(wgtFile));
+        _D("Widget package comment: %s", m_zip->GetGlobalComment().c_str());
+
+
+        // Widget package must not be empty
+        if (m_zip->empty()) {
+            ThrowMsg(Exceptions::ZipEmpty, wgtFile);
+        }
+
+        // Set iterator to first file
+        m_zipIterator = m_zip->begin();
+
+        unzipProgress(destination);
+
+        // Unzip finished, close internal structures
+        m_zip.reset();
+
+        // Done
+        _D("Unzip finished");
+    }
+    Catch(DPL::ZipInput::Exception::OpenFailed)
+    {
+        ReThrowMsg(Exceptions::OpenZipFailed, wgtFile);
+    }
+    Catch(DPL::ZipInput::Exception::SeekFileFailed)
+    {
+        ThrowMsg(Exceptions::ExtractFileFailed, wgtFile);
+    }
+    Catch(Exceptions::DrmDecryptFailed)
+    {
+        ReThrowMsg(Exceptions::ExtractFileFailed, wgtFile);
+    }
+}
+
 } //namespace WidgetInstall
 } //namespace Jobs