    public ConfigDatabase(final DataSource dataSource, final XStreamInfoSerialBinding binding) {
        this(dataSource, binding, null);
    }

Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component.


    private Dialect dialect() {
        if (dialect == null) {
            this.dialect = Dialect.detect(dataSource);
        }
        return dialect;
    }


    public ConfigDatabase(
            final DataSource dataSource,
            final XStreamInfoSerialBinding binding,
            CacheProvider cacheProvider) {

        this.binding = binding;
        this.template = new NamedParameterJdbcTemplate(dataSource);
        // cannot use dataSource at this point due to spring context config hack
        // in place to support tx during testing
        this.dataSource = dataSource;

        this.catalogRowMapper = new InfoRowMapper<CatalogInfo>(CatalogInfo.class, binding);
        this.configRowMapper = new InfoRowMapper<Info>(Info.class, binding);

        if (cacheProvider == null) {
            cacheProvider = DefaultCacheProvider.findProvider();
        }
        cache = cacheProvider.getCache("catalog");
        identityCache = cacheProvider.getCache("catalogNames");
        serviceCache = cacheProvider.getCache("services");
        locks = new ConcurrentHashMap<>();
    }


    public <T extends CatalogInfo> int count(final Class<T> of, final Filter filter) {

        QueryBuilder<T> sqlBuilder = QueryBuilder.forCount(dialect, of, dbMappings).filter(filter);

        final StringBuilder sql = sqlBuilder.build();
        final Filter unsupportedFilter = sqlBuilder.getUnsupportedFilter();
        final boolean fullySupported = Filter.INCLUDE.equals(unsupportedFilter);
        if (LOGGER.isLoggable(Level.FINER)) {
            LOGGER.finer("Original filter: " + filter);
            LOGGER.finer("Supported filter: " + sqlBuilder.getSupportedFilter());
            LOGGER.finer("Unsupported filter: " + sqlBuilder.getUnsupportedFilter());
        }
        final int count;
        if (fullySupported) {
            final Map<String, Object> namedParameters = sqlBuilder.getNamedParameters();
            logStatement(sql, namedParameters);

            count = template.queryForObject(sql.toString(), namedParameters, Integer.class);
        } else {
            LOGGER.fine(
                    "Filter is not fully supported, doing scan of supported part to return the number of matches");
            // going the expensive route, filtering as much as possible
            CloseableIterator<T> iterator = query(of, filter, null, null, (SortBy) null);
            try {
                return Iterators.size(iterator);
            } finally {
                iterator.close();
            }
        }
        return count;
    }


    public static Dialect detect(DataSource dataSource) {
        Dialect dialect;
        try {
            Connection conn = dataSource.getConnection();
            String driver = conn.getMetaData().getDriverName();
            if (driver.contains("Oracle")) {
                dialect = new OracleDialect();
            } else {
                dialect = new Dialect();
            }
            conn.close();
        } catch (SQLException ex) {
            throw new RuntimeException(ex);
        }
        return dialect;
    }


    public Object visit(PropertyIsNil filter, Object extraData) {
        final PropertyName propertyName = (PropertyName) filter.getExpression();
        final String propertyTypesParam = propertyTypesParam(propertyName);

        StringBuilder builder =
                append(
                        extraData,
                        "oid IN (SELECT oid FROM object_property WHERE property_type IN (:",
                        propertyTypesParam,
                        ") AND value IS NULL) /* ",
                        filter.toString(),
                        " */\n");
        return builder;
    }


    public Object visit(IncludeFilter filter, Object extraData) {
        append(extraData, "1 = 1 /* INCLUDE */\n");
        return extraData;
    }


    public Object visit(And filter, Object extraData) {
        StringBuilder sql = (StringBuilder) extraData;

        List<Filter> children = filter.getChildren();
        checkArgument(children.size() > 0);
        sql.append("(\n    ");

        for (Iterator<Filter> it = children.iterator(); it.hasNext(); ) {
            Filter child = it.next();
            sql = (StringBuilder) child.accept(this, sql);
            if (it.hasNext()) {
                sql = append(extraData, "    AND\n    ");
            }
        }
        sql.append(")");
        return sql;
    }


    public FilterToCatalogSQL(Class<?> queryType, DbMappings dbMappings) {
        this.queryType = queryType;
        this.dbMappings = dbMappings;
        List<Integer> concreteQueryTypes = dbMappings.getConcreteQueryTypes(queryType);
        namedParams.put("types", concreteQueryTypes);
    }


    public Object visit(Not filter, Object extraData) {
        filter.getFilter().accept(this, append(extraData, "NOT ("));
        return append(extraData, ")");
    }


    public Object visit(ExcludeFilter filter, Object extraData) {
        append(extraData, "0 = 1 /* EXCLUDE */\n");
        return extraData;
    }


    public Object visit(Or filter, Object extraData) {
        StringBuilder sql = (StringBuilder) extraData;

        List<Filter> children = filter.getChildren();
        checkArgument(children.size() > 0);
        sql.append("(");
        for (Iterator<Filter> it = children.iterator(); it.hasNext(); ) {
            Filter child = it.next();
            sql = (StringBuilder) child.accept(this, sql);
            if (it.hasNext()) {
                sql = append(extraData, "    OR\n    ");
            }
        }
        sql.append(")");
        return sql;
    }


    private String handleInstanceOf(IsInstanceOf instanceOf) {
        Expression expression1 = instanceOf.getParameters().get(0);

        Class<?> clazz = expression1.evaluate(null, Class.class);

        if (clazz == null || dbMappings.getTypeId(clazz) == null) {
            return "0 = 1 /* EXCLUDE */\n";
        }

        Integer typeId = dbMappings.getTypeId(clazz);

        return "type_id = " + typeId + " /* isInstanceOf " + clazz.getName() + " */\n";
    }


    public Object visit(PropertyIsNull filter, Object extraData) {
        final PropertyName propertyName = (PropertyName) filter.getExpression();
        final String propertyTypesParam = propertyTypesParam(propertyName);

        StringBuilder builder =
                append(
                        extraData,
                        "(oid IN (SELECT oid FROM object_property WHERE property_type IN (:",
                        propertyTypesParam,
                        ") AND value IS NULL) OR oid NOT IN (SELECT oid FROM object_property WHERE property_type IN (:"
                                + propertyTypesParam
                                + "))) /* ",
                        filter.toString(),
                        " */\n");
        return builder;
    }


    public void applyOffsetLimit(
            StringBuilder sql, @Nullable Integer offset, @Nullable Integer limit) {
        // some db's require limit to be present of offset is
        if (offset != null && limit == null) {
            limit = Integer.MAX_VALUE; // ensure we don't wrap around
        }
        if (limit != null && offset == null) {
            offset = 0;
            limit += 1; // not zero-based
        }
        if (offset != null && limit != null) {
            sql.insert(0, "SELECT * FROM (SELECT query.*, rownum rnum FROM (\n");
            sql.append(") query\n");
            if (limit != Integer.MAX_VALUE) {
                limit = offset + limit;
            }
            sql.append("WHERE rownum <= ").append(limit).append(")\n");
            sql.append("WHERE rnum > ").append(offset);
        }
    }


    public StringBuilder build() {

        StringBuilder whereClause = buildWhereClause();

        StringBuilder query = new StringBuilder();
        if (isCountQuery) {
            if (Filter.INCLUDE.equals(this.originalFilter)) {
                query.append("SELECT COUNT(oid) FROM object WHERE type_id IN (:types)");
            } else {
                query.append("SELECT COUNT(oid) FROM object WHERE type_id IN (:types) AND (\n");
                query.append(whereClause).append(")");
            }
        } else {
            SortBy[] orders = this.sortOrder;
            if (orders == null) {
                query.append("SELECT id FROM object WHERE type_id IN (:types) AND (\n");
                query.append(whereClause).append(")");
                query.append(" ORDER BY oid");
            } else {
                querySortBy(query, whereClause, orders);
            }
            applyOffsetLimit(query);
        }

        return query;
    }


        public ConfigDatabase configDatabase() {
            return new ConfigDatabase(
                    dataSource(), new XStreamInfoSerialBinding(new XStreamPersisterFactory()));
        }


    public void testSort3() {
        Filter filter = Predicates.acceptAll();
        StringBuilder build =
                QueryBuilder.forIds(dialect, WorkspaceInfo.class, dbMappings)
                        .filter(filter)
                        .sortOrder(
                                Predicates.asc("foo"),
                                Predicates.desc("bar"),
                                Predicates.asc("baz"))
                        .build();
    }


    public void testIsNil() {
        // Create the filter
        Filter filter = Predicates.isNull("name");
        // Build it
        StringBuilder build =
                QueryBuilder.forIds(dialect, WorkspaceInfo.class, dbMappings)
                        .filter(filter)
                        .build();
        String sql = build.toString();

        String sqlNil =
                "oid IN (SELECT oid FROM object_property WHERE property_type IN (:"
                        + "ptype0) AND value IS NULL)";
        // Ensure the following sql is present
        assertThat(sql, containsString(sqlNil));
    }


    public void testSort1() {
        Filter filter = Predicates.acceptAll();
        StringBuilder build =
                QueryBuilder.forIds(dialect, WorkspaceInfo.class, dbMappings)
                        .filter(filter)
                        .sortOrder(Predicates.asc("foo"))
                        .build();
    }


    public void testSort3WithFilter() {
        Filter filter = Predicates.equal("name", "quux");
        StringBuilder build =
                QueryBuilder.forIds(dialect, WorkspaceInfo.class, dbMappings)
                        .filter(filter)
                        .sortOrder(
                                Predicates.asc("foo"),
                                Predicates.desc("bar"),
                                Predicates.asc("baz"))
                        .build();
    }


    public void testSort2() {
        Filter filter = Predicates.acceptAll();
        StringBuilder build =
                QueryBuilder.forIds(dialect, WorkspaceInfo.class, dbMappings)
                        .filter(filter)
                        .sortOrder(Predicates.asc("foo"), Predicates.desc("bar"))
                        .build();
    }


    public void testIsInstanceOf() {
        // Create the filter
        Filter filter = Predicates.isInstanceOf(LayerInfo.class);
        // Build it
        StringBuilder build =
                QueryBuilder.forIds(dialect, WorkspaceInfo.class, dbMappings)
                        .filter(filter)
                        .build();
        String sql = build.toString();
        // Ensure the following sql is present
        assertThat(sql, containsString("type_id = " + dbMappings.getTypeId(LayerInfo.class)));
    }


    public void setUp() throws Exception {
        dialect = new Dialect();
        dbMappings = new DbMappings(dialect);
        testSupport =
                new JDBCConfigTestSupport(
                        (JDBCConfigTestSupport.DBConfig)
                                JDBCConfigTestSupport.parameterizedDBConfigs().get(0)[0]);
        testSupport.setUp();
        dbMappings = testSupport.getDbMappings();
    }


    public void testNotEquals() {
        // Create the filter
        Filter filter = Predicates.notEqual("name", "quux");
        // Build it
        StringBuilder build =
                QueryBuilder.forIds(dialect, WorkspaceInfo.class, dbMappings)
                        .filter(filter)
                        .build();
        String sql = build.toString();
        // Ensure the following sql is present
        assertThat(
                sql,
                containsString(
                        "NOT (oid IN (SELECT oid FROM object_property WHERE property_type IN (:ptype0) AND UPPER(value) = :value0)"));
    }


    public void testQueryAll() {
        Filter filter = Predicates.equal("name", "ws1");
        StringBuilder build =
                QueryBuilder.forIds(dialect, WorkspaceInfo.class, dbMappings)
                        .filter(filter)
                        .build();
    }


    public void testIsNull() {
        // Create the filter
        Filter filter = Predicates.isNull("name");
        // Build it
        StringBuilder build =
                QueryBuilder.forIds(dialect, WorkspaceInfo.class, dbMappings)
                        .filter(filter)
                        .build();
        String sql = build.toString();

        String sqlNull =
                "oid IN (SELECT oid FROM object_property WHERE property_type IN (:"
                        + "ptype0) AND value IS NULL) OR oid NOT IN (SELECT oid FROM object_property WHERE property_type IN (:"
                        + "ptype0))";
        // Ensure the following sql is present
        assertThat(sql, containsString(sqlNull));
    }


    public Object visit(PropertyIsLike filter, Object extraData) {
        char esc = filter.getEscape().charAt(0);
        char multi = filter.getWildCard().charAt(0);
        char single = filter.getSingleChar().charAt(0);
        boolean matchCase = filter.isMatchingCase();

        String literal = filter.getLiteral();
        Expression att = filter.getExpression();

        // JD: hack for date values, we append some additional padding to handle
        // the matching of time/timezone/etc...
        Class attributeType = getExpressionType(att);
        // null check if returnType of expression is Object, null is returned
        // from getExpressionType
        if (attributeType != null && Date.class.isAssignableFrom(attributeType)) {
            literal += multi;
        }

        String pattern = LikeFilterImpl.convertToSQL92(esc, multi, single, matchCase, literal);

        try {
            if (!matchCase) {
                out.write(" UPPER(");
            }

            att.accept(this, extraData);

            if (!matchCase) {
                out.write(") LIKE '");
            } else {
                out.write(" LIKE '");
            }

            out.write(pattern);
            out.write("' ");
        } catch (java.io.IOException ioe) {
            throw new RuntimeException(IO_ERROR, ioe);
        }
        return extraData;
    }


    protected void writeLiteral(Object literal) throws IOException {
        if (literal == null) {
            out.write("NULL");
        } else if (literal instanceof Number || literal instanceof Boolean) {
            out.write(String.valueOf(literal));
        } else if (literal instanceof java.sql.Date || literal instanceof java.sql.Timestamp) {
            // java.sql.date toString declares to always format to yyyy-mm-dd
            // (and TimeStamp uses a similar approach)
            out.write("'" + literal + "'");
        } else if (literal instanceof java.util.Date) {
            // get back to the previous case
            Timestamp ts = new java.sql.Timestamp(((Date) literal).getTime());
            out.write("'" + ts + "'");
        } else if (literal instanceof Instant) {
            java.util.Date date = ((Instant) literal).getPosition().getDate();
            Timestamp ts = new java.sql.Timestamp(date.getTime());
            out.write("'" + ts + "'");
        } else if (literal.getClass().isArray()) {
            // write as a SQL99 array
            out.write("ARRAY[");
            int length = Array.getLength(literal);
            for (int i = 0; i < length; i++) {
                writeLiteral(Array.get(literal, i));
                if (i < length - 1) {
                    out.write(", ");
                }
            }
            out.write("]");
        } else {
            // we don't know the type...just convert back to a string
            String encoding = Converters.convert(literal, String.class, null);
            if (encoding == null) {
                // could not convert back to string, use original l value
                encoding = literal.toString();
            }

            // sigle quotes must be escaped to have a valid sql string
            String escaped = encoding.replaceAll("'", "''");
            out.write("'" + escaped + "'");
        }
    }


    public Object visit(Id filter, Object extraData) {
        if (primaryKey == null) {
            throw new RuntimeException("Must set primary key before trying to encode FIDFilters");
        }

        Set ids = filter.getIdentifiers();

        LOGGER.finer("Exporting FID=" + ids);
        try {
            if (ids.size() > 1) {
                out.write("(");
            }
            List<PrimaryKeyColumn> columns = primaryKey.getColumns();
            for (Iterator i = ids.iterator(); i.hasNext(); ) {
                Identifier id = (Identifier) i.next();
                List<Object> attValues = JDBCDataStore.decodeFID(primaryKey, id.toString(), false);

                out.write("(");

                for (int j = 0; j < attValues.size(); j++) {
                    // in case of join the pk columns need to be qualified with alias
                    if (filter instanceof JoinId) {
                        out.write(escapeName(((JoinId) filter).getAlias()));
                        out.write(".");
                    }
                    out.write(escapeName(columns.get(j).getName()));
                    out.write(" = '");
                    out.write(
                            attValues.get(j).toString()); // DJB: changed this to attValues[j] from
                    // attValues[i].
                    out.write("'");

                    if (j < (attValues.size() - 1)) {
                        out.write(" AND ");
                    }
                }

                out.write(")");

                if (i.hasNext()) {
                    out.write(" OR ");
                }
            }
            if (ids.size() > 1) {
                out.write(")");
            }
        } catch (java.io.IOException e) {
            throw new RuntimeException(IO_ERROR, e);
        }

        return extraData;
    }


    public static String convertToSQL92(
            char escape, char multi, char single, boolean matchCase, String pattern)
            throws IllegalArgumentException {
        if ((escape == '\'') || (multi == '\'') || (single == '\''))
            throw new IllegalArgumentException("do not use single quote (') as special char!");

        StringBuffer result = new StringBuffer(pattern.length() + 5);
        for (int i = 0; i < pattern.length(); i++) {
            char chr = pattern.charAt(i);
            if (chr == escape) {
                // emit the next char and skip it
                if (i != (pattern.length() - 1)) result.append(pattern.charAt(i + 1)); //
                i++; // skip next char
            } else if (chr == single) {
                result.append('_');
            } else if (chr == multi) {
                result.append('%');
            } else if (chr == '\'') {
                result.append('\'');
                result.append('\'');
            } else {
                result.append(matchCase ? chr : Character.toUpperCase(chr));
            }
        }

        return result.toString();
    }


    public String getSQL92LikePattern() throws IllegalArgumentException {
        if (escape.length() != 1) {
            throw new IllegalArgumentException(
                    "Like Pattern --> escape char should be of length exactly 1");
        }
        if (wildcardSingle.length() != 1) {
            throw new IllegalArgumentException(
                    "Like Pattern --> wildcardSingle char should be of length exactly 1");
        }
        if (wildcardMulti.length() != 1) {
            throw new IllegalArgumentException(
                    "Like Pattern --> wildcardMulti char should be of length exactly 1");
        }
        return LikeFilterImpl.convertToSQL92(
                escape.charAt(0),
                wildcardMulti.charAt(0),
                wildcardSingle.charAt(0),
                matchingCase,
                pattern);
    }


    public void testLikeToSQL() {
        Assert.assertEquals(
                "BroadWay%", LikeFilterImpl.convertToSQL92('!', '*', '.', true, "BroadWay*"));
        Assert.assertEquals(
                "broad#ay", LikeFilterImpl.convertToSQL92('!', '*', '.', true, "broad#ay"));
        Assert.assertEquals(
                "broadway", LikeFilterImpl.convertToSQL92('!', '*', '.', true, "broadway"));

        Assert.assertEquals(
                "broad_ay", LikeFilterImpl.convertToSQL92('!', '*', '.', true, "broad.ay"));
        Assert.assertEquals(
                "broad.ay", LikeFilterImpl.convertToSQL92('!', '*', '.', true, "broad!.ay"));

        Assert.assertEquals(
                "broa''dway", LikeFilterImpl.convertToSQL92('!', '*', '.', true, "broa'dway"));
        Assert.assertEquals(
                "broa''''dway",
                LikeFilterImpl.convertToSQL92('!', '*', '.', true, "broa" + "''dway"));

        Assert.assertEquals(
                "broadway_", LikeFilterImpl.convertToSQL92('!', '*', '.', true, "broadway."));
        Assert.assertEquals(
                "broadway", LikeFilterImpl.convertToSQL92('!', '*', '.', true, "broadway!"));
        Assert.assertEquals(
                "broadway!", LikeFilterImpl.convertToSQL92('!', '*', '.', true, "broadway!!"));
    }


    public FilterToSQL createFilterToSQL() {
        return new MySQLFilterToSQL(delegate.getUsePreciseSpatialOps());
    }


            new UnWrapper() {

                @Override
                public Statement unwrap(Statement statement) {
                    throw new UnsupportedOperationException();
                }

                @Override
                public Connection unwrap(Connection conn) {
                    throw new UnsupportedOperationException();
                }

                @Override
                public boolean canUnwrap(Statement st) {
                    return false;
                }

                @Override
                public boolean canUnwrap(Connection conn) {
                    return false;
                }
            };


    public String jsonExists(Function function) {
        PropertyName columnName = (PropertyName) getParameter(function, 0, true);
        Literal jsonPath = (Literal) getParameter(function, 1, true);
        Expression expected = getParameter(function, 2, true);

        String[] pointers = jsonPath.getValue().toString().split("/");
        if (pointers.length > 0) {
            String strJsonPath = String.join(".", pointers);
            return String.format(
                    "json_exists(%s, '$%s?(@ == \"%s\")')",
                    columnName, strJsonPath, expected.evaluate(null));
        } else {
            throw new IllegalArgumentException(
                    "Cannot encode filter Invalid pointer " + jsonPath.getValue());
        }
    }


    protected void doSDODistance(
            BinarySpatialOperator filter, Expression e1, Expression e2, Object extraData)
            throws IOException {
        double distance = ((DistanceBufferOperator) filter).getDistance();
        String unit = getSDOUnitFromOGCUnit(((DistanceBufferOperator) filter).getDistanceUnits());

        String within = filter instanceof DWithin ? "TRUE" : "FALSE";

        out.write("SDO_WITHIN_DISTANCE(");
        e1.accept(this, extraData);
        out.write(",");
        e2.accept(this, extraData);

        // encode the unit verbatim when available
        if (unit != null && !"".equals(unit.trim()))
            out.write(",'distance=" + distance + " unit=" + unit + "') = '" + within + "' ");
        else out.write(",'distance=" + distance + "') = '" + within + "' ");
    }


    public String buildJsonFromStrPointer(String[] pointers, Expression expectedExp) {
        if (!"".equals(pointers[0])) {
            if (pointers.length == 1) {
                final String expected =
                        getBaseType(expectedExp).isAssignableFrom(String.class)
                                ? String.format(
                                        "\"%s\"", ((Literal) expectedExp).getValue().toString())
                                : ((Literal) expectedExp).getValue().toString();
                return String.format("\"%s\": [%s]", pointers[0], expected);
            } else {
                return String.format(
                        "\"%s\": { %s }",
                        pointers[0],
                        buildJsonFromStrPointer(
                                Arrays.copyOfRange(pointers, 1, pointers.length), expectedExp));
            }
        } else
            return buildJsonFromStrPointer(
                    Arrays.copyOfRange(pointers, 1, pointers.length), expectedExp);
    }


    private void encodeJsonArrayContains(Function jsonArrayContains) throws IOException {
        PropertyName column = (PropertyName) getParameter(jsonArrayContains, 0, true);
        Literal jsonPath = (Literal) getParameter(jsonArrayContains, 1, true);
        Expression expected = getParameter(jsonArrayContains, 2, true);

        String[] strJsonPath = jsonPath.getValue().toString().split("/");
        if (strJsonPath.length > 0) {
            String jsonFilter =
                    String.format("{ %s }", buildJsonFromStrPointer(strJsonPath, expected));
            out.write(
                    String.format(
                            "\"%s\"::jsonb @> '%s'::jsonb", column.getPropertyName(), jsonFilter));
        } else {
            throw new IllegalArgumentException(
                    "Cannot encode filter Invalid pointer " + jsonPath.getValue());
        }
    }


    public void testFunctionJsonArrayContains() throws Exception {
        filterToSql.setFeatureType(testSchema);
        Function pointer =
                ff.function(
                        "jsonArrayContains",
                        ff.property("OPERATIONS"),
                        ff.literal("/operations"),
                        ff.literal("OP1"));
        filterToSql.encode(pointer);
        String sql = writer.toString().trim();
        assertEquals("\"OPERATIONS\"::jsonb @> '{ \"operations\": [\"OP1\"] }'::jsonb", sql);
    }


    public void testNestedObjectJsonArrayContains() throws Exception {
        filterToSql.setFeatureType(testSchema);
        Function pointer =
                ff.function(
                        "jsonArrayContains",
                        ff.property("OPERATIONS"),
                        ff.literal("/operations/parameters"),
                        ff.literal("P1"));
        filterToSql.encode(pointer);
        String sql = writer.toString().trim();
        assertEquals(
                "\"OPERATIONS\"::jsonb @> '{ \"operations\": { \"parameters\": [\"P1\"] } }'::jsonb",
                sql);
    }


    public void testFunctionJsonArrayContainsNumber() throws Exception {
        filterToSql.setFeatureType(testSchema);
        Function pointer =
                ff.function(
                        "jsonArrayContains",
                        ff.property("OPERATIONS"),
                        ff.literal("/operations"),
                        ff.literal(1));
        filterToSql.encode(pointer);
        String sql = writer.toString().trim();
        assertEquals("\"OPERATIONS\"::jsonb @> '{ \"operations\": [1] }'::jsonb", sql);
    }


  public void validate(final OidcCredentials credentials, final WebContext context) {
    final AuthorizationCode code = credentials.getCode();
    // if we have a code
    if (code != null) {
      try {
        final String computedCallbackUrl = client.computeFinalCallbackUrl(context);
        // Token request
        final TokenRequest request = createTokenRequest(new AuthorizationCodeGrant(code, new URI(computedCallbackUrl)));
        HTTPRequest tokenHttpRequest = request.toHTTPRequest();
        tokenHttpRequest.setConnectTimeout(configuration.getConnectTimeout());
        tokenHttpRequest.setReadTimeout(configuration.getReadTimeout());

        final HTTPResponse httpResponse = tokenHttpRequest.send();
        logger.debug("Token response: status={}, content={}", httpResponse.getStatusCode(),
            httpResponse.getContent());

        final TokenResponse response = OIDCTokenResponseParser.parse(httpResponse);
        if (response instanceof TokenErrorResponse) {
          throw new TechnicalException("Bad token response, error=" + ((TokenErrorResponse) response).getErrorObject());
        }
        logger.debug("Token response successful");
        final OIDCTokenResponse tokenSuccessResponse = (OIDCTokenResponse) response;

        // save tokens in credentials
        final OIDCTokens oidcTokens = tokenSuccessResponse.getOIDCTokens();
        credentials.setAccessToken(oidcTokens.getAccessToken());
        credentials.setRefreshToken(oidcTokens.getRefreshToken());
        credentials.setIdToken(oidcTokens.getIDToken());

      } catch (final URISyntaxException | IOException | ParseException e) {
        throw new TechnicalException(e);
      }
    }
  }

