Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

' urn:microsoft-com:wmc-1-0' leading space makes it an invalid URI #402

Open
LeBirlante opened this issue May 5, 2020 · 19 comments
Open

Comments

@LeBirlante
Copy link

Hello,

I think this is the same error as in #363 , but this time the affected hardware is the Marantz AV7702 receiver. Running pulseaudio-dlna --debug clearly shows the leading space in the URI :

05-05 19:29:36 pyupnpv2                                       DEBUG    Response from UPNP device (http://192.168.98.45:8080/description.xml)
<?xml version="1.0"?>
<root
  xmlns="urn:schemas-upnp-org:device-1-0"
  xmlns:ms=" urn:microsoft-com:wmc-1-0"
           ^^

  xmlns:smsc="www.smsc.com"
  xmlns:qq="http://www.tencent.com"
  xmlns:pnpx="http://schemas.microsoft.com/windows/pnpx/2005/11"
  xmlns:df="http://schemas.microsoft.com/windows/2008/09/devicefoundation">
        <specVersion>
                <major>1</major>
                <minor>0</minor>
        </specVersion>
        <device>
                <dlna:X_DLNADOC xmlns:dlna="urn:schemas-dlna-org:device-1-0">DMR-1.50</dlna:X_DLNADOC>
                <pnpx:X_compatibleId>MS_DigitalMediaDeviceClass_DMR_V001
                                </pnpx:X_compatibleId>
                <pnpx:X_deviceCategory>MediaDevices
                                </pnpx:X_deviceCategory>
                <pnpx:X_hardwareId>VEN_0126&amp;DEV_0048&amp;REV_01
                                </pnpx:X_hardwareId>
                <df:X_deviceCategory>Multimedia.DMR
                                </df:X_deviceCategory>
                <deviceType>urn:schemas-upnp-org:device:MediaRenderer:1</deviceType>
                <friendlyName>Marantz AV7702</friendlyName>
                <manufacturer>Marantz</manufacturer>
                <manufacturerURL>http://www.marantz.com</manufacturerURL>
                <modelDescription>AV PRE TUNER</modelDescription>
                <modelName>*AV7702</modelName>
                <modelNumber>7702</modelNumber>
                <modelURL>http://www.marantz.com</modelURL>
                <serialNumber>000678271138</serialNumber>
                <UDN>uuid:5f9ec1b3-ff59-19bb-8530-000678271138</UDN>
                <UPC>123810928305</UPC>

Which, in turn, will raise :

05-05 19:29:36 pyupnpv2                                       DEBUG    Got broken xml, trying to fix it.
Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/pyupnpv2/__init__.py", line 716, in from_xml
    xml_root = lxml.etree.fromstring(xml)
  File "src/lxml/etree.pyx", line 3235, in lxml.etree.fromstring
  File "src/lxml/parser.pxi", line 1876, in lxml.etree._parseMemoryDocument
  File "src/lxml/parser.pxi", line 1764, in lxml.etree._parseDoc
  File "src/lxml/parser.pxi", line 1127, in lxml.etree._BaseParser._parseDoc
  File "src/lxml/parser.pxi", line 601, in lxml.etree._ParserContext._handleParseResultDoc
  File "src/lxml/parser.pxi", line 711, in lxml.etree._handleParseResult
  File "src/lxml/parser.pxi", line 640, in lxml.etree._raiseParseError
  File "<string>", line 4
lxml.etree.XMLSyntaxError: xmlns:ms: ' urn:microsoft-com:wmc-1-0' is not a valid URI, line 4, column 40

I know that, where phyton2 simply threw a warning whenever a leading space was found in an URI, python3 now throws an error, hence the old py2-based pulseaudio-dlna would work perfectly with the Marantz, but now the same Maranzt is breaking the newer py3-based pulseaudio-dlna.

Is there any way of fixing this ? The AV7702 is a great DLNA-enabled AV receiver, and it is quite a pity not being able to use it with pulseaudio-dlna.

thanks,

@stuaxo
Copy link

stuaxo commented Sep 22, 2020

Does the solution in the ticket you linked work ? #363 (comment)

@Tenyun
Copy link

Tenyun commented Oct 31, 2020

Hello,
I have a similar problem with the Pioneer VXS-922 but with a different error.

10-31 09:12:50 urllib3.connectionpool                         DEBUG    Starting new HTTP connection (1): 10.0.0.60:8080
10-31 09:12:50 urllib3.connectionpool                         DEBUG    http://10.0.0.60:8080 "GET /description.xml HTTP/1.1" 200 3281
10-31 09:12:50 pyupnpv2                                       DEBUG    Response from UPNP device (http://10.0.0.60:8080/description.xml)
<?xml version="1.0"?>
<root
  xmlns="urn:schemas-upnp-org:device-1-0"
  xmlns:ms=" urn:microsoft-com:wmc-1-0"
  xmlns:pnpx="http://schemas.microsoft.com/windows/pnpx/2005/11"
  xmlns:df="http://schemas.microsoft.com/windows/2008/09/devicefoundation">
	<specVersion>
		<major>1</major>
		<minor>0</minor>
	</specVersion>
	<device
	  ms:X_MS_SupportsWMDRM="true">
		<av:X_ipRemoteReady xmlns:av="http://www.pioneerelectronics.com/xmlns/av">1</av:X_ipRemoteReady>
		<av:X_ipRemoteTcpPort xmlns:av="http://www.pioneerelectronics.com/xmlns/av">8102</av:X_ipRemoteTcpPort>
		<dlna:X_DLNADOC xmlns:dlna="urn:schemas-dlna-org:device-1-0">DMR-1.50</dlna:X_DLNADOC>
		<pnpx:X_compatibleId>MS_DigitalMediaDeviceClass_DMR_V001
				</pnpx:X_compatibleId>
		<pnpx:X_deviceCategory>MediaDevices
				</pnpx:X_deviceCategory>
		<pnpx:X_hardwareId>VEN_0112&amp;DEV_0002&amp;REV_01 VEN_0033&amp;DEV_000C&amp;REV_01
				</pnpx:X_hardwareId>
		<df:X_deviceCategory>Multimedia.DMR
				</df:X_deviceCategory>
		<deviceType>urn:schemas-upnp-org:device:MediaRenderer:1</deviceType>
		<friendlyName>VSX-922</friendlyName>
		<manufacturer>PIONEER CORPORATION</manufacturer>
		<manufacturerURL>http://www.pioneerelectronics.com</manufacturerURL>
		<modelDescription>Digital Media Client</modelDescription>
		<modelName>VSX-922/SYXE8</modelName>
		<modelNumber>Digital Media Client</modelNumber>
		<UDN>uuid:5F9EC1B3-ED59-79BB-4530-745E1C106437</UDN>
		<UPC>123810928305556upc</UPC>
		<iconList>
			<icon>
				<mimetype>image/jpeg</mimetype>
				<width>48</width>
				<height>48</height>
				<depth>24</depth>
				<url>/pioneer_icon_sm.jpg</url>
			</icon>
			<icon>
				<mimetype>image/jpeg</mimetype>
				<width>120</width>
				<height>120</height>
				<depth>24</depth>
				<url>/pioneer_icon_lrg.jpg</url>
			</icon>
			<icon>
				<mimetype>image/png</mimetype>
				<width>48</width>
				<height>48</height>
				<depth>24</depth>
				<url>/pioneer_icon_sm.png</url>
			</icon>
			<icon>
				<mimetype>image/png</mimetype>
				<width>120</width>
				<height>120</height>
				<depth>24</depth>
				<url>/pioneer_icon_lrg.png</url>
			</icon>
		</iconList>
		<serviceList>
			<service>
				<serviceType>urn:schemas-upnp-org:service:RenderingControl:1</serviceType>
				<serviceId>urn:upnp-org:serviceId:RenderingControl</serviceId>
				<SCPDURL>/RenderingControl/desc.xml</SCPDURL>
				<controlURL>/RenderingControl/ctrl</controlURL>
				<eventSubURL>/RenderingControl/evt</eventSubURL>
			</service>
			<service>
				<serviceType>urn:schemas-upnp-org:service:ConnectionManager:1</serviceType>
				<serviceId>urn:upnp-org:serviceId:ConnectionManager</serviceId>
				<SCPDURL>/ConnectionManager/desc.xml</SCPDURL>
				<controlURL>/ConnectionManager/ctrl</controlURL>
				<eventSubURL>/ConnectionManager/evt</eventSubURL>
			</service>
			<service>
				<serviceType>urn:schemas-upnp-org:service:AVTransport:1</serviceType>
				<serviceId>urn:upnp-org:serviceId:AVTransport</serviceId>
				<SCPDURL>/AVTransport/desc.xml</SCPDURL>
				<controlURL>/AVTransport/ctrl</controlURL>
				<eventSubURL>/AVTransport/evt</eventSubURL>
			</service>
		</serviceList>
		<presentationURL>http://10.0.0.60</presentationURL>
	</device>
</root>

Error message:

10-31 09:12:50 pyupnpv2                                       DEBUG    Got broken xml, trying to fix it.
----------------------------------------
Exception happened during processing of request from ('10.0.0.60', 5645)
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/pyupnpv2/__init__.py", line 716, in from_xml
    xml_root = lxml.etree.fromstring(xml)
  File "src/lxml/etree.pyx", line 3237, in lxml.etree.fromstring
  File "src/lxml/parser.pxi", line 1896, in lxml.etree._parseMemoryDocument
  File "src/lxml/parser.pxi", line 1784, in lxml.etree._parseDoc
  File "src/lxml/parser.pxi", line 1141, in lxml.etree._BaseParser._parseDoc
  File "src/lxml/parser.pxi", line 615, in lxml.etree._ParserContext._handleParseResultDoc
  File "src/lxml/parser.pxi", line 725, in lxml.etree._handleParseResult
  File "src/lxml/parser.pxi", line 654, in lxml.etree._raiseParseError
  File "<string>", line 4
lxml.etree.XMLSyntaxError: xmlns:ms: ' urn:microsoft-com:wmc-1-0' is not a valid URI, line 4, column 40

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.8/socketserver.py", line 650, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python3.8/socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python3.8/socketserver.py", line 720, in __init__
    self.handle()
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/ssdp/listener.py", line 48, in handle
    self.server.cb_on_device_alive(header)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/__init__.py", line 36, in wrapper
    device = f(*args, **kwargs)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/__init__.py", line 89, in _on_device_added
    return DLNAMediaRendererFactory.from_header(header)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/renderer.py", line 290, in from_header
    upnp_device = pyupnpv2.UpnpMediaRendererFactory.from_header(header)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/pyupnpv2/__init__.py", line 734, in from_header
    return cls.from_url(header['location'])
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/pyupnpv2/__init__.py", line 651, in from_url
    return cls.from_xml(url, response.content)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/pyupnpv2/__init__.py", line 720, in from_xml
    xml = byto.repair_xml(xml)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/pyupnpv2/byto.py", line 38, in repair_xml
    bytes = re.sub(
  File "/usr/lib/python3.8/re.py", line 210, in sub
    return _compile(pattern, flags).sub(repl, string, count)
TypeError: cannot use a string pattern on a bytes-like object

I do not know Python well enough to fix the bug or to debug it more closely.
It looks like a conversion error from string to bytes or vice versa.

@stuaxo
Copy link

stuaxo commented Oct 31, 2020

You can try changing repair_xml in byto.py to look like this:

def repair_xml(bytes):

    def strip_namespaces(match):
        return 'xmlns{prefix}="{content}"'.format(
            prefix=match.group(1) if match.group(1) else '',
            content=match.group(2).strip(),
        )

    bytes = re.sub(
        b'xmlns(:.*?)?="(.*?)"', strip_namespaces, bytes,
        flags=re.IGNORECASE)

    return bytes

I'm not sure that's a full fix though.

I don't have the equipment to test this, but the error goes away when I used the data you posted.

@Tenyun
Copy link

Tenyun commented Oct 31, 2020

Thanks for your quick help but with this change I now get the following error:

TypeError: sequence item 1: expected a bytes-like object, str found

@stuaxo
Copy link

stuaxo commented Oct 31, 2020

I thought something somewhere else might break, is there a stacktrace or is that the whole error?

@Tenyun
Copy link

Tenyun commented Oct 31, 2020

Sorry that I was a little lazy.
To me the rest of the error message looked the same.
But maybe I just missed something.

10-31 13:18:55 pyupnpv2                                       DEBUG    Got broken xml, trying to fix it.
Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/pyupnpv2/__init__.py", line 716, in from_xml
    xml_root = lxml.etree.fromstring(xml)
  File "src/lxml/etree.pyx", line 3237, in lxml.etree.fromstring
  File "src/lxml/parser.pxi", line 1896, in lxml.etree._parseMemoryDocument
  File "src/lxml/parser.pxi", line 1784, in lxml.etree._parseDoc
  File "src/lxml/parser.pxi", line 1141, in lxml.etree._BaseParser._parseDoc
  File "src/lxml/parser.pxi", line 615, in lxml.etree._ParserContext._handleParseResultDoc
  File "src/lxml/parser.pxi", line 725, in lxml.etree._handleParseResult
  File "src/lxml/parser.pxi", line 654, in lxml.etree._raiseParseError
  File "<string>", line 4
lxml.etree.XMLSyntaxError: xmlns:ms: ' urn:microsoft-com:wmc-1-0' is not a valid URI, line 4, column 40

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/__init__.py", line 53, in launch_discover
    discover.search(ssdp_ttl=ttl)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/ssdp/discover.py", line 66, in search
    self._search(self.host or '', ssdp_ttl, ssdp_mx, ssdp_amount)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/ssdp/discover.py", line 111, in _search
    self.cb_on_device_response(header, address)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/__init__.py", line 36, in wrapper
    device = f(*args, **kwargs)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/__init__.py", line 83, in _on_device_response
    return DLNAMediaRendererFactory.from_header(header)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/renderer.py", line 290, in from_header
    upnp_device = pyupnpv2.UpnpMediaRendererFactory.from_header(header)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/pyupnpv2/__init__.py", line 734, in from_header
    return cls.from_url(header['location'])
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/pyupnpv2/__init__.py", line 651, in from_url
    return cls.from_xml(url, response.content)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/pyupnpv2/__init__.py", line 720, in from_xml
    xml = byto.repair_xml(xml)
  File "/usr/lib/python3.8/site-packages/pulseaudio_dlna/plugins/dlna/pyupnpv2/byto.py", line 51, in repair_xml
    bytes = re.sub(
  File "/usr/lib/python3.8/re.py", line 210, in sub
    return _compile(pattern, flags).sub(repl, string, count)
TypeError: sequence item 1: expected a bytes-like object, str found

@blackd
Copy link

blackd commented Oct 31, 2020

I have the same problem the code below fixes it... but is technically like opening the door with explosives :) because you lost the key.

import re
def repair_xml(bytes):

    def strip_namespaces(match):
        return 'xmlns{prefix}="{content}"'.format(
            prefix=match.group(1) if match.group(1) else '',
            content=match.group(2).strip(),
        )

    st = bytes.decode('utf-8')
    st = re.sub(
        r'xmlns(:.*?)?="(.*?)"', strip_namespaces, st,
        flags=re.IGNORECASE)
    bytes = st.encode('utf-8')

    return bytes

@Tenyun
Copy link

Tenyun commented Oct 31, 2020

Thank you,
I can confirm that this code works.
How robust the code is cannot be evaluated from my point of view but maybe someone will find a way to make it acceptable for everyone.

@stuaxo
Copy link

stuaxo commented Oct 31, 2020

OK, I don't know what the project will accept as a PR, but I reckon to clean this up need to make the inner strip_namespace work with bytes, then we won't need the bytes->unicode->bytes dance.

@stuaxo
Copy link

stuaxo commented Oct 31, 2020

Can you add some debug for me in pulseaudio_dlna/plugins/dlna/pyupnpv2/init.py

    @classmethod
    def from_xml(cls, url, xml):

And add

    @classmethod
    def from_xml(cls, url, xml):
        print("xml: ", type(xml))

As I'm not sure if it's a string or bytes at that point yet.

@stuaxo
Copy link

stuaxo commented Oct 31, 2020

Trying things a little blindly, but this one should work if they are always bytes going in:

def repair_xml(xml_bytes):
    def strip_namespaces(match):
        return b'xmlns%s="%s"' % (
            match.group(1) if match.group(1) else b"",
            match.group(2).strip(),
        )

    xml_bytes = re.sub(
        b'xmlns(:.*?)?="(.*?)"', strip_namespaces, xml_bytes, flags=re.IGNORECASE
    )

    return xml_bytes

@Tenyun
Copy link

Tenyun commented Oct 31, 2020

Confirm
The new code also works.

Here is the debug output as desired.

10-31 14:34:02 pyupnpv2                                       DEBUG    Got broken xml, trying to fix it.
10-31 14:34:02 urllib3.connectionpool                         DEBUG    Starting new HTTP connection (1): 10.0.0.60:8080
10-31 14:34:02 urllib3.connectionpool                         DEBUG    http://10.0.0.60:8080 "GET /RenderingControl/desc.xml HTTP/1.1" 200 4526
10-31 14:34:02 urllib3.connectionpool                         DEBUG    http://10.0.0.60:8080 "GET /ConnectionManager/desc.xml HTTP/1.1" 200 4085
10-31 14:34:02 urllib3.connectionpool                         DEBUG    http://10.0.0.60:8080 "GET /AVTransport/desc.xml HTTP/1.1" 200 14494
10-31 14:34:03 urllib3.connectionpool                         DEBUG    Starting new HTTP connection (1): 10.0.0.60:8080
10-31 14:34:03 urllib3.connectionpool                         DEBUG    http://10.0.0.60:8080 "GET /description.xml HTTP/1.1" 200 3281
10-31 14:34:03 pyupnpv2                                       DEBUG    Response from UPNP device (http://10.0.0.60:8080/description.xml)
<?xml version="1.0"?>
<root
  xmlns="urn:schemas-upnp-org:device-1-0"
  xmlns:ms=" urn:microsoft-com:wmc-1-0"
  xmlns:pnpx="http://schemas.microsoft.com/windows/pnpx/2005/11"
  xmlns:df="http://schemas.microsoft.com/windows/2008/09/devicefoundation">
	<specVersion>
		<major>1</major>
		<minor>0</minor>
	</specVersion>
	<device
	  ms:X_MS_SupportsWMDRM="true">
		<av:X_ipRemoteReady xmlns:av="http://www.pioneerelectronics.com/xmlns/av">1</av:X_ipRemoteReady>
		<av:X_ipRemoteTcpPort xmlns:av="http://www.pioneerelectronics.com/xmlns/av">8102</av:X_ipRemoteTcpPort>
		<dlna:X_DLNADOC xmlns:dlna="urn:schemas-dlna-org:device-1-0">DMR-1.50</dlna:X_DLNADOC>
		<pnpx:X_compatibleId>MS_DigitalMediaDeviceClass_DMR_V001
				</pnpx:X_compatibleId>
		<pnpx:X_deviceCategory>MediaDevices
				</pnpx:X_deviceCategory>
		<pnpx:X_hardwareId>VEN_0112&amp;DEV_0002&amp;REV_01 VEN_0033&amp;DEV_000C&amp;REV_01
				</pnpx:X_hardwareId>
		<df:X_deviceCategory>Multimedia.DMR
				</df:X_deviceCategory>
		<deviceType>urn:schemas-upnp-org:device:MediaRenderer:1</deviceType>
		<friendlyName>VSX-922</friendlyName>
		<manufacturer>PIONEER CORPORATION</manufacturer>
		<manufacturerURL>http://www.pioneerelectronics.com</manufacturerURL>
		<modelDescription>Digital Media Client</modelDescription>
		<modelName>VSX-922/SYXE8</modelName>
		<modelNumber>Digital Media Client</modelNumber>
		<UDN>uuid:5F9EC1B3-ED59-79BB-4530-745E1C106437</UDN>
		<UPC>123810928305556upc</UPC>
		<iconList>
			<icon>
				<mimetype>image/jpeg</mimetype>
				<width>48</width>
				<height>48</height>
				<depth>24</depth>
				<url>/pioneer_icon_sm.jpg</url>
			</icon>
			<icon>
				<mimetype>image/jpeg</mimetype>
				<width>120</width>
				<height>120</height>
				<depth>24</depth>
				<url>/pioneer_icon_lrg.jpg</url>
			</icon>
			<icon>
				<mimetype>image/png</mimetype>
				<width>48</width>
				<height>48</height>
				<depth>24</depth>
				<url>/pioneer_icon_sm.png</url>
			</icon>
			<icon>
				<mimetype>image/png</mimetype>
				<width>120</width>
				<height>120</height>
				<depth>24</depth>
				<url>/pioneer_icon_lrg.png</url>
			</icon>
		</iconList>
		<serviceList>
			<service>
				<serviceType>urn:schemas-upnp-org:service:RenderingControl:1</serviceType>
				<serviceId>urn:upnp-org:serviceId:RenderingControl</serviceId>
				<SCPDURL>/RenderingControl/desc.xml</SCPDURL>
				<controlURL>/RenderingControl/ctrl</controlURL>
				<eventSubURL>/RenderingControl/evt</eventSubURL>
			</service>
			<service>
				<serviceType>urn:schemas-upnp-org:service:ConnectionManager:1</serviceType>
				<serviceId>urn:upnp-org:serviceId:ConnectionManager</serviceId>
				<SCPDURL>/ConnectionManager/desc.xml</SCPDURL>
				<controlURL>/ConnectionManager/ctrl</controlURL>
				<eventSubURL>/ConnectionManager/evt</eventSubURL>
			</service>
			<service>
				<serviceType>urn:schemas-upnp-org:service:AVTransport:1</serviceType>
				<serviceId>urn:upnp-org:serviceId:AVTransport</serviceId>
				<SCPDURL>/AVTransport/desc.xml</SCPDURL>
				<controlURL>/AVTransport/ctrl</controlURL>
				<eventSubURL>/AVTransport/evt</eventSubURL>
			</service>
		</serviceList>
		<presentationURL>http://10.0.0.60</presentationURL>
	</device>
</root>
xml:  <class 'bytes'>

I think it is bytes if I understand the last line correctly

@stuaxo
Copy link

stuaxo commented Oct 31, 2020

Nice, I'll turn it into a PR later.

@Tenyun
Copy link

Tenyun commented Oct 31, 2020

Thanks again for the fast and good help.

stuaxo added a commit to stuaxo/pulseaudio-dlna that referenced this issue Oct 31, 2020
Fix for masmu#402

I also ran the code through Black for formatting, renamed "bytes" to "xml_bytes" so we don't shadow the bytes builtin.
@farax4de
Copy link

farax4de commented Dec 8, 2020

Trying things a little blindly, but this one should work if they are always bytes going in:

def repair_xml(xml_bytes):
    def strip_namespaces(match):
        return b'xmlns%s="%s"' % (
            match.group(1) if match.group(1) else b"",
            match.group(2).strip(),
        )

    xml_bytes = re.sub(
        b'xmlns(:.*?)?="(.*?)"', strip_namespaces, xml_bytes, flags=re.IGNORECASE
    )

    return xml_bytes

I had the same problem with my DENON DNP-F109 and get the Exception "XMLSyntaxError" in the modul „pyupnpv2“:

xmlns:ms: ' urn:microsoft-com:wmc-1-0' is not a valid URI, line 4, column 40 (<string>, line 4)

My current hack is patching the file "/usr/lib/python3.[?]/site-packages/pulseaudio_dlna/plugins/dlna/pyupnpv2/init.py" and add a simple replace(). I think this is perhaps a bit more straightforward and robust for this problem than "re.sub()" (Stackoveflow: "Use Python's string.replace vs re.sub"). But in the end, it's not really nice.

xml = xml.replace(b' urn:microsoft-com', b'urn:microsoft-com')
        try:
            xml = xml.replace(b' urn:microsoft-com', b'urn:microsoft-com')
            xml_root = lxml.etree.fromstring(xml)
            return process_xml(url, xml_root, xml)
        except Exception as msg:
            logger.debug('Got broken xml, trying to fix it.')
            xml = byto.repair_xml(xml)
            try:
                xml_root = lxml.etree.fromstring(xml)
                return process_xml(url, xml_root, xml)
            except Exception:
                import traceback
                traceback.print_exc()
                logger.error('No valid XML returned from {url}.'.format(
                    url=url))
                return None

update syntax, thanks to stuaxo

@stuaxo
Copy link

stuaxo commented Dec 8, 2020

bytes has a .replace so you should be able to do it without the conversion

xml = xml.replace(b' urn:microsoft-com', b'urn:microsoft-com')

@stuaxo
Copy link

stuaxo commented Dec 8, 2020

Though I guess this does a sort of similar thing to repair_xml it would be good to have this in just one place.

It would be nice to know if this is always meant to be bytes too, the bit that captures Exception seems overly wide, but that`s probably out of scope for this fix.

@stuaxo
Copy link

stuaxo commented Dec 8, 2020

I don't know what all the kinds of bad XML can come through, but the advantage of the regex is it will catch xml with more than one space in it, but I don't know if that's ever an issue.

@stuaxo
Copy link

stuaxo commented Dec 9, 2020

I've been using this for a over a month and it's been fine, so I've made it a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants