/*
 * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.wso2.carbon.apimgt.gateway.handlers.security.utils;

import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.MessageContext;
import org.apache.synapse.commons.json.JsonUtil;
import org.apache.synapse.core.axis2.Axis2MessageContext;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

public class SchemaValidationUtils {

    private static final Log logger = LogFactory.getLog(SchemaValidationUtils.class);

    /**
     * Utility function to extract collection of String from Map when the key is given.
     *
     * @param map  Map of String, Collection<String>
     * @param name key
     * @return Collection of Strings
     */
    public static Collection<String> getFromMapOrEmptyList(Map<String, Collection<String>> map, String name) {

        if (name != null && map.containsKey(name)) {

            return map.get(name).stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
        } else {
            return Collections.emptyList();
        }

    }

    /**
     * Method to remove query params from request path.
     *
     * @param subResourcePath full request path.
     * @return cleaned request path.
     */
    public static String getRestSubRequestPath(String subResourcePath) {

        if (subResourcePath.contains("?")) {
            return subResourcePath.split("\\?")[0];
        } else if (subResourcePath.contains("#")) {
            return subResourcePath.split("#")[0];
        } else {
            return subResourcePath;
        }
    }

    /**
     * Utility function to extract query params from resource path.
     *
     * @param apiResource reource path with query params.
     * @param path        path without query params.
     * @return Map of Query params.
     * @throws UnsupportedEncodingException When failed to decode
     */
    public static Map<String, Collection<String>> getQueryParams(String apiResource, String path)
            throws UnsupportedEncodingException {

        Map<String, String> queryParams = new HashMap<>();
        if (!apiResource.equals(path) && apiResource.contains("?")) {
            String queryString = apiResource.replace(path + "?", "");
            String[] query = queryString.split("&");
            for (String keyValue : query) {
                int idx = keyValue.indexOf("=");
                queryParams.put(
                        URLDecoder.decode(keyValue.substring(0, idx), "UTF-8"),
                        URLDecoder.decode(keyValue.substring(idx + 1), "UTF-8"));
            }
        }
        return queryParams.entrySet()
                .stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey, entry -> Collections.singleton(entry.getValue())));
    }

    /**
     * Get the Request/Response messageContent as a JsonObject.
     *
     * @param messageContext Message context
     * @return JsonElement which contains the request/response message content
     */
    public static Optional<String> getMessageContent(MessageContext messageContext) {

        Optional<String> payloadObject = Optional.empty();
        org.apache.axis2.context.MessageContext axis2Context = ((Axis2MessageContext) messageContext)
                .getAxis2MessageContext();
        if (JsonUtil.hasAJsonPayload(axis2Context)) {
            payloadObject = Optional.of(JsonUtil.jsonPayloadToString(axis2Context));
        } else if (messageContext.getEnvelope().getBody() != null) {
            Object objFirstElement = messageContext.getEnvelope().getBody().getFirstElement();
            if (objFirstElement != null) {
                OMElement xmlResponse = messageContext.getEnvelope().getBody().getFirstElement();
                try {
                    payloadObject = Optional.of(JsonUtil.toJsonString(xmlResponse).toString());
                } catch (AxisFault axisFault) {
                    logger.error(" Error occurred while converting the String payload to Json");
                }
            }
        }
        return payloadObject;
    }

}

@@ -3207,31 +3207,21 @@
 rce.
-replace(path + %22?%22, %22%22)
+split(%22?%22)%5B1%5D
 ;%0A  

Fix query param issue in SchemaValidation feature