Splashscreen ad support. Wait dialog for ad click/browser start.
[qtmads] / src / qtmadsservice.cpp
1 /*
2  * Copyright (c) 2009 Eetu Lehmusvuo.
3  *
4  * This file is part of QtMAds.
5  *
6  * QtMAds is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * QtMAds is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with QtMAds.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "qtmadsservice.h"
22
23 #include <QHttp>
24 #include <QUrl>
25 #include <QDebug>
26 #include <QImage>
27 #include <QFile>
28 #include <QXmlStreamReader>
29 #include <QDir>
30 #include <QPluginLoader>
31
32 QtmadsService::QtmadsService()
33 {
34 }
35
36 QtmadsService::~QtmadsService()
37 {
38     http->close();
39     delete http;
40 }
41
42 bool QtmadsService::initializeService(QString service, quint32 adGroup, AdType defaultAdType)
43 {
44     this->serviceName = service;
45     this->adGroupId = adGroup;
46     this->defAdType = defaultAdType;
47
48     bool parseSuccess = true;
49     // ../plugins/SERVICE_NAME_adconfigure.xml
50     QString path("plugins/confs/");
51     path.append(this->serviceName);
52     path.append("_adconfigure.xml");
53     QFile file(path);
54     parseSuccess = file.exists();
55
56     /*if(!file.exists()){
57         // ./default_adconfigure.xml
58         file.setFileName("." + CONF_FILE);
59         parseSuccess = file.exists();
60     }*/
61
62     if(parseSuccess){
63         file.open(QIODevice::ReadOnly);
64         this->parseXmlConfFile(file);
65     }
66
67     if(parseSuccess){
68         initialized = true;
69     }else{
70         initialized = false;
71         //TODO: parse failed
72     }
73
74     return isInitialized();
75 }
76
77 bool QtmadsService::isInitialized()
78 {
79     return initialized;
80 }
81
82 void QtmadsService::getAd(QHash<QString, QVariant> &adParameters)
83 {
84     //qDebug() << "QtmadsService::getAd()";
85     if(isInitialized()){
86         QList<QPair<QString,QString> > parameters;
87         this->parseUrlParameters(adParameters, parameters);
88
89         QUrl url(this->serviceUrl);
90         url.setQueryItems(parameters);
91         QByteArray path = QUrl::toPercentEncoding(url.path(), "!$&'()*+,;=:@/?");
92         if (path.isEmpty())
93             path = "/";
94         path.append(QUrl::toPercentEncoding("?", "!$&'()*+,;=:@/?"));
95         path.append(url.encodedQuery());
96
97         http = new QHttp(this);
98         connect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(adRequestFinished(int, bool)));
99         http->setHost(url.host());
100         //qDebug() << "Url: " <<  url.toString();
101         adTrasactionId = http->get(path);
102     }else{
103         emit adRequestFailed();
104     }
105 }
106
107
108 void QtmadsService::adRequestFinished(int transactionId, bool error)
109 {
110     //qDebug() << "adRequestFinished()";
111     if(adTrasactionId != transactionId){
112                 return;
113         }
114         adTrasactionId = -1;
115
116         if(!error){
117                 QByteArray data = http->readAll();
118
119                 qDebug() << "Data: " << data;
120
121                 QHash<QString, QVariant> adParams;// = new QHash<QString, QVariant>();
122                 this->parseReceivedAd(data, adParams);
123                 QHash<QString, QVariant>::iterator i;
124
125
126                 /*for(i = adParams.begin(); i !=  adParams.end(); i++){
127                     qDebug() << "key: " << i.key() << " value: " << i.value().toString();
128                 }*/
129
130                 emit adRequestReady(adParams);
131         }else{
132             qDebug() << "adRequestFailed()";
133                 emit adRequestFailed();
134         }
135
136         disconnect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(adRequestFinished(int, bool)));
137 }
138
139 void QtmadsService::getRemoteImage(QString urlString)
140 {
141     QUrl url(urlString);
142     QByteArray path = QUrl::toPercentEncoding(url.path(), "!$&'()*+,;=:@/?");
143     if (path.isEmpty())
144         path = "/";
145
146     connect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(imageRequestFinished(int, bool)));
147     http->setHost(url.host());
148     imageTrasactionId = http->get(path);
149 }
150
151
152 void QtmadsService::imageRequestFinished(int transactionId, bool error)
153 {
154     if(imageTrasactionId != transactionId){
155         return;
156     }
157     imageTrasactionId = -1;
158
159     if(!error){
160         QImage *image = new QImage();
161         if(image->loadFromData(http->readAll())){
162             emit imageRequestReady(image);
163             delete image;
164         }else{
165             delete image;
166             emit imageRequestFailed();
167         }
168     }
169
170     disconnect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(imageRequestFinished(int, bool)));
171 }
172
173
174 void QtmadsService::setDefaultAdType(AdType type)
175 {
176     this->defAdType = type;
177 }
178
179 AdType QtmadsService::defaultAdType()
180 {
181     return this->defAdType;
182 }
183
184 bool QtmadsService::parseXmlConfFile(QFile &file)
185 {
186     //qDebug() << "QtmadsService::parseXmlConfFile()";
187     //TODO: apply some sanity to if-hell
188     bool success = false;
189     QXmlStreamReader xmlReader(&file);
190
191     while (!xmlReader.atEnd()) {
192         // find right servicename tag
193         if(QXmlStreamReader::StartElement == xmlReader.readNext()
194                 && 0 == xmlReader.name().compare(TAG_SERVICE)
195                 && 0 == xmlReader.attributes().value("name").compare(this->serviceName)){
196             this->serviceUrl.clear();
197             this->serviceUrl.append(xmlReader.attributes().value("url"));
198
199             // until </service>
200             while (!(QXmlStreamReader::EndElement == xmlReader.readNext()
201                     && 0 == xmlReader.name().compare(TAG_SERVICE))) {
202                 success = true;
203
204                 if(QXmlStreamReader::StartElement == xmlReader.tokenType()){
205                     if(0 == xmlReader.name().compare(TAG_ACCOUNTID)){
206                         parameterTags.insert(
207                                 QString(TAG_ACCOUNTID),xmlReader.attributes().value(TAG_KEY).toString());
208                         this->accountId.clear();
209                         this->accountId.append(xmlReader.attributes().value(TAG_VALUE));
210                     }else if(0 == xmlReader.name().compare(TAG_PASSWORD)){
211                         parameterTags.insert(
212                                 QString(TAG_PASSWORD),xmlReader.attributes().value(TAG_KEY).toString());
213                         this->password.clear();
214                         this->password.append(xmlReader.attributes().value(TAG_VALUE));
215                     }else if(0 == xmlReader.name().compare(TAG_CAMPAIGN)){
216
217                         if(0 == xmlReader.attributes().value("id").compare(QString("%1").arg(this->adGroupId))){
218                             // until </campaign>
219                             while(!(QXmlStreamReader::EndElement == xmlReader.readNext()
220                                     && 0 == xmlReader.name().compare(TAG_CAMPAIGN))){
221                                 if(QXmlStreamReader::StartElement == xmlReader.tokenType()){
222                                     /*qDebug() << "name: " << xmlReader.name()
223                                         << "key: " << xmlReader.attributes().value(TAG_KEY).toString()
224                                         << "value: " << xmlReader.attributes().value(TAG_VALUE).toString();*/
225                                     if(0 == xmlReader.name().compare(TAG_ADTYPE)){
226                                         parameterTags.insert(
227                                                 QString(TAG_ADTYPE),xmlReader.attributes().value(TAG_KEY).toString());
228                                         this->defAdType = this->getAdTypeFromString(xmlReader.attributes().value(TAG_VALUE).toString());
229
230                                     }else if(0 == xmlReader.name().compare(TAG_LANGUAGE)){
231                                         parameterTags.insert(
232                                                 QString(TAG_LANGUAGE),xmlReader.attributes().value(TAG_KEY).toString());
233                                         this->language = xmlReader.attributes().value(TAG_VALUE).toString();
234
235                                     }else if(0 == xmlReader.name().compare(TAG_TRANSACTIONID)){
236                                         parameterTags.insert(
237                                                 QString(TAG_TRANSACTIONID),xmlReader.attributes().value(TAG_KEY).toString());
238                                         this->transactionId = xmlReader.attributes().value(TAG_VALUE).toString();
239
240                                     }else{
241                                         qDebug() << "Unknown element: " << xmlReader.tokenString();
242                                         if(xmlReader.atEnd()){
243                                             // TODO: throw exception?
244                                             qDebug() << "Unexpected end of document!";
245                                             return false;
246                                         }
247
248                                     }
249                                 }
250                             }
251                         }
252                     }else{
253                         qDebug() << "Unknown element: " << xmlReader.tokenString();
254                         if(xmlReader.atEnd()){
255                             // TODO: throw exception?
256                             qDebug() << "Unexpected end of document!";
257                             return false;
258                         }
259                     }
260                 }
261             }
262         }
263     }
264
265     /*while (!xmlReader.atEnd()) {
266     qDebug() << "Type: "<< xmlReader.readNext();
267     qDebug() << " Tokenstring: " << xmlReader.tokenString();
268     qDebug() << " name: " << xmlReader.name(); //<< " key: " << xmlReader.attributes().value("key") << " value: " << xmlReader.attributes().value("value");
269     qDebug() << " ";
270     }*/
271
272     return success;
273 }
274
275 AdType QtmadsService::getAdTypeFromString(QString adStr)
276 {
277     AdType adType = anyAd;
278
279     if(0 == adStr.compare("txtAd")){
280         adType = txtAd;
281     }else if(0 == adStr.compare("imageAd")){
282         adType = imageAd;
283     }else if(0 == adStr.compare("txtBannerAd")){
284         adType = txtBannerAd;
285     }else if(0 == adStr.compare("imageBannerAd")){
286         adType = imageBannerAd;
287     }else if(0 == adStr.compare("audioAd")){
288         adType = audioAd;
289     }else if(0 == adStr.compare("videoAd")){
290         adType = videoAd;
291     }
292     return adType;
293 }
294
295 QString QtmadsService::getStringFromAdType(AdType adType)
296 {
297     QString adStr;
298     switch(adType){
299         default:
300         case anyAd:
301             adStr.append("anyAd");
302             break;
303         case txtAd:
304             adStr.append("txtAd");
305             break;
306         case imageAd:
307             adStr.append("imageAd");
308             break;
309         case txtBannerAd:
310             adStr.append("txtBannerAd");
311             break;
312         case imageBannerAd:
313             adStr.append("imageBannerAd");
314             break;
315         case audioAd:
316             adStr.append("audioAd");
317             break;
318         case videoAd:
319             adStr.append("videoAd");
320             break;
321     }
322     return adStr;
323 }