Search in sources :

Example 1 with Either

use of com.evolvedbinary.j8fu.Either in project exist by eXist-db.

the class Parse method eval.

@Override
public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException {
    if (args[0].getItemCount() == 0) {
        return Sequence.EMPTY_SEQUENCE;
    }
    final String xmlContent = args[0].itemAt(0).getStringValue();
    if (xmlContent.isEmpty()) {
        return Sequence.EMPTY_SEQUENCE;
    }
    final StringReader reader = new StringReader(xmlContent);
    final ValidationReport report = new ValidationReport();
    final SAXAdapter adapter = new SAXAdapter(context);
    XMLReader xr = null;
    try {
        final InputSource src = new InputSource(reader);
        final Optional<Either<Throwable, XMLReader>> maybeReaderInst = HtmlToXmlParser.getHtmlToXmlParser(context.getBroker().getConfiguration());
        if (maybeReaderInst.isPresent()) {
            final Either<Throwable, XMLReader> readerInst = maybeReaderInst.get();
            if (readerInst.isLeft()) {
                final String msg = "Unable to parse HTML to XML please ensure the parser is configured in conf.xml and is present on the classpath";
                final Throwable t = readerInst.left().get();
                LOG.error(msg, t);
                throw new XPathException(this, ErrorCodes.EXXQDY0002, t);
            } else {
                xr = readerInst.right().get();
            }
        } else {
            throw new XPathException(this, ErrorCodes.EXXQDY0002, "There is no HTML to XML parser configured in conf.xml");
        }
        xr.setErrorHandler(report);
        xr.setContentHandler(adapter);
        xr.setProperty(Namespaces.SAX_LEXICAL_HANDLER, adapter);
        xr.parse(src);
    } catch (final SAXException e) {
        logger.debug("Error while parsing XML: {}", e.getMessage(), e);
    } catch (final IOException e) {
        throw new XPathException(this, ErrorCodes.EXXQDY0002, "Error while parsing XML: " + e.getMessage(), args[0], e);
    } finally {
        if (!isCalledAs("parse-html") && xr != null) {
            context.getBroker().getBrokerPool().getParserPool().returnXMLReader(xr);
        }
    }
    if (report.isValid()) {
        return adapter.getDocument();
    } else {
        context.pushDocumentContext();
        try {
            final MemTreeBuilder builder = context.getDocumentBuilder();
            final NodeImpl result = Shared.writeReport(report, builder);
            throw new XPathException(this, ErrorCodes.EXXQDY0002, report.toString(), result);
        } finally {
            context.popDocumentContext();
        }
    }
}
Also used : InputSource(org.xml.sax.InputSource) NodeImpl(org.exist.dom.memtree.NodeImpl) IOException(java.io.IOException) SAXException(org.xml.sax.SAXException) MemTreeBuilder(org.exist.dom.memtree.MemTreeBuilder) ValidationReport(org.exist.validation.ValidationReport) StringReader(java.io.StringReader) SAXAdapter(org.exist.dom.memtree.SAXAdapter) Either(com.evolvedbinary.j8fu.Either) XMLReader(org.xml.sax.XMLReader)

Example 2 with Either

use of com.evolvedbinary.j8fu.Either in project exist by eXist-db.

the class Deployment method deploy.