The product deserializes untrusted data without sufficiently verifying that the resulting data will be valid.


    private boolean isImage(MultipartFile file) {
        BufferedImage image = null;
        try (InputStream input = file.getInputStream()) {
            image = ImageIO.read(input);
        } catch (IOException e) {
            LogUtil.error(e.getMessage(), e);
            return false;
        }
        if (image == null || image.getWidth() <= 0 || image.getHeight() <= 0) {
            return false;
        }
        return true;
    }

Unrestricted Upload of File with Dangerous Type

The product allows the attacker to upload or transfer files of dangerous types that can be automatically processed within the product's environment.


    public void backup(File targetDir, DataSource dataSource, DbProperties dbProperties) throws InterruptedException, TimeoutException, IOException {
        ProcessResult processResult = createProcessExecutor(targetDir, dbProperties).execute();

        if (processResult.getExitValue() == 0) {
            log.info("MySQL backup finished successfully.");
        } else {
            log.warn("There was an error backing up the database using `mysqldump`. The `mysqldump` process exited with status code {}.", processResult.getExitValue());
            throw new RuntimeException("There was an error backing up the database using `mysqldump`. The `mysqldump` process exited with status code " + processResult.getExitValue() +
                    ". Please see the server logs for more errors");
        }
    }

Insertion of Sensitive Information into Log File

