[Installer] Add installation drm file
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_encrypt_resource.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /**
17  * @file    task_ecnrypt_resource.cpp
18  * @author  Soyoung Kim (sy037.kim@samsung.com)
19  * @version 1.0
20  * @brief   Implementation file for installer task encrypt resource
21  */
22 #include "task_encrypt_resource.h"
23
24 #undef __USE_FILE_OFFSET64
25
26 #include <unistd.h>
27 #include <string>
28 #include <sys/stat.h>
29 #include <fts.h>
30
31 #include <dpl/log/log.h>
32 #include <dpl/errno_string.h>
33 #include <dpl/foreach.h>
34 #include <dpl/wrt-dao-ro/global_config.h>
35
36 #include <widget_install/job_widget_install.h>
37 #include <widget_install/widget_install_context.h>
38 #include <widget_install/widget_install_errors.h>
39
40 using namespace WrtDB;
41 using namespace WRTEncryptor;
42
43 namespace {
44 std::set<std::string>& getSupportedForEncryption()
45 {
46     static std::set<std::string> encryptSet;
47     if (encryptSet.empty()) {
48         encryptSet.insert(".html");
49         encryptSet.insert(".css");
50         encryptSet.insert(".js");
51     }
52     return encryptSet;
53 }
54
55 bool isSupportedForEncryption(const std::string &file)
56 {
57     size_t foundKey = file.rfind(".");
58     if (std::string::npos != foundKey) {
59         std::string mimeType = file.substr(foundKey);
60         return getSupportedForEncryption().count(mimeType) > 0;
61     }
62     return false;
63 }
64 }
65
66 namespace Jobs {
67 namespace WidgetInstall {
68 TaskEncryptResource::TaskEncryptResource(InstallerContext& context) :
69     DPL::TaskDecl<TaskEncryptResource>(this),
70     m_context(context)
71 {
72     AddStep(&TaskEncryptResource::StepEncryptResource);
73 }
74
75 void TaskEncryptResource::StepEncryptResource()
76 {
77     LogDebug("Step Encrypt resource");
78     m_resEnc = new ResourceEncryptor;
79     m_resEnc->CreateEncryptionKey(DPL::ToUTF8String(*m_context.
80                 widgetConfig.pkgname));
81
82     EncryptDirectory(m_context.locations->getTemporaryRootDir());
83 }
84
85 void TaskEncryptResource::EncryptDirectory(std::string path)
86 {
87     FTS *fts;
88     FTSENT *ftsent;
89     char * const paths[] = {const_cast<char * const>(path.c_str()), NULL};
90
91     if ((fts = fts_open(paths, FTS_PHYSICAL|FTS_NOCHDIR, NULL)) == NULL) {
92         //ERROR
93         int error = errno;
94         LogWarning(__PRETTY_FUNCTION__ << ": fts_open failed with error: "
95                 << strerror(error));
96         ThrowMsg(Exceptions::InternalError, "Error reading directory: "
97                 << path);
98     }
99
100     while ((ftsent = fts_read(fts)) != NULL) {
101         switch (ftsent->fts_info) {
102             case FTS_DP:
103             case FTS_DC:
104             case FTS_D:
105             case FTS_DEFAULT:
106             case FTS_SLNONE:
107                 //directories, non-regular files, dangling symbolic links
108                 break;
109             case FTS_F:
110             case FTS_NSOK:
111             case FTS_SL:
112                 //regular files and other objects that can be counted
113                 if (isSupportedForEncryption(ftsent->fts_path)) {
114                     EncryptFile(ftsent->fts_path);
115                 }
116                 break;
117             case FTS_NS:
118             case FTS_DOT:
119             case FTS_DNR:
120             case FTS_ERR:
121             default:
122                 LogWarning(__PRETTY_FUNCTION__
123                         << ": traversal failed on file: "
124                         << ftsent->fts_path
125                         << " with error: "
126                         << strerror(ftsent->fts_errno));
127                 ThrowMsg(Exceptions::InternalError, "Error reading file");
128         }
129     }
130
131     if (fts_close(fts) == -1) {
132         int error = errno;
133         LogWarning(__PRETTY_FUNCTION__ << ": fts_close failed with error: "
134                 << strerror(error));
135     }
136 }
137
138 void TaskEncryptResource::EncryptFile(const std::string &fileName)
139 {
140     Try
141     {
142         LogDebug("Need to ecnrypt file Name " << fileName);
143         std::string encFile = fileName + ".enc";
144
145         struct stat buf;
146         int ret = stat(fileName.c_str(), &buf);
147         if(ret == 0) {
148             size_t fileSize = buf.st_size;
149
150             FILE* resFp = fopen(fileName.c_str(), "r");
151             if ( NULL == resFp) {
152                 LogError("Couldnot open file : " << fileName);
153                 return;
154             }
155
156             int blockSize = m_resEnc->GetBlockSize(fileSize);
157             LogDebug("Get block size : " << blockSize);
158
159             unsigned char readBuf[fileSize];
160             unsigned char outEncBuf[blockSize];
161             memset(readBuf, 0, fileSize);
162             memset(outEncBuf, 0, blockSize);
163
164             fread(readBuf, sizeof(unsigned char), fileSize, resFp);
165
166             m_resEnc->EncryptChunk(readBuf, outEncBuf, fileSize);
167
168             FILE* encFp = fopen(encFile.c_str(), "w");
169             if (NULL == encFp) {
170                 LogError("Failed to open ecryption file");
171                 return;
172             }
173             fwrite(outEncBuf, sizeof(unsigned char), blockSize, encFp);
174
175             fclose(resFp);
176             fclose(encFp);
177
178             LogDebug("Success to encrypt file");
179             LogDebug("Remove unecrypted file : " << fileName);
180
181             unlink(fileName.c_str());
182             if ((rename(encFile.c_str(), fileName.c_str())) != 0) {
183                 ThrowMsg(Exceptions::ExtractFileFailed, fileName);
184             }
185
186             std::string realPath = fileName;
187             realPath.replace(0, m_context.locations->getTemporaryRootDir().length(),
188                     m_context.locations->getSourceDir());
189
190             WrtDB::EncryptedFileInfo info;
191             info.fileName = DPL::FromUTF8String(realPath);
192             info.fileSize = fileSize;
193
194             m_context.widgetConfig.encryptedFiles.insert(info);
195         }
196     }
197     Catch(ResourceEncryptor::Exception::Base)
198     {
199         ReThrowMsg(Exceptions::ExtractFileFailed, fileName);
200     }
201 }
202 } //namespace WidgetInstall
203 } //namespace Jobs