Could not parse service descriptor: java.lang.RuntimeException: org.xml.sax.SAXNotRecognizedException: http://javax.xml.XMLConstants/feature/secure-processing
javaertj opened this issue · comments
Could not parse service descriptor: java.lang.RuntimeException: org.xml.sax.SAXNotRecognizedException: http://javax.xml.XMLConstants/feature/secure-processing
androidOsVersion="9.0"
clingVersion = "2.1.2"
jettyVersion = "8.1.22.v20160922"
slf4jVersion = "1.7.25"
In order to solve the exception, I rewrote several classes.
“
public class DLNABrowserService extends AndroidUpnpServiceImpl {
@OverRide
protected UpnpServiceConfiguration createConfiguration() {
return new AndroidUpnpServiceConfiguration() {
@Override
public ServiceDescriptorBinder createServiceDescriptorBinderUDA10() {
return new DLNAUDA10ServiceDescriptorBinderSAXImpl();
}
};
}
}
”
“
public class DLNASAXParser extends SAXParser {
protected XMLReader create() {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
//fix bug .see https://stackoverflow.com/questions/10837706/solve-security-issue-parsing-xml-using-sax-parser
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
// Configure factory to prevent XXE attacks
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setXIncludeAware(false);
factory.setNamespaceAware(true);
if (getSchemaSources() != null) {
factory.setSchema(createSchema(getSchemaSources()));
}
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
xmlReader.setErrorHandler(getErrorHandler());
return xmlReader;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
”
“
public class DLNAUDA10ServiceDescriptorBinderSAXImpl extends UDA10ServiceDescriptorBinderSAXImpl {
private static Logger log = Logger.getLogger(ServiceDescriptorBinder.class.getName());
@Override
public <S extends Service> S describe(S undescribedService, String descriptorXml) throws DescriptorBindingException, ValidationException {
if (descriptorXml == null || descriptorXml.length() == 0) {
throw new DescriptorBindingException("Null or empty descriptor");
}
try {
log.fine("Reading service from XML descriptor");
SAXParser parser = new DLNASAXParser();
MutableService descriptor = new MutableService();
hydrateBasic(descriptor, undescribedService);
new RootHandler(descriptor, parser);
parser.parse(
new InputSource(
// TODO: UPNP VIOLATION: Virgin Media Superhub sends trailing spaces/newlines after last XML element, need to trim()
new StringReader(descriptorXml.trim())
)
);
// Build the immutable descriptor graph
return (S)descriptor.build(undescribedService.getDevice());
} catch (ValidationException ex) {
throw ex;
} catch (Exception ex) {
throw new DescriptorBindingException("Could not parse service descriptor: " + ex.toString(), ex);
}
}
}
”
Finally, I solved the problem that the upnp protocol could not be resolved by rewriting the SAXParser referenced in UDA10ServiceDescriptorBinderSAXImpl and commenting out a few lines of code.
“
public class DLNASAXParser extends SAXParser {
protected XMLReader create() {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
// Configure factory to prevent XXE attacks
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
//commenting
//factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
//factory.setXIncludeAware(false);
//factory.setNamespaceAware(true);
if (getSchemaSources() != null) {
factory.setSchema(createSchema(getSchemaSources()));
}
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
xmlReader.setErrorHandler(getErrorHandler());
return xmlReader;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
”
still Exception
05-11 20:58:56.859 18002-18002/com.tv.cast.castdemo2 D/devicetest: Discovery failed of 'Xiaomi MediaRenderer':org.fourthline.cling.binding.xml.DescriptorBindingException: Could not parse service descriptor: java.lang.RuntimeException: org.xml.sax.SAXNotRecognizedException: http://apache.org/xml/features/disallow-doctype-decl
you can switch to the safer implementation and not use the SAX, which only works with devices using perfect Upnp 1.0 implementations (this is Kotlin, Java should look similar but different), as described in the manual :
override fun getServiceDescriptorBinderUDA10(): ServiceDescriptorBinder? {
return UDA10ServiceDescriptorBinderImpl()
}