2 * This file is part of Jenirok.
4 * Jenirok is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Jenirok is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Jenirok. If not, see <http://www.gnu.org/licenses/>.
19 #include <QtCore/QDebug>
20 #include "dasoertliche.h"
23 DasOertliche::DasOertliche(QObject* parent): Source(parent)
27 DasOertliche::~DasOertliche()
32 void DasOertliche::abort()
36 for(int i = 0; i < pendingSearches_.size(); i++)
38 delete pendingSearches_[i];
39 pendingSearches_[i] = 0;
42 pendingSearches_.clear();
46 void DasOertliche::search(Source::SearchDetails const& details)
50 SearchData* newData = new SearchData;
51 newData->details = details;
52 newData->currentPage = 1;
53 newData->finishedSearches = 0;
55 if(details.type == Source::BOTH)
57 newData->totalSearches = 2;
58 Source::SearchDetails tmpDetails = details;
59 tmpDetails.type = Source::PERSONS;
60 int id1 = sendQuery(tmpDetails, 1);
61 tmpDetails.type = Source::YELLOW_PAGES;
62 int id2 = sendQuery(tmpDetails, 1);
63 newData->searchIds.insert(id1);
64 newData->searchIds.insert(id2);
68 newData->totalSearches = 1;
69 int id = sendQuery(details, 1);
70 newData->searchIds.insert(id);
73 pendingSearches_.push_back(newData);
76 void DasOertliche::handleHttpData(int id, QByteArray const& data)
78 QString decoded = QString::fromUtf8(data.data());
80 for(int i = 0; i < pendingSearches_.size(); i++)
82 if(pendingSearches_.at(i) && pendingSearches_.at(i)->searchIds.find(id) !=
83 pendingSearches_.at(i)->searchIds.end())
85 addNumbers(pendingSearches_.at(i), decoded, i);
91 void DasOertliche::handleHttpError(int id)
93 for(int i = 0; i < pendingSearches_.size(); i++)
95 if(pendingSearches_.at(i) && pendingSearches_.at(i)->searchIds.find(id) !=
96 pendingSearches_.at(i)->searchIds.end())
99 setError(Source::CONNECTION_FAILURE, http_.errorString());
100 emitRequestFinished(pendingSearches_.at(i), true, i);
106 void DasOertliche::addNumbers(SearchData* searchData,
110 //qDebug() << "data: " << data;
112 if(data.indexOf("<div class=\"counter c02\">") == -1)
114 addOnlyNumber(searchData, data, index);
119 QRegExp rx("<div class=\"adresse\">(.*)<div class=\"adresse\">");
120 QRegExp name("<div class=\"counter.*\">*.*<a.*>(.*)<span>");
121 QRegExp number("<td class=\"nummer\">(.*)<br/>");
122 QRegExp address("<div class=\"strasse\">*(.*),(.*)</div>");
125 name.setMinimal(true);
126 address.setMinimal(true);
127 number.setMinimal(true);
129 int maxResults = getMaxResults();
131 while((pos = rx.indexIn(data, pos)) != -1)
133 pos += rx.matchedLength();
135 if(searchData->results.size() >= maxResults)
140 QString part = rx.cap(1);
141 Source::Result result;
147 if(name.indexIn(part) != -1)
149 nameStr = name.cap(1);
152 if(address.indexIn(part) != -1)
154 streetStr = address.cap(1);
155 cityStr = address.cap(2);
158 if(number.indexIn(part) != -1)
160 numberStr = number.cap(1);
163 if(formatResult(nameStr, numberStr, streetStr,
166 emit resultAvailable(result, searchData->details);
167 searchData->results.push_back(result);
172 searchData->finishedSearches++;
174 if(searchData->results.size() >= maxResults)
176 emitRequestFinished(searchData, false, index);
180 if(data.indexOf("Neste") > 0)
182 searchData->currentPage++;
183 int id = sendQuery(searchData->details, searchData->currentPage);
184 searchData->searchIds.insert(id);
186 else if(searchData->finishedSearches >= searchData->totalSearches)
188 emitRequestFinished(searchData, false, index);
194 void DasOertliche::addOnlyNumber(SearchData* searchData,
198 QRegExp name("<div class=\"counter c01\">.*<a.*>(.*)<span>");
199 QRegExp number("<td class=\"nummer\">(.*)<br/>");
200 QRegExp address("<div class=\"strasse\">(.*),(.*)</div>");
201 name.setMinimal(true);
202 number.setMinimal(true);
203 address.setMinimal(true);
205 Source::Result result;
212 if(name.indexIn(data) != -1)
214 nameStr = name.cap(1);
217 if(number.indexIn(data) != -1)
219 numberStr = number.cap(1);
222 if(address.indexIn(data) != -1)
224 streetStr = address.cap(1);
225 cityStr = address.cap(2);
228 if(formatResult(nameStr, numberStr, streetStr,
231 searchData->results.push_back(result);
232 emit resultAvailable(result, searchData->details);
235 emitRequestFinished(searchData, false, index);
238 bool DasOertliche::formatResult(QString& name, QString& number,
239 QString& street, QString& city,
240 Source::Result& result)
242 name = stripTags(name);
243 name = htmlEntityDecode(name);
244 result.name = name.trimmed();
245 number = stripTags(number);
246 number = cleanUpNumber(number);
247 result.number = number.trimmed();
248 street = stripTags(street);
249 street = htmlEntityDecode(street);
250 city = stripTags(city);
251 city = htmlEntityDecode(city);
252 result.street = street.trimmed();
253 result.city = city.trimmed();
255 if(!result.name.isEmpty() && (!getFindNumber() || !result.number.isEmpty()))
263 void DasOertliche::emitRequestFinished(SearchData* data,
264 bool error, int index)
266 QVector<Source::Result> results = data->results;
267 Source::SearchDetails details = data->details;
269 emit requestFinished(results, details, error);
270 delete pendingSearches_[index];
271 pendingSearches_[index] = 0;
272 pendingSearches_.removeAt(index);
275 int DasOertliche::sendQuery(Source::SearchDetails const& details,
278 QUrl url("http://www.dasoertliche.de/");
279 QString query = details.query;
281 if(isPhoneNumber(query))
283 url.addQueryItem("form_name","search_inv");
284 url.addQueryItem("ph",query);
288 url.addQueryItem("form_name","search_reg");
289 url.addQueryItem("kw",query);
291 if(!details.location.isEmpty())
293 url.addQueryItem("ci",details.location);
297 /* TODO No differentiation between personal and professional entries yet
298 if(details.type == Source::YELLOW_PAGES)
300 url.addQueryItem("t", "c");
304 url.addQueryItem("t", "p");
308 /* TODO No multi-page results yet.
311 url.addQueryItem("p", QString::number(page));
317 //They want us to have a name, therefore setting User-Agent here...
318 QHttpRequestHeader header("GET", url.encodedPath()+ '?' + url.encodedQuery());
319 header.setValue("User-Agent","Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10");
320 header.setValue("Host", url.encodedHost());
322 http_.setHost(url.host(), url.port(80));
324 return http_.request(header);