use of org.exist.security.PermissionDeniedException in project exist by eXist-db.
the class XQueryTrigger method prepare.
private void prepare(int event, DBBroker broker, Txn transaction, XmldbURI src, XmldbURI dst, boolean isCollection) throws TriggerException {
// get the query
final Source query = getQuerySource(broker);
if (query == null) {
return;
}
// avoid infinite recursion by allowing just one trigger per thread
if (!TriggerStatePerThread.verifyUniqueTriggerPerThreadBeforePrepare(this, src)) {
return;
}
TriggerStatePerThread.setTransaction(transaction);
final XQueryContext context = new XQueryContext(broker.getBrokerPool());
// TODO : further initialisations ?
CompiledXQuery compiledQuery;
try {
// compile the XQuery
compiledQuery = service.compile(context, query);
// declare external variables
context.declareVariable(bindingPrefix + "type", EVENT_TYPE_PREPARE);
context.declareVariable(bindingPrefix + "event", new StringValue(eventToString(event)));
if (isCollection) {
context.declareVariable(bindingPrefix + "collection", new AnyURIValue(src));
} else {
context.declareVariable(bindingPrefix + "collection", new AnyURIValue(src.removeLastSegment()));
}
context.declareVariable(bindingPrefix + "uri", new AnyURIValue(src));
if (dst == null) {
context.declareVariable(bindingPrefix + "new-uri", Sequence.EMPTY_SEQUENCE);
} else {
context.declareVariable(bindingPrefix + "new-uri", new AnyURIValue(dst));
}
// For backward compatibility
context.declareVariable(bindingPrefix + "eventType", EVENT_TYPE_PREPARE);
context.declareVariable(bindingPrefix + "triggerEvent", new StringValue(eventToString(event)));
if (isCollection) {
context.declareVariable(bindingPrefix + "collectionName", new AnyURIValue(src));
} else {
context.declareVariable(bindingPrefix + "collectionName", new AnyURIValue(src.removeLastSegment()));
context.declareVariable(bindingPrefix + "documentName", new AnyURIValue(src));
}
// declare user defined parameters as external variables
for (Object o : userDefinedVariables.keySet()) {
final String varName = (String) o;
final String varValue = userDefinedVariables.getProperty(varName);
context.declareVariable(bindingPrefix + varName, new StringValue(varValue));
}
} catch (final XPathException | IOException | PermissionDeniedException e) {
TriggerStatePerThread.setTriggerRunningState(TriggerStatePerThread.NO_TRIGGER_RUNNING, this, null);
TriggerStatePerThread.setTransaction(null);
throw new TriggerException(PREPARE_EXCEPTION_MESSAGE, e);
}
// execute the XQuery
try {
// TODO : should we provide another contextSet ?
final NodeSet contextSet = NodeSet.EMPTY_SET;
service.execute(broker, compiledQuery, contextSet);
// TODO : should we have a special processing ?
LOG.debug("Trigger fired for prepare");
} catch (final XPathException | PermissionDeniedException e) {
TriggerStatePerThread.setTriggerRunningState(TriggerStatePerThread.NO_TRIGGER_RUNNING, this, null);
TriggerStatePerThread.setTransaction(null);
throw new TriggerException(PREPARE_EXCEPTION_MESSAGE, e);
}
}
use of org.exist.security.PermissionDeniedException in project exist by eXist-db.
the class RESTServer method doPost.
/**
* Handles POST requests. If the path leads to a binary resource with
* mime-type "application/xquery", that resource will be read and executed
* by the XQuery engine. Otherwise, the request content is loaded and parsed
* as XML. It may either contain an XUpdate or a query request.
*
* @param broker the database broker
* @param transaction the database transaction
* @param request the request
* @param response the response
* @param path the path of the request
*
* @throws BadRequestException if a bad request is made
* @throws PermissionDeniedException if the request has insufficient permissions
* @throws NotFoundException if the request resource cannot be found
* @throws IOException if an I/O error occurs
*/
public void doPost(final DBBroker broker, final Txn transaction, final HttpServletRequest request, final HttpServletResponse response, final String path) throws BadRequestException, PermissionDeniedException, IOException, NotFoundException {
// if required, set character encoding
if (request.getCharacterEncoding() == null) {
request.setCharacterEncoding(formEncoding);
}
final Properties outputProperties = new Properties(defaultOutputKeysProperties);
final XmldbURI pathUri = XmldbURI.createInternal(path);
LockedDocument lockedDocument = null;
DocumentImpl resource = null;
final String encoding = outputProperties.getProperty(OutputKeys.ENCODING);
String mimeType = outputProperties.getProperty(OutputKeys.MEDIA_TYPE);
try {
// check if path leads to an XQuery resource.
// if yes, the resource is loaded and the XQuery executed.
final String xquery_mime_type = MimeType.XQUERY_TYPE.getName();
final String xproc_mime_type = MimeType.XPROC_TYPE.getName();
lockedDocument = broker.getXMLResource(pathUri, LockMode.READ_LOCK);
resource = lockedDocument == null ? null : lockedDocument.getDocument();
XmldbURI servletPath = pathUri;
// xquery resource
while (null == resource) {
// traverse up the path looking for xquery objects
servletPath = servletPath.removeLastSegment();
if (servletPath == XmldbURI.EMPTY_URI) {
break;
}
lockedDocument = broker.getXMLResource(servletPath, LockMode.READ_LOCK);
resource = lockedDocument == null ? null : lockedDocument.getDocument();
if (null != resource && (resource.getResourceType() == DocumentImpl.BINARY_FILE && xquery_mime_type.equals(resource.getMimeType()) || resource.getResourceType() == DocumentImpl.XML_FILE && xproc_mime_type.equals(resource.getMimeType()))) {
// found a binary file with mime-type xquery or XML file with mime-type xproc
break;
} else if (null != resource) {
// not an xquery or xproc resource. This means we have a path
// that cannot contain an xquery or xproc object even if we keep
// moving up the path, so bail out now
lockedDocument.close();
lockedDocument = null;
resource = null;
break;
}
}
// either xquery binary file or xproc xml file
if (resource != null) {
if (resource.getResourceType() == DocumentImpl.BINARY_FILE && xquery_mime_type.equals(resource.getMimeType()) || resource.getResourceType() == DocumentImpl.XML_FILE && xproc_mime_type.equals(resource.getMimeType())) {
// found an XQuery resource, fixup request values
final String pathInfo = pathUri.trimFromBeginning(servletPath).toString();
try {
if (xquery_mime_type.equals(resource.getMimeType())) {
// Execute the XQuery
executeXQuery(broker, transaction, resource, request, response, outputProperties, servletPath.toString(), pathInfo);
} else {
// Execute the XProc
executeXProc(broker, transaction, resource, request, response, outputProperties, servletPath.toString(), pathInfo);
}
} catch (final XPathException e) {
if (MimeType.XML_TYPE.getName().equals(mimeType)) {
writeXPathException(response, HttpServletResponse.SC_BAD_REQUEST, encoding, null, path, e);
} else {
writeXPathExceptionHtml(response, HttpServletResponse.SC_BAD_REQUEST, encoding, null, path, e);
}
}
return;
}
}
} finally {
if (lockedDocument != null) {
lockedDocument.close();
}
}
// check the content type to see if its XML or a parameter string
String requestType = request.getContentType();
if (requestType != null) {
final int semicolon = requestType.indexOf(';');
if (semicolon > 0) {
requestType = requestType.substring(0, semicolon).trim();
}
}
// content type != application/x-www-form-urlencoded
if (requestType == null || !requestType.equals(MimeType.URL_ENCODED_TYPE.getName())) {
// third, normal POST: read the request content and check if
// it is an XUpdate or a query request.
int howmany = 10;
int start = 1;
boolean typed = false;
ElementImpl variables = null;
boolean enclose = true;
boolean cache = false;
String query = null;
try {
final String content = getRequestContent(request);
final NamespaceExtractor nsExtractor = new NamespaceExtractor();
final ElementImpl root = parseXML(broker.getBrokerPool(), content, nsExtractor);
final String rootNS = root.getNamespaceURI();
if (rootNS != null && rootNS.equals(Namespaces.EXIST_NS)) {
if (Query.xmlKey().equals(root.getLocalName())) {
// process <query>xpathQuery</query>
String option = root.getAttribute(Start.xmlKey());
if (option != null) {
try {
start = Integer.parseInt(option);
} catch (final NumberFormatException e) {
//
}
}
option = root.getAttribute(Max.xmlKey());
if (option != null) {
try {
howmany = Integer.parseInt(option);
} catch (final NumberFormatException e) {
//
}
}
option = root.getAttribute(Enclose.xmlKey());
if (option != null) {
if ("no".equals(option)) {
enclose = false;
}
} else {
option = root.getAttribute(Wrap.xmlKey());
if (option != null) {
if ("no".equals(option)) {
enclose = false;
}
}
}
option = root.getAttribute(Method.xmlKey());
if ((option != null) && (!option.isEmpty())) {
outputProperties.setProperty(SERIALIZATION_METHOD_PROPERTY, option);
}
option = root.getAttribute(Typed.xmlKey());
if (option != null) {
if ("yes".equals(option)) {
typed = true;
}
}
option = root.getAttribute(Mime.xmlKey());
if ((option != null) && (!option.isEmpty())) {
mimeType = option;
}
if ((option = root.getAttribute(Cache.xmlKey())) != null) {
cache = "yes".equals(option);
}
if ((option = root.getAttribute(Session.xmlKey())) != null && option.length() > 0) {
outputProperties.setProperty(Serializer.PROPERTY_SESSION_ID, option);
}
final NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
final Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE && child.getNamespaceURI().equals(Namespaces.EXIST_NS)) {
if (Text.xmlKey().equals(child.getLocalName())) {
final StringBuilder buf = new StringBuilder();
Node next = child.getFirstChild();
while (next != null) {
if (next.getNodeType() == Node.TEXT_NODE || next.getNodeType() == Node.CDATA_SECTION_NODE) {
buf.append(next.getNodeValue());
}
next = next.getNextSibling();
}
query = buf.toString();
} else if (Variables.xmlKey().equals(child.getLocalName())) {
variables = (ElementImpl) child;
} else if (Properties.xmlKey().equals(child.getLocalName())) {
Node node = child.getFirstChild();
while (node != null) {
if (node.getNodeType() == Node.ELEMENT_NODE && node.getNamespaceURI().equals(Namespaces.EXIST_NS) && Property.xmlKey().equals(node.getLocalName())) {
final Element property = (Element) node;
final String key = property.getAttribute("name");
final String value = property.getAttribute("value");
LOG.debug("{} = {}", key, value);
if (key != null && value != null) {
outputProperties.setProperty(key, value);
}
}
node = node.getNextSibling();
}
}
}
}
}
// execute query
if (query != null) {
try {
search(broker, transaction, query, path, nsExtractor.getNamespaces(), variables, howmany, start, typed, outputProperties, enclose, cache, request, response);
} catch (final XPathException e) {
if (MimeType.XML_TYPE.getName().equals(mimeType)) {
writeXPathException(response, HttpServletResponse.SC_BAD_REQUEST, encoding, null, path, e);
} else {
writeXPathExceptionHtml(response, HttpServletResponse.SC_BAD_REQUEST, encoding, null, path, e);
}
}
} else {
throw new BadRequestException("No query specified");
}
} else if (rootNS != null && rootNS.equals(XUpdateProcessor.XUPDATE_NS)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Got xupdate request: {}", content);
}
if (xupdateSubmission == EXistServlet.FeatureEnabled.FALSE) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
return;
} else if (xupdateSubmission == EXistServlet.FeatureEnabled.AUTHENTICATED_USERS_ONLY) {
final Subject currentSubject = broker.getCurrentSubject();
if (!currentSubject.isAuthenticated() || currentSubject.getId() == RealmImpl.GUEST_GROUP_ID) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
return;
}
}
final MutableDocumentSet docs = new DefaultDocumentSet();
final boolean isCollection;
try (final Collection collection = broker.openCollection(pathUri, LockMode.READ_LOCK)) {
if (collection != null) {
isCollection = true;
collection.allDocs(broker, docs, true);
} else {
isCollection = false;
}
}
if (!isCollection) {
final DocumentImpl xupdateDoc = broker.getResource(pathUri, Permission.READ);
if (xupdateDoc != null) {
docs.add(xupdateDoc);
} else {
broker.getAllXMLResources(docs);
}
}
final XUpdateProcessor processor = new XUpdateProcessor(broker, docs);
long mods = 0;
try (final Reader reader = new StringReader(content)) {
final Modification[] modifications = processor.parse(new InputSource(reader));
for (Modification modification : modifications) {
mods += modification.process(transaction);
broker.flush();
}
}
// FD : Returns an XML doc
writeXUpdateResult(response, encoding, mods);
// END FD
} else {
throw new BadRequestException("Unknown XML root element: " + root.getNodeName());
}
} catch (final SAXException e) {
Exception cause = e;
if (e.getException() != null) {
cause = e.getException();
}
LOG.debug("SAX exception while parsing request: {}", cause.getMessage(), cause);
throw new BadRequestException("SAX exception while parsing request: " + cause.getMessage());
} catch (final ParserConfigurationException e) {
throw new BadRequestException("Parser exception while parsing request: " + e.getMessage());
} catch (final XPathException e) {
throw new BadRequestException("Query exception while parsing request: " + e.getMessage());
} catch (final IOException e) {
throw new BadRequestException("IO exception while parsing request: " + e.getMessage());
} catch (final EXistException e) {
throw new BadRequestException(e.getMessage());
} catch (final LockException e) {
throw new PermissionDeniedException(e.getMessage());
}
// content type = application/x-www-form-urlencoded
} else {
doGet(broker, transaction, request, response, path);
}
}
use of org.exist.security.PermissionDeniedException in project exist by eXist-db.
the class Launcher method checkInstalledApps.
private void checkInstalledApps() {
try {
final BrokerPool pool = BrokerPool.getInstance();
try (final DBBroker broker = pool.get(Optional.of(pool.getSecurityManager().getSystemSubject()))) {
final XQuery xquery = pool.getXQueryService();
final Sequence pkgs = xquery.execute(broker, "repo:list()", null);
for (final SequenceIterator i = pkgs.iterate(); i.hasNext(); ) {
final ExistRepository.Notification notification = new ExistRepository.Notification(ExistRepository.Action.INSTALL, i.nextItem().getStringValue());
final Optional<ExistRepository> expathRepo = pool.getExpathRepo();
if (expathRepo.isPresent()) {
update(expathRepo.get(), notification);
utilityPanel.update(expathRepo.get(), notification);
}
expathRepo.orElseThrow(() -> new EXistException("EXPath repository is not available."));
}
}
} catch (final EXistException | XPathException | PermissionDeniedException e) {
System.err.println("Failed to check installed packages: " + e.getMessage());
e.printStackTrace();
}
}
use of org.exist.security.PermissionDeniedException in project exist by eXist-db.
the class XQueryURLRewrite method getSource.
private SourceInfo getSource(final DBBroker broker, final String moduleLoadPath) throws ServletException {
final SourceInfo sourceInfo;
if (query.startsWith(XmldbURI.XMLDB_URI_PREFIX)) {
// Is the module source stored in the database?
try {
final XmldbURI locationUri = XmldbURI.xmldbUriFor(query);
try (final LockedDocument lockedSourceDoc = broker.getXMLResource(locationUri.toCollectionPathURI(), LockMode.READ_LOCK)) {
if (lockedSourceDoc == null) {
throw new ServletException("XQuery resource: " + query + " not found in database");
}
final DocumentImpl sourceDoc = lockedSourceDoc.getDocument();
if (sourceDoc.getResourceType() != DocumentImpl.BINARY_FILE || !"application/xquery".equals(sourceDoc.getMimeType())) {
throw new ServletException("XQuery resource: " + query + " is not an XQuery or " + "declares a wrong mime-type");
}
sourceInfo = new SourceInfo(new DBSource(broker, (BinaryDocument) sourceDoc, true), locationUri.toString());
} catch (final PermissionDeniedException e) {
throw new ServletException("permission denied to read module source from " + query);
}
} catch (final URISyntaxException e) {
throw new ServletException(e.getMessage(), e);
}
} else {
try {
sourceInfo = new SourceInfo(SourceFactory.getSource(broker, moduleLoadPath, query, true), moduleLoadPath);
} catch (final IOException e) {
throw new ServletException("IO error while reading XQuery source: " + query);
} catch (final PermissionDeniedException e) {
throw new ServletException("Permission denied while reading XQuery source: " + query);
}
}
return sourceInfo;
}
use of org.exist.security.PermissionDeniedException in project exist by eXist-db.
the class BinaryDoc method eval.
@Override
public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException {
final Sequence emptyParamReturnValue = (isCalledAs(FS_BINARY_DOC_NAME) || isCalledAs(FS_BINARY_DOC_CONTENT_DIGEST_NAME)) ? Sequence.EMPTY_SEQUENCE : BooleanValue.FALSE;
if (args[0].isEmpty()) {
return emptyParamReturnValue;
}
final String path = args[0].getStringValue();
try (final LockedDocument lockedDoc = context.getBroker().getXMLResource(XmldbURI.xmldbUriFor(path), LockMode.READ_LOCK)) {
if (lockedDoc == null) {
return emptyParamReturnValue;
}
final DocumentImpl doc = lockedDoc.getDocument();
if (doc.getResourceType() != DocumentImpl.BINARY_FILE) {
return emptyParamReturnValue;
} else if (isCalledAs(FS_BINARY_DOC_NAME)) {
try (final Txn transaction = context.getBroker().continueOrBeginTransaction()) {
final BinaryDocument bin = (BinaryDocument) doc;
final InputStream is = context.getBroker().getBinaryResource(transaction, bin);
final Base64BinaryDocument b64doc = Base64BinaryDocument.getInstance(context, is);
b64doc.setUrl(path);
transaction.commit();
return b64doc;
}
} else if (isCalledAs(FS_BINARY_DOC_CONTENT_DIGEST_NAME)) {
final String algorithm = args[1].getStringValue();
final DigestType digestType;
try {
digestType = DigestType.forCommonName(algorithm);
} catch (final IllegalArgumentException e) {
throw new XPathException(this, "Invalid algorithm: " + algorithm, e);
}
try (final Txn transaction = context.getBroker().getBrokerPool().getTransactionManager().beginTransaction()) {
final BinaryDocument bin = (BinaryDocument) doc;
final MessageDigest messageDigest = context.getBroker().getBinaryResourceContentDigest(transaction, bin, digestType);
final InputStream is = new UnsynchronizedByteArrayInputStream(messageDigest.getValue());
final Sequence result = BinaryValueFromInputStream.getInstance(context, new HexBinaryValueType(), is);
transaction.commit();
return result;
}
} else {
return BooleanValue.TRUE;
}
} catch (final URISyntaxException e) {
logger.error("Invalid resource URI", e);
throw new XPathException(this, "Invalid resource uri", e);
} catch (final PermissionDeniedException e) {
logger.error("{}: permission denied to read resource", path, e);
throw new XPathException(this, path + ": permission denied to read resource");
} catch (final IOException | TransactionException e) {
logger.error("{}: I/O error while reading resource", path, e);
throw new XPathException(this, path + ": I/O error while reading resource", e);
}
}
Aggregations