Information written to log files can be of a sensitive nature and give valuable guidance to an attacker or expose sensitive user information.


    private ProcessExecutor createProcessExecutor(File targetDir, DbProperties dbProperties) {
        ConnectionUrl connectionUrlInstance = ConnectionUrl.getConnectionUrlInstance(dbProperties.url(), dbProperties.connectionProperties());

        LinkedHashMap<String, String> env = new LinkedHashMap<>();
        if (isNotBlank(dbProperties.password())) {
            env.put("MYSQL_PWD", dbProperties.password());
        }
        // override with any user specified environment
        env.putAll(dbProperties.extraBackupEnv());

        ArrayList<String> argv = new ArrayList<>();
        argv.add("mysqldump");

        String dbName = connectionUrlInstance.getDatabase();
        HostInfo mainHost = connectionUrlInstance.getMainHost();

        if (mainHost != null) {
            argv.add("--host=" + mainHost.getHost());
            argv.add("--port=" + mainHost.getPort());
        }
        if (isNotBlank(dbProperties.user())) {
            argv.add("--user=" + dbProperties.user());
        }

        // append any user specified args for mysqldump
        if (isNotBlank(dbProperties.extraBackupCommandArgs())) {
            Collections.addAll(argv, Commandline.translateCommandline(dbProperties.extraBackupCommandArgs()));
        }

        argv.add("--result-file=" + new File(targetDir, "db." + dbName).toString());
        argv.add(connectionUrlInstance.getDatabase());

        ProcessExecutor processExecutor = new ProcessExecutor();
        processExecutor.redirectOutputAlsoTo(Slf4jStream.of(getClass()).asDebug());
        processExecutor.redirectErrorAlsoTo(Slf4jStream.of(getClass()).asDebug());
        processExecutor.environment(env);
        processExecutor.command(argv);
        return processExecutor;
    }


    public void backup(File targetDir, DataSource dataSource, DbProperties dbProperties) throws Exception {
        ProcessResult processResult = createProcessExecutor(targetDir, dbProperties).execute();

        if (processResult.getExitValue() == 0) {
            log.info("PostgreSQL backup finished successfully.");
        } else {
            log.warn("There was an error backing up the database using `pg_dump`. The `pg_dump` process exited with status code {}.", processResult.getExitValue());
            throw new RuntimeException("There was an error backing up the database using `pg_dump`. The `pg_dump` process exited with status code " + processResult.getExitValue() +
                    ". Please see the server logs for more errors.");

        }
    }


    ProcessExecutor createProcessExecutor(File targetDir, DbProperties dbProperties) {
        Properties connectionProperties = dbProperties.connectionProperties();
        Properties pgProperties = Driver.parseURL(dbProperties.url(), connectionProperties);

        ArrayList<String> argv = new ArrayList<>();
        LinkedHashMap<String, String> env = new LinkedHashMap<>();
        if (isNotBlank(dbProperties.password())) {
            env.put("PGPASSWORD", dbProperties.password());
        }

        // override with any user specified environment
        env.putAll(dbProperties.extraBackupEnv());

        String dbName = pgProperties.getProperty("PGDBNAME");
        argv.add("pg_dump");
        argv.add("--host=" + pgProperties.getProperty("PGHOST"));
        argv.add("--port=" + pgProperties.getProperty("PGPORT"));
        argv.add("--dbname=" + dbName);
        if (isNotBlank(dbProperties.user())) {
            argv.add("--username=" + dbProperties.user());
        }
        argv.add("--no-password");
        // append any user specified args for pg_dump
        if (isNotBlank(dbProperties.extraBackupCommandArgs())) {
            Collections.addAll(argv, Commandline.translateCommandline(dbProperties.extraBackupCommandArgs()));
        }
        argv.add("--file=" + new File(targetDir, "db." + dbName));
        ProcessExecutor processExecutor = new ProcessExecutor();
        processExecutor.redirectOutputAlsoTo(Slf4jStream.of(getClass()).asDebug());
        processExecutor.redirectErrorAlsoTo(Slf4jStream.of(getClass()).asDebug());
        processExecutor.environment(env);
        processExecutor.command(argv);
        return processExecutor;
    }


    public void visit(Modification modification) {
        modifiedFilesJson = new ArrayList();

        Map<String, Object> jsonMap = new LinkedHashMap<>();
        jsonMap.put("user", modification.getUserDisplayName());
        jsonMap.put("revision", modification.getRevision());
        jsonMap.put("date", formatISO8601(modification.getModifiedTime()));
        String comment = modification.getComment();
        if (!revision.getMaterial().getMaterialType().equals(TYPE)) {
            comment = commentRenderer.render(comment);
        }
        jsonMap.put("comment", comment);
        jsonMap.put("modifiedFiles", modifiedFilesJson);

        modificationsJson.add(jsonMap);
    }

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.


    public void visit(MaterialRevision revision) {
        this.revision = revision;
        modificationsJson = new ArrayList();

        materialJson = new LinkedHashMap();
        materialJson.put("revision", revision.getRevision().getRevision());
        materialJson.put("revision_href", revision.getRevision().getRevisionUrl());
        materialJson.put("user", revision.buildCausedBy());
        materialJson.put("date", formatISO8601(revision.getDateOfLatestModification()));
        materialJson.put("changed", valueOf(revision.isChanged()));
        materialJson.put("modifications", modificationsJson);

        materials.add(materialJson);
    }


    public List json() {
        return materials;
    }


    private Map<String, Object> createJobDetailModel() {
        GitMaterialConfig gitMaterialConfig = gitMaterialConfig();

        MaterialRevisions materialRevisions = new MaterialRevisions();
        materialRevisions.addRevision(new GitMaterial(gitMaterialConfig),
                new Modification("Ernest Hemingway <oldman@sea.com>", "comment", "email", new Date(), "12", ""));

        Pipeline pipeline = schedule(pipelineConfig("pipeline", new MaterialConfigs(gitMaterialConfig)), createWithModifications(materialRevisions, ""));
        JobDetailPresentationModel model = new JobDetailPresentationModel(building("job"), new JobInstances(), null,
                pipeline, new Tabs(), new TrackingTool(),
                mock(ArtifactsService.class), StageMother.custom("stage"));

        return minimalModelFrom(model);
    }


    public void setUp() throws Exception {
        super.setUp("build_detail/build_detail_page.ftl");
    }


    public void shouldRenderIframeSandboxForTestsTab() {
        JobDetailPresentationModel jobDetailPresentationModel = mock(JobDetailPresentationModel.class, RETURNS_SMART_NULLS);
        when(jobDetailPresentationModel.hasTests()).thenReturn(true);
        when(jobDetailPresentationModel.getCustomizedTabs()).thenReturn(new Tabs());

        Document actualDoc = Jsoup.parse(view.render(minimalModelFrom(jobDetailPresentationModel)));

        assertThat(actualDoc.select("#tab-content-of-tests").last().html(), containsString("<iframe sandbox=\"allow-scripts\""));
    }


    public void shouldEscapeBuildCauseInTrimPathTemplate() {
        Document actualDoc = Jsoup.parse(view.render(createJobDetailModel()));
        assertThat(actualDoc.select("#build-summary-template").last().html(), containsString("modified by Ernest Hemingway &lt;oldman@sea.com&gt;"));
    }


    public void shouldEscapeBuildCauseOnVelocityTemplate() {
        Document actualDoc = Jsoup.parse(view.render(createJobDetailModel()));
        assertThat(actualDoc.select("#build-detail-summary").last().html(), containsString("modified by Ernest Hemingway <oldman@sea.com>"));
    }


    public void shouldHaveErrorMessageAlongWithCustomMessageInOutputOfTemplate() {
        Map<String, Object> data = new HashMap<>();
        data.put("errorMessage", "ERROR MESSAGE");

        String output = view.render(data);
        assertThat(output, containsString("$('trans_content').update(\"Sorry, an unexpected error occurred [ERROR MESSAGE]. :( Please check the server logs for more information.\");"));
    }


    public void shouldHaveTheGenericMessageInOutputOfTemplateWhenCustomErrorMessageIsNotProvided() {
        String output = view.render(new HashMap<>());
        assertThat(output, containsString("$('trans_content').update(\"Sorry, an unexpected error occurred. :( Please check the server logs for more information.\");"));
    }


    public void setLogid(String logid) {
        synchronized (this) {
            if ("-".equals(logid)) {
                this.logid = "";
            } else {
                this.logid = SolrTools.escapeSpecialCharacters(logid);
            }
        }
    }


    public void setImageToShow(String imageToShow) {
        synchronized (lock) {
            this.imageToShow = imageToShow;
            if (viewManager != null) {
                viewManager.setDropdownSelected(String.valueOf(imageToShow));
            }
            // Reset LOGID (the LOGID setter is called later by PrettyFaces, so if a value is passed, it will still be set)
            setLogid("");
            logger.trace("imageToShow: {}", this.imageToShow);
        }
    }


	protected void copyResponse(InputStream is, OutputStream out, byte[] head,
			boolean base64) throws IOException
	{
		if (base64)
		{
			try (BufferedInputStream in = new BufferedInputStream(is,
					BUFFER_SIZE))
			{
				ByteArrayOutputStream os = new ByteArrayOutputStream();
			    byte[] buffer = new byte[0xFFFF];

				os.write(head, 0, head.length);

			    for (int len = is.read(buffer); len != -1; len = is.read(buffer))
			    {
			        os.write(buffer, 0, len);
			    }

				out.write(mxBase64.encodeToString(os.toByteArray(), false).getBytes());
			}
		}
		else
		{
			out.write(head);
			Utils.copy(is, out);
		}
	}

