16 #include <QTextStream>
17 #include <QHostAddress>
26 #include "libmythbase/mythversion.h"
51 QDomDocument doc (
"upnp" );
52 QFile
file( sFileName );
54 if ( !
file.open( QIODevice::ReadOnly ) )
60 bool bSuccess = doc.setContent( &
file,
false,
61 &sErrMsg, &nErrLine, &nErrCol );
67 LOG(VB_GENERAL, LOG_ERR,
68 QString(
"UPnpDeviceDesc::Load - Error parsing: %1 "
69 "at line: %2 column: %3")
70 .arg(sFileName) .arg(nErrLine)
72 LOG(VB_GENERAL, LOG_ERR,
73 QString(
"UPnpDeviceDesc::Load - Error Msg: %1" ) .arg(sErrMsg));
94 QDomNode oNode = xmlDevDesc.documentElement();
107 QString pin =
GetMythDB()->GetSetting(
"SecurityPin",
"");
108 pCurDevice->
m_securityPin = !(pin.isEmpty() || pin ==
"0000");
110 for ( oNode = oNode.firstChild();
112 oNode = oNode.nextSibling() )
114 QDomElement e = oNode.toElement();
120 if ( e.tagName() ==
"deviceType" )
122 else if ( e.tagName() ==
"friendlyName" )
124 else if ( e.tagName() ==
"manufacturer" )
126 else if ( e.tagName() ==
"manufacturerURL" )
128 else if ( e.tagName() ==
"modelDescription" )
130 else if ( e.tagName() ==
"modelName" )
132 else if ( e.tagName() ==
"modelNumber" )
134 else if ( e.tagName() ==
"modelURL" )
136 else if ( e.tagName() ==
"serialNumber" )
138 else if ( e.tagName() ==
"UPC" )
140 else if ( e.tagName() ==
"presentationURL" )
142 else if ( e.tagName() ==
"UDN" )
144 else if ( e.tagName() ==
"iconList" )
146 else if ( e.tagName() ==
"serviceList" )
148 else if ( e.tagName() ==
"deviceList" )
150 else if ( e.tagName() ==
"mythtv:X_secure" )
152 else if ( e.tagName() ==
"mythtv:X_protocol" )
160 QDomNamedNodeMap attributes = e.attributes();
161 for (
int i = 0; i < attributes.size(); i++)
164 attributes.item(i).nodeValue(),
178 for ( QDomNode oNode = oListNode.firstChild();
180 oNode = oNode.nextSibling() )
182 QDomElement e = oNode.toElement();
187 if ( e.tagName() ==
"icon" )
192 SetStrValue( e.namedItem(
"mimetype" ), pIcon->m_sMimeType );
193 SetNumValue( e.namedItem(
"width" ), pIcon->m_nWidth );
194 SetNumValue( e.namedItem(
"height" ), pIcon->m_nHeight );
195 SetNumValue( e.namedItem(
"depth" ), pIcon->m_nDepth );
196 SetStrValue( e.namedItem(
"url" ), pIcon->m_sURL );
207 for ( QDomNode oNode = oListNode.firstChild();
209 oNode = oNode.nextSibling() )
211 QDomElement e = oNode.toElement();
216 if ( e.tagName() ==
"service" )
221 SetStrValue(e.namedItem(
"serviceType" ), pService->m_sServiceType);
222 SetStrValue(e.namedItem(
"serviceId" ), pService->m_sServiceId);
223 SetStrValue(e.namedItem(
"SCPDURL" ), pService->m_sSCPDURL);
224 SetStrValue(e.namedItem(
"controlURL" ), pService->m_sControlURL);
225 SetStrValue(e.namedItem(
"eventSubURL" ), pService->m_sEventSubURL);
227 LOG(VB_UPNP, LOG_INFO,
228 QString(
"ProcessServiceList adding service : %1 : %2 :")
229 .arg(pService->m_sServiceType,
230 pService->m_sServiceId));
242 for ( QDomNode oNode = oListNode.firstChild();
244 oNode = oNode.nextSibling() )
246 QDomElement e = oNode.toElement();
251 if ( e.tagName() ==
"device")
266 QDomText oText = n.firstChild().toText();
269 sValue = oText.nodeValue();
279 QDomText oText = n.firstChild().toText();
282 nValue = oText.nodeValue().toInt();
290 QDomText oText = n.firstChild().toText();
294 QString s = oText.nodeValue();
295 nValue = (s ==
"yes" || s ==
"true" || (s.toInt() != 0));
307 QTextStream os( &sXML, QIODevice::WriteOnly );
319 const QString &,
int ,
320 QTextStream &os,
const QString &sUserAgent )
323 os.setEncoding( QTextStream::UnicodeUTF8 );
325 os <<
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
326 "<root xmlns=\"urn:schemas-upnp-org:device-1-0\" "
327 " xmlns:mythtv=\"mythtv.org\">\n"
345 const QString &sUserAgent )
347 if (pDevice ==
nullptr)
350 QString sFriendlyName = QString(
"%1: %2" )
363 os <<
FormatValue(
"friendlyName" , sFriendlyName );
373 sUserAgent.startsWith(QString(
"Xbox/2.0"), Qt::CaseInsensitive) ||
374 sUserAgent.startsWith(QString(
"Mozilla/4.0"), Qt::CaseInsensitive);
402 for (
const auto & nit : std::as_const(pDevice->
m_lstExtra))
413 os <<
"<iconList>\n";
415 for (
auto *icon : std::as_const(pDevice->
m_listIcons))
418 os <<
FormatValue(
"mimetype", icon->m_sMimeType );
425 os <<
"</iconList>\n";
450 bool bDSM = sUserAgent.startsWith(
"INTEL_NMPR/2.1 DLNADOC/1.00",
false);
453 os <<
"<serviceList>\n";
457 if (!bIsXbox360 && service->m_sServiceType.startsWith(
458 "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar",
459 Qt::CaseInsensitive))
465 os <<
FormatValue(
"serviceType", service->m_sServiceType );
466 os <<
FormatValue(
"serviceId" , service->m_sServiceId );
467 os <<
FormatValue(
"SCPDURL" , service->m_sSCPDURL );
468 os <<
FormatValue(
"controlURL" , service->m_sControlURL );
469 os <<
FormatValue(
"eventSubURL", service->m_sEventSubURL );
470 os <<
"</service>\n";
472 os <<
"</serviceList>\n";
481 os <<
"<deviceList>";
483 UPnpDeviceList::iterator it;
491 os <<
"</deviceList>";
506 NameValues::iterator it;
509 sAttributes += QString(
" %1='%2'").arg((*it).m_sName, (*it).m_sValue);
511 sStr = QString(
"<%1%2>%3</%1>\n").arg(node.
m_sName, sAttributes, node.
m_sValue);
521 const QString &sValue )
525 if (sValue.length() > 0)
526 sStr = QString(
"<%1>%2</%1>\n") .arg(sName, sValue);
535 return( QString(
"<%1>%2</%1>\n") .arg(sName) .arg(nValue) );
545 if (sST.section(
':', 0, -2) == pDevice->
m_sDeviceType.section(
':', 0, -2))
548 if (sST.section(
':', 0, -2) == pDevice->
GetUDN().section(
':', 0, -2))
559 if (sST.section(
':', 0, -2) == (*sit)->m_sServiceType.section(
':', 0, -2))
570 if (sUDN.length() > 0)
591 const QString &sURI )
594 if ( sURI.section(
':', 0, -2) == pDevice->
m_sDeviceType.section(
':', 0, -2) )
601 for (
const auto & dev : std::as_const(pDevice->
m_listDevices))
605 if (pFound !=
nullptr)
620 LOG(VB_UPNP, LOG_DEBUG, QString(
"UPnpDeviceDesc::Retrieve( %1 )")
627 QString sXml(buffer);
629 if (ok && sXml.startsWith( QString(
"<?xml") ))
633 QDomDocument xml(
"upnp" );
635 if ( xml.setContent( sXml,
false, &sErrorMsg ))
638 pDevice->
Load( xml );
644 LOG(VB_UPNP, LOG_ERR,
645 QString(
"Error parsing device description xml [%1]")
651 LOG(VB_UPNP, LOG_ERR, QString(
"Invalid response '%1'").arg(sXml));
667 QString localHostName = QHostInfo::localHostName();
668 if (localHostName.isEmpty())
669 LOG(VB_GENERAL, LOG_ERR,
670 "UPnpDeviceDesc: Error, could not determine host name." +
ENO);
687 m_sModelNumber(MYTH_BINARY_VERSION),
689 m_protocolVersion(MYTH_PROTO_VERSION)
705 pngIconLrg->m_nDepth = 24;
706 pngIconLrg->m_nHeight = 120;
707 pngIconLrg->m_nWidth = 120;
708 pngIconLrg->m_sMimeType =
"image/png";
709 pngIconLrg->m_sURL =
"/images/icons/upnp_large_icon.png";
714 jpgIconLrg->m_nDepth = 24;
715 jpgIconLrg->m_nHeight = 120;
716 jpgIconLrg->m_nWidth = 120;
717 jpgIconLrg->m_sMimeType =
"image/jpeg";
718 jpgIconLrg->m_sURL =
"/images/icons/upnp_large_icon.jpg";
723 pngIconSm->m_nDepth = 24;
724 pngIconSm->m_nHeight = 48;
725 pngIconSm->m_nWidth = 48;
726 pngIconSm->m_sMimeType =
"image/png";
727 pngIconSm->m_sURL =
"/images/icons/upnp_small_icon.png";
732 jpgIconSm->m_nDepth = 24;
733 jpgIconSm->m_nHeight = 48;
734 jpgIconSm->m_nWidth = 48;
735 jpgIconSm->m_sMimeType =
"image/jpeg";
736 jpgIconSm->m_sURL =
"/images/icons/upnp_small_icon.jpg";
792 if (service->m_sServiceType.section(
':', 0, -2) == urn.section(
':', 0, -2))
804 srv = (*dit)->GetService(urn, &done);
816 QString(
"UPnP Device\n"
821 "manufacturerURL: %4\n"
822 "modelDescription: %5\n"
834 QString(
"serialNumber: %1\n"
836 "presentationURL: %3\n"
845 ret +=
"Extra key value pairs\n";
846 for (
const auto & extra : std::as_const(
m_lstExtra))
848 ret += extra.m_sName;
850 int int_padding = 18 - (extra.m_sName.length() + 1);
851 for (
int i = 0; i < int_padding; i++)
853 ret += QString(
"%1\n").arg(extra.m_sValue);
859 ret +=
"Icon List:\n";
861 ret += icon->toString(padding+2) +
"\n";
866 ret +=
"Service List:\n";
868 ret += service->toString(padding+2) +
"\n";
873 ret +=
"Device List:\n";
875 ret += device->toString(padding+2) +
"\n";
880 if (ret.endsWith(
"\n"))
881 ret = ret.left(ret.length()-1);
887 for (
uint i = 0; i < padding; i++)
889 ret = pad + ret.replace(
"\n", QString(
"\n%1").arg(pad));