File: NokogiriEntityResolver.java

package info (click to toggle)
ruby-nokogiri 1.13.10%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 7,416 kB
  • sloc: ansic: 38,198; xml: 28,086; ruby: 22,271; java: 15,517; cpp: 7,037; yacc: 244; sh: 148; makefile: 136
file content (140 lines) | stat: -rw-r--r-- 4,005 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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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.addError(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;
  }

}