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>
30 #include <sys/types.h>
35 #include <dpl/log/log.h>
41 namespace ValidationCore {
45 const char *AUTHOR_SIGNATURE = "author-signature.xml";
46 const char *REGEXP_DISTRIBUTOR_SIGNATURE = "^signature[1-9][0-9]*\\.xml";
47 const char MARK_ENCODED_CHAR = '%';
49 struct dirent *readdir(DIR *dirp) {
51 auto ret = ::readdir(dirp);
53 LogWarning("Error read dir.");
57 } // anonymous namespace
59 class ReferenceValidator::Impl {
61 Impl(const std::string &dirpath)
63 , m_signatureRegexp(REGEXP_DISTRIBUTOR_SIGNATURE)
68 Result checkReferences(const SignatureData &signatureData)
70 const ReferenceSet &refSet = signatureData.getReferenceSet();
71 ReferenceSet refDecoded;
74 for (auto it = refSet.begin(); it != refSet.end(); ++it) {
75 if (std::string::npos != it->find(MARK_ENCODED_CHAR))
76 refDecoded.insert(decodeProcent(*it));
78 refDecoded.insert(*it);
81 return ERROR_DECODING_URL;
84 return dfsCheckDirectories(
87 signatureData.isAuthorSignature());
90 Result checkOutbound(const std::string &linkPath, const std::string &appPath)
92 char resolvedPath[PATH_MAX];
94 if (realpath((appPath + "/" + linkPath).c_str(), resolvedPath) == NULL)
95 return ERROR_READING_LNK;
97 std::string linkRealPath(resolvedPath);
99 if (linkRealPath.compare(0, appPath.size(), appPath) == 0)
102 return ERROR_OUTBOUND_LNK;
106 int hexToInt(char hex);
107 std::string decodeProcent(const std::string &path);
109 Result dfsCheckDirectories(
110 const ReferenceSet &referenceSet,
111 const std::string &directory,
112 bool isAuthorSignature);
114 inline bool isDistributorSignature(const char *cstring) const
116 return m_signatureRegexp.FullMatch(cstring);
119 std::string m_dirpath;
120 pcrecpp::RE m_signatureRegexp;
123 int ReferenceValidator::Impl::hexToInt(char a)
125 if (a >= '0' && a <= '9') return a - '0';
127 if (a >= 'A' && a <= 'F') return a - 'A' + 10;
129 if (a >= 'a' && a <= 'f') return a - 'a' + 10;
131 LogError("Symbol '" << a << "' is out of scope.");
132 throw ERROR_DECODING_URL;
135 std::string ReferenceValidator::Impl::decodeProcent(const std::string &path)
137 std::vector<int> input(path.begin(), path.end());
138 std::vector<char> output;
143 while (i < input.size()) {
144 if (MARK_ENCODED_CHAR == input[i]) {
145 if (i + 2 >= input.size())
146 throw ERROR_DECODING_URL;
148 int result = hexToInt(input[i + 1]) * 16 + hexToInt(input[i + 2]);
149 output.push_back(static_cast<char>(result));
152 output.push_back(static_cast<char>(input[i]));
157 LogError("Error while decoding url path : " << path);
158 throw ERROR_DECODING_URL;
161 return std::string(output.begin(), output.end());
164 ReferenceValidator::Result ReferenceValidator::Impl::dfsCheckDirectories(
165 const ReferenceSet &referenceSet,
166 const std::string &directory,
167 bool isAuthorSignature)
169 std::string currentDir = m_dirpath;
170 if (!directory.empty())
171 currentDir += ("/" + directory);
173 std::unique_ptr<DIR, std::function<int(DIR *)>> dp(::opendir(currentDir.c_str()),
176 LogError("Error opening directory : " << currentDir);
177 return ERROR_OPENING_DIR;
180 while (auto dirp = ValidationCore::readdir(dp.get())) {
181 if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, ".."))
184 if (dirp->d_type == DT_UNKNOWN) {
185 // try to stat inode when readdir is not returning known type
186 std::string path = currentDir + "/" + dirp->d_name;
188 if (lstat(path.c_str(), &s) != 0)
191 if (S_ISREG(s.st_mode))
192 dirp->d_type = DT_REG;
193 else if (S_ISDIR(s.st_mode))
194 dirp->d_type = DT_DIR;
197 if (currentDir == m_dirpath && dirp->d_type == DT_REG)
198 if ((!strcmp(dirp->d_name, AUTHOR_SIGNATURE) && isAuthorSignature) ||
199 isDistributorSignature(dirp->d_name))
202 if (dirp->d_type == DT_DIR) {
203 LogDebug("Open directory : " << (directory + dirp->d_name));
204 std::string tmp_directory = directory + dirp->d_name + "/";
205 Result result = dfsCheckDirectories(referenceSet,
208 if (result != NO_ERROR)
210 } else if (dirp->d_type == DT_REG) {
211 if (referenceSet.end() == referenceSet.find(directory + dirp->d_name)) {
212 LogError("Cannot find : " << (directory + dirp->d_name));
213 return ERROR_REFERENCE_NOT_FOUND;
215 } else if (dirp->d_type == DT_LNK) {
216 std::string linkPath(directory + dirp->d_name);
217 if (referenceSet.end() == referenceSet.find(linkPath)) {
218 LogError("Cannot find : " << (directory + dirp->d_name));
219 return ERROR_REFERENCE_NOT_FOUND;
222 Result result = checkOutbound(linkPath, m_dirpath);
223 if (result != NO_ERROR) {
224 LogError("Link file point wrong path. : " << linkPath);
228 LogError("Unknown file type.");
229 return ERROR_UNSUPPORTED_FILE_TYPE;
238 ReferenceValidator::ReferenceValidator(const std::string &dirpath)
239 : m_impl(new Impl(dirpath))
242 ReferenceValidator::~ReferenceValidator()
247 ReferenceValidator::Result ReferenceValidator::checkReferences(
248 const SignatureData &signatureData)
250 return m_impl->checkReferences(signatureData);
253 ReferenceValidator::Result ReferenceValidator::checkOutbound(
254 const std::string &linkPath, const std::string &appPath)
256 return m_impl->checkOutbound(linkPath, appPath);