File indexing completed on 2024-04-28 04:44:22

0001 /*
0002    SPDX-FileCopyrightText: 2015 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr>
0003 
0004    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005  */
0006 
0007 #include "upnpservicedescriptionparser.h"
0008 
0009 #include "upnplogging.h"
0010 
0011 #include "upnpactiondescription.h"
0012 #include "upnpservicedescription.h"
0013 
0014 #include <QNetworkAccessManager>
0015 #include <QNetworkReply>
0016 #include <QNetworkRequest>
0017 
0018 #include <QDomDocument>
0019 
0020 #include <QLoggingCategory>
0021 
0022 class UpnpServiceDescriptionParserPrivate
0023 {
0024 public:
0025     UpnpServiceDescriptionParserPrivate(QNetworkAccessManager *aNetworkAccess, UpnpServiceDescription &serviceDescription)
0026         : mNetworkAccess(aNetworkAccess)
0027         , mServiceDescription(serviceDescription)
0028         , mServiceURL()
0029     {
0030     }
0031 
0032     QNetworkAccessManager *mNetworkAccess;
0033 
0034     UpnpServiceDescription &mServiceDescription;
0035 
0036     QUrl mServiceURL;
0037 };
0038 
0039 UpnpServiceDescriptionParser::UpnpServiceDescriptionParser(QNetworkAccessManager *aNetworkAccess, UpnpServiceDescription &deviceDescription, QObject *parent)
0040     : QObject(parent)
0041     , d(std::make_unique<UpnpServiceDescriptionParserPrivate>(aNetworkAccess, deviceDescription))
0042 {
0043 }
0044 
0045 UpnpServiceDescriptionParser::~UpnpServiceDescriptionParser() = default;
0046 
0047 void UpnpServiceDescriptionParser::downloadServiceDescription(const QUrl &serviceUrl)
0048 {
0049     d->mServiceURL = serviceUrl;
0050     d->mNetworkAccess->get(QNetworkRequest(serviceUrl));
0051 }
0052 
0053 void UpnpServiceDescriptionParser::finishedDownload(QNetworkReply *reply)
0054 {
0055     if (reply->url() == d->mServiceURL) {
0056         if (reply->isFinished() && reply->error() == QNetworkReply::NoError) {
0057             parseServiceDescription(reply);
0058         } else if (reply->isFinished()) {
0059             qCDebug(orgKdeUpnpLibQtUpnp()) << "UpnpAbstractServiceDescription::finishedDownload"
0060                                            << "error";
0061         }
0062     }
0063 }
0064 
0065 void UpnpServiceDescriptionParser::parseServiceDescription(QIODevice *serviceDescriptionContent)
0066 {
0067     QDomDocument serviceDescriptionDocument;
0068     serviceDescriptionDocument.setContent(serviceDescriptionContent);
0069 
0070     const QDomElement &scpdRoot = serviceDescriptionDocument.documentElement();
0071 
0072     const QDomElement &actionListRoot = scpdRoot.firstChildElement(QStringLiteral("actionList"));
0073     QDomNode currentChild = actionListRoot.firstChild();
0074     while (!currentChild.isNull()) {
0075         const QDomNode &nameNode = currentChild.firstChildElement(QStringLiteral("name"));
0076 
0077         QString actionName;
0078         if (!nameNode.isNull()) {
0079             actionName = nameNode.toElement().text();
0080         }
0081 
0082         UpnpActionDescription newAction;
0083 
0084         newAction.mName = actionName;
0085 
0086         const QDomNode &argumentListNode = currentChild.firstChildElement(QStringLiteral("argumentList"));
0087         QDomNode argumentNode = argumentListNode.firstChild();
0088         while (!argumentNode.isNull()) {
0089             const QDomNode &argumentNameNode = argumentNode.firstChildElement(QStringLiteral("name"));
0090             const QDomNode &argumentDirectionNode = argumentNode.firstChildElement(QStringLiteral("direction"));
0091             const QDomNode &argumentRetvalNode = argumentNode.firstChildElement(QStringLiteral("retval"));
0092             const QDomNode &argumentRelatedStateVariableNode = argumentNode.firstChildElement(QStringLiteral("relatedStateVariable"));
0093 
0094             UpnpActionArgumentDescription newArgument;
0095             newArgument.mName = argumentNameNode.toElement().text();
0096             newArgument.mDirection = (argumentDirectionNode.toElement().text() == QStringLiteral("in") ? UpnpArgumentDirection::In : UpnpArgumentDirection::Out);
0097             newArgument.mIsReturnValue = !argumentRetvalNode.isNull();
0098             newArgument.mRelatedStateVariable = argumentRelatedStateVariableNode.toElement().text();
0099 
0100             newAction.mArguments.push_back(newArgument);
0101 
0102             d->mServiceDescription.addAction(newAction);
0103 
0104             argumentNode = argumentNode.nextSibling();
0105         }
0106 
0107         currentChild = currentChild.nextSibling();
0108     }
0109 
0110 #if 0
0111     const QDomElement &serviceStateTableRoot = scpdRoot.firstChildElement(QStringLiteral("serviceStateTable"));
0112     currentChild = serviceStateTableRoot.firstChild();
0113     while (!currentChild.isNull()) {
0114         const QDomNode &nameNode = currentChild.firstChildElement(QStringLiteral("name"));
0115         if (!nameNode.isNull()) {
0116             qCDebug(orgKdeUpnpLibQtUpnp()) << "state variable name" << nameNode.toElement().text();
0117         }
0118 
0119         currentChild = currentChild.nextSibling();
0120     }
0121 #endif
0122 
0123     Q_EMIT descriptionParsed(d->mServiceDescription.serviceId());
0124 }
0125 
0126 #include "moc_upnpservicedescriptionparser.cpp"