File indexing completed on 2024-05-12 04:58:11
0001 /* 0002 * Copyright 2009 Jakub Wieczorek <faw217@gmail.com> 0003 * 0004 * This program is free software; you can redistribute it and/or modify 0005 * it under the terms of the GNU General Public License as published by 0006 * the Free Software Foundation; either version 2 of the License, or 0007 * (at your option) any later version. 0008 * 0009 * This program is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 * GNU General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU General Public License 0015 * along with this program; if not, write to the Free Software 0016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301 USA 0018 */ 0019 /* ============================================================ 0020 * Falkon - Qt web browser 0021 * Copyright (C) 2010-2014 David Rosca <nowrep@gmail.com> 0022 * 0023 * This program is free software: you can redistribute it and/or modify 0024 * it under the terms of the GNU General Public License as published by 0025 * the Free Software Foundation, either version 3 of the License, or 0026 * (at your option) any later version. 0027 * 0028 * This program is distributed in the hope that it will be useful, 0029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0031 * GNU General Public License for more details. 0032 * 0033 * You should have received a copy of the GNU General Public License 0034 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0035 * ============================================================ */ 0036 #include "opensearchreader.h" 0037 0038 #include "opensearchengine.h" 0039 0040 #include <qiodevice.h> 0041 0042 /*! 0043 \class OpenSearchReader 0044 \brief A class reading a search engine description from an external source 0045 0046 OpenSearchReader is a class that can be used to read search engine descriptions 0047 formed using the OpenSearch format. 0048 0049 It inherits QXmlStreamReader and thus provides additional functions, such as 0050 QXmlStreamReader::error(), QXmlStreamReader::hasError() that can be used to make sure 0051 the reading procedure succeeded. 0052 0053 For more information see: 0054 http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_4#OpenSearch_description_document 0055 0056 \sa OpenSearchEngine, OpenSearchWriter 0057 */ 0058 0059 /*! 0060 Constructs a new reader. 0061 0062 \note One instance can be used to read multiple files, one by one. 0063 */ 0064 OpenSearchReader::OpenSearchReader() 0065 : QXmlStreamReader() 0066 { 0067 } 0068 0069 /*! 0070 Reads an OpenSearch engine from the \a device and returns an OpenSearchEngine object, 0071 filled in with all the data that has been retrieved from the document. 0072 0073 If the \a device is closed, it will be opened. 0074 0075 To make sure if the procedure succeeded, check QXmlStreamReader::error(). 0076 0077 \return a new constructed OpenSearchEngine object 0078 0079 \note The function returns an object of the OpenSearchEngine class even if the document 0080 is bad formed or doesn't conform to the specification. It needs to be manually 0081 deleted afterwards, if intended. 0082 \note The lifetime of the returned OpenSearchEngine object is up to the user. 0083 The object should be deleted once it is not used anymore to avoid memory leaks. 0084 */ 0085 OpenSearchEngine* OpenSearchReader::read(QIODevice* device) 0086 { 0087 clear(); 0088 0089 if (!device->isOpen()) { 0090 device->open(QIODevice::ReadOnly); 0091 } 0092 0093 setDevice(device); 0094 return read(); 0095 } 0096 0097 OpenSearchEngine* OpenSearchReader::read() 0098 { 0099 auto* engine = new OpenSearchEngine(); 0100 m_searchXml = QString::fromLatin1(device()->peek(1024 * 5)); 0101 0102 if (!m_searchXml.contains(QLatin1String("http://a9.com/-/spec/opensearch/1.1/")) && 0103 !m_searchXml.contains(QLatin1String("http://www.mozilla.org/2006/browser/search/")) 0104 ) { 0105 raiseError(QObject::tr("The file is not an OpenSearch 1.1 file.")); 0106 return engine; 0107 } 0108 0109 // It just skips the XML declaration 0110 // The parsing code bellow for some reason doesn't like it -,- 0111 0112 int index = m_searchXml.indexOf(QLatin1String("<?xml")); 0113 if (index > 0) { 0114 int end = m_searchXml.indexOf(QLatin1String("?>"), index); 0115 0116 if (end > 0) { 0117 device()->read(end + 2); 0118 } 0119 } 0120 0121 while (!isStartElement() && !atEnd()) { 0122 readNext(); 0123 } 0124 0125 0126 while (!atEnd()) { 0127 readNext(); 0128 0129 if (!isStartElement()) { 0130 continue; 0131 } 0132 0133 if (name() == QLatin1String("ShortName") || name() == QLatin1String("os:ShortName")) { 0134 engine->setName(readElementText()); 0135 } 0136 else if (name() == QLatin1String("Description") || name() == QLatin1String("os:Description")) { 0137 engine->setDescription(readElementText()); 0138 } 0139 else if (name() == QLatin1String("Url") || name() == QLatin1String("os:Url")) { 0140 QString type = attributes().value(QLatin1String("type")).toString(); 0141 QString url = attributes().value(QLatin1String("template")).toString(); 0142 QString method = attributes().value(QLatin1String("method")).toString(); 0143 0144 if (type == QLatin1String("application/x-suggestions+json") && 0145 !engine->suggestionsUrlTemplate().isEmpty() 0146 ) { 0147 continue; 0148 } 0149 0150 if ((type.isEmpty() || 0151 type == QLatin1String("text/html") || 0152 type == QLatin1String("application/xhtml+xml")) && 0153 !engine->searchUrlTemplate().isEmpty() 0154 ) { 0155 continue; 0156 } 0157 0158 if (url.isEmpty()) { 0159 continue; 0160 } 0161 0162 QList<OpenSearchEngine::Parameter> parameters; 0163 0164 readNext(); 0165 0166 while (!isEndElement() || (name() != QLatin1String("Url") && name() != QLatin1String("os:Url"))) { 0167 if (!isStartElement() || (name() != QLatin1String("Param") && name() != QLatin1String("Parameter") && 0168 name() != QLatin1String("os:Param") && name() != QLatin1String("os:Parameter")) 0169 ) { 0170 readNext(); 0171 continue; 0172 } 0173 0174 QString key = attributes().value(QLatin1String("name")).toString(); 0175 QString value = attributes().value(QLatin1String("value")).toString(); 0176 0177 if (!key.isEmpty() && !value.isEmpty()) { 0178 parameters.append(OpenSearchEngine::Parameter(key, value)); 0179 } 0180 0181 while (!isEndElement()) { 0182 readNext(); 0183 } 0184 } 0185 0186 if (type == QLatin1String("application/x-suggestions+json")) { 0187 engine->setSuggestionsUrlTemplate(url); 0188 engine->setSuggestionsParameters(parameters); 0189 engine->setSuggestionsMethod(method); 0190 } 0191 else if (type.isEmpty() || type == QLatin1String("text/html") || type == QLatin1String("application/xhtml+xml")) { 0192 engine->setSearchUrlTemplate(url); 0193 engine->setSearchParameters(parameters); 0194 engine->setSearchMethod(method); 0195 } 0196 0197 } 0198 else if (name() == QLatin1String("Image") || name() == QLatin1String("os:Image")) { 0199 engine->setImageUrl(readElementText()); 0200 } 0201 0202 if (!engine->name().isEmpty() && 0203 !engine->description().isEmpty() && 0204 !engine->suggestionsUrlTemplate().isEmpty() && 0205 !engine->searchUrlTemplate().isEmpty() && 0206 !engine->imageUrl().isEmpty() 0207 ) { 0208 break; 0209 } 0210 } 0211 0212 return engine; 0213 } 0214