1 /*
2 SPDX-FileCopyrightText: 2009 Jakub Wieczorek <faw217@gmail.com>
3 SPDX-FileCopyrightText: 2009 Christian Franke <cfchris6@ts2server.com>
4 SPDX-FileCopyrightText: 2009 Fredy Yanardi <fyanardi@gmail.com>
5
6 SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "OpenSearchEngine.h"
10
11 #include <QRegExp>
12 #include <QStringList>
13 #include <QScriptEngine>
14 #include <QScriptValue>
15 #include <QLocale>
16 #include <QUrlQuery>
17
OpenSearchEngine(QObject *)18 OpenSearchEngine::OpenSearchEngine(QObject *)
19 : m_scriptEngine(nullptr)
20 {
21 }
22
~OpenSearchEngine()23 OpenSearchEngine::~OpenSearchEngine()
24 {
25 delete m_scriptEngine;
26 }
27
parseTemplate(const QString & searchTerm,const QString & searchTemplate)28 QString OpenSearchEngine::parseTemplate(const QString &searchTerm, const QString &searchTemplate)
29 {
30 QString result = searchTemplate;
31 result.replace(QLatin1String("{count}"), QLatin1String("20"));
32 result.replace(QLatin1String("{startIndex}"), QLatin1String("0"));
33 result.replace(QLatin1String("{startPage}"), QLatin1String("0"));
34 result.replace(QLatin1String("{language}"), QLocale::languageToString(QLocale().language()));
35 result.replace(QLatin1String("{inputEncoding}"), QLatin1String("UTF-8"));
36 result.replace(QLatin1String("{outputEncoding}"), QLatin1String("UTF-8"));
37 result.replace(QLatin1String("{searchTerms}"), searchTerm);
38 return result;
39 }
40
name() const41 QString OpenSearchEngine::name() const
42 {
43 return m_name;
44 }
45
setName(const QString & name)46 void OpenSearchEngine::setName(const QString &name)
47 {
48 m_name = name;
49 }
50
description() const51 QString OpenSearchEngine::description() const
52 {
53 return m_description;
54 }
55
setDescription(const QString & description)56 void OpenSearchEngine::setDescription(const QString &description)
57 {
58 m_description = description;
59 }
60
searchUrlTemplate() const61 QString OpenSearchEngine::searchUrlTemplate() const
62 {
63 return m_searchUrlTemplate;
64 }
65
setSearchUrlTemplate(const QString & searchUrlTemplate)66 void OpenSearchEngine::setSearchUrlTemplate(const QString &searchUrlTemplate)
67 {
68 m_searchUrlTemplate = searchUrlTemplate;
69 }
70
searchUrl(const QString & searchTerm) const71 QUrl OpenSearchEngine::searchUrl(const QString &searchTerm) const
72 {
73 if (m_searchUrlTemplate.isEmpty()) {
74 return QUrl();
75 }
76
77 QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, m_searchUrlTemplate).toUtf8());
78 QUrlQuery query(retVal);
79
80 QList<Parameter>::const_iterator end = m_searchParameters.constEnd();
81 QList<Parameter>::const_iterator i = m_searchParameters.constBegin();
82 for (; i != end; ++i) {
83 query.addQueryItem(i->first, parseTemplate(searchTerm, i->second));
84 }
85
86 retVal.setQuery(query);
87 return retVal;
88 }
89
providesSuggestions() const90 bool OpenSearchEngine::providesSuggestions() const
91 {
92 return !m_suggestionsUrlTemplate.isEmpty();
93 }
94
suggestionsUrlTemplate() const95 QString OpenSearchEngine::suggestionsUrlTemplate() const
96 {
97 return m_suggestionsUrlTemplate;
98 }
99
setSuggestionsUrlTemplate(const QString & suggestionsUrlTemplate)100 void OpenSearchEngine::setSuggestionsUrlTemplate(const QString &suggestionsUrlTemplate)
101 {
102 m_suggestionsUrlTemplate = suggestionsUrlTemplate;
103 }
104
suggestionsUrl(const QString & searchTerm) const105 QUrl OpenSearchEngine::suggestionsUrl(const QString &searchTerm) const
106 {
107 if (m_suggestionsUrlTemplate.isEmpty()) {
108 return QUrl();
109 }
110
111 QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, m_suggestionsUrlTemplate).toUtf8());
112 QUrlQuery query(retVal);
113
114 QList<Parameter>::const_iterator end = m_suggestionsParameters.constEnd();
115 QList<Parameter>::const_iterator i = m_suggestionsParameters.constBegin();
116 for (; i != end; ++i) {
117 query.addQueryItem(i->first, parseTemplate(searchTerm, i->second));
118 }
119
120 retVal.setQuery(query);
121 return retVal;
122 }
123
searchParameters() const124 QList<OpenSearchEngine::Parameter> OpenSearchEngine::searchParameters() const
125 {
126 return m_searchParameters;
127 }
128
setSearchParameters(const QList<Parameter> & searchParameters)129 void OpenSearchEngine::setSearchParameters(const QList<Parameter> &searchParameters)
130 {
131 m_searchParameters = searchParameters;
132 }
133
suggestionsParameters() const134 QList<OpenSearchEngine::Parameter> OpenSearchEngine::suggestionsParameters() const
135 {
136 return m_suggestionsParameters;
137 }
138
setSuggestionsParameters(const QList<Parameter> & suggestionsParameters)139 void OpenSearchEngine::setSuggestionsParameters(const QList<Parameter> &suggestionsParameters)
140 {
141 m_suggestionsParameters = suggestionsParameters;
142 }
143
imageUrl() const144 QString OpenSearchEngine::imageUrl() const
145 {
146 return m_imageUrl;
147 }
148
setImageUrl(const QString & imageUrl)149 void OpenSearchEngine::setImageUrl(const QString &imageUrl)
150 {
151 m_imageUrl = imageUrl;
152 }
153
image() const154 QImage OpenSearchEngine::image() const
155 {
156 return m_image;
157 }
158
setImage(const QImage & image)159 void OpenSearchEngine::setImage(const QImage &image)
160 {
161 m_image = image;
162 }
163
isValid() const164 bool OpenSearchEngine::isValid() const
165 {
166 return (!m_name.isEmpty() && !m_searchUrlTemplate.isEmpty());
167 }
168
operator ==(const OpenSearchEngine & other) const169 bool OpenSearchEngine::operator==(const OpenSearchEngine &other) const
170 {
171 return (m_name == other.m_name
172 && m_description == other.m_description
173 && m_imageUrl == other.m_imageUrl
174 && m_searchUrlTemplate == other.m_searchUrlTemplate
175 && m_suggestionsUrlTemplate == other.m_suggestionsUrlTemplate
176 && m_searchParameters == other.m_searchParameters
177 && m_suggestionsParameters == other.m_suggestionsParameters);
178 }
179
operator <(const OpenSearchEngine & other) const180 bool OpenSearchEngine::operator<(const OpenSearchEngine &other) const
181 {
182 return (m_name < other.m_name);
183 }
184
parseSuggestion(const QByteArray & resp)185 QStringList OpenSearchEngine::parseSuggestion(const QByteArray &resp)
186 {
187 const QString response = QString::fromUtf8(resp.constData(), resp.size()).trimmed();
188
189 if (response.isEmpty()) {
190 return QStringList();
191 }
192
193 if (!response.startsWith(QLatin1Char('[')) || !response.endsWith(QLatin1Char(']'))) {
194 return QStringList();
195 }
196
197 #ifdef __GNUC__
198 #warning "QScriptEngine is deprecated, port to QJsonDocument"
199 #endif
200
201 if (!m_scriptEngine) {
202 m_scriptEngine = new QScriptEngine();
203 }
204
205 // Evaluate the JSON response using QtScript.
206 if (!m_scriptEngine->canEvaluate(response)) {
207 return QStringList();
208 }
209
210 QScriptValue responseParts = m_scriptEngine->evaluate(response);
211
212 if (!responseParts.property(1).isArray()) {
213 return QStringList();
214 }
215
216 QStringList suggestionsList;
217 qScriptValueToSequence(responseParts.property(1), suggestionsList);
218
219 return suggestionsList;
220 }
221
222