public Optional<String> deploy(final DBBroker broker, final Txn transaction, final String pkgName, final Optional<ExistRepository> repo, final String userTarget) throws PackageException, IOException {
    final Optional<Path> maybePackageDir = getPackageDir(pkgName, repo);
    if (!maybePackageDir.isPresent()) {
        throw new PackageException("Package not found: " + pkgName);
    }
    final Path packageDir = maybePackageDir.get();
    final DocumentImpl repoXML = getRepoXML(broker, packageDir);
    if (repoXML == null) {
        return Optional.empty();
    }
    try {
        // if there's a <setup> element, run the query it points to
        final Optional<ElementImpl> setup = findElement(repoXML, SETUP_ELEMENT);
        final Optional<String> setupPath = setup.map(ElementImpl::getStringValue).filter(s -> !s.isEmpty());
        if (setupPath.isPresent()) {
            runQuery(broker, null, packageDir, setupPath.get(), pkgName, QueryPurpose.SETUP);
            return Optional.empty();
        } else {
            // otherwise create the target collection
            XmldbURI targetCollection = null;
            if (userTarget != null) {
                try {
                    targetCollection = XmldbURI.create(userTarget);
                } catch (final IllegalArgumentException e) {
                    throw new PackageException("Bad collection URI: " + userTarget, e);
                }
            } else {
                final Optional<ElementImpl> target = findElement(repoXML, TARGET_COLL_ELEMENT);
                final Optional<String> targetPath = target.map(ElementImpl::getStringValue).filter(s -> !s.isEmpty());
                if (targetPath.isPresent()) {
                    // determine target collection
                    try {
                        targetCollection = XmldbURI.create(getTargetCollection(broker, targetPath.get()));
                    } catch (final IllegalArgumentException e) {
                        throw new PackageException("Bad collection URI for <target> element: " + targetPath.get(), e);
                    }
                } else {
                    LOG.warn("EXPath Package '{}' does not contain a <target> in its repo.xml, no files will be deployed to /apps", pkgName);
                }
            }
            if (targetCollection == null) {
                // no target means: package does not need to be deployed into database
                // however, we need to preserve a copy for backup purposes
                final Optional<Package> pkg = getPackage(pkgName, repo);
                pkg.orElseThrow(() -> new XPathException("expath repository is not available so the package was not stored."));
                final String pkgColl = pkg.get().getAbbrev() + "-" + pkg.get().getVersion();
                targetCollection = XmldbURI.SYSTEM.append("repo/" + pkgColl);
            }
            // extract the permissions (if any)
            final Optional<ElementImpl> permissions = findElement(repoXML, PERMISSIONS_ELEMENT);
            final Optional<RequestedPerms> requestedPerms = permissions.flatMap(elem -> {
                final Optional<Either<Integer, String>> perms = Optional.ofNullable(elem.getAttribute("mode")).flatMap(mode -> {
                    try {
                        return Optional.of(Either.Left(Integer.parseInt(mode, 8)));
                    } catch (final NumberFormatException e) {
                        if (mode.matches("^[rwx-]{9}")) {
                            return Optional.of(Either.Right(mode));
                        } else {
                            return Optional.empty();
                        }
                    }
                });
                return perms.map(p -> new RequestedPerms(elem.getAttribute("user"), elem.getAttribute("password"), Optional.ofNullable(elem.getAttribute("group")), p));
            });
            // check that if there were permissions then we were able to parse them, a failure would be related to the mode string
            if (permissions.isPresent() && !requestedPerms.isPresent()) {
                final String mode = permissions.map(elem -> elem.getAttribute("mode")).orElse(null);
                throw new PackageException("Bad format for mode attribute in <permissions>: " + mode);
            }
            // run the pre-setup query if present
            final Optional<ElementImpl> preSetup = findElement(repoXML, PRE_SETUP_ELEMENT);
            final Optional<String> preSetupPath = preSetup.map(ElementImpl::getStringValue).filter(s -> !s.isEmpty());
            if (preSetupPath.isPresent()) {
                runQuery(broker, targetCollection, packageDir, preSetupPath.get(), pkgName, QueryPurpose.PREINSTALL);
            }
            // TODO: if the user already exists, check and ensure the user is assigned to the specified group
            if (requestedPerms.isPresent()) {
                checkUserSettings(broker, requestedPerms.get());
            }
            final InMemoryNodeSet resources = findElements(repoXML, RESOURCES_ELEMENT);
            // store all package contents into database, using the user/group/mode in the permissions element. however:
            // 1. repo.xml is excluded for now, since it may contain the default user's password in the clear
            // 2. contents of directories identified in the path attribute of any <resource path=""/> element are stored as binary
            final List<String> errors = scanDirectory(broker, transaction, packageDir, targetCollection, resources, true, false, requestedPerms);
            // store repo.xml, filtering out the default user's password
            storeRepoXML(broker, transaction, repoXML, targetCollection, requestedPerms);
            // run the post-setup query if present
            final Optional<ElementImpl> postSetup = findElement(repoXML, POST_SETUP_ELEMENT);
            final Optional<String> postSetupPath = postSetup.map(ElementImpl::getStringValue).filter(s -> !s.isEmpty());
            if (postSetupPath.isPresent()) {
                runQuery(broker, targetCollection, packageDir, postSetupPath.get(), pkgName, QueryPurpose.POSTINSTALL);
            }
            if (!errors.isEmpty()) {
                throw new PackageException("Deployment incomplete, " + errors.size() + " issues found: " + String.join("; ", errors));
            }
            return Optional.ofNullable(targetCollection.getCollectionPath());
        }
    } catch (final XPathException e) {
        throw new PackageException("Error found while processing repo.xml: " + e.getMessage(), e);
    }
}
Also used : Path(java.nio.file.Path) DependencyVersion(org.expath.pkg.repo.deps.DependencyVersion) Txn(org.exist.storage.txn.Txn) java.util(java.util) BufferedInputStream(java.io.BufferedInputStream) QName(org.exist.dom.QName) SequenceIterator(org.exist.xquery.value.SequenceIterator) PermissionDeniedException(org.exist.security.PermissionDeniedException) org.exist.xquery(org.exist.xquery) DirectoryStream(java.nio.file.DirectoryStream) JarEntry(java.util.jar.JarEntry) org.exist.dom.memtree(org.exist.dom.memtree) Collection(org.exist.collections.Collection) UnixStylePermission(org.exist.security.UnixStylePermission) XmldbURI(org.exist.xmldb.XmldbURI) Attributes(org.xml.sax.Attributes) JarInputStream(java.util.jar.JarInputStream) EXistException(org.exist.EXistException) DocUtils(org.exist.xquery.util.DocUtils) DateTimeValue(org.exist.xquery.value.DateTimeValue) SystemProperties(org.exist.SystemProperties) Path(java.nio.file.Path) Permission(org.exist.security.Permission) Nullable(javax.annotation.Nullable) BatchUserInteraction(org.expath.pkg.repo.tui.BatchUserInteraction) PermissionFactory(org.exist.security.PermissionFactory) InputSource(org.xml.sax.InputSource) Files(java.nio.file.Files) GroupAider(org.exist.security.internal.aider.GroupAider) Type(org.exist.xquery.value.Type) FileSource(org.exist.source.FileSource) IOException(java.io.IOException) UserAider(org.exist.security.internal.aider.UserAider) Either(com.evolvedbinary.j8fu.Either) org.expath.pkg.repo(org.expath.pkg.repo) Logger(org.apache.logging.log4j.Logger) Element(org.w3c.dom.Element) Stream(java.util.stream.Stream) DBBroker(org.exist.storage.DBBroker) SAXException(org.xml.sax.SAXException) org.exist.util(org.exist.util) Sequence(org.exist.xquery.value.Sequence) TriggerException(org.exist.collections.triggers.TriggerException) LogManager(org.apache.logging.log4j.LogManager) Package(org.expath.pkg.repo.Package) AttrList(org.exist.util.serializer.AttrList) InputStream(java.io.InputStream) Either(com.evolvedbinary.j8fu.Either) Package(org.expath.pkg.repo.Package) XmldbURI(org.exist.xmldb.XmldbURI)

