Yortw / RSSDP

Really Simple Service Discovery Protocol - a 100% .Net implementation of the SSDP protocol for publishing custom/basic devices, and discovering all device types on a network.
http://yortw.github.io/RSSDP/
MIT License
282 stars 66 forks source link

Made Xml reading more lenient #89

Closed plinth666 closed 5 years ago

Yortw commented 5 years ago

Hi,

Thanks for this, and sorry for the delayed response. Do you have some sample XML that I could use as a unit test to ensure this doesn't regress in future?

plinth666 commented 5 years ago

I uploaded XML generated by my receiver which includes a single 0x01 in the middle on the XML (thanks Denon, you're the best).

Yortw commented 5 years ago

Hi,

I am struggling a bit with this. Even with the change to set the CheckCharacters setting to false I'm still getting errors when processing the denonbad.xml file you provided.

First error is in SsdpDevice around line 691 where it is trying to read the friendly name (presumably where the bad character exists). It's an XmlException with the message

Exception thrown: 'System.Xml.XmlException' in System.Xml.dll Additional information: ' ', hexadecimal value 0x01, is an invalid character. Line 24, position 80.

If I ignore that error, then it fails again SsdpRootDevice around line 158 with the same error. So far I haven't found anyway to get the system to read the xml when that character is present.

Has this change actually fixed your problem, or is it untested? I'm not sure why I'd get different results to you.

plinth666 commented 5 years ago

It's untested - at the time, I was working with a nuget, so I was going blind. I think the way to really fix this is to try something like this on the xml string:

static string EscapeBadXml (string text) {
    return IsValisXmlString (text) ? text : XmlConvert.EncodeName(text);
}
static bool IsValidXmlString(string text) {
    try {
        XmlConvert.VerifyXmlChars(text);
        return true;
    } catch {
        return false;
    }
}

And apply that before parsing it. Alternately, at the point where the text is read, you could apply a filter to the stream:

public Func<Stream, Stream> StreamFilterFactory { get; set; }
// ...
    StreamFilterFactory = stm => stm; // default - does nothing or set to a Stream instance that uses XmlConvert.IsXmlChar on read to escape or drop bad characters.