agsh / onvif

ONVIF node.js implementation
https://onvif.pages.dev
MIT License
703 stars 240 forks source link

discovery emits invalid XML #88

Closed fbertone closed 4 years ago

fbertone commented 6 years ago

Hi,

I'm trying to convert the XML sent as discovery response event into json (using x2js).

onvif.Discovery.on('device', (cam, rinfo, xml) => {
       let jsonObj = x2js.xml_str2json(xml)
[...]
}

The camera originally sends this XML:

<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:enc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsa5="http://www.w3.org/2005/08/addressing" xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:dn="http://www.onvif.org/ver10/network/wsdl" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:tds="http://www.onvif.org/ver10/device/wsdl">
    <s:Header>
        <wsa:MessageID>urn:uuid:469290615c923cf8-6d5824f4-538fe2e4-34ae2769-1314ab9a5d94c3b54c85133d</wsa:MessageID>
        <wsa:RelatesTo>urn:uuid:039ca873-190f-8762-641f-e34d1dcd76ce</wsa:RelatesTo>
        <wsa:To s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
        <wsa:Action s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches</wsa:Action>
    </s:Header>
    <s:Body>
        <d:ProbeMatches>
            <d:ProbeMatch>
                <wsa:EndpointReference>
                    <wsa:Address>urn:uuid:812b12f7-45a0-11b5-8404-c056e3a2e020</wsa:Address>
                </wsa:EndpointReference>
                <d:Types>dn:NetworkVideoTransmitter</d:Types>
                <d:Scopes>onvif://www.onvif.org/type/Network_Transmitter onvif://www.onvif.org/type/video_encoder onvif://www.onvif.org/type/ptz onvif://www.onvif.org/type/audio_encoder onvif://www.onvif.org/type/video_analytics onvif://www.onvif.org/hardware/IP-camera onvif://www.onvif.org/name/IP-camera onvif://www.onvif.org/location/country/China onvif://www.onvif.org/Profile/Streaming </d:Scopes>
                <d:XAddrs>http://192.168.0.30:10080/onvif/device_service</d:XAddrs>
                <d:MetadataVersion>1</d:MetadataVersion>
            </d:ProbeMatch>
        </d:ProbeMatches>
    </s:Body>
</s:Envelope>

which is valid XML.

However, this XML gets filtered through parseSOAPString that filters out xml name spaces before firing the event. This transforms the original XML in

<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope          >
    <s:Header>
        <wsa:MessageID>urn:uuid:469290615c923cf8-6d5824f4-538fe2e4-34ae2769-1314ab9a5d94c3b54c85133d</wsa:MessageID>
        <wsa:RelatesTo>urn:uuid:039ca873-190f-8762-641f-e34d1dcd76ce</wsa:RelatesTo>
        <wsa:To s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
        <wsa:Action s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches</wsa:Action>
    </s:Header>
    <s:Body>
        <d:ProbeMatches>
            <d:ProbeMatch>
                <wsa:EndpointReference>
                    <wsa:Address>urn:uuid:812b12f7-45a0-11b5-8404-c056e3a2e020</wsa:Address>
                </wsa:EndpointReference>
                <d:Types>dn:NetworkVideoTransmitter</d:Types>
                <d:Scopes>onvif://www.onvif.org/type/Network_Transmitter onvif://www.onvif.org/type/video_encoder onvif://www.onvif.org/type/ptz onvif://www.onvif.org/type/audio_encoder onvif://www.onvif.org/type/video_analytics onvif://www.onvif.org/hardware/IP-camera onvif://www.onvif.org/name/IP-camera onvif://www.onvif.org/location/country/China onvif://www.onvif.org/Profile/Streaming </d:Scopes>
                <d:XAddrs>http://192.168.0.30:10080/onvif/device_service</d:XAddrs>
                <d:MetadataVersion>1</d:MetadataVersion>
            </d:ProbeMatch>
        </d:ProbeMatches>
    </s:Body>
</s:Envelope>

that unfortunately is no more valid XML because all the prefixes (s, d, wda, ecc) are now linked to nothing. This breaks the conversion of x2js (and possibly other libraries). The event should either send the original XML or parseSOAPString should clean up also all the prefixes to make a valid xml. To me either ways is fine, but I don't see why remove the names spaces in the first place. Apparently a similar thing appens here but in this case the raw XML is sent

hawkeye64 commented 6 years ago

This makes sense to me in case you needed to do some extra parsing then the namespaces will be necessary.

fbertone commented 6 years ago

just to add some info to the conversation: this regex

/<(\/?)(\w*):(\w*)((\s+[\w\d=":]+)*)\s*(\/?)>/g

matches open and closing tags, even short "self-closing" tags This can be used like

xml.replace(/<(\/?)(\w*):(\w*)((\s+[\w\d=":]+)*)\s*(\/?)>/g, '<$1$3$4$6>')

to remove all prefixes from tags (opening and closing) short explanation: $1 matches the initial closing '/' $3 matches the tag name ($2 is the prefix that we want to remove) $4 matches all inner attributes $6 matches the closing '/' for self-closing tags

However, this does not remove prefixes from attributes inside tags, so it does not yet guarantee a valid xml If we remove $4 we eliminate also attributes inside tags, that could solve the problem but at the cost of losing the attributes

A further manipulation to remove prefixes from attributes could be done with something like:

xml.replace(/(\s\w+:)(\w+=?"?\w*"?)/g, ' $2')

This matches all strings starting with a white space (' '), followed by a string, a ':' and another string, outputting just the second string and eliminating the first part. The issue with this regex is that it does not check if it is inside a tag, the side effect is that it could corrupt the values between tags if they match the rule. I don't know how to solve this issue at the moment

agsh commented 5 years ago

@hawkeye64 Do you agree with @fbertone? Because it looks reasonable to me.

chriswiggins commented 4 years ago

Closing out old issue - PR would be great to sort this