ip2cupdater.cpp
1 //------------------------------------------------------------------------------
2 // ip2cupdater.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301, USA.
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2009 "Blzut3" <admin@maniacsvault.net>
22 //------------------------------------------------------------------------------
23 #include "ip2cupdater.h"
24 
25 #include <QDateTime>
26 #include <QDebug>
27 #include <QDir>
28 #include <QFileInfo>
29 #include <QTemporaryFile>
30 #include <zlib.h>
31 
32 #include "log.h"
33 #include "version.h"
34 
35 IP2CUpdater::IP2CUpdater()
36 {
37  pCurrentNetworkReply = NULL;
38  pNetworkAccessManager = new FixedNetworkAccessManager();
39 }
40 
41 IP2CUpdater::~IP2CUpdater()
42 {
43  if (pCurrentNetworkReply != NULL)
44  {
45  pCurrentNetworkReply->disconnect();
46  pCurrentNetworkReply->abort();
47  pCurrentNetworkReply->deleteLater();
48  }
49 
50  if (pNetworkAccessManager != NULL)
51  {
52  pNetworkAccessManager->deleteLater();
53  }
54 }
55 
56 void IP2CUpdater::downloadDatabase(const QUrl& netLocation)
57 {
58  retrievedData.clear();
59 
60  QNetworkRequest request;
61  request.setUrl(netLocation);
62  qDebug() << netLocation;
63  request.setRawHeader("User-Agent", Version::userAgent().toAscii());
64 
65  pCurrentNetworkReply = pNetworkAccessManager->get(request);
66  this->connect(pCurrentNetworkReply, SIGNAL( downloadProgress(qint64, qint64) ),
67  SIGNAL( downloadProgress(qint64, qint64) ) );
68  this->connect(pCurrentNetworkReply, SIGNAL( finished() ),
69  SLOT( downloadFinished() ) );
70 }
71 
72 void IP2CUpdater::downloadFinished()
73 {
74  QByteArray data = pCurrentNetworkReply->readAll();
75 
76  QUrl possibleRedirectUrl = pCurrentNetworkReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
77  QUrl url = pCurrentNetworkReply->request().url();
78  if (!possibleRedirectUrl.isEmpty()
79  && possibleRedirectUrl != url)
80  {
81  // Redirect.
82  if (possibleRedirectUrl.isRelative())
83  {
84  possibleRedirectUrl = url.resolved(possibleRedirectUrl);
85  }
86 
87  pCurrentNetworkReply->deleteLater();
88  downloadDatabase(possibleRedirectUrl);
89  }
90  else
91  {
92  pCurrentNetworkReply->deleteLater();
93  pCurrentNetworkReply = NULL;
94 
95  // First we need to write it to a temporary file
96  QTemporaryFile tmpFile;
97  if(tmpFile.open())
98  {
99  tmpFile.write(data);
100 
101  QString tmpFilePath = tmpFile.fileName();
102 
103  QByteArray uncompressedData;
104  gzFile gz = gzopen(tmpFilePath.toAscii().constData(), "rb");
105  if(gz != NULL)
106  {
107  char chunk[131072]; // 128k
108  int bytesRead = 0;
109  while((bytesRead = gzread(gz, chunk, 131072)) != 0)
110  {
111  uncompressedData.append(QByteArray(chunk, bytesRead));
112  }
113  gzclose(gz);
114 
115  retrievedData = uncompressedData;
116  }
117  }
118 
119  emit databaseDownloadFinished(retrievedData);
120  }
121 }
122 
124 {
125  rollbackData.clear();
126 
127  QFile file(pathToFile);
128  if (!file.exists())
129  {
130  return false;
131  }
132 
133  if (!file.open(QIODevice::ReadOnly))
134  {
135  return false;
136  }
137 
138  rollbackData = file.readAll();
139  file.close();
140 
141  return true;
142 }
143 
144 bool IP2CUpdater::needsUpdate(const QString& filePath, unsigned minimumUpdateAge)
145 {
146  if (filePath.isEmpty())
147  {
148  return false;
149  }
150 
151  if (minimumUpdateAge == 0)
152  {
153  minimumUpdateAge = 1;
154  }
155 
156  QFileInfo fileInfo(filePath);
157  if (fileInfo.exists())
158  {
159  QDateTime current = QDateTime::currentDateTime();
160  QDateTime lastModified = fileInfo.lastModified();
161 
162  int daysTo = lastModified.daysTo(current);
163 
164  // Handle file system errors.
165  if (daysTo < 0)
166  {
167  return true;
168  }
169 
170  return (unsigned)daysTo >= minimumUpdateAge;
171  }
172 
173  return true;
174 }
175 
177 {
178  bool bSuccess = save(rollbackData);
179  rollbackData.clear();
180 
181  return bSuccess;
182 }
183 
184 bool IP2CUpdater::save(const QByteArray& saveWhat)
185 {
186  if (saveWhat.isEmpty())
187  {
188  return false;
189  }
190 
191  QFile file(pathToFile);
192  if (!file.open(QIODevice::WriteOnly))
193  {
194  return false;
195  }
196 
197  file.write(saveWhat);
198  file.close();
199 
200  return true;
201 }
202 
204 {
205  return save(retrievedData);
206 }
static bool needsUpdate(const QString &filePath, unsigned minimumUpdateAge)
Checks if IP2C file must be updated.
bool getRollbackData()
Obtains rollback data from pathToFile file.
void databaseDownloadFinished(const QByteArray &downloadedData)
In case of failure the downloadedData array will be empty.
static QString userAgent()
WWW User Agent used for HTTP communications.
Definition: version.cpp:59
bool rollback()
Saves data to the pathToFile file. This data must be first obtained through the rollback method...
bool saveDownloadedData()
Saves recently downloaded data to the pathToFile file.