/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

/***************************************************************************
 * Copyright (C) 2017-2026 ZmartZone Holding BV
 * All rights reserved.
 *
 * DISCLAIMER OF WARRANTIES:
 *
 * THE SOFTWARE PROVIDED HEREUNDER IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
 * ANY WARRANTIES OR REPRESENTATIONS EXPRESS, IMPLIED OR STATUTORY; INCLUDING,
 * WITHOUT LIMITATION, WARRANTIES OF QUALITY, PERFORMANCE, NONINFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  NOR ARE THERE ANY
 * WARRANTIES CREATED BY A COURSE OR DEALING, COURSE OF PERFORMANCE OR TRADE
 * USAGE.  FURTHERMORE, THERE ARE NO WARRANTIES THAT THE SOFTWARE WILL MEET
 * YOUR NEEDS OR BE FREE FROM ERRORS, OR THAT THE OPERATION OF THE SOFTWARE
 * WILL BE UNINTERRUPTED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @Author: Hans Zandbelt - hans.zandbelt@openidc.com
 */

#ifndef _MOD_AUTH_OPENIDC_UTIL_H_
#define _MOD_AUTH_OPENIDC_UTIL_H_

#include "jose.h"
#include "json.h"

// appinfo.c

// base64.c
char *oidc_util_base64_decode(apr_pool_t *pool, const char *input, char **output, int *output_len);
typedef enum {
	OIDC_BASE64URL_PADDING_KEEP = 0,  /* keep the trailing "=" padding */
	OIDC_BASE64URL_PADDING_STRIP = 1, /* strip the padding, per RFC 7515 base64url */
} oidc_base64url_padding_t;

int oidc_util_base64url_encode(request_rec *r, char **dst, const char *src, int src_len,
			       oidc_base64url_padding_t padding);
int oidc_util_base64url_decode(apr_pool_t *pool, char **dst, const char *src);

// expr.c
apr_byte_t oidc_util_regexp_substitute(apr_pool_t *pool, const char *input, const char *regexp, const char *replace,
				       char **output, char **error_str);
apr_byte_t oidc_util_regexp_first_match(apr_pool_t *pool, const char *input, const char *regexp, char **output,
					char **error_str);
typedef enum {
	OIDC_APR_EXPR_RESULT_BOOLEAN = 0, /* the expression evaluates to true/false */
	OIDC_APR_EXPR_RESULT_STRING = 1,  /* the expression produces a string value */
} oidc_apr_expr_result_t;

// file.c
/* refuse to read a whole file, or a single cache entry's value, larger than this into memory */
#define OIDC_UTIL_FILE_SIZE_MAX (16 * 1024 * 1024)
apr_byte_t oidc_util_file_is_regular(apr_pool_t *pool, const char *path, apr_byte_t follow, apr_finfo_t *finfo);
apr_byte_t oidc_util_file_read(request_rec *r, const char *path, apr_pool_t *pool, char **result);
apr_byte_t oidc_util_file_read_server(server_rec *s, const char *path, apr_pool_t *pool, char **result);
apr_byte_t oidc_util_file_write(request_rec *r, const char *path, const char *data);

// html.c
int oidc_util_html_send(request_rec *r, const char *title, const char *html_head, const char *on_load,
			const char *html_body, int status_code);
int oidc_util_html_content_prep(request_rec *r, const char *request_state_key, const char *title, const char *html_head,
				const char *on_load, const char *html_body);
int oidc_util_html_content_send(request_rec *r);
int oidc_util_html_send_error(request_rec *r, const char *error, const char *description, int status_code);
char *oidc_util_html_escape(apr_pool_t *pool, const char *input);
char *oidc_util_html_javascript_escape(apr_pool_t *pool, const char *input);
typedef enum {
	OIDC_POST_PRESERVE_ESCAPE_NONE = 0,
	OIDC_POST_PRESERVE_ESCAPE_HTML = 1,
	OIDC_POST_PRESERVE_ESCAPE_JAVASCRIPT = 2,
} oidc_post_preserve_escape_t;

int oidc_util_html_send_in_template(request_rec *r, const char *filename, char **static_template_content,
				    const char *arg1, oidc_post_preserve_escape_t arg1_esc, const char *arg2,
				    oidc_post_preserve_escape_t arg2_esc);

// jq.c
const char *oidc_util_jq_filter(request_rec *r, const oidc_json_t *json, const char *filter);

// jwt.c

// key.c
apr_byte_t oidc_util_key_symmetric_create(request_rec *r, const char *client_secret, unsigned int r_key_len,
					  const char *hash_algo, apr_byte_t set_kid, oidc_jwk_t **jwk);
apr_hash_t *oidc_util_key_sets_merge(apr_pool_t *pool, apr_hash_t *k1, const apr_array_header_t *k2);
apr_hash_t *oidc_util_key_sets_hash_merge(apr_pool_t *pool, apr_hash_t *k1, apr_hash_t *k2);
apr_hash_t *oidc_util_key_symmetric_merge(apr_pool_t *pool, const apr_array_header_t *keys, const oidc_jwk_t *jwk);
oidc_jwk_t *oidc_util_key_list_first(const apr_array_header_t *key_list, int kty, const char *use);
apr_byte_t oidc_util_key_derive_passphrase_key(const char *passphrase, unsigned char *out, apr_size_t out_len);

// random.c
unsigned int oidc_util_rand_int(unsigned int mod);
apr_byte_t oidc_util_rand_str(request_rec *r, char **output, int len);
char *oidc_util_rand_hex_str(request_rec *r, apr_pool_t *pool, int len);

// url.c
apr_byte_t oidc_util_url_cur_matches(request_rec *r, const char *url);
apr_byte_t oidc_util_url_has_parameter(request_rec *r, const char *param);
apr_byte_t oidc_util_url_parameter_get(request_rec *r, char *name, char **value);

// util.c
char *oidc_util_hex_encode(apr_pool_t *pool, const unsigned char *bytes, unsigned int len);
apr_byte_t oidc_util_strcmp_const_time(const char *a, const char *b);
apr_byte_t oidc_util_hash_string_and_base64url_encode(request_rec *r, const char *openssl_hash_algo, const char *input,
						      char **output);
int oidc_util_strnenvcmp(const char *a, const char *b, int len);
char *oidc_util_openssl_version(apr_pool_t *pool);
apr_byte_t oidc_util_issuer_match(const char *a, const char *b);
apr_hash_t *oidc_util_spaced_string_to_hashtable(apr_pool_t *pool, const char *str);
apr_byte_t oidc_util_spaced_string_equals(apr_pool_t *pool, const char *a, const char *b);
apr_byte_t oidc_util_spaced_string_contains(apr_pool_t *pool, const char *str, const char *match);
void oidc_util_table_add_query_encoded_params(apr_pool_t *pool, apr_table_t *table, const char *params);
apr_byte_t oidc_util_cookie_domain_valid(const char *hostname, const char *cookie_domain);
apr_byte_t oidc_util_hostname_endswith(const char *hostname, const char *suffix);
const char *oidc_util_strcasestr(const char *s1, const char *s2);
void oidc_util_apr_hash_clear(apr_hash_t *ht);
apr_time_t oidc_util_apr_time_from_sec(double seconds);
apr_time_t oidc_util_apr_time_add(apr_time_t a, apr_time_t b);

#endif /* _MOD_AUTH_OPENIDC_UTIL_H_ */