Example 3 with Either

use of com.evolvedbinary.j8fu.Either in project exist by eXist-db.

the class PermissionFactory method chmod_impl.

private static void chmod_impl(final DBBroker broker, final Permission permission, final Optional<Either<String, Integer>> mode, final Optional<List<ACEAider>> acl) throws PermissionDeniedException {
    if ((!mode.isPresent()) && !acl.isPresent()) {
        throw new IllegalArgumentException("Either mode or acl must be provided");
    }
    try {
        final boolean changeMode;
        if (mode.isPresent()) {
            if (mode.get().isLeft()) {
                final Subject effectiveUser = broker.getCurrentSubject();
                final Permission other = new UnixStylePermission(broker.getBrokerPool().getSecurityManager(), effectiveUser.getId(), effectiveUser.getDefaultGroup().getId(), 0);
                other.setMode(mode.get().left().get());
                changeMode = permission.getMode() != other.getMode();
            } else {
                changeMode = permission.getMode() != mode.get().right().get();
            }
        } else {
            changeMode = false;
        }
        final boolean changeAcl = acl.map(desiredAces -> !aclEquals(permission, desiredAces)).orElse(false);
        /*
                To change the permission bits of a file, the effective user ID of the process must be equal to the owner ID
                of the file, or the process must have superuser permissions.
            */
        if ((changeMode || changeAcl) && (!permission.isCurrentSubjectDBA()) && !permission.isCurrentSubjectOwner()) {
            throw new PermissionDeniedException("Only a DBA or the resources owner can change the mode of a resource.");
        }
        // change the mode
        if (changeMode) {
            final boolean matchedGroup = permission.isCurrentSubjectInGroup();
            if (permission.isCurrentSubjectDBA() || matchedGroup) {
                if (mode.get().isLeft()) {
                    permission.setMode(mode.get().left().get());
                } else {
                    permission.setMode(mode.get().right().get());
                }
            } else {
                /*
                    If the group ID of the file does not equal either the effective group ID of the process or one of
                    the process’s supplementary group IDs and if the process does not have superuser privileges,
                    then the set-group-ID bit is automatically turned off.
                    This prevents a user from creating a set-group-ID file owned by a group that the user doesn’t
                    belong to.
                */
                if (mode.get().isLeft()) {
                    permission.setMode(removeSetGid(mode.get().left().get()));
                } else {
                    permission.setMode(removeSetGid(mode.get().right().get()));
                }
            }
        }
        // change the acl
        if (changeAcl) {
            final ACLPermission aclPermission = (ACLPermission) permission;
            aclPermission.clear();
            for (final ACEAider ace : acl.get()) {
                aclPermission.addACE(ace.getAccessType(), ace.getTarget(), ace.getWho(), ace.getMode());
            }
        }
    } catch (final SyntaxException se) {
        throw new PermissionDeniedException("Unrecognised mode syntax: " + se.getMessage(), se);
    }
}
Also used : ACEAider(org.exist.security.internal.aider.ACEAider) LockMode(org.exist.storage.lock.Lock.LockMode) Txn(org.exist.storage.txn.Txn) LockedDocument(org.exist.dom.persistent.LockedDocument) BrokerPool(org.exist.storage.BrokerPool) IOException(java.io.IOException) SIMPLE_SYMBOLIC_MODE_PATTERN(org.exist.security.AbstractUnixStylePermission.SIMPLE_SYMBOLIC_MODE_PATTERN) UNIX_SYMBOLIC_MODE_PATTERN(org.exist.security.AbstractUnixStylePermission.UNIX_SYMBOLIC_MODE_PATTERN) Either(com.evolvedbinary.j8fu.Either) List(java.util.List) Matcher(java.util.regex.Matcher) Logger(org.apache.logging.log4j.Logger) POSIX_CHOWN_RESTRICTED_PROPERTY(org.exist.storage.DBBroker.POSIX_CHOWN_RESTRICTED_PROPERTY) DBBroker(org.exist.storage.DBBroker) Collection(org.exist.collections.Collection) SyntaxException(org.exist.util.SyntaxException) XmldbURI(org.exist.xmldb.XmldbURI) Optional(java.util.Optional) DocumentImpl(org.exist.dom.persistent.DocumentImpl) Pattern(java.util.regex.Pattern) ConsumerE(com.evolvedbinary.j8fu.function.ConsumerE) LogManager(org.apache.logging.log4j.LogManager) XPathException(org.exist.xquery.XPathException) Permission(org.exist.security.Permission) SyntaxException(org.exist.util.SyntaxException) ACEAider(org.exist.security.internal.aider.ACEAider) Permission(org.exist.security.Permission)

