2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
18 * Sangwan Kwon (sangwan.kwon@samsung.com)
19 * @file ReferenceValidator.cpp
21 * @brief Compare signature reference list and list of widget file.
23 #include <vcore/ReferenceValidator.h>
31 #include <sys/types.h>
36 #include <dpl/log/log.h>
44 const char *SPECIAL_SYMBOL_CURRENT_DIR = ".";
45 const char *SPECIAL_SYMBOL_UPPER_DIR = "..";
46 const char *SPECIAL_SYMBOL_AUTHOR_SIGNATURE_FILE = "author-signature.xml";
47 const char *REGEXP_DISTRIBUTOR_SIGNATURE = "^signature[1-9][0-9]*\\.xml";
49 const char MARK_ENCODED_CHAR = '%';
51 } // namespace anonymous
53 namespace ValidationCore {
55 class ReferenceValidator::Impl {
57 Impl(const std::string &dirpath)
59 , m_signatureRegexp(REGEXP_DISTRIBUTOR_SIGNATURE)
64 Result checkReferences(const SignatureData &signatureData)
66 const ReferenceSet &refSet = signatureData.getReferenceSet();
67 ReferenceSet refDecoded;
70 for (auto it = refSet.begin(); it != refSet.end(); ++it) {
71 if (std::string::npos != it->find(MARK_ENCODED_CHAR))
72 refDecoded.insert(decodeProcent(*it));
74 refDecoded.insert(*it);
77 return ERROR_DECODING_URL;
80 return dfsCheckDirectories(
83 signatureData.isAuthorSignature());
86 Result checkOutbound(const std::string &linkPath, const std::string &appPath)
88 char resolvedPath[PATH_MAX];
90 if (realpath((appPath + "/" + linkPath).c_str(), resolvedPath) == NULL)
91 return ERROR_READING_LNK;
93 std::string linkRealPath(resolvedPath);
95 if (linkRealPath.compare(0, appPath.size(), appPath) == 0)
98 return ERROR_OUTBOUND_LNK;
102 int hexToInt(char hex);
103 std::string decodeProcent(const std::string &path);
105 Result dfsCheckDirectories(
106 const ReferenceSet &referenceSet,
107 const std::string &directory,
108 bool isAuthorSignature);
110 inline bool isDistributorSignature(const char *cstring) const
112 return m_signatureRegexp.FullMatch(cstring);
115 std::string m_dirpath;
116 pcrecpp::RE m_signatureRegexp;
119 int ReferenceValidator::Impl::hexToInt(char a)
121 if (a >= '0' && a <= '9') return a - '0';
123 if (a >= 'A' && a <= 'F') return a - 'A' + 10;
125 if (a >= 'a' && a <= 'f') return a - 'a' + 10;
127 LogError("Symbol '" << a << "' is out of scope.");
128 throw ERROR_DECODING_URL;
131 std::string ReferenceValidator::Impl::decodeProcent(const std::string &path)
133 std::vector<int> input(path.begin(), path.end());
134 std::vector<char> output;
139 while (i < input.size()) {
140 if (MARK_ENCODED_CHAR == input[i]) {
141 if (i + 2 >= input.size())
142 throw ERROR_DECODING_URL;
144 int result = hexToInt(input[i + 1]) * 16 + hexToInt(input[i + 2]);
145 output.push_back(static_cast<char>(result));
148 output.push_back(static_cast<char>(input[i]));
153 LogError("Error while decoding url path : " << path);
154 throw ERROR_DECODING_URL;
157 return std::string(output.begin(), output.end());
160 ReferenceValidator::Result ReferenceValidator::Impl::dfsCheckDirectories(
161 const ReferenceSet &referenceSet,
162 const std::string &directory,
163 bool isAuthorSignature)
168 struct dirent *result;
169 std::string currentDir = m_dirpath;
171 if (!directory.empty()) {
173 currentDir += directory;
176 if ((dirp = opendir(currentDir.c_str())) == NULL) {
177 LogError("Error opening directory : " << currentDir);
178 return ERROR_OPENING_DIR;
181 for (ret = readdir_r(dirp, &entry, &result);
182 ret == 0 && result != NULL;
183 ret = readdir_r(dirp, &entry, &result)) {
184 if (!strcmp(result->d_name, SPECIAL_SYMBOL_CURRENT_DIR)) {
188 if (!strcmp(result->d_name, SPECIAL_SYMBOL_UPPER_DIR)) {
192 if (result->d_type == DT_UNKNOWN) {
193 // try to stat inode when readdir is not returning known type
194 std::string path = currentDir + "/" + result->d_name;
197 if (lstat(path.c_str(), &s) != 0) {
202 if (S_ISREG(s.st_mode)) {
203 result->d_type = DT_REG;
204 } else if (S_ISDIR(s.st_mode)) {
205 result->d_type = DT_DIR;
209 if (currentDir == m_dirpath && result->d_type == DT_REG &&
210 !strcmp(result->d_name, SPECIAL_SYMBOL_AUTHOR_SIGNATURE_FILE) &&
215 if (currentDir == m_dirpath && result->d_type == DT_REG &&
216 isDistributorSignature(result->d_name)) {
220 if (result->d_type == DT_DIR) {
221 LogDebug("Open directory : " << (directory + result->d_name));
222 std::string tmp_directory = directory + result->d_name + "/";
223 Result result = dfsCheckDirectories(referenceSet,
227 if (result != NO_ERROR) {
231 } else if (result->d_type == DT_REG) {
232 if (referenceSet.end() ==
233 referenceSet.find(directory + result->d_name)) {
234 LogDebug("Found file : " << (directory + result->d_name));
235 LogError("Unknown ERROR_REFERENCE_NOT_FOUND.");
237 return ERROR_REFERENCE_NOT_FOUND;
239 } else if (result->d_type == DT_LNK) {
240 std::string linkPath(directory + result->d_name);
242 if (referenceSet.end() ==
243 referenceSet.find(linkPath)) {
244 LogDebug("Found file : " << (directory + result->d_name));
245 LogError("Unknown ERROR_REFERENCE_NOT_FOUND.");
247 return ERROR_REFERENCE_NOT_FOUND;
250 Result ret = checkOutbound(linkPath, m_dirpath);
252 if (ret != NO_ERROR) {
253 LogError("Link file point wrong path");
258 LogError("Unknown file type.");
260 return ERROR_UNSUPPORTED_FILE_TYPE;
266 return ERROR_READING_DIR;
273 ReferenceValidator::ReferenceValidator(const std::string &dirpath)
274 : m_impl(new Impl(dirpath))
277 ReferenceValidator::~ReferenceValidator()
282 ReferenceValidator::Result ReferenceValidator::checkReferences(
283 const SignatureData &signatureData)
285 return m_impl->checkReferences(signatureData);
288 ReferenceValidator::Result ReferenceValidator::checkOutbound(
289 const std::string &linkPath, const std::string &appPath)
291 return m_impl->checkOutbound(linkPath, appPath);