Example #1
0
bool LsColXMLParser::parse( const QByteArray& xml, QHash<QString, qint64> *sizes, const QString& expectedPath)
{
    // Parse DAV response
    QXmlStreamReader reader(xml);
    reader.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration("d", "DAV:"));

    QStringList folders;
    QString currentHref;
    QMap<QString, QString> currentTmpProperties;
    QMap<QString, QString> currentHttp200Properties;
    bool currentPropsHaveHttp200 = false;
    bool insidePropstat = false;
    bool insideProp = false;
    bool insideMultiStatus = false;

    while (!reader.atEnd()) {
        QXmlStreamReader::TokenType type = reader.readNext();
        QString name = reader.name().toString();
        // Start elements with DAV:
        if (type == QXmlStreamReader::StartElement && reader.namespaceUri() == QLatin1String("DAV:")) {
            if (name == QLatin1String("href")) {
                // We don't use URL encoding in our request URL (which is the expected path) (QNAM will do it for us)
                // but the result will have URL encoding..
                QString hrefString = QString::fromUtf8(QByteArray::fromPercentEncoding(reader.readElementText().toUtf8()));
                if (!hrefString.startsWith(expectedPath)) {
                    qDebug() << "Invalid href" << hrefString << "expected starting with" << expectedPath;
                    return false;
                }
                currentHref = hrefString;
            } else if (name == QLatin1String("response")) {
            } else if (name == QLatin1String("propstat")) {
                insidePropstat = true;
            } else if (name == QLatin1String("status") && insidePropstat) {
                QString httpStatus = reader.readElementText();
                if (httpStatus.startsWith("HTTP/1.1 200")) {
                    currentPropsHaveHttp200 = true;
                } else {
                    currentPropsHaveHttp200 = false;
                }
            } else if (name == QLatin1String("prop")) {
                insideProp = true;
                continue;
            } else if (name == QLatin1String("multistatus")) {
                insideMultiStatus = true;
                continue;
            }
        }

        if (type == QXmlStreamReader::StartElement && insidePropstat && insideProp) {
            // All those elements are properties
            QString propertyContent = readContentsAsString(reader);
            if (name == QLatin1String("resourcetype") && propertyContent.contains("collection")) {
                folders.append(currentHref);
            } else if (name == QLatin1String("quota-used-bytes")) {
                bool ok = false;
                auto s = propertyContent.toLongLong(&ok);
                if (ok && sizes) {
                    sizes->insert(currentHref, s);
                }
            }
            currentTmpProperties.insert(reader.name().toString(), propertyContent);
        }

        // End elements with DAV:
        if (type == QXmlStreamReader::EndElement) {
            if (reader.namespaceUri() == QLatin1String("DAV:")) {
                if (reader.name() == "response") {
                    if (currentHref.endsWith('/')) {
                        currentHref.chop(1);
                    }
                    emit directoryListingIterated(currentHref, currentHttp200Properties);
                    currentHref.clear();
                    currentHttp200Properties.clear();
                } else if (reader.name() == "propstat") {
                    insidePropstat = false;
                    if (currentPropsHaveHttp200) {
                        currentHttp200Properties = QMap<QString,QString>(currentTmpProperties);
                    }
                    currentTmpProperties.clear();
                    currentPropsHaveHttp200 = false;
                } else if (reader.name() == "prop") {
                    insideProp = false;
                }
            }
        }
    }

    if (reader.hasError()) {
        // XML Parser error? Whatever had been emitted before will come as directoryListingIterated
        qDebug() << "ERROR" << reader.errorString() << xml;
        return false;
    } else if (!insideMultiStatus) {
        qDebug() << "ERROR no WebDAV response?" << xml;
        return false;
    } else {
        emit directoryListingSubfolders(folders);
        emit finishedWithoutError();
    }
    return true;

}
Example #2
0
bool LsColJob::finished()
{
    QString contentType = reply()->header(QNetworkRequest::ContentTypeHeader).toString();
    int httpCode = reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    if (httpCode == 207 && contentType.contains("application/xml; charset=utf-8")) {
        // Parse DAV response
        QByteArray xml = reply()->readAll();
        QXmlStreamReader reader(xml);
        reader.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration("d", "DAV:"));

        QStringList folders;
        QString currentHref;
        QMap<QString, QString> currentTmpProperties;
        QMap<QString, QString> currentHttp200Properties;
        bool currentPropsHaveHttp200 = false;
        bool insidePropstat = false;
        bool insideProp = false;

        while (!reader.atEnd()) {
            QXmlStreamReader::TokenType type = reader.readNext();
            QString name = reader.name().toString();
            // Start elements with DAV:
            if (type == QXmlStreamReader::StartElement && reader.namespaceUri() == QLatin1String("DAV:")) {
                if (name == QLatin1String("href")) {
                    currentHref = QUrl::fromPercentEncoding(reader.readElementText().toUtf8());
                } else if (name == QLatin1String("response")) {
                } else if (name == QLatin1String("propstat")) {
                    insidePropstat = true;
                } else if (name == QLatin1String("status") && insidePropstat) {
                    QString httpStatus = reader.readElementText();
                    if (httpStatus.startsWith("HTTP/1.1 200")) {
                        currentPropsHaveHttp200 = true;
                    } else {
                        currentPropsHaveHttp200 = false;
                    }
                } else if (name == QLatin1String("prop")) {
                    insideProp = true;
                    continue;
                }
            }

            if (type == QXmlStreamReader::StartElement && insidePropstat && insideProp) {
                // All those elements are properties
                QString propertyContent = readContentsAsString(reader);
                if (name == QLatin1String("resourcetype") && propertyContent.contains("collection")) {
                    folders.append(currentHref);
                } else if (name == QLatin1String("quota-used-bytes")) {
                    bool ok = false;
                    auto s = propertyContent.toLongLong(&ok);
                    if (ok) {
                        _sizes[currentHref] = s;
                    }
                }
                currentTmpProperties.insert(reader.name().toString(), propertyContent);
            }

            // End elements with DAV:
            if (type == QXmlStreamReader::EndElement) {
                if (reader.namespaceUri() == QLatin1String("DAV:")) {
                    if (reader.name() == "response") {
                        if (currentHref.endsWith('/')) {
                            currentHref.chop(1);
                        }
                        emit directoryListingIterated(currentHref, currentHttp200Properties);
                        currentHref.clear();                        
                        currentHttp200Properties.clear();
                    } else if (reader.name() == "propstat") {
                        insidePropstat = false;
                        if (currentPropsHaveHttp200) {
                            currentHttp200Properties = QMap<QString,QString>(currentTmpProperties);
                        }
                        currentTmpProperties.clear();
                        currentPropsHaveHttp200 = false;
                    } else if (reader.name() == "prop") {
                        insideProp = false;
                    }
                }
            }
        }
        emit directoryListingSubfolders(folders);
        emit finishedWithoutError();
    } else if (httpCode == 207) {
        // wrong content type
        emit finishedWithError(reply());
    } else {
        // wrong HTTP code
        emit finishedWithError(reply());
    }
    return true;
}