Example 4 with Either

use of com.evolvedbinary.j8fu.Either in project exist by eXist-db.

the class LocalCollection method getHtmlReader.

/**
 * Get's the HTML Reader
 *
 * @return the HTML reader configured in conf.xml
 *
 * @throws XMLDBException if the HTML reader cannot be retrieved.
 */
private XMLReader getHtmlReader() throws XMLDBException {
    final Optional<Either<Throwable, XMLReader>> maybeReaderInst = HtmlToXmlParser.getHtmlToXmlParser(brokerPool.getConfiguration());
    if (maybeReaderInst.isPresent()) {
        final Either<Throwable, XMLReader> readerInst = maybeReaderInst.get();
        if (readerInst.isLeft()) {
            final String msg = "Unable to parse HTML to XML please ensure the parser is configured in conf.xml and is present on the classpath";
            final Throwable t = readerInst.left().get();
            LOG.error(msg, t);
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, msg, t);
        } else {
            final XMLReader htmlReader = readerInst.right().get();
            if (LOG.isDebugEnabled()) {
                LOG.debug("Converting HTML to XML using: {}", htmlReader.getClass().getName());
            }
            return htmlReader;
        }
    } else {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "There is no HTML to XML parser configured in conf.xml");
    }
}
Also used : Either(com.evolvedbinary.j8fu.Either) XMLDBException(org.xmldb.api.base.XMLDBException) XMLReader(org.xml.sax.XMLReader)

