/* * Zed Attack Proxy (ZAP) and its related class files. * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * * Copyright 2013 The ZAP Development Team * * 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.zaproxy.zap.utils; import net.sf.json.JSONObject; import java.util.Locale; import org.parosproxy.paros.model.Model; import org.zaproxy.zap.extension.api.ApiException; import org.zaproxy.zap.extension.api.ApiException.Type; import org.zaproxy.zap.model.Context; /** * Utils for manipulating API calls and parameters. */ public final class ApiUtils { /** * Gets the int param with a given name and throws an exception accordingly if not found or * valid. * * @param params the params * @param paramName the param name * @return the int param * @throws ApiException the api exception */ public static int getIntParam(JSONObject params, String paramName) throws ApiException { int value; try { value = params.getInt(paramName); } catch (Exception ex) { throw new ApiException(Type.MISSING_PARAMETER, paramName + ": " + ex.getLocalizedMessage()); } return value; } /** * Gets an optional string param, returning null if the parameter was not found. * * @param params the params * @param paramName the param name * @return the optional string param */ public static String getOptionalStringParam(JSONObject params, String paramName) { if (params.containsKey(paramName)) { return params.getString(paramName); } return null; } /** * Gets the non empty string param with a given name and throws an exception accordingly if not * found or empty. * * @param params the params * @param paramName the param name * @return the non empty string param * @throws ApiException the api exception thown if param not found or string empty */ public static String getNonEmptyStringParam(JSONObject params, String paramName) throws ApiException { if (!params.containsKey(paramName)) { throw new ApiException(Type.MISSING_PARAMETER, paramName); } String value = params.getString(paramName); if (value == null || value.isEmpty()) { throw new ApiException(Type.MISSING_PARAMETER, paramName); } return value; } /** * Gets an optional enum param, returning {@code null} if the parameter was not found. * * @param <E> the type of the enum that will be returned * @param params the params * @param paramName the param name * @param enumType the type of the enum * @return the enum, or {@code null} * @throws ApiException if the param value does not match any of the possible enum values */ public static <E extends Enum<E>> E getOptionalEnumParam(JSONObject params, String paramName, Class<E> enumType) throws ApiException { String enumValS = params.optString(paramName, null); E enumVal = null; if (enumValS != null && !enumValS.isEmpty()) { try { enumVal = Enum.valueOf(enumType, enumValS); } catch (Exception ex) { throw new ApiException(ApiException.Type.ILLEGAL_PARAMETER, paramName + ": " + ex.getLocalizedMessage()); } } return enumVal; } /** * Gets the {@link Context} whose id is provided as a parameter with the given name. Throws an * exception accordingly if not found or valid. * * @param params the params * @param contextIdParamName the context id param name * @return the context * @throws ApiException the api exception */ public static Context getContextByParamId(JSONObject params, String contextIdParamName) throws ApiException { int contextId = getIntParam(params, contextIdParamName); Context context = Model.getSingleton().getSession().getContext(contextId); if (context == null) { throw new ApiException(Type.CONTEXT_NOT_FOUND, contextIdParamName); } return context; } /** * Returns the {@code Context} with the given name. The context's name is obtained from the given {@code parameters}, whose * name is the value of {@code parameterName}. * <p> * The parameter must exist, that is, it should be a mandatory parameter, otherwise a runtime exception is thrown. * * @param parameters the parameters that contain the context's name * @param parameterName the name of the parameter used to obtain the context's name * @return the {@code Context} with the given name * @throws ApiException If the context with the given name does not exist * @since 2.4.3 * @see #getContextByName(String) * @see JSONObject#getString(String) */ public static Context getContextByName(JSONObject parameters, String parameterName) throws ApiException { return getContextByName(parameters.getString(parameterName)); } /** * Returns the {@code Context} with the given name. * * @param contextName the name of the context * @return the {@code Context} with the given name * @throws ApiException If the context with the given name does not exist * @since 2.4.3 * @see #getContextByName(JSONObject, String) */ public static Context getContextByName(String contextName) throws ApiException { Context context = Model.getSingleton().getSession().getContext(contextName); if (context == null) { throw new ApiException(ApiException.Type.DOES_NOT_EXIST, contextName); } return context; } /** * Returns the authority of the given {@code site} (i.e. host ":" port ). * <p> * For example, the result of returning the authority from: * <blockquote><pre>http://example.com:8080/some/path?a=b#c</pre></blockquote> is: * <blockquote><pre>example.com:8080</pre></blockquote> * <p> * If the provided site does not have a port, it's added the default of the used scheme. * <p> * <strong>Note:</strong> The implementation is optimised to handle only HTTP and HTTPS schemes, the behaviour is undefined * for other schemes. * * @param site the site whose authority will be extracted * @return the authority of the site * @since 2.5.0 */ public static String getAuthority(String site) { String authority = site; boolean isSecure = false; // Remove http(s):// if (authority.toLowerCase(Locale.ROOT).startsWith("http://")) { authority = authority.substring(7); } else if (authority.toLowerCase(Locale.ROOT).startsWith("https://")) { authority = authority.substring(8); isSecure = true; } // Remove trailing chrs int idx = authority.indexOf('/'); if (idx > 0) { authority = authority.substring(0, idx); } if (!authority.isEmpty() && authority.indexOf(':') == -1) { if (isSecure) { return authority + ":443"; } return authority + ":80"; } return authority; } private ApiUtils() { // Utility class } }