The product does not properly control the allocation and maintenance of a limited resource, thereby enabling an actor to influence the amount of resources consumed, eventually leading to the exhaustion of available resources.


	public static void copy(InputStream in, OutputStream out, int bufferSize)
			throws IOException
	{
		byte[] b = new byte[bufferSize];
		int read;

		while ((read = in.read(b)) != -1)
		{
			out.write(b, 0, read);
		}
	}


private String generateTooltipHtml(CmsListInfoBean infoBean) {

        StringBuffer result = new StringBuffer();
        result.append("
").append(CmsClientStringUtil.shortenString(infoBean.getTitle(), 70)).append("
");
        if (infoBean.hasAdditionalInfo()) {
            for (CmsAdditionalInfoBean additionalInfo : infoBean.getAdditionalInfo()) {
                result.append("
").append(additionalInfo.getName()).append(": ");
                // shorten the value to max 45 characters
                result.append(CmsClientStringUtil.shortenString(additionalInfo.getValue(), 45)).append("
");
            }
        }
        return result.toString();
    }


  public Handler<ServerWebSocket> webSocketHandler() {
    if (!options.isWebsocketBridge()) {
      return null;
    }

    StompServerHandler stomp;
    synchronized (this) {
      stomp = this.handler;
    }

    return socket -> {
      if (!socket.path().equals(options.getWebsocketPath())) {
        LOGGER.error("Receiving a web socket connection on an invalid path (" + socket.path() + "), the path is " +
            "configured to " + options.getWebsocketPath() + ". Rejecting connection");
        socket.reject();
        return;
      }
      StompServerConnection connection = new StompServerWebSocketConnectionImpl(socket, this, writingFrameHandler);
      FrameParser parser = new FrameParser(options);
      socket.exceptionHandler((exception) -> {
        LOGGER.error("The STOMP server caught a WebSocket error - closing connection", exception);
        connection.close();
      });
      socket.endHandler(v -> connection.close());
      parser
          .errorHandler((exception) -> {
                connection.write(
                    Frames.createInvalidFrameErrorFrame(exception));
                connection.close();
              }
          )
          .handler(frame -> stomp.handle(new ServerFrameImpl(frame, connection)));
      socket.handler(parser);
    };
  }

When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct.


  public StompServer listen(int port, String host, Handler<AsyncResult<StompServer>> handler) {
    if (port == -1) {
      handler.handle(Future.failedFuture("TCP server disabled. The port is set to '-1'."));
      return this;
    }
    StompServerHandler stomp;
    synchronized (this) {
      stomp = this.handler;
    }

    Objects.requireNonNull(stomp, "Cannot open STOMP server - no StompServerConnectionHandler attached to the " +
        "server.");
    server
        .connectHandler(socket -> {
          StompServerConnection connection = new StompServerTCPConnectionImpl(socket, this, writingFrameHandler);
          FrameParser parser = new FrameParser(options);
          socket.exceptionHandler((exception) -> {
            LOGGER.error("The STOMP server caught a TCP socket error - closing connection", exception);
            connection.close();
          });
          socket.endHandler(v -> connection.close());
          parser
              .errorHandler((exception) -> {
                    connection.write(
                        Frames.createInvalidFrameErrorFrame(exception));
                    connection.close();
                  }
              )
              .handler(frame -> stomp.handle(new ServerFrameImpl(frame, connection)));
          socket.handler(parser);
        })
        .listen(port, host).onComplete(ar -> {
          if (ar.failed()) {
            if (handler != null) {
              vertx.runOnContext(v -> handler.handle(Future.failedFuture(ar.cause())));
            } else {
              LOGGER.error(ar.cause());
            }
          } else {
            listening = true;
            LOGGER.info("STOMP server listening on " + ar.result().actualPort());
            if (handler != null) {
              vertx.runOnContext(v -> handler.handle(Future.succeededFuture(this)));
            }
          }
        });
    return this;
  }


  public void setUp(TestContext context) {
    vertx = rule.vertx();
    AuthenticationProvider provider = PropertyFileAuthentication.create(vertx, "test-auth.properties");
    server = StompServer.create(vertx, new StompServerOptions().setSecured(true))
        .handler(StompServerHandler.create(vertx).authProvider(provider));
    server.listen().onComplete(context.asyncAssertSuccess());
  }


  void validate(TestContext context, Buffer buffer) {
    context.assertTrue(buffer.toString().contains("CONNECTED"));
    context.assertTrue(buffer.toString().contains("version:1.2"));

    User user = server.stompHandler().getUserBySession(extractSession(buffer.toString()));
    context.assertNotNull(user);
  }


    public List<Map<String, Object>> getAllUserGroup(@PathVariable("userId") String userId) {
        return groupService.getAllUserGroup(userId);
    }

The product does not perform an authorization check when an actor attempts to access a resource or perform an action.


	public <A extends Output<E>, E extends Exception> void append(A a, char c) throws E {
		switch (c) {
			case '&' -> {
				a.append(AMP);
			}
			case '<' -> {
				a.append(LT);
			}
			case '>' -> {
				a.append(GT);
			}
			case '"' -> {
				a.append(QUOT);
			}
			default -> {
				a.append(c);
			}
		}
	}


	public <A extends Output<E>, E extends Exception> void append(A a, CharSequence csq, int start, int end) throws E {
		csq = csq == null ? "null" : csq;
		for (int i = start; i < end; i++) {
			char c = csq.charAt(i);
			switch (c) {
				case '&' -> {
					a.append(csq, start, i);
					start = i + 1;
					a.append(AMP);

				}
				case '<' -> {
					a.append(csq, start, i);
					start = i + 1;
					a.append(LT);

				}
				case '>' -> {
					a.append(csq, start, i);
					start = i + 1;
					a.append(GT);
				}
				case '"' -> {
					a.append(csq, start, i);
					start = i + 1;
					a.append(QUOT);
				}

			}
		}
		a.append(csq, start, end);

	}


	public void testParent() throws Exception {
		LambdaSectionParent m = new LambdaSectionParent("ignore");
		String actual = JStachio.render(m);
		String expected = """
				bingo
				LambdaSectionParent[stuff=ignore]
								""";
		assertEquals(expected, actual);
	}


	public AFile getAFile(String nameOrPath) throws IOException {
		final SFile filecurrent;
		// Log.info("AParentFolderRegular::looking for " + nameOrPath);
		// Log.info("AParentFolderRegular::dir = " + dir);
		if (dir == null) {
			filecurrent = new SFile(nameOrPath);
		} else {
			filecurrent = dir.getAbsoluteFile().file(nameOrPath);
		}
		// Log.info("AParentFolderRegular::Filecurrent " + filecurrent);
		if (filecurrent.exists()) {
			return new AFileRegular(filecurrent.getCanonicalFile());
		}
		return null;
	}

The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.


	public void drawU(UGraphic ug) {
		for (String s : tmp) {
			final Display display = Display.getWithNewlines("<:1f4c4:>" + s);
			TextBlock result = display.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam);
			result.drawU(ug);
			ug = ug.apply(UTranslate.dy(result.calculateDimension(ug.getStringBounder()).getHeight()));
		}

	}


	public void add(String line) {
		if (line.startsWith("/"))
			tmp.add(line.substring(1));
	}


	public UImage toUImage(ColorMapper colorMapper, HColor backcolor, HColor forecolor) {
		final BufferedImage im = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

		if (backcolor == null) {
			backcolor = HColors.WHITE;
		}
		if (forecolor == null) {
			forecolor = HColors.BLACK;
		}
		final HColorGradient gradient = HColors.gradient(backcolor, forecolor, '\0');
		for (int col = 0; col < width; col++) {
			for (int line = 0; line < height; line++) {
				final int localColor = color[line][col];
				if (localColor == -1) {
					final double coef = 1.0 * gray[line][col] / (16 - 1);
					final Color c = gradient.getColor(colorMapper, coef, 255);
					im.setRGB(col, line, c.getRGB());
				} else {
					im.setRGB(col, line, localColor);
				}
			}
		}
		return new UImage(new PixelImage(im, AffineTransformType.TYPE_BILINEAR));
	}


	public void setGray(int x, int y, int level) {
		if (x < 0 || x >= width) {
			return;
		}
		if (y < 0 || y >= height) {
			return;
		}
		if (level < 0 || level >= 16) {
			throw new IllegalArgumentException();
		}
		gray[y][x] = level;
		color[y][x] = -1;
	}


	public void setColor(int x, int y, int col) {
		if (x < 0 || x >= width) {
			return;
		}
		if (y < 0 || y >= height) {
			return;
		}
		gray[y][x] = -1;
		color[y][x] = col;
	}


	private TValue executeReturnLegacyDefine(LineLocation location, TContext context, TMemory memory, List<TValue> args)
			throws EaterException, EaterExceptionLocated {
		if (legacyDefinition == null) {
			throw new IllegalStateException();
		}
		final TMemory copy = getNewMemory(memory, args, Collections.<String, TValue>emptyMap());
		final String tmp = context.applyFunctionsAndVariables(copy, location, legacyDefinition);
		if (tmp == null) {
			return TValue.fromString("");
		}
		return TValue.fromString(tmp);
		// eaterReturn.execute(context, copy);
		// // System.err.println("s3=" + eaterReturn.getValue2());
		// return eaterReturn.getValue2();
	}


	public void executeProcedureInternal(TContext context, TMemory memory, List<TValue> args, Map<String, TValue> named)
			throws EaterException, EaterExceptionLocated {
		if (functionType != TFunctionType.PROCEDURE && functionType != TFunctionType.LEGACY_DEFINELONG) {
			throw new IllegalStateException();
		}
		final TMemory copy = getNewMemory(memory, args, named);
		context.executeLines(copy, body, TFunctionType.PROCEDURE, false);
	}


	public TFunctionImpl(String functionName, List<TFunctionArgument> args, boolean unquoted,
			TFunctionType functionType) {
		final Set<String> names = new HashSet<>();
		for (TFunctionArgument tmp : args) {
			names.add(tmp.getName());
		}
		this.signature = new TFunctionSignature(functionName, args.size(), names);
		this.args = args;
		this.unquoted = unquoted;
		this.functionType = functionType;
	}


	public boolean canCover(int nbArg, Set<String> namedArguments) {
		for (String n : namedArguments) {
			if (signature.getNamedArguments().contains(n) == false) {
				return false;
			}
		}
		if (nbArg > args.size()) {
			return false;
		}
		assert nbArg <= args.size();
		int neededArgument = 0;
		for (TFunctionArgument arg : args) {
			if (namedArguments.contains(arg.getName())) {
				continue;
			}
			if (arg.getOptionalDefaultValue() == null) {
				neededArgument++;
			}
		}
		if (nbArg < neededArgument) {
			return false;
		}
		assert nbArg >= neededArgument;
		return true;
	}


	public void addBody(StringLocated s) throws EaterExceptionLocated {
		body.add(s);
		if (s.getType() == TLineType.RETURN) {
			this.containsReturn = true;
			if (functionType == TFunctionType.PROCEDURE) {
				throw EaterExceptionLocated
						.located("A procedure cannot have !return directive. Declare it as a function instead ?", s);
				// this.functionType = TFunctionType.RETURN;
			}
		}
	}


	public void finalizeEnddefinelong() {
		if (functionType != TFunctionType.LEGACY_DEFINELONG) {
			throw new UnsupportedOperationException();
		}
		if (body.size() == 1) {
			this.functionType = TFunctionType.LEGACY_DEFINE;
			this.legacyDefinition = body.get(0).getString();
		}
	}


	public TValue executeReturnFunction(TContext context, TMemory memory, LineLocation location, List<TValue> args,
			Map<String, TValue> named) throws EaterException, EaterExceptionLocated {
		if (functionType == TFunctionType.LEGACY_DEFINE) {
			return executeReturnLegacyDefine(location, context, memory, args);
		}
		if (functionType != TFunctionType.RETURN_FUNCTION) {
			throw EaterException.unlocated("Illegal call here. Is there a return directive in your function?");
		}
		final TMemory copy = getNewMemory(memory, args, named);
		final TValue result = context.executeLines(copy, body, TFunctionType.RETURN_FUNCTION, true);
		if (result == null) {
			throw EaterException.unlocated("No return directive found in your function");
		}
		return result;
	}


	private TMemory getNewMemory(TMemory memory, List<TValue> values, Map<String, TValue> namedArguments) {
		final Map<String, TValue> result = new HashMap<String, TValue>();
		int ivalue = 0;
		for (TFunctionArgument arg : args) {
			final TValue value;
			if (namedArguments.containsKey(arg.getName())) {
				value = namedArguments.get(arg.getName());
			} else if (ivalue < values.size()) {
				value = values.get(ivalue);
				ivalue++;
			} else {
				value = arg.getOptionalDefaultValue();
			}
			if (value == null) {
				throw new IllegalStateException();
			}
			result.put(arg.getName(), value);
		}
		return memory.forkFromGlobal(result);
	}


	public static Collection<SFile> fileCandidates() {
		final Set<SFile> result = new TreeSet<>();
		final String classpath = System.getProperty("java.class.path");
		String[] classpathEntries = classpath.split(SFile.pathSeparator);
		for (String s : classpathEntries) {
			if (s == null)
				continue;
			SFile dir = new SFile(s);
			if (dir.isFile()) {
				dir = dir.getParentFile();
			}
			if (dir != null && dir.isDirectory()) {
				result.add(dir.file("license.txt"));
			}
		}
		return result;
	}


	public static BufferedImage retrieveDistributorImage(LicenseInfo licenseInfo) {
		if (licenseInfo.getLicenseType() != LicenseType.DISTRIBUTOR) {
			return null;
		}
		try {
			final byte[] s1 = PLSSignature.retrieveDistributorImageSignature();
			if (SignatureUtils.toHexString(s1).equals(SignatureUtils.toHexString(licenseInfo.sha)) == false) {
				return null;
			}
			final InputStream dis = PSystemVersion.class.getResourceAsStream("/distributor.png");
			if (dis == null) {
				return null;
			}
			try {
				final BufferedImage result = SImageIO.read(dis);
				return result;
			} finally {
				dis.close();
			}
		} catch (Exception e) {
			Logme.error(e);
		}
		return null;
	}


	public static synchronized LicenseInfo retrieveNamedSlow() {
		cache = LicenseInfo.NONE;
		if (OptionFlags.ALLOW_INCLUDE == false) {
			return cache;
		}
		final String key = prefs.get("license", "");
		if (key.length() > 0) {
			cache = setIfValid(retrieveNamed(key), cache);
			if (cache.isValid()) {
				return cache;
			}
		}
		for (SFile f : fileCandidates()) {
			try {
				if (f.exists() && f.canRead()) {
					final LicenseInfo result = retrieve(f);
					if (result == null) {
						return null;
					}
					cache = setIfValid(result, cache);
					if (cache.isValid()) {
						return cache;
					}
				}
			} catch (IOException e) {
				Log.info("Error " + e);
				// Logme.error(e);
			}
		}
		return cache;
	}


	private static LicenseInfo retrieve(SFile f) throws IOException {
		final BufferedReader br = f.openBufferedReader();
		if (br == null) {
			return null;
		}
		try {
			final String s = br.readLine();
			final LicenseInfo result = retrieveNamed(s);
			if (result != null) {
				Log.info("Reading license from " + f.getAbsolutePath());
			}
			return result;
		} finally {
			br.close();
		}
	}


	public static LicenseInfo retrieveDistributor() {
		final InputStream dis = PSystemVersion.class.getResourceAsStream("/distributor.txt");
		if (dis == null) {
			return null;
		}
		try {
			final BufferedReader br = new BufferedReader(new InputStreamReader(dis));
			final String licenseString = br.readLine();
			br.close();
			final LicenseInfo result = PLSSignature.retrieveDistributor(licenseString);
			final Throwable creationPoint = new Throwable();
			creationPoint.fillInStackTrace();
			for (StackTraceElement ste : creationPoint.getStackTrace()) {
				if (ste.toString().contains(result.context)) {
					return result;
				}
			}
			return null;
		} catch (Exception e) {
			Logme.error(e);
			return null;
		}
	}


	private static LicenseInfo setIfValid(LicenseInfo value, LicenseInfo def) {
		if (value.isValid() || def.isNone()) {
			return value;
		}
		return def;
	}


	static public void setAllowIncludeFalse() {
		ALLOW_INCLUDE = false;
	}

The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor.


	private boolean isAllowed(AFile file) throws IOException {
		// ::comment when __CORE__
		if (OptionFlags.ALLOW_INCLUDE)
			return true;

		if (file != null) {
			final SFile folder = file.getSystemFolder();
			// System.err.println("canonicalPath=" + path + " " + folder + " " +
			// INCLUDE_PATH);
			if (includePath().contains(folder))
				return true;

		}
		// ::done
		return false;
	}


	public AFile getAFile(String nameOrPath) throws IOException {
		// Log.info("ImportedFiles::getAFile nameOrPath = " + nameOrPath);
		// Log.info("ImportedFiles::getAFile currentDir = " + currentDir);
		final AParentFolder dir = currentDir;
		if (dir == null || isAbsolute(nameOrPath)) {
			return new AFileRegular(new SFile(nameOrPath).getCanonicalFile());
		}
		// final File filecurrent = SecurityUtils.File(dir.getAbsoluteFile(),
		// nameOrPath);
		final AFile filecurrent = dir.getAFile(nameOrPath);
		Log.info("ImportedFiles::getAFile filecurrent = " + filecurrent);
		if (filecurrent != null && filecurrent.isOk()) {
			return filecurrent;
		}
		for (SFile d : getPath()) {
			if (d.isDirectory()) {
				final SFile file = d.file(nameOrPath);
				if (file.exists()) {
					return new AFileRegular(file.getCanonicalFile());
				}
			} else if (d.isFile()) {
				final AFileZipEntry zipEntry = new AFileZipEntry(d, nameOrPath);
				if (zipEntry.isOk()) {
					return zipEntry;
				}
			}
		}
		return filecurrent;
	}


	public ImportedFiles withCurrentDir(AParentFolder newCurrentDir) {
		if (newCurrentDir == null) {
			return this;
		}
		return new ImportedFiles(imported, newCurrentDir);
	}


	public FileWithSuffix getFile(String filename, String suffix) throws IOException {
		final int idx = filename.indexOf('~');
		final AFile file;
		final String entry;
		if (idx == -1) {
			file = getAFile(filename);
			entry = null;
		} else {
			file = getAFile(filename.substring(0, idx));
			entry = filename.substring(idx + 1);
		}
		if (isAllowed(file) == false)
			return FileWithSuffix.none();

		return new FileWithSuffix(filename, suffix, file, entry);
	}


	private boolean isFileOk() {
		// ::comment when __CORE__
		if (SecurityUtils.getSecurityProfile() == SecurityProfile.SANDBOX)
			// In SANDBOX, we cannot read any files
			return false;

		// In any case SFile should not access the security folders
		// (the files must be handled internally)
		try {
			if (isDenied())
				return false;
		} catch (IOException e) {
			return false;
		}
		// Files in "plantuml.include.path" and "plantuml.allowlist.path" are ok.
		if (isInAllowList(SecurityUtils.getPath(SecurityUtils.PATHS_INCLUDES)))
			return true;

		if (isInAllowList(SecurityUtils.getPath(SecurityUtils.ALLOWLIST_LOCAL_PATHS)))
			return true;

		if (SecurityUtils.getSecurityProfile() == SecurityProfile.INTERNET)
			return false;

		if (SecurityUtils.getSecurityProfile() == SecurityProfile.ALLOWLIST)
			return false;

		if (SecurityUtils.getSecurityProfile() != SecurityProfile.UNSECURE) {
			// For UNSECURE, we did not do those checks
			final String path = getCleanPathSecure();
			if (path.startsWith("/etc/") || path.startsWith("/dev/") || path.startsWith("/boot/")
					|| path.startsWith("/proc/") || path.startsWith("/sys/"))
				return false;

			if (path.startsWith("//"))
				return false;

		}
		// ::done
		return true;
	}


	public static SFile fromFile(File internal) {
		if (internal == null) {
			return null;
		}
		return new SFile(internal);
	}


	private boolean isUrlOk() {
		// ::comment when __CORE__
		if (SecurityUtils.getSecurityProfile() == SecurityProfile.SANDBOX)
			// In SANDBOX, we cannot read any URL
			return false;

		if (SecurityUtils.getSecurityProfile() == SecurityProfile.LEGACY)
			return true;

		if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
			// We are UNSECURE anyway
			return true;

		if (isInUrlAllowList())
			// ::done
			return true;
		// ::comment when __CORE__

		if (SecurityUtils.getSecurityProfile() == SecurityProfile.INTERNET) {
			if (forbiddenURL(cleanPath(internal.toString())))
				return false;

			final int port = internal.getPort();
			// Using INTERNET profile, port 80 and 443 are ok
			return port == 80 || port == 443 || port == -1;
		}
		return false;
		// ::done
	}


	public static boolean isSecurityEnv(String name) {
		return name != null && name.toLowerCase().startsWith("plantuml.security.");
	}


	private boolean fileExists(String path) {
		final SFile f = new SFile(path);
		return f.exists();
	}


	public TValue executeReturnFunction(TContext context, TMemory memory, LineLocation location, List<TValue> values,
			Map<String, TValue> named) throws EaterException, EaterExceptionLocated {
		// ::comment when __CORE__
		if (OptionFlags.ALLOW_INCLUDE == false)
			// ::done
			return TValue.fromBoolean(false);
		// ::comment when __CORE__

		final String path = values.get(0).toString();
		return TValue.fromBoolean(fileExists(path));
		// ::done
	}


	private String getenv(String name) {
		// Check, if the script requests secret information.
		// A plantuml server should have an own SecurityManager to
		// avoid access to properties and environment variables, but we should
		// also stop here in other deployments.
		if (SecurityUtils.isSecurityEnv(name))
			return null;
		final String env = System.getProperty(name);
		if (env != null)
			return env;

		return System.getenv(name);
	}


	public TValue executeReturnFunction(TContext context, TMemory memory, LineLocation location, List<TValue> values,
			Map<String, TValue> named) throws EaterException, EaterExceptionLocated {
		// ::comment when __CORE__
		if (OptionFlags.ALLOW_INCLUDE == false)
			// ::done
			return TValue.fromString("");
		// ::comment when __CORE__

		final String name = values.get(0).toString();
		final String value = getenv(name);
		if (value == null)
			return TValue.fromString("");

		return TValue.fromString(value);
		// ::done
	}


	private String loadStringData(String path, String charset) throws EaterException, UnsupportedEncodingException {

		byte[] byteData = null;
		if (path.startsWith("http://") || path.startsWith("https://")) {
			final SURL url = SURL.create(path);
			if (url == null)
				throw EaterException.located("load JSON: Invalid URL " + path);
			byteData = url.getBytes();
			// ::comment when __CORE__
		} else {
			try {
				final SFile file = FileSystem.getInstance().getFile(path);
				if (file != null && file.exists() && file.canRead() && !file.isDirectory()) {
					final ByteArrayOutputStream out = new ByteArrayOutputStream(1024 * 8);
					FileUtils.copyToStream(file, out);
					byteData = out.toByteArray();
				}
			} catch (IOException e) {
				Logme.error(e);
				throw EaterException.located("load JSON: Cannot read file " + path + ". " + e.getMessage());
			}
			// ::done
		}

		if (byteData == null || byteData.length == 0)
			return null; // no length, no data (we want the default)

		return new String(byteData, charset);

	}


	public static synchronized LicenseInfo retrieveNamedSlow() {
		cache = LicenseInfo.NONE;
		if (OptionFlags.ALLOW_INCLUDE == false)
			return cache;

		final String key = prefs.get("license", "");
		if (key.length() > 0) {
			cache = setIfValid(retrieveNamed(key), cache);
			if (cache.isValid())
				return cache;

		}
		for (SFile f : fileCandidates()) {
			try {
				if (f.exists() && f.canRead()) {
					final LicenseInfo result = retrieve(f);
					if (result == null)
						return null;

					cache = setIfValid(result, cache);
					if (cache.isValid())
						return cache;

				}
			} catch (IOException e) {
				Log.info("Error " + e);
				// Logme.error(e);
			}
		}
		return cache;
	}


	public static PSystemVersion createShowVersion2(UmlSource source) {
		final List<String> strings = new ArrayList<>();
		strings.add("<b>PlantUML version " + Version.versionString() + "</b> (" + Version.compileTimeString() + ")");
		strings.add("(" + License.getCurrent() + " source distribution)");
		// :: uncomment when __CORE__
//		strings.add(" ");
//		strings.add("Compiled with CheerpJ 2.3");
//		strings.add("Powered by CheerpJ, a Leaning Technologies Java tool");
		// :: done
		// :: comment when __CORE__
		GraphvizCrash.checkOldVersionWarning(strings);
		if (OptionFlags.ALLOW_INCLUDE) {
			if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
				strings.add("Loaded from " + Version.getJarPath());

			if (OptionFlags.getInstance().isWord()) {
				strings.add("Word Mode");
				strings.add("Command Line: " + Run.getCommandLine());
				strings.add("Current Dir: " + new SFile(".").getAbsolutePath());
				strings.add("plantuml.include.path: " + PreprocessorUtils.getenv(SecurityUtils.PATHS_INCLUDES));
			}
		}
		strings.add(" ");

		GraphvizUtils.addDotStatus(strings, true);
		strings.add(" ");
		for (String name : OptionPrint.interestingProperties())
			strings.add(name);

		for (String v : OptionPrint.interestingValues())
			strings.add(v);

		// ::done

		return new PSystemVersion(source, true, strings);
	}


    public static byte[] compress(int[] input)
            throws IOException
    {
        return rawCompress(input, input.length * 4); // int uses 4 bytes
    }

The product performs a calculation that can produce an integer overflow or wraparound, when the logic assumes that the resulting value will always be larger than the original value. This can introduce other weaknesses when the calculation is used for resource management or execution control.


    public static byte[] compress(double[] input)
            throws IOException
    {
        return rawCompress(input, input.length * 8); // double uses 8 bytes
    }


    public static byte[] compress(float[] input)
            throws IOException
    {
        return rawCompress(input, input.length * 4); // float uses 4 bytes
    }


    public static byte[] compress(short[] input)
            throws IOException
    {
        return rawCompress(input, input.length * 2); // short uses 2 bytes
    }


    public static byte[] compress(char[] input)
            throws IOException
    {
        return rawCompress(input, input.length * 2); // char uses 2 bytes
    }


    public static byte[] compress(long[] input)
            throws IOException
    {
        return rawCompress(input, input.length * 8); // long uses 8 bytes
    }


    public AbstractSniHandler() {
        this(0L);
    }


    public SniHandler(Mapping<? super String, ? extends SslContext> mapping, long handshakeTimeoutMillis) {
        this(new AsyncMappingAdapter(mapping), handshakeTimeoutMillis);
    }


    public SniHandler(AsyncMapping<? super String, ? extends SslContext> mapping) {
        this(mapping, 0L);
    }


    public SniHandler(AsyncMapping<? super String, ? extends SslContext> mapping, long handshakeTimeoutMillis) {
        super(handshakeTimeoutMillis);
        this.mapping = (AsyncMapping<String, SslContext>) ObjectUtil.checkNotNull(mapping, "mapping");
    }


    public void testSniHandlerFiresHandshakeTimeout() throws Exception {
        SniHandler handler = new SniHandler(new Mapping<String, SslContext>() {
            @Override
            public SslContext map(String input) {
                throw new UnsupportedOperationException("Should not be called");
            }
        }, 10);

        final AtomicReference<SniCompletionEvent> completionEventRef =
            new AtomicReference<SniCompletionEvent>();
        EmbeddedChannel ch = new EmbeddedChannel(handler, new ChannelInboundHandlerAdapter() {
            @Override
            public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
                if (evt instanceof SniCompletionEvent) {
                    completionEventRef.set((SniCompletionEvent) evt);
                }
            }
        });
        try {
            while (completionEventRef.get() == null) {
                Thread.sleep(100);
                // We need to run all pending tasks as the handshake timeout is scheduled on the EventLoop.
                ch.runPendingTasks();
            }
            SniCompletionEvent completionEvent = completionEventRef.get();
            assertNotNull(completionEvent);
            assertNotNull(completionEvent.cause());
            assertEquals(SslHandshakeTimeoutException.class, completionEvent.cause().getClass());
        } finally {
            ch.finishAndReleaseAll();
        }
    }


    public void testDecorationWithNull() {
        Http2ConnectionDecoder delegate = mock(Http2ConnectionDecoder.class);

        Http2EmptyDataFrameConnectionDecoder decoder = new Http2EmptyDataFrameConnectionDecoder(delegate, 2);
        decoder.frameListener(null);
        assertNull(decoder.frameListener());
    }


    public void testDecoration() {
        Http2ConnectionDecoder delegate = mock(Http2ConnectionDecoder.class);
        final ArgumentCaptor<Http2FrameListener> listenerArgumentCaptor =
                ArgumentCaptor.forClass(Http2FrameListener.class);
        when(delegate.frameListener()).then(new Answer<Http2FrameListener>() {
            @Override
            public Http2FrameListener answer(InvocationOnMock invocationOnMock) {
                return listenerArgumentCaptor.getValue();
            }
        });
        Http2FrameListener listener = mock(Http2FrameListener.class);
        Http2EmptyDataFrameConnectionDecoder decoder = new Http2EmptyDataFrameConnectionDecoder(delegate, 2);
        decoder.frameListener(listener);
        verify(delegate).frameListener(listenerArgumentCaptor.capture());

        assertThat(decoder.frameListener(),
                CoreMatchers.not(CoreMatchers.instanceOf(Http2EmptyDataFrameListener.class)));
        assertThat(decoder.frameListener0(), CoreMatchers.instanceOf(Http2EmptyDataFrameListener.class));
    }


	public Bin(String name, Object value) {
		this.name = name;
		this.value = Value.get(value);
	}


	public static Bin asBlob(String name, Object value) {
		return new Bin(name, Value.getAsBlob(value));
	}


		public int write(byte[] buffer, int offset) {
			System.arraycopy(bytes, 0, buffer, offset, bytes.length);
			return bytes.length;
		}


	public static Value getAsBlob(Object value) {
		return (value == null)? NullValue.INSTANCE : new BlobValue(value);
	}


		public int getType() {
			return ParticleType.JBLOB;
		}


		public void pack(Packer packer) {
			packer.packBlob(object);
		}


		public static byte[] serialize(Object val) {
			if (DisableSerializer) {
				throw new AerospikeException("Object serializer has been disabled");
			}

			try (ByteArrayOutputStream bstream = new ByteArrayOutputStream()) {
				try (ObjectOutputStream ostream = new ObjectOutputStream(bstream)) {
					ostream.writeObject(val);
				}
				return bstream.toByteArray();
			}
			catch (Throwable e) {
				throw new AerospikeException.Serialize(e);
			}
		}


		public void validateKeyType() {
			throw new AerospikeException(ResultCode.PARAMETER_ERROR, "Invalid key type: jblob");
		}


		public String toString() {
			return Buffer.bytesToHexString(bytes);
		}


		public Object getObject() {
			return object;
		}


		public int hashCode() {
			return object.hashCode();
		}


		public boolean equals(Object other) {
			return (other != null &&
				this.getClass().equals(other.getClass()) &&
				this.object.equals(((BlobValue)other).object));
		}


		public BlobValue(Object object) {
			this.object = object;
		}


		public int estimateSize() throws AerospikeException.Serialize {
			bytes = serialize(object);
			return bytes.length;
		}


	public static Value get(Object value) {
		if (value == null) {
			return NullValue.INSTANCE;
		}

		if (value instanceof Value) {
			return (Value)value;
		}

		if (value instanceof byte[]) {
			return new BytesValue((byte[])value);
		}

		if (value instanceof String) {
			return new StringValue((String)value);
		}

		if (value instanceof Integer) {
			return new IntegerValue((Integer)value);
		}

		if (value instanceof Long) {
			return new LongValue((Long)value);
		}

		if (value instanceof List<?>) {
			return new ListValue((List<?>)value);
		}

		if (value instanceof Map<?,?>) {
			return new MapValue((Map<?,?>)value);
		}

		if (value instanceof Double) {
			return new DoubleValue((Double)value);
		}

		if (value instanceof Float) {
			return new FloatValue((Float)value);
		}

		if (value instanceof Short) {
			return new ShortValue((Short)value);
		}

		if (value instanceof Boolean) {
			if (UseBoolBin) {
				return new BooleanValue((Boolean)value);
			}
			else {
				return new BoolIntValue((Boolean)value);
			}
		}

		if (value instanceof Byte) {
			return new ByteValue((byte)value);
		}

		if (value instanceof Character) {
			return Value.get(((Character)value).charValue());
		}

		if (value instanceof Enum) {
        	return new StringValue(value.toString());
		}

		if (value instanceof UUID) {
			return new StringValue(value.toString());
		}

		if (value instanceof ByteBuffer) {
			ByteBuffer bb = (ByteBuffer)value;
			return new BytesValue(bb.array());
		}

		return new BlobValue(value);
	}


		public LuaValue getLuaValue(LuaInstance instance) {
			return LuaString.valueOf(bytes);
		}


	public static Object bytesToObject(byte[] buf, int offset, int length) {
		if (length <= 0) {
			return null;
		}

		if (Value.DisableDeserializer) {
			throw new AerospikeException.Serialize("Object deserializer has been disabled");
		}

		try (ByteArrayInputStream bastream = new ByteArrayInputStream(buf, offset, length)) {
			try (ObjectInputStream oistream = new ObjectInputStream(bastream)) {
				return oistream.readObject();
			}
		}
		catch (Throwable e) {
			throw new AerospikeException.Serialize(e);
		}
	}


	public static Object bytesToParticle(int type, byte[] buf, int offset, int len)
		throws AerospikeException {

		switch (type) {
		case ParticleType.STRING:
			return Buffer.utf8ToString(buf, offset, len);

		case ParticleType.INTEGER:
			return Buffer.bytesToNumber(buf, offset, len);

		case ParticleType.BOOL:
			return Buffer.bytesToBool(buf, offset, len);

		case ParticleType.DOUBLE:
			return Buffer.bytesToDouble(buf, offset);

		case ParticleType.BLOB:
			return Arrays.copyOfRange(buf, offset, offset+len);

		case ParticleType.JBLOB:
			return Buffer.bytesToObject(buf, offset, len);

		case ParticleType.GEOJSON:
			return Buffer.bytesToGeoJSON(buf, offset, len);

		case ParticleType.HLL:
			return Buffer.bytesToHLL(buf, offset, len);

		case ParticleType.LIST:
			return Unpacker.unpackObjectList(buf, offset, len);

		case ParticleType.MAP:
			return Unpacker.unpackObjectMap(buf, offset, len);

		default:
			return null;
		}
	}


	public LuaValue getLuaValue(int type, byte[] buf, int offset, int len) throws AerospikeException {
		if (len <= 0) {
			return LuaValue.NIL;
		}

		switch (type) {
		case ParticleType.STRING:
			byte[] copy = new byte[len];
			System.arraycopy(buf, offset, copy, 0, len);
			return LuaString.valueOf(copy, 0, len);

		case ParticleType.INTEGER:
			if (len <= 4) {
				return LuaInteger.valueOf(Buffer.bytesToInt(buf, offset));
			}

			if (len <= 8) {
				return LuaInteger.valueOf(Buffer.bytesToLong(buf, offset));
			}
			throw new AerospikeException("Lua BigInteger not implemented.");

		case ParticleType.BOOL:
			return LuaBoolean.valueOf(Buffer.bytesToBool(buf, offset, len));

		case ParticleType.DOUBLE:
			return LuaDouble.valueOf(Buffer.bytesToDouble(buf, offset));

		case ParticleType.BLOB:
			byte[] blob = new byte[len];
			System.arraycopy(buf, offset, blob, 0, len);
			return new LuaBytes(this, blob);

		case ParticleType.JBLOB:
			Object object = Buffer.bytesToObject(buf, offset, len);
			return new LuaJavaBlob(object);

		case ParticleType.LIST: {
			LuaUnpacker unpacker = new LuaUnpacker(this, buf, offset, len);
			return unpacker.unpackList();
		}

		case ParticleType.MAP: {
			LuaUnpacker unpacker = new LuaUnpacker(this, buf, offset, len);
			return unpacker.unpackMap();
		}

		case ParticleType.GEOJSON:
			// skip the flags
			int ncells = Buffer.bytesToShort(buf, offset + 1);
			int hdrsz = 1 + 2 + (ncells * 8);
			return new LuaGeoJSON(new String(buf, offset + hdrsz, len - hdrsz));

		default:
			return LuaValue.NIL;
		}
	}


	protected LuaValue getJavaBlob(Object value) {
		return new LuaJavaBlob(value);
	}


	public void packBlob(Object val) {
		byte[] bytes = BlobValue.serialize(val);
		packByteArrayBegin(bytes.length + 1);
		packByte(ParticleType.JBLOB);
		packByteArray(bytes, 0, bytes.length);
	}


	public void packObject(Object obj) {
		if (obj == null) {
			packNil();
			return;
		}

		if (obj instanceof Value) {
			Value value = (Value)obj;
			value.pack(this);
			return;
		}

		if (obj instanceof byte[]) {
			packParticleBytes((byte[])obj);
			return;
		}

		if (obj instanceof String) {
			packParticleString((String)obj);
			return;
		}

		if (obj instanceof Integer) {
			packInt((Integer)obj);
			return;
		}

		if (obj instanceof Long) {
			packLong((Long)obj);
			return;
		}

		if (obj instanceof List<?>) {
			packList((List<?>)obj);
			return;
		}

		if (obj instanceof Map<?,?>) {
			packMap((Map<?,?>)obj);
			return;
		}

		if (obj instanceof Double) {
			packDouble((Double)obj);
			return;
		}

		if (obj instanceof Float) {
			packFloat((Float)obj);
			return;
		}

		if (obj instanceof Short) {
			packInt((Short)obj);
			return;
		}

		if (obj instanceof Boolean) {
			packBoolean((Boolean)obj);
			return;
		}

		if (obj instanceof Byte) {
			packInt(((Byte)obj) & 0xff);
			return;
		}

		if (obj instanceof Character) {
			packInt(((Character)obj).charValue());
			return;
		}

		if (obj instanceof Enum) {
			packString(obj.toString());
			return;
		}

		if (obj instanceof UUID) {
			packString(obj.toString());
			return;
		}

		if (obj instanceof ByteBuffer) {
			packByteBuffer((ByteBuffer) obj);
			return;
		}

		packBlob(obj);
	}


	private T unpackBlob(int count) throws IOException, ClassNotFoundException {
		int type = buffer[offset++] & 0xff;
		count--;
		T val;

		switch (type) {
		case ParticleType.STRING:
			val = getString(Buffer.utf8ToString(buffer, offset, count));
			break;

		case ParticleType.JBLOB:
			if (Value.DisableDeserializer) {
				throw new AerospikeException.Serialize("Object deserializer has been disabled");
			}

			try (ByteArrayInputStream bastream = new ByteArrayInputStream(buffer, offset, count)) {
				try (ObjectInputStream oistream = new ObjectInputStream(bastream)) {
					val = getJavaBlob(oistream.readObject());
				}
			}
			catch (Throwable e) {
				throw new AerospikeException.Serialize(e);
			}
			break;

		case ParticleType.GEOJSON:
			val = getGeoJSON(Buffer.utf8ToString(buffer, offset, count));
			break;

		default:
			val = getBlob(Arrays.copyOfRange(buffer, offset, offset + count));
			break;
		}
		offset += count;
		return val;
	}


		protected Object getJavaBlob(Object value) {
			return value;
		}


	public void runListRangeExample(AerospikeClient client, Parameters params) {
		Key key = new Key(params.namespace, params.set, "mapkey");
		String binName = "mapbin";

		// Delete record if it already exists.
		client.delete(params.writePolicy, key);

		List<Value> l1 = new ArrayList<Value>();
		l1.add(Value.get(new GregorianCalendar(2018, 1, 1).getTime()));
		l1.add(Value.get(1));

		List<Value> l2 = new ArrayList<Value>();
		l2.add(Value.get(new GregorianCalendar(2018, 1, 2).getTime()));
		l2.add(Value.get(2));

		List<Value> l3 = new ArrayList<Value>();
		l3.add(Value.get(new GregorianCalendar(2018, 2, 1).getTime()));
		l3.add(Value.get(3));

		List<Value> l4 = new ArrayList<Value>();
		l4.add(Value.get(new GregorianCalendar(2018, 2, 2).getTime()));
		l4.add(Value.get(4));

		List<Value> l5 = new ArrayList<Value>();
		l5.add(Value.get(new GregorianCalendar(2018, 2, 5).getTime()));
		l5.add(Value.get(5));

		Map<Value,Value> inputMap = new HashMap<Value,Value>();
		inputMap.put(Value.get("Charlie"), Value.get(l1));
		inputMap.put(Value.get("Jim"), Value.get(l2));
		inputMap.put(Value.get("John"), Value.get(l3));
		inputMap.put(Value.get("Harry"), Value.get(l4));
		inputMap.put(Value.get("Bill"), Value.get(l5));

		// Write values to empty map.
		Record record = client.operate(params.writePolicy, key,
				MapOperation.putItems(MapPolicy.Default, binName, inputMap)
				);

		console.info("Record: " + record);

		List<Value> end = new ArrayList<Value>();
		end.add(Value.get(new GregorianCalendar(2018, 2, 2).getTime()));
		end.add(Value.getAsNull());

		// Delete values < end.
		record = client.operate(params.writePolicy, key,
				MapOperation.removeByValueRange(binName, null, Value.get(end), MapReturnType.COUNT)
				);

		console.info("Record: " + record);
	}


	public void addNullValue() {
		Version version = Version.getServerVersion(client, null);

		// Do not run on servers < 3.6.1
		if (version.isLess(3, 6, 1)) {
			return;
		}

		Key key = new Key(args.namespace, args.set, "addkey");
		String binName = "addbin";

		// Delete record if it already exists.
		client.delete(null, key);

		Bin bin = new Bin(binName, (Long)null);

		AerospikeException ae = assertThrows(AerospikeException.class, new ThrowingRunnable() {
			public void run() {
				client.add(null, key, bin);
			}
		});

		assertEquals(ae.getResultCode(), ResultCode.PARAMETER_ERROR);
	}


  public void setKeyParams() throws Exception {
    assertPlotParam("key", "out");
    assertPlotParam("key", "left");
    assertPlotParam("key", "top");
    assertPlotParam("key", "center");
    assertPlotParam("key", "right");
    assertPlotParam("key", "horiz");
    assertPlotParam("key", "box");
    assertPlotParam("key", "bottom");
    assertInvalidPlotParam("yrange", "out%20right%20top%0aset%20yrange%20[33:system(%20");
  }

Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')

The product constructs all or part of a command, data structure, or record using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify how it is parsed or interpreted when it is sent to a downstream component.


  public void setLabelParams() throws Exception {
    assertPlotParam("ylabel", "This is good");
    assertPlotParam("ylabel", " and so Is this - _ yay");
    assertInvalidPlotParam("ylabel", "[33:system(%20");
    assertInvalidPlotParam("title", "[33:system(%20");
    assertInvalidPlotParam("y2label", "[33:system(%20");
  }


  public void setSmoothParams() throws Exception {
    assertPlotParam("smooth", "unique");
    assertPlotParam("smooth", "frequency");
    assertPlotParam("smooth", "fnormal");
    assertPlotParam("smooth", "cumulative");
    assertPlotParam("smooth", "cnormal");
    assertPlotParam("smooth", "bins");
    assertPlotParam("smooth", "csplines");
    assertPlotParam("smooth", "acsplines");
    assertPlotParam("smooth", "mcsplines");
    assertPlotParam("smooth", "bezier");
    assertPlotParam("smooth", "sbezier");
    assertPlotParam("smooth", "unwrap");
    assertPlotParam("smooth", "zsort");
    assertInvalidPlotParam("smooth", "[33:system(%20");
  }


  public void setFormatParams() throws Exception {
    assertPlotParam("yformat", "%25.2f");
    assertPlotParam("y2format", "%25.2f");
    assertPlotParam("xformat", "%25.2f");
    assertPlotParam("yformat", "%253.0em");
    assertPlotParam("yformat", "%253.0em%25%25");
    assertPlotParam("yformat", "%25.2f seconds");
    assertPlotParam("yformat", "%25.0f ms");
    assertInvalidPlotParam("yformat", "%252.[33:system");
  }


  public void setStyleParams() throws Exception {
    assertPlotParam("style", "linespoint");
    assertPlotParam("style", "points");
    assertPlotParam("style", "circles");
    assertPlotParam("style", "dots");
    assertInvalidPlotParam("style", "dots%20[33:system(%20");
  }


public void badRequest(final BadRequestException exception) {
    logWarn("Bad Request on " + request().getUri() + ": " + exception.getMessage());
    if (this.api_version > 0) {
      // always default to the latest version of the error formatter since we
      // need to return something
      switch (this.api_version) {
        case 1:
        default:
          sendReply(exception.getStatus(), serializer.formatErrorV1(exception));
      }
      return;
    }
    if (hasQueryStringParam("json")) {
      final StringBuilder buf = new StringBuilder(10 +
          exception.getDetails().length());
      buf.append("{\"err\":\"");
      HttpQuery.escapeJson(exception.getMessage(), buf);
      buf.append("\"}");
      sendReply(HttpResponseStatus.BAD_REQUEST, buf);
    } else {
      sendReply(HttpResponseStatus.BAD_REQUEST,
                makePage("Bad Request", "Looks like it's your fault this time",
                         "
"
                         + "
Bad Request
"
                         + "Sorry but your request was rejected as being"
                         + " invalid.

"
                         + "The reason provided was:
"
                         + exception.getMessage()
                         + "

"));
    }
  }


public void internalError(final Exception cause) {
    logError("Internal Server Error on " + request().getUri(), cause);

    if (this.api_version > 0) {
      // always default to the latest version of the error formatter since we
      // need to return something
      switch (this.api_version) {
        case 1:
        default:
          sendReply(HttpResponseStatus.INTERNAL_SERVER_ERROR,
              serializer.formatErrorV1(cause));
      }
      return;
    }

    ThrowableProxy tp = new ThrowableProxy(cause);
    tp.calculatePackagingData();
    final String pretty_exc = ThrowableProxyUtil.asString(tp);
    tp = null;
    if (hasQueryStringParam("json")) {
      // 32 = 10 + some extra space as exceptions always have \t's to escape.
      final StringBuilder buf = new StringBuilder(32 + pretty_exc.length());
      buf.append("{\"err\":\"");
      HttpQuery.escapeJson(pretty_exc, buf);
      buf.append("\"}");
      sendReply(HttpResponseStatus.INTERNAL_SERVER_ERROR, buf);
    } else {
      sendReply(HttpResponseStatus.INTERNAL_SERVER_ERROR,
                makePage("Internal Server Error", "Houston, we have a problem",
                         "
"
                         + "
Internal Server Error
"
                         + "Oops, sorry but your request failed due to a"
                         + " server error.

"
                         + "Please try again in 30 seconds.
"
                         + pretty_exc
                         + "

"));
    }
  }


  public void executeNSU() throws Exception {
    final DeferredGroupException dge = mock(DeferredGroupException.class);
    when(dge.getCause()).thenReturn(new NoSuchUniqueName("foo", "metrics"));

    when(query_result.configureFromQuery((TSQuery)any(), anyInt()))
      .thenReturn(Deferred.fromError(dge));

    final HttpQuery query = NettyMocks.getQuery(tsdb,
        "/api/query?start=1h-ago&m=sum:sys.cpu.user");
    rpc.execute(tsdb, query);
    assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
    final String json =
        query.response().getContent().toString(Charset.forName("UTF-8"));
    assertTrue(json.contains("No such name for 'foo': 'metrics'"));
  }


  public void postQueryNoMetricBadRequest() throws Exception {
    final DeferredGroupException dge = mock(DeferredGroupException.class);
    when(dge.getCause()).thenReturn(new NoSuchUniqueName("foo", "metrics"));

    when(query_result.configureFromQuery((TSQuery)any(), anyInt()))
      .thenReturn(Deferred.fromError(dge));

    HttpQuery query = NettyMocks.postQuery(tsdb, "/api/query",
        "{\"start\":1425440315306,\"queries\":" +
          "[{\"metric\":\"nonexistent\",\"aggregator\":\"sum\",\"rate\":true," +
          "\"rateOptions\":{\"counter\":false}}]}");
    rpc.execute(tsdb, query);
    assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
    final String json =
        query.response().getContent().toString(Charset.forName("UTF-8"));
    assertTrue(json.contains("No such name for 'foo': 'metrics'"));
  }


    protected boolean validateIssuerAudienceAndAzp(@NonNull JwtClaims claims,
                                                   @NonNull String iss,
                                                   @NonNull List<String> audiences,
                                                   @NonNull String clientId,
                                                   @NonNull OpenIdClientConfiguration openIdClientConfiguration) {
        if (openIdClientConfiguration.getIssuer().isPresent()) {
            Optional<URL> issuerOptional = openIdClientConfiguration.getIssuer();
            if (issuerOptional.isPresent()) {
                String issuer = issuerOptional.get().toString();
                return issuer.equalsIgnoreCase(iss) ||
                        audiences.contains(clientId) &&
                                validateAzp(claims, clientId, audiences);
            }
        }
        return false;
    }


        public boolean matches(InetAddress socketAddress) {
            return socketAddress.isAnyLocalAddress()
                || socketAddress.isLoopbackAddress()
                || socketAddress.isLinkLocalAddress()
                || socketAddress.isSiteLocalAddress();
        }


    public static Map processResponse(Response samlResponse, String target)
        throws SAMLException {
        List assertions = null;
        SAMLServiceManager.SOAPEntry partnerdest = null;
        Subject assertionSubject = null;
        if (samlResponse.isSigned()) {
            // verify the signature
            boolean isSignedandValid = verifySignature(samlResponse);
            if (!isSignedandValid) {
                throw new SAMLException(bundle.getString("invalidResponse"));
            }
        }
        // check Assertion and get back a Map of relevant data including,
        // Subject, SOAPEntry for the partner and the List of Assertions.
        Map ssMap = verifyAssertionAndGetSSMap(samlResponse);
        if (debug.messageEnabled()) {
            debug.message("processResponse: ssMap = " + ssMap);
        }

        if (ssMap == null) {
            throw new SAMLException(bundle.getString("invalidAssertion"));
        }
        assertionSubject = (com.sun.identity.saml.assertion.Subject)
            ssMap.get(SAMLConstants.SUBJECT);
        if (assertionSubject == null) {
            throw new SAMLException(bundle.getString("nullSubject"));
        }

        partnerdest = (SAMLServiceManager.SOAPEntry)ssMap
            .get(SAMLConstants.SOURCE_SITE_SOAP_ENTRY);
        if (partnerdest == null) {
            throw new SAMLException(bundle.getString("failedAccountMapping"));
        }

        assertions = (List)ssMap.get(SAMLConstants.POST_ASSERTION);
        Map sessMap = null;
        try {
            sessMap = getAttributeMap(partnerdest, assertions,
                assertionSubject, target);
        } catch (Exception se) {
            debug.error("SAMLUtils.processResponse :" , se);
            throw new SAMLException(
                bundle.getString("failProcessResponse"));
        }
        return sessMap;
    }


    public void shutdown() {

        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                logger.warn("Non-Managed connection could not be closed. Whoops!", e);
            }
        }

    }


    private static String getDatabaseUrl(DatabaseConfiguration dbConfig) {

        int port = dbConfig.getDatabasePort();
        return "jdbc:" + dbConfig.getDatabaseType().toLowerCase() + "://" + dbConfig.getDatabaseHost()
                + ((port == 0) ? "" : (":" + port)) + "/" + dbConfig.getDatabaseName();

    }


    public Connection getConnection(DatabaseConfiguration databaseConfiguration, boolean forceNewConnection)
            throws DatabaseServiceException {
        try {

            // logger.info("connection::{}, forceNewConnection: {}", connection, forceNewConnection);

            if (connection != null && !forceNewConnection) {
                // logger.debug("connection closed::{}", connection.isClosed());
                if (!connection.isClosed()) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Returning existing connection::{}", connection);
                    }

                    return connection;
                }
            }

            Class.forName(type.getClassPath());
            DriverManager.setLoginTimeout(10);
            String dbURL = getDatabaseUrl(databaseConfiguration);
            connection = DriverManager.getConnection(dbURL, databaseConfiguration.getDatabaseUser(),
                    databaseConfiguration.getDatabasePassword());

            if (logger.isDebugEnabled()) {
                logger.debug("*** Acquired New  connection for ::{} **** ", dbURL);
            }

            return connection;

        } catch (ClassNotFoundException e) {
            logger.error("Jdbc Driver not found", e);
            throw new DatabaseServiceException(e.getMessage());
        } catch (SQLException e) {
            logger.error("SQLException::Couldn't get a Connection!", e);
            throw new DatabaseServiceException(true, e.getSQLState(), e.getErrorCode(), e.getMessage());
        }
    }


    public Connection getConnection(DatabaseConfiguration databaseConfiguration, boolean forceNewConnection)
            throws DatabaseServiceException {
        try {

            if (connection != null && !forceNewConnection) {
                // logger.info("connection closed::{}", connection.isClosed());
                if (!connection.isClosed()) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Returning existing connection::{}", connection);
                    }

                    return connection;
                }
            }
            String dbURL = getDatabaseUrl(databaseConfiguration);
            Class.forName(type.getClassPath());

            // logger.info("*** type.getClassPath() ::{}, {}**** ", type.getClassPath());

            DriverManager.setLoginTimeout(10);

            connection = DriverManager.getConnection(dbURL, databaseConfiguration.getDatabaseUser(),
                    databaseConfiguration.getDatabasePassword());

            if (logger.isDebugEnabled()) {
                logger.debug("*** Acquired New  connection for ::{} **** ", dbURL);
            }

            return connection;

        } catch (ClassNotFoundException e) {
            logger.error("Jdbc Driver not found", e);
            throw new DatabaseServiceException(e.getMessage());
        } catch (SQLException e) {
            logger.error("SQLException::Couldn't get a Connection!", e);
            throw new DatabaseServiceException(true, e.getSQLState(), e.getErrorCode(), e.getMessage());
        }
    }


    private String getDatabaseUrl(DatabaseConfiguration dbConfig) {

        int port = dbConfig.getDatabasePort();
        return "jdbc:" + dbConfig.getDatabaseType() + "://" + dbConfig.getDatabaseHost()
                + ((port == 0) ? "" : (":" + port)) + "/" + dbConfig.getDatabaseName() + "?useSSL=" + dbConfig.isUseSSL();

    }


    public Connection getConnection(DatabaseConfiguration databaseConfiguration, boolean forceNewConnection)
            throws DatabaseServiceException {
        try {

            // logger.info("connection::{}, forceNewConnection: {}", connection, forceNewConnection);

            if (connection != null && !forceNewConnection) {
                // logger.info("connection closed::{}", connection.isClosed());
                if (!connection.isClosed()) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Returning existing connection::{}", connection);
                    }
                    return connection;
                }
            }

            Class.forName(type.getClassPath());
            DriverManager.setLoginTimeout(10);
            String dbURL = getDatabaseUrl(databaseConfiguration);
            connection = DriverManager.getConnection(dbURL, databaseConfiguration.getDatabaseUser(),
                    databaseConfiguration.getDatabasePassword());

            logger.debug("*** Acquired New  connection for ::{} **** ", dbURL);

            return connection;

        } catch (ClassNotFoundException e) {
            logger.error("Jdbc Driver not found", e);
            throw new DatabaseServiceException(e.getMessage());
        } catch (SQLException e) {
            logger.error("SQLException::Couldn't get a Connection!", e);
            throw new DatabaseServiceException(true, e.getSQLState(), e.getErrorCode(), e.getMessage());
        }
    }