Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions exist-core/src/main/java/org/exist/http/RESTServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
*/
package org.exist.http;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.exist.EXistException;
Expand Down Expand Up @@ -84,8 +86,6 @@
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.XMLFilterImpl;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;
Expand All @@ -96,6 +96,8 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Properties;
import java.util.*;
import java.util.function.BiFunction;
Expand Down Expand Up @@ -1374,7 +1376,7 @@ protected void search(final DBBroker broker, final Txn transaction, final String
}

context.setStaticallyKnownDocuments(new XmldbURI[]{pathUri});
context.setBaseURI(new AnyURIValue(pathUri.toString()));
context.setBaseURI(BaseURI.dbBaseURIFromLocation(pathUri.getURI()));

declareNamespaces(context, namespaces);
declareVariables(context, variables, request, response);
Expand Down Expand Up @@ -1559,6 +1561,12 @@ private void executeXQuery(final DBBroker broker, final Txn transaction, final D
context.prepareForReuse();
}

try {
context.setBaseURI(BaseURI.dbBaseURIFromLocation(new URI(servletPath)));
} catch (URISyntaxException e) {
LOG.warn("Path {} is not valid for forming a base URI, base URI not set.", servletPath);
}

// TODO: don't hardcode this?
context.setModuleLoadPath(
XmldbURI.EMBEDDED_SERVER_URI.append(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
*/
package org.exist.http.servlets;

import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.exist.EXistException;
Expand All @@ -39,19 +45,15 @@
import org.exist.util.serializer.XQuerySerializer;
import org.exist.xmldb.XmldbURI;
import org.exist.xquery.*;
import org.exist.xquery.value.AnyURIValue;
import org.exist.xquery.value.Item;
import org.exist.xquery.value.Sequence;

import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import javax.xml.transform.OutputKeys;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.nio.file.Files;
Expand Down Expand Up @@ -435,6 +437,7 @@ protected void process(HttpServletRequest request, HttpServletResponse response)
if (query==null) {
context = new XQueryContext(getPool());
context.setModuleLoadPath(moduleLoadPath);
context.setBaseURI(new AnyURIValue(new URI("file:///").resolve(path).toString()));
try {
query = xquery.compile(context, source);

Expand All @@ -446,9 +449,11 @@ protected void process(HttpServletRequest request, HttpServletResponse response)
}

} else {
context = query.getContext();
context.setModuleLoadPath(moduleLoadPath);
context.prepareForReuse();
context = query.getContext();

context.setModuleLoadPath(moduleLoadPath);
context.setBaseURI(new AnyURIValue(new URI("file:///").resolve(path).toString()));
context.prepareForReuse();
}

final Properties outputProperties = new Properties();
Expand Down
54 changes: 54 additions & 0 deletions exist-core/src/main/java/org/exist/util/BaseURI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* eXist-db Open Source Native XML Database
* Copyright (C) 2001 The eXist-db Authors
*
* info@exist-db.org
* http://www.exist-db.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.exist.util;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.exist.xmldb.XmldbURI;
import org.exist.xquery.XPathException;
import org.exist.xquery.value.AnyURIValue;

import java.net.URI;

public class BaseURI {

private final static Logger LOG = LogManager.getLogger(BaseURI.class);

/**
* Convert the location of a resource function into an XML database URI
* @param uri the location of the resource function
* @return the input uri with an xmldb:exist:// prefix (if it had no scheme before)
* if uri has a scheme (is absolute) the original uri is wrapped, unaltered
*/
public static AnyURIValue dbBaseURIFromLocation(final URI uri) {
if (uri.getScheme() == null) {
try {
return new AnyURIValue(XmldbURI.EMBEDDED_SERVER_URI_PREFIX + uri);
} catch (XPathException e) {
LOG.warn("Could not create {} URI from {}", XmldbURI.XMLDB_URI_PREFIX, uri);
throw new RuntimeException(e);
}
}
// already absolute
return new AnyURIValue(uri);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,9 @@
*/
package org.exist.xquery.functions.fn;

import java.net.URI;
import java.net.URISyntaxException;

import org.exist.dom.QName;
import org.exist.xquery.Cardinality;
import org.exist.xquery.Dependency;
import org.exist.xquery.ErrorCodes;
import org.exist.xquery.Function;
import org.exist.xquery.FunctionSignature;
import org.exist.xquery.Profiler;
import org.exist.xquery.XPathException;
import org.exist.xquery.XQueryContext;
import org.exist.xquery.value.AnyURIValue;
import org.exist.xquery.value.FunctionParameterSequenceType;
import org.exist.xquery.value.FunctionReturnSequenceType;
import org.exist.xquery.value.Item;
import org.exist.xquery.value.Sequence;
import org.exist.xquery.value.SequenceType;
import org.exist.xquery.value.Type;
import org.exist.xquery.*;
import org.exist.xquery.value.*;

/**
* Implements the fn:resolve-uri() function.
Expand Down Expand Up @@ -131,20 +115,12 @@ public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathExc
relative = (AnyURIValue)item;
} catch (final XPathException e) {
throw new XPathException(this, ErrorCodes.FORG0002, "invalid argument to fn:resolve-uri(): " + e.getMessage(), seq, e);
}
URI relativeURI;
URI baseURI;
}
try {
relativeURI = new URI(relative.getStringValue());
baseURI = new URI(base.getStringValue() );
} catch (final URISyntaxException e) {
return base.resolve(relative);
} catch (XPathException e) {
throw new XPathException(this, ErrorCodes.FORG0009, "unable to resolve a relative URI against a base URI in fn:resolve-uri(): " + e.getMessage(), null, e);
}
if (relativeURI.isAbsolute()) {
result = relative;
} else {
result = new AnyURIValue(this, baseURI.resolve(relativeURI));
}
}

if (context.getProfiler().isEnabled())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.net.URISyntaxException;
import java.net.URL;
import java.util.BitSet;
import java.util.regex.Pattern;

/**
* @author <a href="mailto:wolfgang@exist-db.org">Wolfgang Meier</a>
Expand Down Expand Up @@ -434,6 +435,56 @@ public URI toURI() throws XPathException {
}
}

final Pattern nonstandardScheme = Pattern.compile("(\\w+:)(\\w+:)?");

/**
* Resolution of AnyURI which resolves non-standard XmldbURI-style URIs
* as well as the URIs the rest of the world understands.
*
* @param relativeURI to resolve using this as the base
* @return a resolved AnyURI by the rules of resolution in
* {@link <a href="https://datatracker.ietf.org/doc/html/rfc3986">...</a>}
*
* @throws XPathException if the URIs are not valid or resolvable
*/
public AnyURIValue resolve(AnyURIValue relativeURI) throws XPathException {
try {
var base = escape(uri);
var relative = new URI(escape(relativeURI.uri));
if (relative.isAbsolute()) {
return relativeURI;
}
var matcher = nonstandardScheme.matcher(base);
if (matcher.find(0) && matcher.groupCount() > 1 && matcher.group(2) != null) {
// rewrite non-standard URIs for resolution:
// "xmldb:exist:<path>" --> "xmldb:<path>"
// "https:<path>" is unchanged
var compliantBase = matcher.group(1) + base.substring(matcher.end(0));
var resolved = escape(new URI(compliantBase).resolve(relative).toString());
var resolvedMatcher = nonstandardScheme.matcher(resolved);
if (!resolvedMatcher.find(0)) {
throw new XPathException(getExpression(), ErrorCodes.FORG0009,
"Failed to resolve " + relativeURI + " against " + this +
", resolved string " + resolved + " did not have the expected pattern " +
nonstandardScheme);
}
if (matcher.group().startsWith(resolvedMatcher.group())) {
// reverse the rewrite
// "xmldb:<path>" --> "xmldb:exist:<path>"
resolved = matcher.group() + resolved.substring(resolvedMatcher.end(0));
}
return new AnyURIValue(resolved);
}

return new AnyURIValue(escape(new URI(base).resolve(relative).toString()));

} catch (URISyntaxException e) {
throw new XPathException(getExpression(),
ErrorCodes.FORG0009,
"Failed to resolve " + relativeURI + " against " + this, e);
}
}

@Override
public int hashCode() {
return uri.hashCode();
Expand Down
Loading