+ * Note that the maximum length of allowed data is limited to prevent Denial of Service + * Attacks. The allowed maximum length can be set through the max-length parameter in + * bytes (see {@link AbstractStringPrimitiveConverter#init(Mapping, SQLFeatureStore)}). + *
+ * + * @see The Base16, Base32, and + * Base64 Data Encodings + * @author Stephan Reichhelm + */ +public class BinaryBase64PrimitiveConverter extends AbstractStringPrimitiveConverter { + + private static final Logger LOG = getLogger(BinaryBase64PrimitiveConverter.class); + + protected final Base64.Decoder decoder; + + protected final Base64.Encoder encoder; + + protected BinaryBase64PrimitiveConverter(Base64.Encoder enc, Base64.Decoder dec) { + super(Types.BLOB); + this.decoder = dec; + this.encoder = enc; + } + + public BinaryBase64PrimitiveConverter() { + this(Base64.getEncoder(), Base64.getDecoder()); + } + + String formatInput(String value) throws SQLException { + return value; + } + + String formatOutput(String value) throws SQLException { + return value; + } + + @Override + public PrimitiveValue toParticle(ResultSet rs, int colIndex) throws SQLException { + try (InputStream is = rs.getBinaryStream(colIndex)) { + if (is == null) { + return null; + } + byte[] raw = IOUtils.toByteArray(is); + return new PrimitiveValue(formatOutput(encoder.encodeToString(raw)), pt); + } + catch (IOException ioe) { + LOG.trace("Exception", ioe); + throw new SQLException("Conversation from binary to Base64 failed: " + ioe.getMessage()); + } + } + + @Override + public void setParticle(PreparedStatement stmt, PrimitiveValue particle, int paramIndex) throws SQLException { + final String val; + if (particle.getValue() != null) { + val = particle.getValue().toString(); + } + else { + val = null; + } + if (val == null) { + try { + stmt.setNull(paramIndex, sqlType); + } + catch (SQLFeatureNotSupportedException ignored) { + stmt.setString(paramIndex, null); + } + } + else if (val.length() > (((float) maxLen / 3) * 4 * 1.1)) { + // NOTE encoded is 4/3 the size of the not encoded content, but 10 percent is + // added for linebreak etc. + throw new SQLException("Maximum length of " + maxLen + " bytes exceeded in pre check."); + } + else { + byte[] raw = decoder.decode(formatInput(val)); + if (raw.length > maxLen) { + throw new SQLException("Maximum length of " + maxLen + " bytes exceeded."); + } + + stmt.setBinaryStream(paramIndex, new ByteArrayInputStream(raw), raw.length); + } + } + +} diff --git a/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/converter/BinaryDataUrlPrimitiveConverter.java b/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/converter/BinaryDataUrlPrimitiveConverter.java new file mode 100644 index 0000000000..90c1b6c5de --- /dev/null +++ b/deegree-datastores/deegree-featurestores/deegree-featurestore-sql/src/main/java/org/deegree/feature/persistence/sql/converter/BinaryDataUrlPrimitiveConverter.java @@ -0,0 +1,147 @@ +/*---------------------------------------------------------------------------- + This file is part of deegree, http://deegree.org/ + Copyright (C) 2001-2024 by: + - Department of Geography, University of Bonn - + and + - lat/lon GmbH - + and + - grit graphische Informationstechnik Beratungsgesellschaft mbH - + + 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., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Contact information: + + grit graphische Informationstechnik Beratungsgesellschaft mbH + Landwehrstr. 143, 59368 Werne + Germany + https://www.grit.de/ + + lat/lon GmbH + Aennchenstr. 19, 53177 Bonn + Germany + http://lat-lon.de/ + + Department of Geography, University of Bonn + Prof. Dr. Klaus Greve + Postfach 1147, 53001 Bonn + Germany + http://www.geographie.uni-bonn.de/deegree/ + + e-mail: info@deegree.org + ----------------------------------------------------------------------------*/ +package org.deegree.feature.persistence.sql.converter; + +import static org.slf4j.LoggerFactory.getLogger; + +import java.sql.SQLException; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; +import org.apache.commons.codec.binary.Hex; +import org.deegree.commons.utils.StringUtils; +import org.deegree.feature.persistence.sql.SQLFeatureStore; +import org.deegree.feature.persistence.sql.jaxb.CustomConverterJAXB; +import org.deegree.feature.persistence.sql.rules.Mapping; +import org.slf4j.Logger; + +/** + * Converts binary database columns from/to primitive strings encoded as data URL + *
+ * Note that the maximum length of allowed data is limited to prevent Denial of Service
+ * Attacks. The allowed maximum length can be set through the max-length parameter in
+ * bytes (see {@link AbstractStringPrimitiveConverter#init(Mapping, SQLFeatureStore)}).
+ * Currently, only some generic image file types are configured by default. Additional
+ * mime mappings can be added by supplied by adding magic numbers with mime type as
+ * parameter. These parameter keys have to start with magic-
followed by the
+ * magic bytes in hex and the corresponding mime type.
+ *
+ * Note that the maximum length of allowed data is limited to prevent Denial of Service + * Attacks. The allowed maximum length can be set through the max-length parameter in + * bytes (see {@link AbstractStringPrimitiveConverter#init(Mapping, SQLFeatureStore)}). + *
+ * + * @author Stephan Reichhelm + */ +public class CharacterPrimitiveConverter extends AbstractStringPrimitiveConverter { + + private static final Logger LOG = getLogger(CharacterPrimitiveConverter.class); + + public CharacterPrimitiveConverter() { + super(Types.CLOB); + } + + @Override + public PrimitiveValue toParticle(ResultSet rs, int colIndex) throws SQLException { + try (Reader rdr = rs.getCharacterStream(colIndex)) { + if (rdr == null) { + return null; + } + return new PrimitiveValue(IOUtils.toString(rdr), pt); + } + catch (IOException ioe) { + LOG.trace("Exception", ioe); + throw new SQLException("Failed to read CLOB: " + ioe.getMessage()); + } + } + + @Override + public void setParticle(PreparedStatement stmt, PrimitiveValue particle, int paramIndex) throws SQLException { + final String val; + if (particle.getValue() != null) { + val = particle.getValue().toString(); + } + else { + val = null; + } + if (val == null) { + try { + stmt.setNull(paramIndex, sqlType); + } + catch (SQLFeatureNotSupportedException ignored) { + stmt.setString(paramIndex, null); + } + } + else if (val.length() > maxLen) { + throw new SQLException("Maximum length of " + maxLen + " bytes exceeded."); + } + else { + stmt.setCharacterStream(paramIndex, new StringReader(val), val.length()); + } + } + +} diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/appendix.adoc b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/appendix.adoc index df3edadcba..909a6e1a86 100644 --- a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/appendix.adoc +++ b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/appendix.adoc @@ -92,4 +92,54 @@ This chapter is only intended as an entry point to make it easier to reach these |org.deegree.services.wms.controller.plugins.GetFeatureInfoProvider |org.deegree.services.wms.controller.plugins.DefaultGetFeatureInfoProvider |0..1 -|=== \ No newline at end of file +|=== + +[[anchor-appendix-customconverter]] +=== Custom converters for the SQL feature store + +Custom converters provide an extension point for plugins to provide a specialized DB-to-ObjectModel converter implementation. + +The configuration is not defined as an XML schema, but consists of the specification of the class and an optional list of parameters, +which in turn consist of keys and values. + +A configuration might look something like this: + +[source,xml] +---- +