26 #include <QTextStream>
27 #include <QHostAddress>
30 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
31 #define QT_FLUSH flush
33 #define QT_FLUSH Qt::flush
56 QDomDocument
doc (
"upnp" );
57 QFile
file( sFileName );
59 if ( !
file.open( QIODevice::ReadOnly ) )
65 bool bSuccess =
doc.setContent( &
file,
false,
66 &sErrMsg, &nErrLine, &nErrCol );
72 LOG(VB_GENERAL, LOG_ERR,
73 QString(
"UPnpDeviceDesc::Load - Error parsing: %1 "
74 "at line: %2 column: %3")
75 .
arg(sFileName) .
arg(nErrLine)
77 LOG(VB_GENERAL, LOG_ERR,
78 QString(
"UPnpDeviceDesc::Load - Error Msg: %1" ) .
arg(sErrMsg));
99 QDomNode oNode = xmlDevDesc.documentElement();
112 QString pin =
GetMythDB()->GetSetting(
"SecurityPin",
"");
113 pCurDevice->
m_securityPin = !(pin.isEmpty() || pin ==
"0000");
115 for ( oNode = oNode.firstChild();
117 oNode = oNode.nextSibling() )
119 QDomElement
e = oNode.toElement();
125 if (
e.tagName() ==
"deviceType" )
127 else if (
e.tagName() ==
"friendlyName" )
129 else if (
e.tagName() ==
"manufacturer" )
131 else if (
e.tagName() ==
"manufacturerURL" )
133 else if (
e.tagName() ==
"modelDescription" )
135 else if (
e.tagName() ==
"modelName" )
137 else if (
e.tagName() ==
"modelNumber" )
139 else if (
e.tagName() ==
"modelURL" )
141 else if (
e.tagName() ==
"serialNumber" )
143 else if (
e.tagName() ==
"UPC" )
145 else if (
e.tagName() ==
"presentationURL" )
147 else if (
e.tagName() ==
"UDN" )
149 else if (
e.tagName() ==
"iconList" )
151 else if (
e.tagName() ==
"serviceList" )
153 else if (
e.tagName() ==
"deviceList" )
155 else if (
e.tagName() ==
"mythtv:X_secure" )
157 else if (
e.tagName() ==
"mythtv:X_protocol" )
165 QDomNamedNodeMap attributes =
e.attributes();
166 for (
int i = 0; i < attributes.size(); i++)
169 attributes.item(i).nodeValue(),
183 for ( QDomNode oNode = oListNode.firstChild();
185 oNode = oNode.nextSibling() )
187 QDomElement
e = oNode.toElement();
192 if (
e.tagName() ==
"icon" )
197 SetStrValue(
e.namedItem(
"mimetype" ), pIcon->m_sMimeType );
199 SetNumValue(
e.namedItem(
"height" ), pIcon->m_nHeight );
212 for ( QDomNode oNode = oListNode.firstChild();
214 oNode = oNode.nextSibling() )
216 QDomElement
e = oNode.toElement();
221 if (
e.tagName() ==
"service" )
226 SetStrValue(
e.namedItem(
"serviceType" ), pService->m_sServiceType);
227 SetStrValue(
e.namedItem(
"serviceId" ), pService->m_sServiceId);
228 SetStrValue(
e.namedItem(
"SCPDURL" ), pService->m_sSCPDURL);
229 SetStrValue(
e.namedItem(
"controlURL" ), pService->m_sControlURL);
230 SetStrValue(
e.namedItem(
"eventSubURL" ), pService->m_sEventSubURL);
232 LOG(VB_UPNP, LOG_INFO,
233 QString(
"ProcessServiceList adding service : %1 : %2 :")
234 .
arg(pService->m_sServiceType)
235 .arg(pService->m_sServiceId));
247 for ( QDomNode oNode = oListNode.firstChild();
249 oNode = oNode.nextSibling() )
251 QDomElement
e = oNode.toElement();
256 if (
e.tagName() ==
"device")
271 QDomText oText = n.firstChild().toText();
274 sValue = oText.nodeValue();
284 QDomText oText = n.firstChild().toText();
287 nValue = oText.nodeValue().toInt();
295 QDomText oText = n.firstChild().toText();
299 QString s = oText.nodeValue();
300 nValue = (s ==
"yes" || s ==
"true" || (s.toInt() != 0));
312 QTextStream os( &sXML, QIODevice::WriteOnly );
324 const QString &,
int ,
325 QTextStream &os,
const QString &sUserAgent )
328 os.setEncoding( QTextStream::UnicodeUTF8 );
330 os <<
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
331 "<root xmlns=\"urn:schemas-upnp-org:device-1-0\" "
332 " xmlns:mythtv=\"mythtv.org\">\n"
350 const QString &sUserAgent )
352 if (pDevice ==
nullptr)
355 QString sFriendlyName = QString(
"%1: %2" )
369 os <<
FormatValue(
"friendlyName" , sFriendlyName );
379 sUserAgent.startsWith(QString(
"Xbox/2.0"), Qt::CaseInsensitive) ||
380 sUserAgent.startsWith(QString(
"Mozilla/4.0"), Qt::CaseInsensitive);
408 for (
const auto & nit : qAsConst(pDevice->
m_lstExtra))
419 os <<
"<iconList>\n";
424 os <<
FormatValue(
"mimetype", icon->m_sMimeType );
431 os <<
"</iconList>\n";
456 bool bDSM = sUserAgent.startsWith(
"INTEL_NMPR/2.1 DLNADOC/1.00",
false);
459 os <<
"<serviceList>\n";
463 if (!bIsXbox360 && service->m_sServiceType.startsWith(
464 "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar",
465 Qt::CaseInsensitive))
471 os <<
FormatValue(
"serviceType", service->m_sServiceType );
472 os <<
FormatValue(
"serviceId" , service->m_sServiceId );
473 os <<
FormatValue(
"SCPDURL" , service->m_sSCPDURL );
474 os <<
FormatValue(
"controlURL" , service->m_sControlURL );
475 os <<
FormatValue(
"eventSubURL", service->m_sEventSubURL );
476 os <<
"</service>\n";
478 os <<
"</serviceList>\n";
487 os <<
"<deviceList>";
489 UPnpDeviceList::iterator it;
497 os <<
"</deviceList>";
512 NameValues::iterator it;
515 sAttributes += QString(
" %1='%2'").arg((*it).m_sName).arg((*it).m_sValue);
517 sStr = QString(
"<%1%2>%3</%1>\n").arg(node.
m_sName).arg(sAttributes).arg(node.
m_sValue);
527 const QString &sValue )
531 if (sValue.length() > 0)
532 sStr = QString(
"<%1>%2</%1>\n") .arg(sName) .arg(sValue);
541 return( QString(
"<%1>%2</%1>\n") .
arg(sName) .
arg(nValue) );
551 if (sST.section(
':', 0, -2) == pDevice->
m_sDeviceType.section(
':', 0, -2))
554 if (sST.section(
':', 0, -2) == pDevice->
GetUDN().section(
':', 0, -2))
565 if (sST.section(
':', 0, -2) == (*sit)->m_sServiceType.section(
':', 0, -2))
576 if (sUDN.length() > 0)
597 const QString &sURI )
600 if ( sURI.section(
':', 0, -2) == pDevice->
m_sDeviceType.section(
':', 0, -2) )
611 if (pFound !=
nullptr)
626 LOG(VB_UPNP, LOG_DEBUG, QString(
"UPnpDeviceDesc::Retrieve( %1 )")
633 QString sXml(buffer);
635 if (ok && sXml.startsWith( QString(
"<?xml") ))
639 QDomDocument xml(
"upnp" );
641 if ( xml.setContent( sXml,
false, &sErrorMsg ))
644 pDevice->
Load( xml );
650 LOG(VB_UPNP, LOG_ERR,
651 QString(
"Error parsing device description xml [%1]")
657 LOG(VB_UPNP, LOG_ERR, QString(
"Invalid response '%1'").
arg(sXml));
673 QString localHostName = QHostInfo::localHostName();
674 if (localHostName.isEmpty())
675 LOG(VB_GENERAL, LOG_ERR,
676 "UPnpDeviceDesc: Error, could not determine host name." +
ENO);
712 pngIconLrg->m_nDepth = 24;
713 pngIconLrg->m_nHeight = 120;
714 pngIconLrg->m_nWidth = 120;
715 pngIconLrg->m_sMimeType =
"image/png";
716 pngIconLrg->m_sURL =
"/images/icons/upnp_large_icon.png";
721 jpgIconLrg->m_nDepth = 24;
722 jpgIconLrg->m_nHeight = 120;
723 jpgIconLrg->m_nWidth = 120;
724 jpgIconLrg->m_sMimeType =
"image/jpeg";
725 jpgIconLrg->m_sURL =
"/images/icons/upnp_large_icon.jpg";
730 pngIconSm->m_nDepth = 24;
731 pngIconSm->m_nHeight = 48;
732 pngIconSm->m_nWidth = 48;
733 pngIconSm->m_sMimeType =
"image/png";
734 pngIconSm->m_sURL =
"/images/icons/upnp_small_icon.png";
739 jpgIconSm->m_nDepth = 24;
740 jpgIconSm->m_nHeight = 48;
741 jpgIconSm->m_nWidth = 48;
742 jpgIconSm->m_sMimeType =
"image/jpeg";
743 jpgIconSm->m_sURL =
"/images/icons/upnp_small_icon.jpg";
799 if (service->m_sServiceType.section(
':', 0, -2) == urn.section(
':', 0, -2))
811 srv = (*dit)->GetService(urn, &done);
823 QString(
"UPnP Device\n"
828 "manufacturerURL: %4\n"
829 "modelDescription: %5\n"
841 QString(
"serialNumber: %1\n"
843 "presentationURL: %3\n"
852 ret +=
"Extra key value pairs\n";
853 for (
const auto & extra : qAsConst(
m_lstExtra))
855 ret += extra.m_sName;
857 int int_padding = 18 - (extra.m_sName.length() + 1);
858 for (
int i = 0; i < int_padding; i++)
860 ret += QString(
"%1\n").arg(extra.m_sValue);
866 ret +=
"Icon List:\n";
868 ret += icon->toString(padding+2) +
"\n";
873 ret +=
"Service List:\n";
875 ret += service->toString(padding+2) +
"\n";
880 ret +=
"Device List:\n";
882 ret += device->toString(padding+2) +
"\n";
887 if (ret.endsWith(
"\n"))
888 ret = ret.left(ret.length()-1);
894 for (
uint i = 0; i < padding; i++)
896 ret = pad + ret.replace(
"\n", QString(
"\n%1").
arg(pad));