2ea97ee6222ac6115e86c486d498622658bfea9d
[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 #include <string.h>
31 #include <errno.h>
32
33 #include <dpl/log/log.h>
34 #include <dpl/errno_string.h>
35 #include <dpl/foreach.h>
36 #include <dpl/wrt-dao-ro/global_config.h>
37
38 #include <widget_install/job_widget_install.h>
39 #include <widget_install/widget_install_context.h>
40 #include <widget_install/widget_install_errors.h>
41
42 using namespace WrtDB;
43 using namespace WRTEncryptor;
44
45 namespace {
46 std::set<std::string>& getSupportedForEncryption()
47 {
48     static std::set<std::string> encryptSet;
49     if (encryptSet.empty()) {
50         encryptSet.insert(".html");
51         encryptSet.insert(".css");
52         encryptSet.insert(".js");
53     }
54     return encryptSet;
55 }
56
57 bool isSupportedForEncryption(const std::string &file)
58 {
59     size_t foundKey = file.rfind(".");
60     if (std::string::npos != foundKey) {
61         std::string mimeType = file.substr(foundKey);
62         return getSupportedForEncryption().count(mimeType) > 0;
63     }
64     return false;
65 }
66 }
67
68 namespace Jobs {
69 namespace WidgetInstall {
70 TaskEncryptResource::TaskEncryptResource(InstallerContext& context) :
71     DPL::TaskDecl<TaskEncryptResource>(this),
72     m_context(context)
73 {
74     AddStep(&TaskEncryptResource::StepEncryptResource);
75 }
76
77 void TaskEncryptResource::StepEncryptResource()
78 {
79     LogDebug("Step Encrypt resource");
80     m_resEnc = new ResourceEncryptor;
81     m_resEnc->CreateEncryptionKey(DPL::ToUTF8String(*m_context.
82                 widgetConfig.pkgname));
83
84     EncryptDirectory(m_context.locations->getTemporaryRootDir());
85 }
86
87 void TaskEncryptResource::EncryptDirectory(std::string path)
88 {
89     FTS *fts;
90     FTSENT *ftsent;
91     char * const paths[] = {const_cast<char * const>(path.c_str()), NULL};
92
93     if ((fts = fts_open(paths, FTS_PHYSICAL|FTS_NOCHDIR, NULL)) == NULL) {
94         //ERROR
95         int error = errno;
96         LogWarning(__PRETTY_FUNCTION__ << ": fts_open failed with error: "
97                 << strerror(error));
98         ThrowMsg(Exceptions::InternalError, "Error reading directory: "
99                 << path);
100     }
101
102     while ((ftsent = fts_read(fts)) != NULL) {
103         switch (ftsent->fts_info) {
104             case FTS_DP:
105             case FTS_DC:
106             case FTS_D:
107             case FTS_DEFAULT:
108             case FTS_SLNONE:
109                 //directories, non-regular files, dangling symbolic links
110                 break;
111             case FTS_F:
112             case FTS_NSOK:
113             case FTS_SL:
114                 //regular files and other objects that can be counted
115                 if (isSupportedForEncryption(ftsent->fts_path)) {
116                     EncryptFile(ftsent->fts_path);
117                 }
118                 break;
119             case FTS_NS:
120             case FTS_DOT:
121             case FTS_DNR:
122             case FTS_ERR:
123             default:
124                 LogWarning(__PRETTY_FUNCTION__
125                         << ": traversal failed on file: "
126                         << ftsent->fts_path
127                         << " with error: "
128                         << strerror(ftsent->fts_errno));
129                 ThrowMsg(Exceptions::InternalError, "Error reading file");
130         }
131     }
132
133     if (fts_close(fts) == -1) {
134         int error = errno;
135         LogWarning(__PRETTY_FUNCTION__ << ": fts_close failed with error: "
136                 << strerror(error));
137     }
138 }
139
140 void TaskEncryptResource::EncryptFile(const std::string &fileName)
141 {
142     Try
143     {
144         LogDebug("Need to ecnrypt file Name " << fileName);
145         std::string encFile = fileName + ".enc";
146
147         struct stat buf;
148         int ret = stat(fileName.c_str(), &buf);
149         if(ret == 0) {
150             size_t fileSize = buf.st_size;
151
152             FILE* resFp = fopen(fileName.c_str(), "r");
153             if ( NULL == resFp) {
154                 LogError("Couldnot open file : " << fileName);
155                 return;
156             }
157
158             int blockSize = m_resEnc->GetBlockSize(fileSize);
159             LogDebug("Get block size : " << blockSize);
160
161             unsigned char readBuf[fileSize];
162             unsigned char outEncBuf[blockSize];
163             memset(readBuf, 0, fileSize);
164             memset(outEncBuf, 0, blockSize);
165
166             ret = fread(readBuf, sizeof(unsigned char), fileSize, resFp);
167             if (ret!=fileSize){
168                 LogError("Failed to read ecryption buffer with error: " << strerror(errno) );
169                 fclose(resFp);
170                 return;
171             }
172
173             m_resEnc->EncryptChunk(readBuf, outEncBuf, fileSize);
174
175             FILE* encFp = fopen(encFile.c_str(), "w");
176             if (NULL == encFp) {
177                 LogError("Failed to open ecryption file");
178                 fclose(resFp);
179                 return;
180             }
181             fwrite(outEncBuf, sizeof(unsigned char), blockSize, encFp);
182
183             fclose(resFp);
184             fclose(encFp);
185
186             LogDebug("Success to encrypt file");
187             LogDebug("Remove unecrypted file : " << fileName);
188
189             unlink(fileName.c_str());
190             if ((rename(encFile.c_str(), fileName.c_str())) != 0) {
191                 ThrowMsg(Exceptions::ExtractFileFailed, fileName);
192             }
193
194             std::string realPath = fileName;
195             realPath.replace(0, m_context.locations->getTemporaryRootDir().length(),
196                     m_context.locations->getSourceDir());
197
198             WrtDB::EncryptedFileInfo info;
199             info.fileName = DPL::FromUTF8String(realPath);
200             info.fileSize = fileSize;
201
202             m_context.widgetConfig.encryptedFiles.insert(info);
203         }
204     }
205     Catch(ResourceEncryptor::Exception::Base)
206     {
207         ReThrowMsg(Exceptions::ExtractFileFailed, fileName);
208     }
209 }
210 } //namespace WidgetInstall
211 } //namespace Jobs