1/*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "sql_analyzer.h"
16
17#include "hilog_wrapper.h"
18
19namespace OHOS {
20namespace Contacts {
21constexpr int POS_ADD_TWO = 2;
22
23SqlAnalyzer::SqlAnalyzer()
24{
25}
26
27SqlAnalyzer::~SqlAnalyzer()
28{
29}
30
31bool SqlAnalyzer::CheckValuesBucket(const OHOS::NativeRdb::ValuesBucket &value)
32{
33    std::map<std::string, NativeRdb::ValueObject> valuesMap;
34    value.GetAll(valuesMap);
35    for (auto it = valuesMap.begin(); it != valuesMap.end(); ++it) {
36        std::string key = it->first;
37        bool isKey = FindIllegalWords(key);
38        if (isKey) {
39            HILOG_ERROR("SqlAnalyzer CheckValuesBucket key is %{public}s error", key.c_str());
40            return false;
41        }
42        NativeRdb::ValueObject value = it->second;
43        if (value.GetType() == NativeRdb::ValueObjectType::TYPE_STRING) {
44            std::string str;
45            value.GetString(str);
46            str = ParseSpecial(str);
47            bool isValue = FindIllegalWords(str);
48            if (isValue) {
49                HILOG_ERROR("SqlAnalyzer CheckValuesBucket value is %{public}s error", str.c_str());
50                return false;
51            }
52        }
53    }
54    return true;
55}
56
57bool SqlAnalyzer::CharCheck(char &ch, std::string sql, std::size_t &pos)
58{
59    if (ch == '[') {
60        pos++;
61        std::size_t found = sql.find(']', pos);
62        if (found == std::string::npos) {
63            return true;
64        }
65        pos++;
66    }
67    if (ch == '-' && PickChar(sql, pos + 1) == '-') {
68        pos += POS_ADD_TWO;
69        std::size_t found = sql.find('\n', pos);
70        if (found == std::string::npos) {
71            return true;
72        }
73        pos++;
74    }
75    if (ch == '/' && PickChar(sql, pos + 1) == '*') {
76        pos += POS_ADD_TWO;
77        std::size_t found = sql.find("*/", pos);
78        if (found == std::string::npos) {
79            return true;
80        }
81        pos += POS_ADD_TWO;
82    }
83    if (ch == ';') {
84        return true;
85    }
86    pos++;
87    return false;
88}
89
90bool SqlAnalyzer::StrCheck(char &ch, std::size_t strlen, std::string sql, std::size_t &pos)
91{
92    if (IsInStr(ch, "'\"`") == 0) {
93        pos++;
94        while (pos < strlen) {
95            std::size_t found = sql.find(ch, pos);
96            if (found == std::string::npos) {
97                return true;
98            }
99            if (PickChar(sql, pos + 1) != ch) {
100                break;
101            }
102            pos += POS_ADD_TWO;
103        }
104    }
105    return false;
106}
107
108bool SqlAnalyzer::FindIllegalWords(std::string sql)
109{
110    if (sql.empty()) {
111        return false;
112    }
113    std::size_t pos = 0;
114    std::size_t strlen = sql.length();
115    while (pos < strlen) {
116        char ch = PickChar(sql, pos);
117        if (IsLetter(ch)) {
118            std::size_t start = pos;
119            pos++;
120            while (IsLetterNumber(PickChar(sql, pos))) {
121                pos++;
122            }
123            std::size_t count = pos - start + 1;
124            sql.substr(start, count);
125        }
126        if (IsInStr(ch, "'\"`") == 0) {
127            if (StrCheck(ch, strlen, sql, pos)) {
128                return true;
129            } else {
130                continue;
131            }
132        }
133        if (CharCheck(ch, sql, pos)) {
134            return true;
135        } else {
136            continue;
137        }
138    }
139    return false;
140}
141} // namespace Contacts
142} // namespace OHOS