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