package com.codicesoftware.plugins.hudson.commands.parsers;

import com.codicesoftware.plugins.hudson.model.ChangeSet;
import hudson.FilePath;
import org.apache.commons.digester3.Digester;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

public class FindOutputParser {
    private static final Logger LOGGER = Logger.getLogger(FindOutputParser.class.getName());

    // Utility classes shouldn't have default constructors
    private FindOutputParser() { }

    public static List<ChangeSet> parseReader(FilePath path) throws IOException, ParseException {
        List<ChangeSet> csetList = new ArrayList<>();

        if (!SafeFilePath.exists(path)) {
            LOGGER.warning("Find command XML output file not found: " + path);
            return csetList;
        }

        Digester digester = new Digester();
        digester.push(csetList);

        digester.addObjectCreate("*/CHANGESET", ChangeSet.class);
        digester.addBeanPropertySetter("*/CHANGESET/CHANGESETID", "version");
        digester.addBeanPropertySetter("*/CHANGESET/COMMENT", "comment");
        digester.addBeanPropertySetter("*/CHANGESET/DATE", "xmlDate");
        digester.addBeanPropertySetter("*/CHANGESET/BRANCH", "branch");
        digester.addBeanPropertySetter("*/CHANGESET/OWNER", "user");
        digester.addBeanPropertySetter("*/CHANGESET/REPNAME", "repoName");
        digester.addBeanPropertySetter("*/CHANGESET/REPSERVER", "repoServer");
        digester.addBeanPropertySetter("*/CHANGESET/GUID", "guid");
        digester.addSetNext("*/CHANGESET", "add");

        try (InputStream stream = SafeFilePath.read(path)) {
            if (stream != null) {
                digester.parse(stream);
            }
        } catch (SAXException e) {
            throw new ParseException("Parse error: " + e.getMessage(), 0);
        }
        return csetList;
    }
}

@@ -216,16 +216,71 @@
 ption;%0A%0A
+import javax.xml.parsers.ParserConfigurationException;%0A
 import j
@@ -1024,16 +1024,777 @@
 ster();%0A
+%0A        digester.setXIncludeAware(false);%0A%0A        if (!Boolean.getBoolean(FindOutputParser.class.getName() + %22.UNSAFE%22)) %7B%0A            try %7B%0A                digester.setFeature(%22http://apache.org/xml/features/disallow-doctype-decl%22, true);%0A                digester.setFeature(%22http://xml.org/sax/features/external-general-entities%22, false);%0A                digester.setFeature(%22http://xml.org/sax/features/external-parameter-entities%22, false);%0A                digester.setFeature(%22http://apache.org/xml/features/nonvalidating/load-external-dtd%22, false);%0A            %7D%0A            catch ( SAXException %7C ParserConfigurationException ex) %7B%0A                throw new IOException(%22Failed to securely configure CVS changelog parser%22, ex);%0A            %7D%0A        %7D%0A%0A
         

fix Digester security configuration