Source code formating unification
[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.tzAppid));
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(
169                     "Failed to read ecryption buffer with error: " <<
170                     strerror(errno) );
171                 fclose(resFp);
172                 return;
173             }
174
175             m_resEnc->EncryptChunk(readBuf, outEncBuf, fileSize);
176
177             FILE* encFp = fopen(encFile.c_str(), "w");
178             if (NULL == encFp) {
179                 LogError("Failed to open ecryption file");
180                 fclose(resFp);
181                 return;
182             }
183             fwrite(outEncBuf, sizeof(unsigned char), blockSize, encFp);
184
185             fclose(resFp);
186             fclose(encFp);
187
188             LogDebug("Success to encrypt file");
189             LogDebug("Remove unecrypted file : " << fileName);
190
191             unlink(fileName.c_str());
192             if ((rename(encFile.c_str(), fileName.c_str())) != 0) {
193                 ThrowMsg(Exceptions::ExtractFileFailed, fileName);
194             }
195
196             std::string realPath = fileName;
197             realPath.replace(0,
198                              m_context.locations->getTemporaryRootDir().length(),
199                              m_context.locations->getSourceDir());
200
201             WrtDB::EncryptedFileInfo info;
202             info.fileName = DPL::FromUTF8String(realPath);
203             info.fileSize = fileSize;
204
205             m_context.widgetConfig.encryptedFiles.insert(info);
206         }
207     }
208     Catch(ResourceEncryptor::Exception::Base)
209     {
210         ReThrowMsg(Exceptions::ExtractFileFailed, fileName);
211     }
212 }
213 } //namespace WidgetInstall
214 } //namespace Jobs