#include "httpinformation.h" #include #include #include #include #include HttpInformation::HttpInformation(QObject *parent) : QObject(parent) { setObjectName("HttpInformation"); _step = Non; _http = 0; _buffer = 0; _beginTime = 0; _localTime = 0; _serverTime = 0; _isUpdated = false; } HttpInformation::~HttpInformation() { qDebug() << "destroyed: " << objectName(); if(_buffer) { delete _buffer; } } void HttpInformation::begin() { _http = new QHttp("www.iruis.net", 80, this); connect(_http, SIGNAL(done(bool)), this, SLOT(httpDone(bool))); connect(_http, SIGNAL(requestFinished(int,bool)), this, SLOT(httpRequestFinished(int,bool))); connect(_http, SIGNAL(stateChanged(int)), this, SLOT(httpStateChanged(int))); _buffer = new QBuffer(this); _buffer->open(QIODevice::ReadWrite); _beginTime = time(NULL); _localTime = _beginTime; _serverTime = _beginTime; _step = One; _reqId = _http->get("/external/MabiTimer/information.php", _buffer); } bool HttpInformation::isUpdated() { return _isUpdated; } int HttpInformation::offsetSeconds() { return _serverTime - _localTime; } QString HttpInformation::timestamp() const { return _timestamp; } QString HttpInformation::version() const { return _version; } QString HttpInformation::html() const { return _html; } void HttpInformation::parseElement(const QString& name, const QString& value) { if(name == "timestamp") { _timestamp = value; } else if(name == "version") { Version newVersion; Version oldVersion; if(parseVersion(newVersion, value) && parseVersion(oldVersion, LONG_VERSION)) { _version = value; qlonglong lnew = QString("%1%2%3%4").arg(newVersion.major, 3, 10, QChar('0')) .arg(newVersion.minor, 3, 10, QChar('0')) .arg(newVersion.patch, 3, 10, QChar('0')) .arg(newVersion.build, 3, 10, QChar('0')).toLongLong(); qlonglong lold = QString("%1%2%3%4").arg(oldVersion.major, 3, 10, QChar('0')) .arg(oldVersion.minor, 3, 10, QChar('0')) .arg(oldVersion.patch, 3, 10, QChar('0')) .arg(oldVersion.build, 3, 10, QChar('0')).toLongLong(); qDebug() << "lnew: " << lnew << ", lold: " << lold; if((oldVersion.patch % 2) == 0) { _isUpdated = true; } else { _isUpdated = (oldVersion.patch % 2) == (newVersion.patch % 2); } _isUpdated = (_isUpdated) && (lnew > lold); } } else if(name == "page") { _page = value; } } bool HttpInformation::parseVersion(Version& ver, const QString& value) { QStringList list = value.split(QChar('.')); if(list.count() == 3 || list.count() == 4) { bool ok; ver.major = list[0].toInt(&ok); if(ok == false) { return false; } ver.minor = list[1].toInt(&ok); if(ok == false) { return false; } ver.patch = list[2].toInt(&ok); if(ok == false) { return false; } if(list.count() == 4) { ver.build = list[3].toInt(&ok); if(ok == false) { return false; } } else { ver.build = 0; } return true; } return false; } void HttpInformation::httpDone(bool error) { Q_UNUSED(error); delete _buffer; _buffer = 0; if(_step == One) { _buffer = new QBuffer(this); _buffer->open(QIODevice::ReadWrite); int now = time(NULL); bool valid = !_timestamp.isEmpty() && !_version.isEmpty() && !_page.isEmpty(); if(valid) { if(qAbs(now - _beginTime) < 5) { bool ok = false; int recvTime = timestamp().toInt(&ok); if(ok) { _serverTime = recvTime; } } _step = Two; _reqId = _http->get(_page, _buffer); } else { emit done(false); } } else if(_step == Two) { qDebug() << "Update check done"; emit done(!_html.isEmpty()); } } void HttpInformation::httpRequestFinished(int requestId, bool error) { if(_reqId == requestId && !error) { _buffer->seek(0); QByteArray bytes = _buffer->readAll(); if(_step == One) { int size; xmlNodeSetPtr nodes; xmlDocPtr doc = xmlReadMemory(bytes.data(), bytes.size(), NULL, NULL, XML_PARSE_COMPACT); xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc); xmlXPathObjectPtr xpathUpdate = xmlXPathEvalExpression(BAD_CAST "/html/body/dl[@id='update']/dd", xpathCtx); nodes = xpathUpdate->nodesetval; size = nodes ? nodes->nodeNr : 0; for(int i = 0; i < size; ++i) { if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE) { xmlNodePtr node = nodes->nodeTab[i]; QString attribute(QString::fromUtf8((char*)xmlGetProp(node, BAD_CAST "id"))); QString content(QString::fromUtf8((char*)xmlNodeGetContent(node))); parseElement(attribute, content); } } xmlXPathFreeObject(xpathUpdate); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); } else if(_step == Two) { _html = QString::fromUtf8(bytes.data(), bytes.count()); } } } void HttpInformation::httpStateChanged(int state) { Q_UNUSED(state); }