File: NokogiriEntityResolver.java

package info (click to toggle)
ruby-nokogiri 1.10.0%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 5,088 kB
  • sloc: xml: 28,081; ruby: 16,687; java: 13,293; ansic: 4,954; yacc: 265; sh: 76; makefile: 19
file content (121 lines) | stat: -rw-r--r-- 4,324 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package nokogiri.internals;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URI;

import nokogiri.internals.ParserContext.Options;

import org.jruby.Ruby;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.ext.EntityResolver2;

/**
 * An entity resolver aware of the fact that the Ruby runtime can
 * change directory but the JVM cannot.  Thus any file based
 * entity resolution that uses relative paths must be translated
 * to be relative to the current directory of the Ruby runtime.
 */
public class NokogiriEntityResolver implements EntityResolver2 {
    protected final Ruby runtime;
    private final NokogiriErrorHandler handler;
    private final Options options;

    public NokogiriEntityResolver(Ruby runtime, NokogiriErrorHandler handler, Options options) {
        super();
        this.runtime = runtime;
        this.handler = handler;
        this.options = options;
    }

    @Override
    public InputSource getExternalSubset(String name, String baseURI)
        throws SAXException, IOException {
        return null;
    }

    @Override
    public InputSource resolveEntity(String publicId, String systemId)
        throws SAXException, IOException {
        return resolveEntity(runtime, null, publicId, null, systemId);
    }

    @Override
    public InputSource resolveEntity(String name,
                                     String publicId,
                                     String baseURI,
                                     String systemId)
        throws SAXException, IOException {
        return resolveEntity(runtime, name, publicId, baseURI, systemId);
    }

    private static File join(String parent, String child) {
        if (new File(parent).isFile()) {
            parent = new File(parent).getParent();
        }
        return new File(parent, child);
    }

    private static InputSource emptyInputSource(InputSource source) {
        source.setByteStream(new ByteArrayInputStream(new byte[0]));
        return source;
    }

    private boolean shouldLoadDtd() {
      return options.dtdLoad || options.dtdValid;
    }

    private void addError(String errorMessage) {
        if (handler != null) handler.errors.add(new Exception(errorMessage));
    }

    /**
     * Create a file base input source taking into account the current
     * directory of <code>runtime</code>.
     * @throws SAXException
     */
    protected InputSource resolveEntity(Ruby runtime, String name, String publicId, String baseURI, String systemId)
        throws IOException, SAXException {
        InputSource s = new InputSource();
        if (name.equals("[dtd]") && !shouldLoadDtd()) {
          return emptyInputSource(s);
        } else if (!name.equals("[dtd]") && !options.noEnt) {
          return emptyInputSource(s);
        }
        String adjustedSystemId;
        URI uri = URI.create(systemId);
        if (options.noNet && uri.getHost() != null) {
          addError("Attempt to load network entity " + systemId);
          return emptyInputSource(s);
        }
        // if this is a url or absolute file name then use it
        if (uri.isAbsolute() && !uri.isOpaque()) {
          adjustedSystemId = uri.toURL().toString();
        } else if (new File(uri.getPath()).isAbsolute()) {
          adjustedSystemId = uri.getPath();
        } else if (baseURI != null) {
          URI baseuri = URI.create(baseURI);
          if (options.noNet && baseuri.getHost() != null) {
            addError("Attempt to load network entity " + systemId);
            return emptyInputSource(s);
          }
          if (baseuri.getHost() == null) {
            // this is a local file
            adjustedSystemId = join(baseuri.getPath(), uri.getPath()).getCanonicalPath();
          } else {
            // this is a url, then resolve uri using baseuri
            adjustedSystemId = baseuri.resolve(systemId).toURL().toString();
          }
        } else {
          // baseURI is null we have to use the current working directory to resolve the entity
          String pwd = runtime.getCurrentDirectory();
          adjustedSystemId = join(pwd, uri.getPath()).getCanonicalPath();
        }
        s.setSystemId(adjustedSystemId);
        s.setPublicId(publicId);
        return s;
    }

}