Example 5 with Either

use of com.evolvedbinary.j8fu.Either in project exist by eXist-db.

the class ModuleUtils method htmlToXHtml.

/**
 * Takes a HTML InputSource and creates an XML representation of the HTML by
 * tidying it
 *
 * @param context
 *            The Context of the calling XQuery
 * @param srcHtml
 *            The InputSource for the HTML
 * @param parserFeatures
 *            The features to set on the Parser
 * @param parserProperties
 *            The properties to set on the Parser
 *
 * @throws SAXException in case of a SAX error
 * @throws IOException in case of error reading input source
 * @return An in-memory Document representing the XML'ised HTML
 */
public static DocumentImpl htmlToXHtml(final XQueryContext context, final InputSource srcHtml, final Map<String, Boolean> parserFeatures, final Map<String, String> parserProperties) throws IOException, SAXException {
    // use the configures HTML parser to parse the HTML content to XML
    final Optional<Either<Throwable, XMLReader>> maybeReaderInst = HtmlToXmlParser.getHtmlToXmlParser(context.getBroker().getConfiguration());
    if (maybeReaderInst.isPresent()) {
        final Either<Throwable, XMLReader> readerInst = maybeReaderInst.get();
        if (readerInst.isLeft()) {
            final String msg = "Unable to parse HTML to XML please ensure the parser is configured in conf.xml and is present on the classpath";
            final Throwable t = readerInst.left().get();
            LOG.error(msg, t);
            throw new IOException(msg, t);
        } else {
            final XMLReader reader = readerInst.right().get();
            if (parserFeatures != null) {
                for (final Map.Entry<String, Boolean> parserFeature : parserFeatures.entrySet()) {
                    reader.setFeature(parserFeature.getKey(), parserFeature.getValue());
                }
            }
            if (parserProperties != null) {
                for (final Map.Entry<String, String> parserProperty : parserProperties.entrySet()) {
                    reader.setProperty(parserProperty.getKey(), parserProperty.getValue());
                }
            }
            if (LOG.isDebugEnabled()) {
                LOG.debug("Converting HTML to XML using: {}", reader.getClass().getName());
            }
            final SAXAdapter adapter = new SAXAdapter();
            // allow multiple attributes of the same name attached to the same element
            // to enhance resilience against bad HTML. The last attribute value wins.
            adapter.setReplaceAttributeFlag(true);
            reader.setContentHandler(adapter);
            reader.setProperty(Namespaces.SAX_LEXICAL_HANDLER, adapter);
            reader.parse(srcHtml);
            final Document doc = adapter.getDocument();
            // we use eXist's in-memory DOM implementation
            final DocumentImpl memtreeDoc = (DocumentImpl) doc;
            memtreeDoc.setContext(context);
            return memtreeDoc;
        }
    } else {
        throw new SAXException("There is no HTML to XML parser configured in conf.xml");
    }
}
Also used : IOException(java.io.IOException) Document(org.w3c.dom.Document) DocumentImpl(org.exist.dom.memtree.DocumentImpl) Either(com.evolvedbinary.j8fu.Either) SAXAdapter(org.exist.dom.memtree.SAXAdapter)

Aggregations

Either (com.evolvedbinary.j8fu.Either)5 IOException (java.io.IOException)4 LogManager (org.apache.logging.log4j.LogManager)2 Logger (org.apache.logging.log4j.Logger)2 Collection (org.exist.collections.Collection)2 SAXAdapter (org.exist.dom.memtree.SAXAdapter)2 Permission (org.exist.security.Permission)2 DBBroker (org.exist.storage.DBBroker)2 Txn (org.exist.storage.txn.Txn)2 XmldbURI (org.exist.xmldb.XmldbURI)2 InputSource (org.xml.sax.InputSource)2 SAXException (org.xml.sax.SAXException)2 ConsumerE (com.evolvedbinary.j8fu.function.ConsumerE)1 BufferedInputStream (java.io.BufferedInputStream)1 InputStream (java.io.InputStream)1 StringReader (java.io.StringReader)1 DirectoryStream (java.nio.file.DirectoryStream)1 Files (java.nio.file.Files)1 Path (java.nio.file.Path)1 java.util (java.util)1